From 4ef5c9af627eff893b5fe6a93760f88caa063654 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 5 Sep 2019 15:35:00 +0200 Subject: [PATCH] C++: Autoformat everything Some files that will change in #1736 have been spared. ./build -j4 target/jars/qlformat find ql/cpp/ql -name "*.ql" -print0 | xargs -0 target/jars/qlformat --input find ql/cpp/ql -name "*.qll" -print0 | xargs -0 target/jars/qlformat --input (cd ql && git checkout 'cpp/ql/src/semmle/code/cpp/ir/implementation/**/*SSA*.qll') buildutils-internal/scripts/pr-checks/sync-identical-files.py --latest --- cpp/ql/src/AlertSuppression.ql | 54 +- .../ClassesWithManyFields.ql | 2 - .../Magic Constants/JapaneseEraDate.ql | 1 - .../Unused Entities/UnusedStaticVariables.ql | 4 +- cpp/ql/src/Critical/FileMayNotBeClosed.ql | 17 +- cpp/ql/src/Critical/MemoryMayNotBeFreed.ql | 18 +- cpp/ql/src/Critical/OverflowDestination.ql | 2 - cpp/ql/src/Critical/OverflowStatic.ql | 1 - cpp/ql/src/DefaultOptions.qll | 26 +- .../src/Documentation/CaptionedComments.qll | 48 +- cpp/ql/src/Documentation/CommentedOutCode.qll | 68 +- cpp/ql/src/Documentation/DocumentApi.ql | 28 +- cpp/ql/src/Documentation/FixmeComments.ql | 1 + cpp/ql/src/Documentation/TodoComments.ql | 2 +- .../src/Documentation/UncommentedFunction.ql | 12 +- .../LOC-2/Rule 03/ExitNonterminatingLoop.ql | 16 +- cpp/ql/src/JPL_C/LOC-2/Rule 03/LoopBounds.ql | 117 +- cpp/ql/src/JPL_C/LOC-2/Rule 04/Recursion.ql | 14 +- cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql | 13 +- .../src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql | 6 +- .../LOC-2/Rule 09/AvoidNestedSemaphores.ql | 14 +- .../JPL_C/LOC-2/Rule 09/AvoidSemaphores.ql | 6 +- .../JPL_C/LOC-2/Rule 09/OutOfOrderLocks.ql | 12 +- cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll | 58 +- .../LOC-2/Rule 11/SimpleControlFlowJmp.ql | 7 +- .../JPL_C/LOC-2/Rule 12/EnumInitialization.ql | 35 +- .../LOC-3/Rule 13/ExternDeclsInHeader.ql | 3 +- .../JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql | 14 +- .../LOC-3/Rule 13/LimitedScopeFunction.ql | 13 +- .../Rule 13/LimitedScopeLocalHidesGlobal.ql | 18 +- .../LOC-3/Rule 14/CheckingReturnValues.ql | 23 +- .../LOC-3/Rule 15/CheckingParameterValues.ql | 18 +- .../LOC-3/Rule 16/UseOfAssertionsConstant.ql | 10 +- .../LOC-3/Rule 16/UseOfAssertionsDensity.ql | 3 +- .../src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql | 28 +- .../LOC-3/Rule 18/CompoundExpressions.ql | 4 +- .../LOC-3/Rule 19/NoBooleanSideEffects.ql | 21 +- .../JPL_C/LOC-4/Rule 20/PreprocessorUse.ql | 17 +- .../LOC-4/Rule 20/PreprocessorUseIfdef.ql | 5 +- .../Rule 20/PreprocessorUseUndisciplined.ql | 8 +- .../src/JPL_C/LOC-4/Rule 21/MacroInBlock.ql | 6 +- .../JPL_C/LOC-4/Rule 23/MismatchedIfdefs.ql | 45 +- .../LOC-4/Rule 24/MultipleStmtsPerLine.ql | 20 +- .../LOC-4/Rule 24/MultipleVarDeclsPerLine.ql | 3 +- .../JPL_C/LOC-4/Rule 25/FunctionSizeLimits.ql | 5 +- .../Rule 26/DeclarationPointerNesting.ql | 4 +- .../LOC-4/Rule 27/PointerDereferenceInStmt.ql | 7 +- .../Rule 28/HiddenPointerDereferenceMacro.ql | 6 +- .../Rule 30/FunctionPointerConversions.ql | 6 +- .../src/JPL_C/LOC-4/Rule 31/IncludesFirst.ql | 20 +- cpp/ql/src/JPL_C/Tasks.qll | 3 +- .../Likely Bugs/AmbiguouslySignedBitField.ql | 20 +- .../Arithmetic/BadAdditionOverflowCheck.qll | 16 +- .../src/Likely Bugs/Arithmetic/BadCheckOdd.ql | 12 +- .../Arithmetic/BitwiseSignCheck.ql | 12 +- .../Arithmetic/ComparisonPrecedence.ql | 2 +- .../ComparisonWithCancelingSubExpr.ql | 66 +- .../Likely Bugs/Arithmetic/FloatComparison.ql | 12 +- .../Likely Bugs/Arithmetic/IntMultToLong.ql | 105 +- .../Arithmetic/PointlessComparison.ql | 47 +- .../Arithmetic/PointlessSelfComparison.ql | 22 +- .../Arithmetic/PointlessSelfComparison.qll | 19 +- .../Likely Bugs/Arithmetic/UnsignedGEZero.ql | 1 + .../Likely Bugs/Arithmetic/UnsignedGEZero.qll | 5 - cpp/ql/src/Likely Bugs/ContinueInFalseLoop.ql | 29 +- .../Conversion/ArrayArgSizeMismatch.ql | 27 +- .../Conversion/CastArrayPointerArithmetic.ql | 34 +- .../Conversion/ConversionChangesSign.ql | 31 +- .../ImplicitDowncastFromBitfield.ql | 11 +- .../Conversion/LossyFunctionResultCast.ql | 22 +- .../Conversion/LossyPointerCast.ql | 3 +- .../Conversion/NonzeroValueCastToPointer.ql | 28 +- .../Likely Bugs/Format/SnprintfOverflow.ql | 8 +- .../Format/TooManyFormatArguments.ql | 14 +- .../Format/WrongNumberOfFormatArguments.ql | 14 +- .../Format/WrongTypeFormatArguments.ql | 150 +- .../Likely Bugs/InconsistentCallOnResult.ql | 19 +- .../InconsistentCheckReturnNull.ql | 220 +- .../JapaneseEra/StructWithExactEraDate.ql | 12 +- cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll | 8 +- .../Likely Typos/AssignWhereCompareMeant.ql | 38 +- .../Likely Typos/BoolValueInBitOp.ql | 9 +- .../Likely Typos/CompareWhereAssignMeant.ql | 8 +- .../Likely Typos/DubiousNullCheck.ql | 21 +- .../Likely Typos/ExprHasNoEffect.ql | 80 +- .../Likely Typos/FutileConditional.ql | 10 +- .../Likely Typos/IncorrectNotOperatorUsage.ql | 24 +- .../Likely Typos/MissingEnumCaseInSwitch.ql | 12 +- .../Likely Typos/ShortCircuitBitMask.ql | 27 +- .../Likely Typos/UsingStrcpyAsBoolean.ql | 6 +- .../Likely Typos/inconsistentLoopDirection.ql | 114 +- .../Memory Management/AllocaInLoop.ql | 3 +- .../Padding/More64BitWaste.ql | 6 +- .../Padding/NonPortablePrintf.ql | 74 +- .../Padding/Suboptimal64BitType.ql | 14 +- .../PotentialBufferOverflow.ql | 18 +- .../ReturnCstrOfLocalStdString.ql | 60 +- .../ReturnStackAllocatedMemory.ql | 9 +- .../Memory Management/StackAddressEscapes.ql | 17 +- .../Memory Management/StrncpyFlippedArgs.ql | 134 +- .../SuspiciousCallToMemset.ql | 93 +- .../SuspiciousCallToStrncat.ql | 10 +- .../Memory Management/SuspiciousSizeof.ql | 29 +- .../Memory Management/UninitializedLocal.ql | 17 +- .../Memory Management/UnsafeUseOfStrcat.ql | 12 +- cpp/ql/src/Likely Bugs/NestedLoopSameVar.ql | 4 +- cpp/ql/src/Likely Bugs/NestedLoopSameVar.qll | 7 +- .../OO/IncorrectConstructorDelegation.ql | 10 +- .../Likely Bugs/OO/NonVirtualDestructor.ql | 9 +- .../OO/NonVirtualDestructorInBaseClass.ql | 22 +- .../src/Likely Bugs/OO/SelfAssignmentCheck.ql | 12 +- .../src/Likely Bugs/OO/ThrowInDestructor.ql | 57 +- .../Likely Bugs/OO/VirtualCallInStructor.ql | 18 +- .../Likely Bugs/RedundantNullCheckSimple.ql | 3 +- cpp/ql/src/Likely Bugs/ReturnConstType.ql | 6 +- .../src/Likely Bugs/ReturnConstTypeCommon.qll | 16 +- .../src/Likely Bugs/ReturnConstTypeMember.ql | 7 +- cpp/ql/src/Likely Bugs/ShortLoopVarName.ql | 27 +- .../MistypedFunctionArguments.ql | 6 +- .../TooFewArguments.ql | 4 +- cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql | 28 +- .../src/Metrics/Classes/CAfferentCoupling.ql | 4 +- .../src/Metrics/Classes/CEfferentCoupling.ql | 4 +- cpp/ql/src/Metrics/Classes/CHalsteadBugs.ql | 1 + .../Metrics/Classes/CHalsteadDifficulty.ql | 1 + cpp/ql/src/Metrics/Classes/CHalsteadEffort.ql | 1 + cpp/ql/src/Metrics/Classes/CHalsteadLength.ql | 1 + .../Metrics/Classes/CHalsteadVocabulary.ql | 1 + cpp/ql/src/Metrics/Classes/CHalsteadVolume.ql | 1 + .../src/Metrics/Classes/CInheritanceDepth.ql | 4 +- .../src/Metrics/Classes/CLackOfCohesionCK.ql | 4 +- .../src/Metrics/Classes/CLackOfCohesionHS.ql | 4 +- cpp/ql/src/Metrics/Classes/CLinesOfCode.ql | 13 +- cpp/ql/src/Metrics/Classes/CNumberOfFields.ql | 6 +- .../src/Metrics/Classes/CNumberOfFunctions.ql | 6 +- .../Metrics/Classes/CNumberOfStatements.ql | 6 +- .../Classes/CPercentageOfComplexCode.ql | 28 +- cpp/ql/src/Metrics/Classes/CResponse.ql | 1 + cpp/ql/src/Metrics/Classes/CSizeOfAPI.ql | 9 +- cpp/ql/src/Metrics/Classes/CSpecialisation.ql | 1 + .../Dependencies/ExternalDependencies.ql | 7 +- .../Dependencies/ExternalDependencies.qll | 57 +- .../ExternalDependenciesSourceLinks.ql | 7 +- .../External/FileCompilationDisplayStrings.ql | 5 +- .../External/FileCompilationSourceLinks.ql | 2 +- cpp/ql/src/Metrics/Files/AutogeneratedLOC.ql | 8 +- .../Files/ConditionalSegmentConditions.ql | 17 +- .../Metrics/Files/ConditionalSegmentLines.ql | 110 +- cpp/ql/src/Metrics/Files/FAfferentCoupling.ql | 4 +- cpp/ql/src/Metrics/Files/FCommentRatio.ql | 4 +- .../Metrics/Files/FCyclomaticComplexity.ql | 27 +- cpp/ql/src/Metrics/Files/FDirectIncludes.ql | 6 +- cpp/ql/src/Metrics/Files/FEfferentCoupling.ql | 4 +- cpp/ql/src/Metrics/Files/FHalsteadBugs.ql | 1 + .../src/Metrics/Files/FHalsteadDifficulty.ql | 1 + cpp/ql/src/Metrics/Files/FHalsteadEffort.ql | 1 + cpp/ql/src/Metrics/Files/FHalsteadLength.ql | 1 + .../src/Metrics/Files/FHalsteadVocabulary.ql | 1 + cpp/ql/src/Metrics/Files/FHalsteadVolume.ql | 1 + cpp/ql/src/Metrics/Files/FLines.ql | 4 +- cpp/ql/src/Metrics/Files/FLinesOfCode.ql | 4 +- .../Metrics/Files/FLinesOfCommentedOutCode.ql | 9 +- cpp/ql/src/Metrics/Files/FLinesOfComments.ql | 4 +- .../Metrics/Files/FLinesOfDuplicatedCode.ql | 15 +- cpp/ql/src/Metrics/Files/FMacroRatio.ql | 20 +- cpp/ql/src/Metrics/Files/FNumberOfClasses.ql | 9 +- cpp/ql/src/Metrics/Files/FNumberOfTests.ql | 14 +- cpp/ql/src/Metrics/Files/FTimeInFrontend.ql | 14 +- cpp/ql/src/Metrics/Files/FTodoComments.ql | 18 +- .../src/Metrics/Files/FTransitiveIncludes.ql | 6 +- .../Files/FTransitiveSourceIncludes.ql | 12 +- cpp/ql/src/Metrics/Files/FunctionLength.ql | 12 +- cpp/ql/src/Metrics/Files/NumberOfFunctions.ql | 9 +- cpp/ql/src/Metrics/Files/NumberOfGlobals.ql | 11 +- .../src/Metrics/Files/NumberOfParameters.ql | 10 +- .../Metrics/Files/NumberOfPublicFunctions.ql | 11 +- .../Metrics/Files/NumberOfPublicGlobals.ql | 26 +- .../Functions/FunCyclomaticComplexity.ql | 1 + .../Functions/FunIterationNestingDepth.ql | 10 +- .../src/Metrics/Functions/FunLinesOfCode.ql | 1 + .../Metrics/Functions/FunLinesOfComments.ql | 1 + .../src/Metrics/Functions/FunNumberOfCalls.ql | 17 +- .../Functions/FunNumberOfParameters.ql | 1 + .../Functions/FunNumberOfStatements.ql | 6 +- .../Functions/FunPercentageOfComments.ql | 1 + .../Functions/StatementNestingDepth.ql | 9 +- cpp/ql/src/Metrics/History/HChurn.ql | 17 +- cpp/ql/src/Metrics/History/HLinesAdded.ql | 17 +- cpp/ql/src/Metrics/History/HLinesDeleted.ql | 17 +- .../src/Metrics/History/HNumberOfAuthors.ql | 2 +- .../src/Metrics/History/HNumberOfChanges.ql | 4 +- .../src/Metrics/History/HNumberOfCoCommits.ql | 10 +- .../src/Metrics/History/HNumberOfReCommits.ql | 14 +- .../Metrics/History/HNumberOfRecentAuthors.ql | 17 +- .../History/HNumberOfRecentChangedFiles.ql | 14 +- .../Metrics/History/HNumberOfRecentChanges.ql | 17 +- .../Internal/CallableDisplayStrings.ql | 1 + .../src/Metrics/Internal/CallableExtents.ql | 21 +- .../Metrics/Internal/CallableSourceLinks.ql | 1 + .../Metrics/Internal/ReftypeDisplayStrings.ql | 1 + .../Metrics/Internal/ReftypeSourceLinks.ql | 1 + .../Metrics/Namespaces/AbstractNamespaces.ql | 11 +- .../Metrics/Namespaces/ConcreteNamespaces.ql | 11 +- .../HighAfferentCouplingNamespaces.ql | 11 +- .../HighDistanceFromMainLineNamespaces.ql | 11 +- .../HighEfferentCouplingNamespaces.ql | 11 +- .../Metrics/Namespaces/StableNamespaces.ql | 11 +- .../Metrics/Namespaces/UnstableNamespaces.ql | 11 +- cpp/ql/src/Microsoft/CallWithNullSAL.ql | 17 +- cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql | 14 +- cpp/ql/src/Microsoft/InconsistentSAL.ql | 21 +- cpp/ql/src/Microsoft/SAL.qll | 33 +- cpp/ql/src/Options.qll | 67 +- cpp/ql/src/PointsTo/Debug.ql | 12 +- cpp/ql/src/PointsTo/PreparedStagedPointsTo.ql | 7 +- cpp/ql/src/PointsTo/Stats.ql | 12 +- cpp/ql/src/PointsTo/TaintedFormatStrings.ql | 127 +- .../src/Power of 10/Rule 1/UseOfRecursion.ql | 14 +- .../Rule 2/BoundedLoopIterations.ql | 101 +- .../Rule 3/DynamicAllocAfterInit.ql | 8 +- .../src/Power of 10/Rule 4/FunctionTooLong.ql | 17 +- .../src/Power of 10/Rule 4/OneStmtPerLine.ql | 18 +- .../Power of 10/Rule 5/AssertionDensity.ql | 26 +- .../Power of 10/Rule 5/ConstantAssertion.ql | 10 +- .../Power of 10/Rule 6/GlobalCouldBeStatic.ql | 14 +- .../Rule 6/VariableScopeTooLarge.ql | 13 +- .../src/Power of 10/Rule 7/CheckArguments.ql | 2 +- .../Power of 10/Rule 7/CheckReturnValues.ql | 23 +- .../Rule 8/AvoidConditionalCompilation.ql | 5 +- .../Rule 8/RestrictPreprocessor.ql | 17 +- .../Power of 10/Rule 8/UndisciplinedMacro.ql | 8 +- .../src/Security/CWE/CWE-022/TaintedPath.ql | 33 +- .../src/Security/CWE/CWE-078/ExecTainted.ql | 15 +- cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql | 13 +- cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql | 22 +- .../CWE-114/UncontrolledProcessOperation.ql | 16 +- .../Security/CWE/CWE-119/OverflowBuffer.ql | 64 +- .../Security/CWE/CWE-120/BadlyBoundedWrite.ql | 12 +- .../src/Security/CWE/CWE-120/OverrunWrite.ql | 20 +- .../Security/CWE/CWE-120/OverrunWriteFloat.ql | 16 +- .../Security/CWE/CWE-120/UnboundedWrite.ql | 21 +- .../CWE/CWE-121/UnterminatedVarargsCall.ql | 35 +- .../CWE-129/ImproperArrayIndexValidation.ql | 19 +- .../CWE/CWE-131/NoSpaceForZeroTerminator.ql | 17 +- .../CWE/CWE-134/UncontrolledFormatString.ql | 13 +- ...ncontrolledFormatStringThroughGlobalVar.ql | 18 +- .../CWE-170/ImproperNullTerminationTainted.ql | 13 +- .../Security/CWE/CWE-190/ArithmeticTainted.ql | 21 +- .../CWE/CWE-190/ArithmeticUncontrolled.ql | 28 +- .../CWE-190/ArithmeticWithExtremeValues.ql | 30 +- .../CWE/CWE-190/ComparisonWithWiderType.ql | 48 +- .../CWE/CWE-190/IntegerOverflowTainted.ql | 28 +- .../CWE/CWE-253/HResultBooleanConversion.ql | 81 +- .../CWE/CWE-290/AuthenticationBypass.ql | 35 +- .../CWE/CWE-311/CleartextBufferWrite.ql | 18 +- .../CWE/CWE-311/CleartextFileWrite.ql | 10 +- .../CWE/CWE-313/CleartextSqliteDatabase.ql | 20 +- .../CWE/CWE-327/BrokenCryptoAlgorithm.ql | 11 +- .../Security/CWE/CWE-327/OpenSslHeartbleed.ql | 27 +- .../CWE/CWE-367/TOCTOUFilesystemRace.ql | 120 +- .../CWE/CWE-428/UnsafeCreateProcessCall.ql | 126 +- .../CWE/CWE-468/IncorrectPointerScaling.ql | 45 +- .../CWE-468/IncorrectPointerScalingChar.ql | 67 +- .../CWE-468/IncorrectPointerScalingCommon.qll | 121 +- .../CWE-468/IncorrectPointerScalingVoid.ql | 28 +- .../CWE/CWE-468/SuspiciousAddWithSizeof.ql | 17 +- .../Security/CWE/CWE-497/ExposedSystemData.ql | 498 ++-- .../CWE/CWE-676/DangerousFunctionOverflow.ql | 1 + .../Security/CWE/CWE-676/DangerousUseOfCin.ql | 101 +- .../CWE-676/PotentiallyDangerousFunction.ql | 2 +- .../CWE/CWE-704/WcharCharConversion.ql | 15 +- .../CWE/CWE-732/DoNotCreateWorldWritable.ql | 17 +- .../Security/CWE/CWE-732/FilePermissions.qll | 131 +- .../CWE-732/UnsafeDaclSecurityDescriptor.ql | 77 +- cpp/ql/src/Security/CWE/CWE-764/LockFlow.qll | 109 +- .../Security/CWE/CWE-764/LockOrderCycle.ql | 8 +- .../src/Security/CWE/CWE-764/TwiceLocked.ql | 14 +- .../Security/CWE/CWE-764/UnreleasedLock.ql | 41 +- .../Security/CWE/CWE-807/TaintedCondition.ql | 19 +- ...initeLoopWithUnsatisfiableExitCondition.ql | 26 +- cpp/ql/src/cpp.qll | 15 - cpp/ql/src/definitions.qll | 139 +- cpp/ql/src/external/CodeDuplication.qll | 248 +- cpp/ql/src/external/DefectFilter.qll | 40 +- cpp/ql/src/external/DuplicateBlock.ql | 20 +- cpp/ql/src/external/DuplicateFunction.ql | 20 +- cpp/ql/src/external/ExternalArtifact.qll | 21 +- cpp/ql/src/external/MetricFilter.qll | 38 +- cpp/ql/src/external/MostlyDuplicateClass.ql | 10 +- cpp/ql/src/external/MostlyDuplicateFile.ql | 4 +- .../src/external/MostlyDuplicateFunction.ql | 7 +- cpp/ql/src/external/MostlySimilarFile.ql | 4 +- cpp/ql/src/external/VCS.qll | 48 +- .../examples/filters/BumpMetricBy10.ql | 4 +- .../examples/filters/EditDefectMessage.ql | 4 +- .../examples/filters/ExcludeGeneratedCode.ql | 8 +- cpp/ql/src/external/tests/DefectFilter.ql | 1 + .../external/tests/DefectFromExternalData.ql | 10 +- cpp/ql/src/external/tests/DefectFromSVN.ql | 14 +- cpp/ql/src/external/tests/MetricFilter.ql | 1 + cpp/ql/src/external/tests/MetricFromSVN.ql | 5 +- cpp/ql/src/filters/ClassifyFiles.ql | 12 +- cpp/ql/src/filters/FilterAutogenerated.ql | 5 +- .../filters/FilterAutogeneratedForMetric.ql | 5 +- cpp/ql/src/filters/FromSource.ql | 3 +- cpp/ql/src/filters/Macros.ql | 6 +- cpp/ql/src/filters/RecentDefects.ql | 9 +- cpp/ql/src/filters/RecentDefectsForMetric.ql | 9 +- .../AV Rule 1.ql | 10 +- .../AV Rule 2.ql | 19 +- .../AV Rule 3.ql | 6 +- cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql | 3 +- cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql | 2 +- cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql | 8 +- cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql | 8 +- cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql | 11 +- cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql | 9 +- cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql | 1 + cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql | 6 +- cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql | 1 + cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql | 1 + cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql | 9 +- cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql | 9 +- cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql | 1 + .../AV Rule 26.ql | 13 +- .../AV Rule 27.ql | 4 +- .../AV Rule 28.ql | 9 +- .../AV Rule 29.ql | 3 +- .../AV Rule 30.ql | 25 +- .../AV Rule 31.ql | 4 +- .../AV Rule 32.ql | 19 +- .../src/jsf/4.07 Header Files/AV Rule 33.ql | 3 +- .../src/jsf/4.07 Header Files/AV Rule 35.ql | 100 +- .../src/jsf/4.07 Header Files/AV Rule 39.ql | 12 +- .../4.08 Implementation Files/AV Rule 40.ql | 19 +- cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql | 2 +- cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql | 13 +- cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql | 2 +- cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql | 2 +- cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql | 17 +- cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql | 12 +- cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql | 8 +- cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql | 93 +- cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql | 16 +- cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql | 33 +- cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql | 17 +- cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql | 15 +- cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql | 18 +- cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql | 8 +- cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql | 3 +- cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql | 21 +- cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql | 24 +- cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql | 25 +- cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql | 2 +- cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql | 2 +- cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql | 158 +- cpp/ql/src/jsf/4.09 Style/Naming.qll | 85 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql | 46 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql | 27 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql | 23 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql | 63 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql | 45 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql | 52 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql | 13 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql | 4 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql | 30 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql | 10 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql | 16 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql | 207 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql | 56 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql | 60 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql | 75 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql | 18 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql | 58 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql | 31 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql | 16 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql | 33 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql | 10 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql | 18 +- cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql | 12 +- cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql | 23 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql | 8 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql | 3 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql | 8 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql | 18 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql | 10 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql | 16 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql | 20 +- cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql | 8 +- cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql | 8 +- cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql | 58 +- .../AV Rule 135.ql | 20 +- .../AV Rule 138.ql | 20 +- .../AV Rule 139.ql | 42 +- .../AV Rule 140.ql | 4 +- .../jsf/4.16 Initialization/AV Rule 142.ql | 26 +- .../jsf/4.16 Initialization/AV Rule 143.ql | 46 +- .../jsf/4.16 Initialization/AV Rule 145.ql | 35 +- cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql | 25 +- cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql | 14 +- cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql | 8 +- cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql | 8 +- .../src/jsf/4.18 Constants/AV Rule 151.1.ql | 4 +- cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql | 27 +- cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql | 34 +- .../4.20 Unions and Bit Fields/AV Rule 153.ql | 3 +- .../4.20 Unions and Bit Fields/AV Rule 154.ql | 18 +- .../4.20 Unions and Bit Fields/AV Rule 155.ql | 6 +- .../4.20 Unions and Bit Fields/AV Rule 156.ql | 10 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql | 9 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql | 11 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql | 16 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql | 18 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql | 20 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql | 14 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql | 24 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql | 6 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql | 4 +- cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql | 8 +- .../AV Rule 170.ql | 8 +- .../AV Rule 171.ql | 18 +- .../AV Rule 173.ql | 21 +- .../AV Rule 175.ql | 8 +- .../AV Rule 176.ql | 11 +- .../jsf/4.23 Type Conversions/AV Rule 178.ql | 18 +- .../jsf/4.23 Type Conversions/AV Rule 179.ql | 17 +- .../jsf/4.23 Type Conversions/AV Rule 180.ql | 124 +- .../jsf/4.23 Type Conversions/AV Rule 181.ql | 14 +- .../jsf/4.23 Type Conversions/AV Rule 182.ql | 28 +- .../jsf/4.23 Type Conversions/AV Rule 184.ql | 20 +- .../jsf/4.23 Type Conversions/AV Rule 185.ql | 15 +- .../AV Rule 186.ql | 11 +- .../AV Rule 187.ql | 28 +- .../AV Rule 188.ql | 3 +- .../AV Rule 189.ql | 8 +- .../AV Rule 190.ql | 3 +- .../AV Rule 191.ql | 18 +- .../AV Rule 192.ql | 20 +- .../AV Rule 193.ql | 23 +- .../AV Rule 194.ql | 24 +- .../AV Rule 195.ql | 8 +- .../AV Rule 196.ql | 11 +- .../AV Rule 197.ql | 1 + .../AV Rule 198.ql | 13 +- .../AV Rule 199.ql | 15 +- .../AV Rule 200.ql | 8 +- .../AV Rule 201.ql | 18 +- .../src/jsf/4.25 Expressions/AV Rule 202.ql | 9 +- .../src/jsf/4.25 Expressions/AV Rule 204.1.ql | 34 +- .../src/jsf/4.25 Expressions/AV Rule 204.ql | 78 +- .../src/jsf/4.25 Expressions/AV Rule 205.ql | 9 +- .../jsf/4.26 Memory Allocation/AV Rule 206.ql | 3 +- .../jsf/4.26 Memory Allocation/AV Rule 207.ql | 26 +- .../jsf/4.27 Fault Handling/AV Rule 208.ql | 3 +- .../src/jsf/4.28 Portable Code/AV Rule 209.ql | 15 +- .../src/jsf/4.28 Portable Code/AV Rule 210.ql | 39 +- .../src/jsf/4.28 Portable Code/AV Rule 212.ql | 17 +- .../src/jsf/4.28 Portable Code/AV Rule 213.ql | 25 +- .../src/jsf/4.28 Portable Code/AV Rule 214.ql | 24 +- .../src/jsf/4.28 Portable Code/AV Rule 215.ql | 3 +- .../section_4_21_Operators/AV_Rule_166.qll | 25 +- cpp/ql/src/semmle/code/cpp/ASTSanity.ql | 2 +- .../src/semmle/code/cpp/AutogeneratedFile.qll | 135 +- cpp/ql/src/semmle/code/cpp/Class.qll | 394 ++- cpp/ql/src/semmle/code/cpp/Comments.qll | 19 +- cpp/ql/src/semmle/code/cpp/Compilation.qll | 46 +- cpp/ql/src/semmle/code/cpp/Declaration.qll | 142 +- cpp/ql/src/semmle/code/cpp/Diagnostics.qll | 8 +- cpp/ql/src/semmle/code/cpp/Element.qll | 122 +- cpp/ql/src/semmle/code/cpp/Enclosing.qll | 60 +- cpp/ql/src/semmle/code/cpp/Enum.qll | 56 +- cpp/ql/src/semmle/code/cpp/Field.qll | 33 +- cpp/ql/src/semmle/code/cpp/File.qll | 194 +- cpp/ql/src/semmle/code/cpp/FriendDecl.qll | 12 +- cpp/ql/src/semmle/code/cpp/Function.qll | 596 ++--- cpp/ql/src/semmle/code/cpp/Include.qll | 14 +- cpp/ql/src/semmle/code/cpp/Initializer.qll | 30 +- cpp/ql/src/semmle/code/cpp/Iteration.qll | 24 +- cpp/ql/src/semmle/code/cpp/Linkage.qll | 25 +- cpp/ql/src/semmle/code/cpp/Location.qll | 81 +- cpp/ql/src/semmle/code/cpp/Macro.qll | 123 +- cpp/ql/src/semmle/code/cpp/NameQualifiers.qll | 66 +- cpp/ql/src/semmle/code/cpp/Namespace.qll | 99 +- cpp/ql/src/semmle/code/cpp/ObjectiveC.qll | 6 +- cpp/ql/src/semmle/code/cpp/PODType03.qll | 93 +- cpp/ql/src/semmle/code/cpp/Parameter.qll | 67 +- cpp/ql/src/semmle/code/cpp/Preprocessor.qll | 36 +- cpp/ql/src/semmle/code/cpp/Print.qll | 288 +-- cpp/ql/src/semmle/code/cpp/PrintAST.ql | 2 +- cpp/ql/src/semmle/code/cpp/PrintAST.qll | 11 +- cpp/ql/src/semmle/code/cpp/Specifier.qll | 96 +- cpp/ql/src/semmle/code/cpp/Struct.qll | 30 +- cpp/ql/src/semmle/code/cpp/TestFile.qll | 26 +- cpp/ql/src/semmle/code/cpp/Type.qll | 722 +++--- cpp/ql/src/semmle/code/cpp/TypedefType.qll | 35 +- cpp/ql/src/semmle/code/cpp/Union.qll | 17 +- cpp/ql/src/semmle/code/cpp/UserType.qll | 66 +- cpp/ql/src/semmle/code/cpp/Variable.qll | 163 +- cpp/ql/src/semmle/code/cpp/XML.qll | 151 +- cpp/ql/src/semmle/code/cpp/commons/Alloc.qll | 146 +- .../semmle/code/cpp/commons/Assertions.qll | 23 +- cpp/ql/src/semmle/code/cpp/commons/Buffer.qll | 99 +- .../semmle/code/cpp/commons/CommonType.qll | 12 +- .../src/semmle/code/cpp/commons/DateTime.qll | 58 +- .../semmle/code/cpp/commons/Dependency.qll | 235 +- .../semmle/code/cpp/commons/Environment.qll | 11 +- .../semmle/code/cpp/commons/Exclusions.qll | 20 +- cpp/ql/src/semmle/code/cpp/commons/File.qll | 32 +- cpp/ql/src/semmle/code/cpp/commons/NULL.qll | 8 +- .../code/cpp/commons/NullTermination.qll | 39 +- .../code/cpp/commons/PolymorphicClass.qll | 6 +- cpp/ql/src/semmle/code/cpp/commons/Printf.qll | 4 +- cpp/ql/src/semmle/code/cpp/commons/Scanf.qll | 158 +- cpp/ql/src/semmle/code/cpp/commons/Strcat.qll | 20 +- .../code/cpp/commons/StringAnalysis.qll | 55 +- .../code/cpp/commons/StructLikeClass.qll | 66 +- .../code/cpp/commons/Synchronization.qll | 88 +- .../semmle/code/cpp/commons/VoidContext.qll | 37 +- .../code/cpp/commons/unix/Constants.qll | 96 +- .../code/cpp/controlflow/BasicBlocks.qll | 116 +- .../code/cpp/controlflow/ControlFlowGraph.qll | 12 +- .../semmle/code/cpp/controlflow/Dataflow.qll | 60 +- .../cpp/controlflow/DefinitionsAndUses.qll | 144 +- .../code/cpp/controlflow/Dereferenced.qll | 109 +- .../semmle/code/cpp/controlflow/Dominance.qll | 56 +- .../semmle/code/cpp/controlflow/Guards.qll | 528 ++-- .../semmle/code/cpp/controlflow/IRGuards.qll | 789 +++--- .../LocalScopeVariableReachability.qll | 127 +- .../semmle/code/cpp/controlflow/Nullness.qll | 182 +- .../src/semmle/code/cpp/controlflow/SSA.qll | 250 +- .../semmle/code/cpp/controlflow/SSAUtils.qll | 444 ++-- .../controlflow/StackVariableReachability.qll | 125 +- .../code/cpp/controlflow/SubBasicBlocks.qll | 52 +- .../code/cpp/controlflow/internal/CFG.qll | 11 +- .../controlflow/internal/ConstantExprs.qll | 533 ++-- .../internal/PrimitiveBasicBlocks.qll | 49 +- .../src/semmle/code/cpp/dataflow/DataFlow.qll | 1 + .../semmle/code/cpp/dataflow/DataFlow2.qll | 1 + .../semmle/code/cpp/dataflow/DataFlow3.qll | 1 + .../semmle/code/cpp/dataflow/DataFlow4.qll | 1 + .../semmle/code/cpp/dataflow/EscapesTree.qll | 35 +- .../code/cpp/dataflow/RecursionPrevention.qll | 4 +- .../semmle/code/cpp/dataflow/StackAddress.qll | 185 +- .../code/cpp/dataflow/TaintTracking.qll | 4 +- .../cpp/dataflow/internal/DataFlowPrivate.qll | 1 - .../cpp/dataflow/internal/DataFlowUtil.qll | 21 +- .../code/cpp/dataflow/internal/FlowVar.qll | 126 +- .../cpp/dataflow/internal/SubBasicBlocks.qll | 52 +- .../dataflow/internal/TaintTrackingUtil.qll | 17 +- cpp/ql/src/semmle/code/cpp/exprs/Access.qll | 105 +- .../code/cpp/exprs/ArithmeticOperation.qll | 63 +- .../src/semmle/code/cpp/exprs/Assignment.qll | 53 +- .../code/cpp/exprs/BitwiseOperation.qll | 9 +- .../code/cpp/exprs/BuiltInOperations.qll | 13 +- cpp/ql/src/semmle/code/cpp/exprs/Call.qll | 215 +- cpp/ql/src/semmle/code/cpp/exprs/Cast.qll | 325 ++- .../code/cpp/exprs/ComparisonOperation.qll | 19 +- cpp/ql/src/semmle/code/cpp/exprs/Expr.qll | 324 ++- cpp/ql/src/semmle/code/cpp/exprs/Lambda.qll | 60 +- cpp/ql/src/semmle/code/cpp/exprs/Literal.qll | 125 +- .../code/cpp/exprs/LogicalOperation.qll | 35 +- .../src/semmle/code/cpp/exprs/ObjectiveC.qll | 61 +- .../code/cpp/headers/MultipleInclusion.qll | 73 +- .../code/cpp/internal/QualifiedName.qll | 19 +- .../semmle/code/cpp/internal/ResolveClass.qll | 30 +- cpp/ql/src/semmle/code/cpp/ir/IRSanity.ql | 2 +- .../semmle/code/cpp/ir/dataflow/DataFlow.qll | 1 + .../semmle/code/cpp/ir/dataflow/DataFlow2.qll | 1 + .../semmle/code/cpp/ir/dataflow/DataFlow3.qll | 1 + .../semmle/code/cpp/ir/dataflow/DataFlow4.qll | 1 + .../ir/dataflow/internal/DataFlowDispatch.qll | 4 +- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 4 +- .../cpp/ir/implementation/IRConfiguration.qll | 8 +- .../ir/implementation/aliased_ssa/IRSanity.ql | 2 +- .../aliased_ssa/constant/ConstantAnalysis.qll | 39 +- .../aliased_ssa/gvn/ValueNumbering.qll | 190 +- .../aliased_ssa/internal/AliasAnalysis.qll | 107 +- .../cpp/ir/implementation/raw/IRSanity.ql | 2 +- .../raw/constant/ConstantAnalysis.qll | 39 +- .../implementation/raw/gvn/ValueNumbering.qll | 190 +- .../raw/internal/IRConstruction.qll | 201 +- .../raw/internal/InstructionTag.qll | 183 +- .../raw/internal/TranslatedCall.qll | 265 +- .../raw/internal/TranslatedCondition.qll | 164 +- .../internal/TranslatedDeclarationEntry.qll | 135 +- .../raw/internal/TranslatedElement.qll | 267 +- .../raw/internal/TranslatedExpr.qll | 2221 +++++++---------- .../raw/internal/TranslatedFunction.qll | 532 ++-- .../raw/internal/TranslatedInitialization.qll | 776 +++--- .../raw/internal/TranslatedStmt.qll | 566 ++--- .../reachability/DominanceInternal.qll | 2 + .../internal/reachability/PrintDominance.qll | 12 +- .../reachability/PrintReachableBlock.qll | 17 +- .../internal/reachability/ReachableBlock.qll | 31 +- .../reachability/ReachableBlockInternal.qll | 2 +- .../implementation/unaliased_ssa/IRSanity.ql | 2 +- .../constant/ConstantAnalysis.qll | 39 +- .../unaliased_ssa/gvn/ValueNumbering.qll | 190 +- .../unaliased_ssa/internal/AliasAnalysis.qll | 107 +- .../reachability/DominanceInternal.qll | 2 + .../internal/reachability/PrintDominance.qll | 12 +- .../reachability/PrintReachableBlock.qll | 17 +- .../internal/reachability/ReachableBlock.qll | 31 +- .../reachability/ReachableBlockInternal.qll | 2 +- .../code/cpp/ir/internal/IRCppLanguage.qll | 43 +- .../code/cpp/ir/internal/IRUtilities.qll | 28 +- .../code/cpp/ir/internal/TempVariableTag.qll | 9 +- .../semmle/code/cpp/metrics/MetricClass.qll | 881 ++++--- .../semmle/code/cpp/metrics/MetricFile.qll | 484 ++-- .../code/cpp/metrics/MetricFunction.qll | 478 ++-- .../code/cpp/metrics/MetricNamespace.qll | 91 +- .../implementations/IdentityFunction.qll | 14 +- .../code/cpp/models/implementations/Inet.qll | 146 +- .../cpp/models/implementations/Memcpy.qll | 42 +- .../code/cpp/models/implementations/Pure.qll | 82 +- .../cpp/models/implementations/Strcat.qll | 80 +- .../cpp/models/implementations/Strcpy.qll | 62 +- .../cpp/models/implementations/Strftime.qll | 27 +- .../code/cpp/models/implementations/Swap.qll | 16 +- .../code/cpp/models/interfaces/Alias.qll | 54 +- .../cpp/models/interfaces/ArrayFunction.qll | 43 +- .../code/cpp/models/interfaces/DataFlow.qll | 5 +- .../models/interfaces/FormattingFunction.qll | 70 +- .../interfaces/FunctionInputsAndOutputs.qll | 170 +- .../code/cpp/models/interfaces/SideEffect.qll | 20 +- .../code/cpp/models/interfaces/Taint.qll | 4 +- .../src/semmle/code/cpp/padding/Padding.qll | 434 ++-- .../semmle/code/cpp/padding/SanityCheck.ql | 3 +- .../semmle/code/cpp/pointsto/CallGraph.qll | 42 +- .../src/semmle/code/cpp/pointsto/PointsTo.qll | 515 ++-- .../semmle/code/cpp/rangeanalysis/Bound.qll | 25 +- .../cpp/rangeanalysis/PointlessComparison.qll | 85 +- .../code/cpp/rangeanalysis/RangeAnalysis.qll | 124 +- .../cpp/rangeanalysis/RangeAnalysisUtils.qll | 239 +- .../code/cpp/rangeanalysis/RangeSSA.qll | 214 +- .../code/cpp/rangeanalysis/RangeUtils.qll | 49 +- .../code/cpp/rangeanalysis/SignAnalysis.qll | 282 ++- .../cpp/rangeanalysis/SimpleRangeAnalysis.qll | 1098 ++++---- .../semmle/code/cpp/security/BufferAccess.qll | 248 +- .../semmle/code/cpp/security/BufferWrite.qll | 391 ++- .../code/cpp/security/CommandExecution.qll | 243 +- .../semmle/code/cpp/security/Encryption.qll | 22 +- .../semmle/code/cpp/security/FileWrite.qll | 129 +- .../cpp/security/FunctionWithWrappers.qll | 127 +- .../semmle/code/cpp/security/OutputWrite.qll | 53 +- .../src/semmle/code/cpp/security/Overflow.qll | 59 +- .../semmle/code/cpp/security/PrintfLike.qll | 9 +- .../src/semmle/code/cpp/security/Security.qll | 242 +- .../code/cpp/security/SecurityOptions.qll | 34 +- .../code/cpp/security/SensitiveExprs.qll | 8 +- .../code/cpp/security/TaintTracking.qll | 708 +++--- cpp/ql/src/semmle/code/cpp/stmts/Block.qll | 36 +- cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll | 421 ++-- .../valuenumbering/GlobalValueNumbering.qll | 395 +-- .../code/cpp/valuenumbering/HashCons.qll | 823 +++--- cpp/ql/src/semmle/uml/MagicDraw.qll | 123 +- .../tokenising/duplications.ql | 1 - cpp/ql/test/examples/BadLocking/DeclStmts.ql | 21 +- .../assignment_to_parameter.ql | 12 +- .../equality_test_on_boolean.ql | 1 + .../non_literal_format_string.ql | 6 +- .../deduplication/functions.ql | 12 +- .../deduplication/variables.ql | 12 +- .../microsoft-pch/microsoft-pch.ql | 2 +- .../multi-target-includes/arrays.ql | 2 +- cpp/ql/test/library-tests/CPP-205/elements.ql | 11 +- .../access/DerivationAccess/actual_member.ql | 4 +- .../DerivationAccess/hypothetical_member.ql | 12 +- .../access/FieldAccess/FieldAccess.ql | 8 +- .../access/MemberOrFriend/MemberOrFriend.ql | 11 +- .../access/canAccessClass/canAccessClass.ql | 16 +- .../access/canAccessMember/canAccessMember.ql | 12 +- .../library-tests/allocators/allocators.ql | 20 +- .../test/library-tests/arguments/arguments.ql | 13 +- cpp/ql/test/library-tests/array_expr/parts.ql | 6 +- cpp/ql/test/library-tests/array_sizes/arr1.ql | 5 +- .../attributes/alignment/alignment.ql | 8 +- .../attributes/availability/availability.ql | 5 +- .../exclusive_locks_required/attributes.ql | 5 +- .../attributes/gnu_visibility/visibility.ql | 7 +- .../library-tests/attributes/nonnull/attrs.ql | 4 +- .../routine_attributes/arguments.ql | 5 +- .../test/library-tests/attributes/sal/sal.ql | 21 +- .../stmt_attributes/clang_fallthrough.ql | 7 +- .../attributes/type_attributes/arguments.ql | 5 +- .../test/library-tests/basic_blocks/bb_cfg.ql | 30 +- cpp/ql/test/library-tests/basic_blocks/cfg.ql | 28 +- cpp/ql/test/library-tests/blocks/c/blocks.ql | 5 +- .../library-tests/blocks/c/code_blocks.ql | 33 +- cpp/ql/test/library-tests/blocks/c/exprs.ql | 1 - .../library-tests/blocks/capture/capture.ql | 6 +- .../library-tests/blocks/capture/quals.ql | 4 +- .../test/library-tests/blocks/cpp/blocks.ql | 5 +- .../library-tests/blocks/cpp/code_blocks.ql | 33 +- cpp/ql/test/library-tests/blocks/cpp/exprs.ql | 2 +- .../blocks/deduplication/deduplication.ql | 4 +- .../builtins/builtins/builtins.ql | 1 - .../test/library-tests/builtins/edg/expr.ql | 1 - .../library-tests/builtins/edg/intaddr.ql | 1 - .../builtins/type_traits/expr.ql | 16 +- .../library-tests/builtins/types/types.ql | 1 - .../library-tests/c++_exceptions/graphable.ql | 28 +- .../library-tests/c++_exceptions/handler.ql | 11 +- .../c++_exceptions/unreachable.ql | 1 - cpp/ql/test/library-tests/c11_generic/test.ql | 3 +- cpp/ql/test/library-tests/calls/Calls1.ql | 7 +- cpp/ql/test/library-tests/calls/Calls3.ql | 1 + cpp/ql/test/library-tests/calls/args.ql | 1 - .../cast_specifiers/cast_specifiers.ql | 31 +- .../clang_builtin_macros/values.ql | 6 +- .../clang_c99_default/clang_c99_default.ql | 3 +- .../test/library-tests/clang_ms/declspec.ql | 1 - .../classes/base_classes/base_classes.ql | 4 +- .../library-tests/classes/classes/Classes1.ql | 6 +- .../library-tests/classes/classes/Classes2.ql | 1 - .../library-tests/classes/classes/Classes3.ql | 11 +- .../library-tests/classes/classes/Classes4.ql | 7 +- .../library-tests/classes/classes/Classes6.ql | 5 +- .../classes/classes/MetricClasses1.ql | 1 - .../classes/classes/MetricClasses2.ql | 1 - .../derivations/derivations/derivations.ql | 3 +- .../classes/derivations/offsets/offsets.ql | 3 +- .../structlikeclass/StructLikeClass.ql | 12 +- .../library-tests/classes/variadic/expr.ql | 1 - .../comments/binding/commentBinding.ql | 6 +- .../compiler_generated/compilerGenerated.ql | 13 +- .../library-tests/complex_numbers/expr.ql | 1 - cpp/ql/test/library-tests/conditions/vars.ql | 1 - .../constants/constants/chars.ql | 4 +- .../library-tests/constants/constants/ints.ql | 9 +- .../constants/constants/strings.ql | 2 +- .../initializerexpr/initializerexpr.ql | 13 +- .../constants/initializers/initializers.ql | 1 - .../library-tests/constants/strlen/expr.ql | 1 - cpp/ql/test/library-tests/constexpr_if/cfg.ql | 28 +- .../library-tests/controlflow/assume/cfg.ql | 28 +- .../controlflow/assume/interesting.ql | 28 +- .../controlflow/SsaCompleteness.ql | 25 +- .../controlflow/SsaCorrespondence.ql | 25 +- .../controlflow/controlflow/SsaDominance.ql | 29 +- .../controlflow/controlflow/SsaLt.ql | 8 +- .../controlflow/controlflow/SsaPhiInputs.ql | 13 +- .../controlflow/controlflow/SsaUniqueness.ql | 16 +- .../controlflow/dominance/bbIDominates.ql | 13 +- .../controlflow/dominance/dominatedByStart.ql | 22 +- .../controlflow/dominance/dominator.ql | 8 +- .../controlflow/dominance/dominatorExists.ql | 12 +- .../controlflow/dominance/dominatorUnique.ql | 9 +- .../controlflow/guards-ir/tests.ql | 78 +- .../controlflow/guards/Guards.ql | 2 +- .../controlflow/guards/GuardsCompare.ql | 21 +- .../controlflow/guards/GuardsControl.ql | 11 +- .../controlflow/guards/GuardsEnsure.ql | 24 +- .../loopentrycondition/forstmt01.ql | 2 +- .../loopentrycondition/whilestmt01.ql | 2 +- .../controlflow/primitives/cfg.ql | 28 +- .../controlflow/primitives/falseSucc.ql | 1 - .../controlflow/primitives/trueSucc.ql | 1 - .../library-tests/conversions/conversions.ql | 18 +- cpp/ql/test/library-tests/cpp11_g/cfg.ql | 27 +- cpp/ql/test/library-tests/ctorinits/ctors.ql | 7 +- cpp/ql/test/library-tests/ctorinits/dtors.ql | 7 +- .../standardFlow.ql | 4 +- .../withAdditionalFlow.ql | 4 +- .../dataflow-edge-tests/additionalEdges.ql | 7 +- .../dataflow-edge-tests/standardEdges.ql | 2 +- .../dataflow-tests/DataflowTestCommon.qll | 4 +- .../dataflow-tests/IRDataflowTestCommon.qll | 4 +- .../dataflow/dataflow-tests/localFlow.ql | 5 +- .../dataflow/dataflow-tests/test_diff.ql | 31 +- .../dataflow/recursion/chained_use.ql | 50 +- .../taint-tests/IRTaintTestCommon.qll | 4 +- .../dataflow/taint-tests/TaintTestCommon.qll | 6 +- .../dataflow/taint-tests/localTaint.ql | 7 +- .../dataflow/taint-tests/test_diff.ql | 31 +- .../declarationEntry/declarationEntry.ql | 9 +- .../declarationEntry/declarationEntry/fde.ql | 3 +- .../local/declarationEntry.ql | 18 +- .../declarationEntry/more/declarationEntry.ql | 1 - .../test/library-tests/declspec/guard/test.ql | 6 +- .../library-tests/declstmt/getDeclaration.ql | 1 - .../declstmt/getDeclarationEntry.ql | 1 - .../default_parameters/variables.ql | 25 +- .../defuse/definitionUsePairEquivalence.ql | 23 +- .../library-tests/defuse/isAddressOfAccess.ql | 10 +- .../library-tests/defuse/parameterUsePair.ql | 2 +- .../library-tests/defuse/useOfVarActual.ql | 11 +- .../library-tests/depends_friends/Friend1.ql | 1 + .../InitializerAccesses.ql | 1 + .../depends_initializers/InitializerCFG.ql | 11 +- .../depends_initializers/InitializerCalls.ql | 1 + .../derived_types/DerivedTypesBaseType.ql | 2 +- cpp/ql/test/library-tests/destructors/cfg.ql | 28 +- .../destructors/jump_destructs.ql | 20 +- .../test/library-tests/enums/enums/Enums1.ql | 9 +- .../test/library-tests/enums/enums/Enums2.ql | 1 + .../test/library-tests/enums/enums/Enums3.ql | 21 +- .../enums/multi_file/enumConstant.ql | 1 - .../comparison_operation.ql | 40 +- .../test/library-tests/exprs/min_max/expr.ql | 1 - .../exprs/unary_operation/unary_operation.ql | 59 +- .../value_categories/value_categories.ql | 3 +- .../library-tests/exprs_basic/ExprsBasic1.ql | 6 +- .../library-tests/exprs_basic/ExprsBasic3.ql | 11 +- .../library-tests/exprs_basic/ExprsBasic4.ql | 12 +- .../library-tests/exprs_basic/ExprsBasic5.ql | 13 +- .../library-tests/exprs_basic/ExprsBasic7.ql | 9 +- .../library-tests/exprs_basic/ExprsBasic8.ql | 9 +- .../library-tests/exprs_basic/ExprsBasic9.ql | 1 - .../library-tests/exprs_cast/ExprsCast1.ql | 1 + .../library-tests/exprs_cast/ExprsCast2.ql | 16 +- .../library-tests/fields/fields/EnumConst.ql | 10 +- .../library-tests/fields/fields/Fields.ql | 26 +- .../fields/fields/MemberVariable.ql | 1 + .../library-tests/fields/segfault/exprs.ql | 1 - cpp/ql/test/library-tests/files/Files1.ql | 1 - cpp/ql/test/library-tests/files/Files2.ql | 15 +- cpp/ql/test/library-tests/files/Files3.ql | 5 +- .../floats/float128/usertypes.ql | 5 +- .../library-tests/floats/floats/floats.ql | 27 +- .../friends/instantiated_template_class.ql | 4 +- .../library-tests/friends/friends/nesting.ql | 5 +- .../function_try_stmt/function_try_stmt.ql | 4 +- .../functionpointerish/functionpointerish.ql | 7 +- .../functions/arguments/arguments.ql | 1 - .../functions/arguments/num_arguments.ql | 1 - .../functions/constexpr/constexpr.ql | 4 +- .../functions/functions/Functions1.ql | 14 +- .../functions/functions/Functions2.ql | 66 +- .../getathrowntype/getAThrownType.ql | 12 +- .../identifiers/qualified_names/unnamed.ql | 1 - .../identity_string/identity_string.ql | 38 +- .../includes/include_next/includes.ql | 1 - .../includes/includes/locations.ql | 1 - .../includes/non_existent/diags.ql | 1 - .../test/library-tests/instantiations/test.ql | 1 - .../ir/constant_func/constant_func.ql | 7 +- .../library-tests/ir/constants/constants.ql | 209 +- cpp/ql/test/library-tests/ir/escape/escape.ql | 5 +- .../library-tests/ir/escape/ssa_escape.ql | 5 +- .../lambdas/calling_conv/calling_conv.ql | 2 +- .../lambdas/captures/captures.ql | 3 +- .../lambdas/captures/elements.ql | 7 +- cpp/ql/test/library-tests/lambdas/cfg/cfg.ql | 28 +- .../library-tests/lambdas/cfg/reachability.ql | 4 +- cpp/ql/test/library-tests/languages/exprs.ql | 5 +- .../duplicate_literal_locations.ql | 1 - .../literal_locations/literal_locations.ql | 1 - .../aggregate_literals/arrays_child_exprs.ql | 4 +- .../aggregate_literals/arrays_value_init.ql | 7 +- .../literals/aggregate_literals/classes.ql | 5 +- .../aggregate_literals/classes_child_exprs.ql | 1 - .../aggregate_literals/classes_value_init.ql | 5 +- .../literals/literals/literals.ql | 1 - .../library-tests/literals/uuidof/uuidof.ql | 5 +- .../locations/constants/locations.ql | 1 + cpp/ql/test/library-tests/loops/loops.ql | 52 +- .../library-tests/macros/affects/affects.ql | 1 - .../macros/arguments/macro_arguments.ql | 19 +- .../inmacroexpansion/inmacroexpansion.ql | 9 +- .../macros/macros/affectedbymacroexpansion.ql | 1 - .../macros/macros/inmacroexpansion.ql | 1 - .../library-tests/members/getters/members.ql | 75 +- .../members/members/functions.ql | 1 - .../members/templates/members.ql | 1 - .../multiple_macro_invocations.ql | 1 - .../preprocbranch/preprocbranch.ql | 30 +- .../name_qualifiers/NameQualifiers1.ql | 5 +- .../name_qualifiers/NameQualifiers2.ql | 4 +- .../namespaces/namespaces/decls.ql | 21 +- .../namespaces/namespaces/namequalifiable.ql | 12 +- .../namespaces/namespaces/namespaces.ql | 9 +- .../namespaces/same_name/decls.ql | 1 - .../nested_functions/namespaces.ql | 22 +- .../nested_functions/nested_functions.ql | 15 +- .../nested_functions/var_uses.ql | 5 +- .../copy_from_prototype.ql | 10 +- .../noexcept/noexcept/noexcept_expr.ql | 4 +- .../noexcept/noexcept/noexcept_specifier.ql | 15 +- .../nulltermination/mayAddNullTerminator.ql | 2 +- .../variableMustBeNullTerminated.ql | 2 +- .../test/library-tests/numlines/numlines.ql | 36 +- cpp/ql/test/library-tests/odasa2646/cfi.ql | 7 +- .../test/library-tests/operators/operators.ql | 3 +- cpp/ql/test/library-tests/opts/options.ql | 47 +- .../parameters/parameters/Parameters2.ql | 7 +- .../parameters/parameters/Parameters3.ql | 16 +- .../parameters/toStrings/params.ql | 1 - .../test/library-tests/permissive/accesses.ql | 1 - cpp/ql/test/library-tests/permissive/calls.ql | 1 - cpp/ql/test/library-tests/permissive/diags.ql | 1 - cpp/ql/test/library-tests/pod/isPOD.ql | 5 +- cpp/ql/test/library-tests/pod/isPOD03.ql | 6 +- .../address-of-assign/PointsToExpr.ql | 17 +- .../pointsto/arguments/Report.ql | 15 +- .../pointsto/basic/PointsToExpr.ql | 17 +- .../pointsto/basic/anythingPointsToExpr.ql | 17 +- .../pointsto/basic/compoundEdge.ql | 3 +- .../test/library-tests/pointsto/basic/sets.ql | 88 +- .../pointsto/more/PointsToExpr.ql | 11 +- .../pointsto/new-virtual/PointsToNew.ql | 7 +- cpp/ql/test/library-tests/predefines/expr.ql | 1 - .../predefines/localVariables.ql | 1 - .../preprocessor/dependent_defs/block.ql | 4 +- .../preprocessor/dependent_defs/init.ql | 4 +- .../hashing/hashing/macroAccess.ql | 1 - .../preprocessor/hashing/undef/preproc.ql | 1 - .../linedirective/linedirective.ql | 9 +- .../macroinvocations/getanaffectedelement.ql | 36 +- .../macroinvocations/macroinvocations.ql | 12 +- .../preprocessor/preprocessor/preproc.ql | 10 +- .../library-tests/proxy_class/locations.ql | 8 +- .../ptr_to_member/segfault/exprs.ql | 1 - .../qualifiers/class-enum/decls.ql | 1 - .../qualifiers/class-enum/expr.ql | 1 - .../library-tests/question_mark_colon/cfg.ql | 10 +- .../RangeSSA/RangeSsaCompleteness.ql | 25 +- .../RangeSSA/RangeSsaCorrespondence.ql | 25 +- .../RangeSSA/RangeSsaDominance.ql | 29 +- .../RangeSSA/RangeSsaPhiInputs.ql | 11 +- .../RangeSSA/RangeSsaUniqueness.ql | 16 +- .../rangeanalysis/RangeAnalysis.ql | 20 +- .../signanalysis/SignAnalysis.ql | 2 +- .../reachability/reachability.ql | 1 - .../library-tests/rvalueCast/rvalueCast.ql | 6 +- .../library-tests/scanf/scanfFormatLiteral.ql | 3 +- .../scopes/includes/function_info.ql | 4 +- .../library-tests/scopes/parents/parents.ql | 4 +- .../library-tests/scopes/scopes/Scopes1.ql | 40 +- .../library-tests/scopes/scopes/Scopes2.ql | 21 +- .../library-tests/scopes/scopes/Scopes3.ql | 7 +- .../library-tests/scopes/scopes/Scopes4.ql | 1 + .../library-tests/scopes/scopes/Scopes5.ql | 1 + .../library-tests/sideEffects/exprs/exprs.ql | 6 +- .../sideEffects/functions/sideEffects.ql | 9 +- .../library-tests/sideEffects/stmts/stmts.ql | 10 +- .../special_members/detect/detect.ql | 34 +- .../special_members/generated_copy/assign.ql | 14 +- .../special_members/generated_copy/ctor.ql | 14 +- .../generated_copy/functions.ql | 6 +- .../library-tests/specifiers/Specifiers1.ql | 5 +- .../library-tests/specifiers/Specifiers2.ql | 5 +- .../library-tests/specifiers/Specifiers3.ql | 10 +- .../library-tests/specifiers2/specifiers2.ql | 36 +- .../library-tests/specifiers2/specifiers2d.ql | 5 +- .../unspecified_member_var_types.ql | 2 +- cpp/ql/test/library-tests/static_cast/expr.ql | 1 - .../stmt/generated_blocks/stmt.ql | 34 +- cpp/ql/test/library-tests/stmt/stmt/stmt.ql | 5 +- cpp/ql/test/library-tests/stmt_expr/cfg.ql | 17 +- .../string_analysis/StringAnalysis.ql | 9 +- .../string_literals/string_literals.ql | 1 - .../string_literals_nul.ql | 5 +- .../structs/compatible_c/compatible.ql | 8 +- .../structs/compatible_c/compatible_types.ql | 1 - .../structs/compatible_cpp/compatible.ql | 8 +- .../compatible_cpp/compatible_types.ql | 1 - .../mutual_recursion/compatible_members.ql | 8 +- .../mutual_recursion/compatible_structs.ql | 5 +- .../library-tests/structs/structs/structs.ql | 15 +- .../library-tests/sub_basic_blocks/cut.ql | 5 +- .../library-tests/sub_basic_blocks/getNode.ql | 4 +- .../library-tests/sub_basic_blocks/no_cut.ql | 2 - .../sub_basic_blocks/sbb_test.qll | 37 +- cpp/ql/test/library-tests/switch/blocks.ql | 1 - .../test/library-tests/switch/switchcase.ql | 27 +- .../test/library-tests/switch/switchstmt.ql | 12 +- cpp/ql/test/library-tests/switch_cfg/cfg.ql | 18 +- .../synchronization/mutextype.ql | 30 +- .../synchronization/synchronization.ql | 24 +- .../synchronization/testoptions.qll | 8 +- .../library-tests/syntax-zoo/drawDifferent.ql | 7 +- .../library-tests/syntax-zoo/tellDifferent.ql | 9 +- .../templates/CPP-202/template_args.ql | 8 +- .../library-tests/templates/CPP-203/decls.ql | 1 - .../templates/CPP-204/element.ql | 7 +- .../library-tests/templates/CPP-223/decls.ql | 1 - .../ambiguous_cctor/ambiguous_cctor.ql | 3 +- .../test/library-tests/templates/bug/class.ql | 1 - .../library-tests/templates/decls/decls.ql | 1 - .../dependent_template_alias/test.ql | 5 +- .../templates/extern/elements.ql | 7 +- .../library-tests/templates/friends/decls.ql | 1 - .../templates/functions/functions.ql | 6 +- .../incomplete_instantiations/test.ql | 7 +- .../instantiation_directive/functions.ql | 1 - .../instantiations.ql | 12 +- .../isfromtemplateinstantiation.ql | 41 +- .../isfromuninstantiatedtemplate.ql | 19 +- .../template_is_template.ql | 19 +- .../prototype_bodies/call_operands.ql | 7 +- .../prototype_bodies/isdef_hasblock.ql | 6 +- .../library-tests/templates/segfault/vars.ql | 1 - .../templates/typedefs/template_typedefs.ql | 6 +- .../templates/variables/template_variables.ql | 11 +- .../library-tests/type_sizes/type_sizes.ql | 4 +- .../test/library-tests/type_strings/exprs.ql | 4 +- .../type_strings/type_strings.ql | 9 +- .../test/library-tests/typedefs/ODASA-6095.ql | 3 +- .../test/library-tests/typedefs/Typedefs2.ql | 5 +- .../test/library-tests/typedefs/Typedefs3.ql | 46 +- .../library-tests/types/__wchar_t/wchar_t.ql | 8 +- .../library-tests/types/alignof/alignof.ql | 12 +- .../types/integral_types/integral_type.ql | 78 +- .../types/pointertypes/pointertypes.ql | 64 +- .../library-tests/types/refersTo/refersTo.ql | 7 +- cpp/ql/test/library-tests/types/scope/expr.ql | 1 - .../test/library-tests/types/segfault/vars.ql | 1 - .../test/library-tests/types/sizeof/sizeof.ql | 12 +- .../test/library-tests/types/typeid/typeid.ql | 15 +- .../test/library-tests/types/types/Types.ql | 113 +- .../library-tests/types/unspecified/exprs.ql | 1 - .../types/wchar_t_typedef/wchar_t.ql | 8 +- cpp/ql/test/library-tests/unions/Unions1.ql | 32 +- cpp/ql/test/library-tests/unnamed/elements.ql | 7 +- .../types/unspecified_type.ql | 12 +- .../unspecified_type/strip_top_level.ql | 4 +- .../unspecified_type/unspecified_type.ql | 5 +- cpp/ql/test/library-tests/usings/Usings2.ql | 3 +- .../GlobalValueNumbering.ql | 13 +- .../GlobalValueNumbering/ir_gvn.ql | 1 + .../valuenumbering/HashCons/HashCons.ql | 13 +- .../variables/constexpr/constexpr.ql | 3 +- .../variables/global/variables.ql | 1 - .../variables/thread_local/thread_local.ql | 4 +- .../variables/variables/structs.ql | 1 - .../variables/variables/types.ql | 36 +- .../variables/variables/variable.ql | 12 +- .../library-tests/vector_types/builtin_ops.ql | 1 - .../virtual_functions/cfg/cfg.ql | 28 +- .../virtual_functions/VirtualFunctions4.ql | 16 +- .../virtual_functions/classes.ql | 6 +- cpp/ql/test/library-tests/vla/cfg.ql | 28 +- cpp/ql/test/library-tests/vla/type.ql | 5 +- cpp/ql/test/library-tests/vla/variable.ql | 5 +- .../formattingFunction.ql | 7 +- .../formattingFunction.ql | 7 +- .../formattingFunction.ql | 7 +- .../StackAddressEscapes/ArrayTypeTest.ql | 11 +- .../Dependencies/ExternalDependencies.ql | 7 +- .../ExternalDependenciesSourceLinks.ql | 7 +- .../Metrics/Dependencies/TestPackage.qll | 16 +- .../semmle/tests/LoopConditionsConst.ql | 15 +- .../semmle/tests/LoopConditionsConst.qll | 11 +- .../query-tests/definitions/locationInfo.ql | 36 +- .../jsf/4.09 Style/AV Rule 53 54/files.ql | 18 +- cpp/ql/test/successor-tests/assignexpr/cfg.ql | 44 +- .../block/emptyblock/emptyblock01.ql | 6 +- .../test/successor-tests/break_labels/cfg.ql | 32 +- .../callexpr/args/membercallexpr/cfg.ql | 44 +- .../callexpr/args/staticmembercallexpr/cfg.ql | 44 +- .../callexpr/noargs/membercallexpr/cfg.ql | 44 +- .../callexpr/noargs/nonmembercallexpr/cfg.ql | 44 +- .../noargs/nonmemberfp2callexpr/cfg.ql | 44 +- .../noargs/nonmemberfpcallexpr/cfg.ql | 44 +- .../callexpr/noargs/pmcallexpr/cfg.ql | 44 +- .../noargs/staticmembercallexpr/cfg.ql | 44 +- .../conditional_destructors/cfg.ql | 28 +- .../defdestructordeleteexpr01.ql | 3 +- .../deleteexpr/deleteexpr/deleteexpr01.ql | 1 + .../test/successor-tests/dostmt/dostmt01.ql | 14 +- .../test/successor-tests/dostmt/dostmt02.ql | 10 +- .../test/successor-tests/dostmt/dostmt03.ql | 2 +- .../test/successor-tests/dostmt/dostmt04.ql | 12 +- .../test/successor-tests/dostmt/dostmt05.ql | 12 +- .../test/successor-tests/dostmt/dostmt06.ql | 34 +- .../test/successor-tests/dostmt/dostmt07.ql | 34 +- .../test/successor-tests/dostmt/dostmt08.ql | 34 +- .../test/successor-tests/dostmt/dostmt09.ql | 34 +- .../test/successor-tests/dostmt/dostmt10.ql | 34 +- cpp/ql/test/successor-tests/enum/cfg.ql | 44 +- .../ellipsisexceptionhandler/graphable.ql | 28 +- .../exceptionhandler/graphable.ql | 28 +- cpp/ql/test/successor-tests/exprstmt/cfg.ql | 44 +- .../fieldaccessexpr/constmemberaccess/cfg.ql | 44 +- .../fieldaccessexpr/fieldaccess/cfg.ql | 44 +- .../forstmt/forstmt/forstmt01.ql | 29 +- .../forstmt/shortforstmt/shortforstmt01.ql | 14 +- .../forstmt/shortforstmt/shortforstmt02.ql | 10 +- .../forstmt/shortforstmt/shortforstmt03.ql | 2 +- .../forstmt/shortforstmt/shortforstmt04.ql | 12 +- .../forstmt/shortforstmt/shortforstmt05.ql | 12 +- .../forstmt/shortforstmt/shortforstmt06.ql | 34 +- .../forstmt/shortforstmt/shortforstmt07.ql | 30 +- .../forstmt/tinyforstmt/cfg.ql | 44 +- cpp/ql/test/successor-tests/gotostmt/cfg.ql | 44 +- .../ifstmt/ifelsestmt/ifelsestmt01.ql | 10 +- .../ifstmt/ifelsestmt/ifelsestmt02.ql | 10 +- .../ifstmt/ifelsestmt/ifelsestmt03.ql | 2 +- .../ifstmt/ifelsestmt/ifelsestmt04.ql | 14 +- .../ifstmt/ifelsestmt/ifelsestmt05.ql | 12 +- .../ifstmt/ifelsestmt/ifelsestmt06.ql | 14 +- .../ifstmt/ifelsestmt/ifelsestmt07.ql | 34 +- .../ifstmt/ifelsestmt/ifelsestmt08.ql | 34 +- .../ifstmt/ifelsestmt/ifelsestmt09.ql | 34 +- .../ifstmt/ifelsestmt/ifelsestmt10.ql | 34 +- .../ifstmt/ifelsestmt/ifelsestmt11.ql | 34 +- .../successor-tests/ifstmt/ifstmt/ifstmt01.ql | 14 +- .../successor-tests/ifstmt/ifstmt/ifstmt02.ql | 12 +- .../successor-tests/ifstmt/ifstmt/ifstmt03.ql | 2 +- .../successor-tests/ifstmt/ifstmt/ifstmt04.ql | 14 +- .../successor-tests/ifstmt/ifstmt/ifstmt05.ql | 12 +- .../successor-tests/ifstmt/ifstmt/ifstmt06.ql | 34 +- .../successor-tests/ifstmt/ifstmt/ifstmt07.ql | 34 +- .../successor-tests/ifstmt/ifstmt/ifstmt08.ql | 34 +- .../successor-tests/ifstmt/ifstmt/ifstmt09.ql | 34 +- .../successor-tests/ifstmt/ifstmt/ifstmt10.ql | 34 +- .../aggregateinitializer01.ql | 29 +- .../constructorinitializer01.ql | 29 +- .../initializer/initializer/initializer01.ql | 29 +- .../parameterinitializer/controlflownode.ql | 4 +- cpp/ql/test/successor-tests/landexpr/cfg.ql | 44 +- cpp/ql/test/successor-tests/lorexpr/cfg.ql | 44 +- .../test/successor-tests/ltrbinopexpr/cfg.ql | 44 +- .../newexpr/defconstructornewexpr/cfg.ql | 44 +- .../successor-tests/newexpr/newexpr/cfg.ql | 44 +- .../test/successor-tests/pruning/graphable.ql | 28 +- .../test/successor-tests/questionexpr/cfg.ql | 44 +- .../successor-tests/returnstmt/graphable.ql | 28 +- .../stackvariables/graphable.ql | 28 +- .../staticlocals/no_dynamic_init/exprs.ql | 1 - .../staticlocals/staticlocals01.ql | 29 +- cpp/ql/test/successor-tests/stmt_expr/cfg.ql | 29 +- .../subscriptexpr/subscriptexpr/cfg.ql | 44 +- .../successor-tests/switchstmt/duff/cfg.ql | 44 +- .../successor-tests/switchstmt/duff2/cfg.ql | 44 +- .../switchstmt/nodefaultswitchstmt/cfg.ql | 44 +- .../switchstmt/switchbody/graphable.ql | 28 +- .../switchstmt/switchstmt/cfg.ql | 44 +- .../test/successor-tests/unaryopexpr/cfg.ql | 44 +- .../successor-tests/whilestmt/whilestmt01.ql | 14 +- .../successor-tests/whilestmt/whilestmt02.ql | 10 +- .../successor-tests/whilestmt/whilestmt03.ql | 2 +- .../successor-tests/whilestmt/whilestmt04.ql | 12 +- .../successor-tests/whilestmt/whilestmt05.ql | 12 +- .../successor-tests/whilestmt/whilestmt06.ql | 34 +- .../successor-tests/whilestmt/whilestmt07.ql | 34 +- .../successor-tests/whilestmt/whilestmt08.ql | 34 +- .../successor-tests/whilestmt/whilestmt09.ql | 34 +- .../successor-tests/whilestmt/whilestmt10.ql | 34 +- .../successor-tests/whilestmt/whilestmt11.ql | 34 +- 1141 files changed, 21968 insertions(+), 23174 deletions(-) diff --git a/cpp/ql/src/AlertSuppression.ql b/cpp/ql/src/AlertSuppression.ql index 48a9568b87d..4fb22b8efbb 100644 --- a/cpp/ql/src/AlertSuppression.ql +++ b/cpp/ql/src/AlertSuppression.ql @@ -16,64 +16,56 @@ class SuppressionComment extends CppStyleComment { SuppressionComment() { text = getContents().suffix(2) and - ( // match `lgtm[...]` anywhere in the comment + ( + // match `lgtm[...]` anywhere in the comment annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _) or // match `lgtm` at the start of the comment and after semicolon - annotation = text.regexpFind("(?i)(?<=^|;)\\s*lgtm(?!\\B|\\s*\\[)", _, _) - .trim() + annotation = text.regexpFind("(?i)(?<=^|;)\\s*lgtm(?!\\B|\\s*\\[)", _, _).trim() ) } - /** Gets the text in this comment, excluding the leading //. */ - string getText() { - result = text - } + string getText() { result = text } /** Gets the suppression annotation in this comment. */ - string getAnnotation() { - result = annotation - } + string getAnnotation() { result = annotation } /** - * Holds if this comment applies to the range from column `startcolumn` of line `startline` - * to column `endcolumn` of line `endline` in file `filepath`. - */ + * Holds if this comment applies to the range from column `startcolumn` of line `startline` + * to column `endcolumn` of line `endline` in file `filepath`. + */ predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) { this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and startcolumn = 1 } /** Gets the scope of this suppression. */ - SuppressionScope getScope() { - result = this - } + SuppressionScope getScope() { result = this } } /** * The scope of an alert suppression comment. */ class SuppressionScope extends ElementBase { - SuppressionScope() { - this instanceof SuppressionComment - } + SuppressionScope() { this instanceof SuppressionComment } /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). - */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn) } } from SuppressionComment c -select c, // suppression comment - c.getText(), // text of suppression comment (excluding delimiters) - c.getAnnotation(), // text of suppression annotation - c.getScope() // scope of suppression - +select c, // suppression comment + c.getText(), // text of suppression comment (excluding delimiters) + c.getAnnotation(), // text of suppression annotation + c.getScope() // scope of suppression diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql index 29791aa63ab..eea6db532cd 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql @@ -42,9 +42,7 @@ newtype TVariableDeclarationInfo = */ class VariableDeclarationLine extends TVariableDeclarationInfo { Class c; - File f; - int line; VariableDeclarationLine() { diff --git a/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql b/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql index 6abdb6feb8c..90996af23bb 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql +++ b/cpp/ql/src/Best Practices/Magic Constants/JapaneseEraDate.ql @@ -42,7 +42,6 @@ predicate eraDate(int year, int month, int day) { year = 2019 and month = 5 and day = 1 } - predicate badStructInitialization(Element target, string message) { exists( StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day, diff --git a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.ql b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.ql index 2e8cee1b8e5..26cf42521e5 100644 --- a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.ql +++ b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.ql @@ -14,9 +14,7 @@ import cpp predicate declarationHasSideEffects(Variable v) { - exists(Class c | c = v.getUnspecifiedType() | - c.hasConstructor() or c.hasDestructor() - ) + exists(Class c | c = v.getUnspecifiedType() | c.hasConstructor() or c.hasDestructor()) } from Variable v diff --git a/cpp/ql/src/Critical/FileMayNotBeClosed.ql b/cpp/ql/src/Critical/FileMayNotBeClosed.ql index 20428710435..fefe43aa845 100644 --- a/cpp/ql/src/Critical/FileMayNotBeClosed.ql +++ b/cpp/ql/src/Critical/FileMayNotBeClosed.ql @@ -26,20 +26,18 @@ class MinusOne extends NullValue { */ predicate mayCallFunction(Expr call, Function f) { call.(FunctionCall).getTarget() = f or - call.(VariableCall).getVariable().getAnAssignedValue(). - getAChild*().(FunctionAccess).getTarget() = f + call.(VariableCall).getVariable().getAnAssignedValue().getAChild*().(FunctionAccess).getTarget() = + f } predicate fopenCallOrIndirect(Expr e) { // direct fopen call fopenCall(e) and - // We are only interested in fopen calls that are // actually closed somehow, as FileNeverClosed // will catch those that aren't. fopenCallMayBeClosed(e) or - exists(ReturnStmt rtn | // indirect fopen call mayCallFunction(e, rtn.getEnclosingFunction()) and @@ -86,7 +84,6 @@ class FOpenVariableReachability extends LocalScopeVariableReachabilityWithReassi exists(node.(AnalysedExpr).getNullSuccessor(v)) or fcloseCallOrIndirect(node, v) or assignedToFieldOrGlobal(v, node) or - // node may be used directly in query v.getFunction() = node.(ReturnStmt).getEnclosingFunction() } @@ -122,12 +119,10 @@ class FOpenReachability extends LocalScopeVariableReachabilityExt { } override predicate isBarrier( - ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, - LocalScopeVariable v) - { + ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v + ) { isSource(source, v) and next = node.getASuccessor() and - // the file (stored in any variable `v0`) opened at `source` is closed or // assigned to a global at node, or NULL checked on the edge node -> next. exists(LocalScopeVariable v0 | fopenVariableReaches(v0, source, node) | @@ -172,6 +167,4 @@ where fopenVariableReaches(v, def, ret) and ret.getAChild*() = v.getAnAccess() ) -select - def, "The file opened here may not be closed at $@.", - ret, "this exit point" +select def, "The file opened here may not be closed at $@.", ret, "this exit point" diff --git a/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql b/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql index 181c57a7e55..9bba8e9896d 100644 --- a/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql +++ b/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql @@ -18,20 +18,18 @@ import semmle.code.cpp.controlflow.LocalScopeVariableReachability */ predicate mayCallFunction(Expr call, Function f) { call.(FunctionCall).getTarget() = f or - call.(VariableCall).getVariable().getAnAssignedValue(). - getAChild*().(FunctionAccess).getTarget() = f + call.(VariableCall).getVariable().getAnAssignedValue().getAChild*().(FunctionAccess).getTarget() = + f } predicate allocCallOrIndirect(Expr e) { // direct alloc call isAllocationExpr(e) and - // We are only interested in alloc calls that are // actually freed somehow, as MemoryNeverFreed // will catch those that aren't. allocMayBeFreed(e) or - exists(ReturnStmt rtn | // indirect alloc call mayCallFunction(e, rtn.getEnclosingFunction()) and @@ -64,7 +62,6 @@ predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode newV.getAnAssignedValue() = reallocCall and node.(AnalysedExpr).getNonNullSuccessor(newV) = verified and // note: this case uses naive flow logic (getAnAssignedValue). - // special case: if the result of the 'realloc' is assigned to the // same variable, we don't descriminate properly between the old // and the new allocation; better to not consider this a free at @@ -116,7 +113,6 @@ class AllocVariableReachability extends LocalScopeVariableReachabilityWithReassi exists(node.(AnalysedExpr).getNullSuccessor(v)) or freeCallOrIndirect(node, v) or assignedToFieldOrGlobal(v, node) or - // node may be used directly in query v.getFunction() = node.(ReturnStmt).getEnclosingFunction() } @@ -152,12 +148,10 @@ class AllocReachability extends LocalScopeVariableReachabilityExt { } override predicate isBarrier( - ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, - LocalScopeVariable v) - { + ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v + ) { isSource(source, v) and next = node.getASuccessor() and - // the memory (stored in any variable `v0`) allocated at `source` is freed or // assigned to a global at node, or NULL checked on the edge node -> next. exists(LocalScopeVariable v0 | allocatedVariableReaches(v0, source, node) | @@ -202,6 +196,4 @@ where allocatedVariableReaches(v, def, ret) and ret.getAChild*() = v.getAnAccess() ) -select - def, "The memory allocated here may not be released at $@.", - ret, "this exit point" +select def, "The memory allocated here may not be released at $@.", ret, "this exit point" diff --git a/cpp/ql/src/Critical/OverflowDestination.ql b/cpp/ql/src/Critical/OverflowDestination.ql index c72fe16e984..d7b02b5d8d5 100644 --- a/cpp/ql/src/Critical/OverflowDestination.ql +++ b/cpp/ql/src/Critical/OverflowDestination.ql @@ -33,12 +33,10 @@ predicate sourceSized(FunctionCall fc, Expr src) { fc.getArgument(2) = size and src = v.getAnAccess() and size.getAChild+() = v.getAnAccess() and - // exception: `dest` is also referenced in the size argument not exists(Variable other | dest = other.getAnAccess() and size.getAChild+() = other.getAnAccess() ) and - // exception: `src` and `dest` are both arrays of the same type and size not exists(ArrayType srctype, ArrayType desttype | dest.getType().getUnderlyingType() = desttype and diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index bd76173b6f4..1892d5acff1 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -33,7 +33,6 @@ class BufferAccess extends ArrayExpr { staticBuffer(this.getArrayBase(), _, size) and size != 0 ) and - // exclude accesses in macro implementation of `strcmp`, // which are carefully controlled but can look dangerous. not exists(Macro m | diff --git a/cpp/ql/src/DefaultOptions.qll b/cpp/ql/src/DefaultOptions.qll index 02759e27d42..27e5584369e 100644 --- a/cpp/ql/src/DefaultOptions.qll +++ b/cpp/ql/src/DefaultOptions.qll @@ -13,14 +13,11 @@ private import Options as CustomOptions /** * Default predicates that specify information about the behavior of - * the program being analyzed. + * the program being analyzed. */ -class Options extends string -{ - Options() { - this = "Options" - } - +class Options extends string { + Options() { this = "Options" } + /** * Holds if we wish to override the "may return NULL" inference for this * call. If this holds, then rather than trying to infer whether this @@ -60,7 +57,8 @@ class Options extends string * `noreturn` attribute. */ predicate exits(Function f) { - f.getAnAttribute().hasName("noreturn") or + f.getAnAttribute().hasName("noreturn") + or exists(string name | f.hasGlobalName(name) | name = "exit" or name = "_exit" or @@ -68,7 +66,8 @@ class Options extends string name = "__assert_fail" or name = "longjmp" or name = "__builtin_unreachable" - ) or + ) + or CustomOptions::exits(f) // old Options.qll } @@ -108,14 +107,11 @@ class Options extends string fc.isInMacroExpansion() or // common way of sleeping using select: - (fc.getTarget().hasGlobalName("select") and - fc.getArgument(0).getValue() = "0") + fc.getTarget().hasGlobalName("select") and + fc.getArgument(0).getValue() = "0" or CustomOptions::okToIgnoreReturnValue(fc) // old Options.qll } } -Options getOptions() -{ - any() -} +Options getOptions() { any() } diff --git a/cpp/ql/src/Documentation/CaptionedComments.qll b/cpp/ql/src/Documentation/CaptionedComments.qll index fd511106a19..33966403d22 100644 --- a/cpp/ql/src/Documentation/CaptionedComments.qll +++ b/cpp/ql/src/Documentation/CaptionedComments.qll @@ -1,26 +1,36 @@ /** * Provides heuristics to find "todo" and "fixme" comments (in all caps). */ + import cpp string getCommentTextCaptioned(Comment c, string caption) { - (caption = "TODO" or caption = "FIXME") and - exists (string commentContents, string commentBody, int offset, string interestingSuffix, int endOfLine, string dontCare, string captionedLine, string followingLine - | commentContents = c.getContents() - and commentContents.matches("%" + caption + "%") - and // Add some '\n's so that any interesting line, and its - // following line, will definitely begin and end with '\n'. - commentBody = commentContents.regexpReplaceAll("(?s)^/\\*(.*)\\*/$|^//(.*)$", "\n$1$2\n\n") - and dontCare = commentBody.regexpFind("\\n[/* \\t\\x0B\\f\\r]*" + caption, _, offset) - and interestingSuffix = commentBody.suffix(offset) - and endOfLine = interestingSuffix.indexOf("\n", 1, 0) - and captionedLine = interestingSuffix.prefix(endOfLine).regexpReplaceAll("^[/*\\s]*" + caption + "\\s*:?", "").trim() - and followingLine = interestingSuffix.prefix(interestingSuffix.indexOf("\n", 2, 0)).suffix(endOfLine).trim() - and if captionedLine = "" - then result = caption + " comment" - else if followingLine = "" - then result = caption + " comment: " + captionedLine - else result = caption + " comment: " + captionedLine + " [...]" - ) + (caption = "TODO" or caption = "FIXME") and + exists( + string commentContents, string commentBody, int offset, string interestingSuffix, int endOfLine, + string dontCare, string captionedLine, string followingLine + | + commentContents = c.getContents() and + commentContents.matches("%" + caption + "%") and + // Add some '\n's so that any interesting line, and its + // following line, will definitely begin and end with '\n'. + commentBody = commentContents.regexpReplaceAll("(?s)^/\\*(.*)\\*/$|^//(.*)$", "\n$1$2\n\n") and + dontCare = commentBody.regexpFind("\\n[/* \\t\\x0B\\f\\r]*" + caption, _, offset) and + interestingSuffix = commentBody.suffix(offset) and + endOfLine = interestingSuffix.indexOf("\n", 1, 0) and + captionedLine = interestingSuffix + .prefix(endOfLine) + .regexpReplaceAll("^[/*\\s]*" + caption + "\\s*:?", "") + .trim() and + followingLine = interestingSuffix + .prefix(interestingSuffix.indexOf("\n", 2, 0)) + .suffix(endOfLine) + .trim() and + if captionedLine = "" + then result = caption + " comment" + else + if followingLine = "" + then result = caption + " comment: " + captionedLine + else result = caption + " comment: " + captionedLine + " [...]" + ) } - diff --git a/cpp/ql/src/Documentation/CommentedOutCode.qll b/cpp/ql/src/Documentation/CommentedOutCode.qll index 8fdf2580f4c..14e74b0a20c 100644 --- a/cpp/ql/src/Documentation/CommentedOutCode.qll +++ b/cpp/ql/src/Documentation/CommentedOutCode.qll @@ -6,44 +6,42 @@ import cpp bindingset[line] private predicate looksLikeCode(string line) { exists(string trimmed | - // trim leading and trailing whitespace, and HTML codes: + // trim leading and trailing whitespace, and HTML codes: // * HTML entities in common notation (e.g. &gt; and &eacute;) // * HTML entities in decimal notation (e.g. a&#768;) // * HTML entities in hexadecimal notation (e.g. &#x705F;) trimmed = line.regexpReplaceAll("(?i)(^\\s+|&#?[a-z0-9]{1,31};|\\s+$)", "") | ( + // Match comment lines ending with '{', '}' or ';' + trimmed.regexpMatch(".*[{};]") and ( - // Match comment lines ending with '{', '}' or ';' - trimmed.regexpMatch(".*[{};]") and - ( - // If this line looks like code because it ends with a closing - // brace that's preceded by something other than whitespace ... - trimmed.regexpMatch(".*.\\}") - implies - // ... then there has to be ") {" (or some variation) - // on the line, suggesting it's a statement like `if` - // or a function definition. Otherwise it's likely to be a - // benign use of braces such as a JSON example or explanatory - // pseudocode. - trimmed.regexpMatch(".*(\\)|const|volatile|override|final|noexcept|&)\\s*\\{.*") - ) - ) or ( - // Match comment lines that look like preprocessor code - trimmed.regexpMatch("#\\s*(include|define|undef|if|ifdef|ifndef|elif|else|endif|error|pragma)\\b.*") + // If this line looks like code because it ends with a closing + // brace that's preceded by something other than whitespace ... + trimmed.regexpMatch(".*.\\}") + implies + // ... then there has to be ") {" (or some variation) + // on the line, suggesting it's a statement like `if` + // or a function definition. Otherwise it's likely to be a + // benign use of braces such as a JSON example or explanatory + // pseudocode. + trimmed.regexpMatch(".*(\\)|const|volatile|override|final|noexcept|&)\\s*\\{.*") ) - ) and ( - // Exclude lines that start with '>' or contain '@{' or '@}'. - // To account for the code generated by protobuf, we also insist that the comment - // does not begin with `optional` or `repeated` and end with a `;`, which would - // normally be a quoted bit of literal `.proto` specification above the associated - // declaration. - // To account for emacs folding markers, we ignore any line containing - // `{{{` or `}}}`. - // Finally, some code tends to embed GUIDs in comments, so we also exclude those. - not trimmed + or + // Match comment lines that look like preprocessor code + trimmed + .regexpMatch("#\\s*(include|define|undef|if|ifdef|ifndef|elif|else|endif|error|pragma)\\b.*") + ) and + // Exclude lines that start with '>' or contain '@{' or '@}'. + // To account for the code generated by protobuf, we also insist that the comment + // does not begin with `optional` or `repeated` and end with a `;`, which would + // normally be a quoted bit of literal `.proto` specification above the associated + // declaration. + // To account for emacs folding markers, we ignore any line containing + // `{{{` or `}}}`. + // Finally, some code tends to embed GUIDs in comments, so we also exclude those. + not trimmed .regexpMatch("(>.*|.*[\\\\@][{}].*|(optional|repeated) .*;|.*(\\{\\{\\{|\\}\\}\\}).*|\\{[-0-9a-zA-Z]+\\})") - ) ) } @@ -76,7 +74,6 @@ private predicate preprocLine(File f, int line) { private int lineInFile(CppStyleComment c, File f) { f = c.getFile() and result = c.getLocation().getStartLine() and - // Ignore comments on the same line as a preprocessor directive. not preprocLine(f, result) } @@ -119,12 +116,11 @@ class CommentBlock extends Comment { this instanceof CppStyleComment implies not exists(CppStyleComment pred, File f | lineInFile(pred, f) + 1 = lineInFile(this, f)) - ) and ( - // Ignore comments on the same line as a preprocessor directive. - not exists(Location l | - l = this.getLocation() and - preprocLine(l.getFile(), l.getStartLine()) - ) + ) and + // Ignore comments on the same line as a preprocessor directive. + not exists(Location l | + l = this.getLocation() and + preprocLine(l.getFile(), l.getStartLine()) ) } diff --git a/cpp/ql/src/Documentation/DocumentApi.ql b/cpp/ql/src/Documentation/DocumentApi.ql index 5e90609ac77..9c78c1f80fc 100644 --- a/cpp/ql/src/Documentation/DocumentApi.ql +++ b/cpp/ql/src/Documentation/DocumentApi.ql @@ -11,26 +11,26 @@ * @tags maintainability * documentation */ -import cpp +import cpp predicate isCommented(FunctionDeclarationEntry f) { exists(Comment c | c.getCommentedElement() = f) } // Uses of 'f' in 'other' -Call uses(File other, Function f) { - result.getTarget() = f and result.getFile() = other -} +Call uses(File other, Function f) { result.getTarget() = f and result.getFile() = other } from File callerFile, Function f, Call use, int numCalls -where numCalls = strictcount(File other | exists(uses(other, f)) and other != f.getFile()) - and not isCommented(f.getADeclarationEntry()) - and not f instanceof Constructor - and not f instanceof Destructor - and not f.hasName("operator=") - and f.getMetrics().getNumberOfLinesOfCode() >= 5 - and numCalls > 1 - and use = uses(callerFile, f) - and callerFile != f.getFile() -select f, "Functions called from other files should be documented (called from $@).", use, use.getFile().getRelativePath() +where + numCalls = strictcount(File other | exists(uses(other, f)) and other != f.getFile()) and + not isCommented(f.getADeclarationEntry()) and + not f instanceof Constructor and + not f instanceof Destructor and + not f.hasName("operator=") and + f.getMetrics().getNumberOfLinesOfCode() >= 5 and + numCalls > 1 and + use = uses(callerFile, f) and + callerFile != f.getFile() +select f, "Functions called from other files should be documented (called from $@).", use, + use.getFile().getRelativePath() diff --git a/cpp/ql/src/Documentation/FixmeComments.ql b/cpp/ql/src/Documentation/FixmeComments.ql index 1562910191e..5ccbf129275 100644 --- a/cpp/ql/src/Documentation/FixmeComments.ql +++ b/cpp/ql/src/Documentation/FixmeComments.ql @@ -9,6 +9,7 @@ * documentation * external/cwe/cwe-546 */ + import cpp import Documentation.CaptionedComments diff --git a/cpp/ql/src/Documentation/TodoComments.ql b/cpp/ql/src/Documentation/TodoComments.ql index be1c321b87e..4eedcba183e 100644 --- a/cpp/ql/src/Documentation/TodoComments.ql +++ b/cpp/ql/src/Documentation/TodoComments.ql @@ -9,10 +9,10 @@ * documentation * external/cwe/cwe-546 */ + import cpp import Documentation.CaptionedComments from Comment c, string message where message = getCommentTextCaptioned(c, "TODO") select c, message - diff --git a/cpp/ql/src/Documentation/UncommentedFunction.ql b/cpp/ql/src/Documentation/UncommentedFunction.ql index 2bb443cc9ab..e11fc54f953 100644 --- a/cpp/ql/src/Documentation/UncommentedFunction.ql +++ b/cpp/ql/src/Documentation/UncommentedFunction.ql @@ -10,10 +10,14 @@ * statistical * non-attributable */ + import cpp from MetricFunction f, int n -where n = f.getNumberOfLines() and n > 100 and - f.getCommentRatio() <= 0.02 and - not f.isMultiplyDefined() -select f, "Poorly documented function: fewer than 2% comments for a function of " + n.toString() + " lines." +where + n = f.getNumberOfLines() and + n > 100 and + f.getCommentRatio() <= 0.02 and + not f.isMultiplyDefined() +select f, + "Poorly documented function: fewer than 2% comments for a function of " + n.toString() + " lines." diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 03/ExitNonterminatingLoop.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 03/ExitNonterminatingLoop.ql index d7886b6a52b..9473998e6ee 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 03/ExitNonterminatingLoop.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 03/ExitNonterminatingLoop.ql @@ -11,20 +11,20 @@ import cpp predicate markedAsNonterminating(Loop l) { - exists(Comment c | c.getContents().matches("%@non-terminating@%") | - c.getCommentedElement() = l - ) + exists(Comment c | c.getContents().matches("%@non-terminating@%") | c.getCommentedElement() = l) } Stmt exitFrom(Loop l) { l.getAChild+() = result and - (result instanceof ReturnStmt or - exists(BreakStmt break | break = result | - not l.getAChild*() = break.getTarget()) + ( + result instanceof ReturnStmt + or + exists(BreakStmt break | break = result | not l.getAChild*() = break.getTarget()) ) } from Loop l, Stmt exit -where markedAsNonterminating(l) and - exit = exitFrom(l) +where + markedAsNonterminating(l) and + exit = exitFrom(l) select exit, "$@ should not be exited.", l, "This permanent loop" diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 03/LoopBounds.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 03/LoopBounds.ql index 3f670c8f76e..6580e8e18a3 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 03/LoopBounds.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 03/LoopBounds.ql @@ -30,7 +30,8 @@ predicate upperBoundCheck(Loop loop, VariableAccess checked) { rop.getGreaterOperand().(VariableAccess).getTarget().isConst() or validVarForBound(loop, rop.getGreaterOperand().(VariableAccess).getTarget()) ) and - not rop.getGreaterOperand() instanceof CharLiteral) + not rop.getGreaterOperand() instanceof CharLiteral + ) } predicate lowerBoundCheck(Loop loop, VariableAccess checked) { @@ -43,20 +44,23 @@ predicate lowerBoundCheck(Loop loop, VariableAccess checked) { rop.getLesserOperand().(VariableAccess).getTarget().isConst() or validVarForBound(loop, rop.getLesserOperand().(VariableAccess).getTarget()) ) and - not rop.getLesserOperand() instanceof CharLiteral) + not rop.getLesserOperand() instanceof CharLiteral + ) } VariableAccess getAnIncrement(Variable var) { result.getTarget() = var and ( result.getParent() instanceof IncrementOperation - or + or exists(AssignAddExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0) - or + or exists(AssignExpr a | a.getLValue() = result | - a.getRValue() = - any(AddExpr ae | ae.getAnOperand() = var.getAnAccess() and - ae.getAnOperand().getValue().toInt() > 0)) + a.getRValue() = any(AddExpr ae | + ae.getAnOperand() = var.getAnAccess() and + ae.getAnOperand().getValue().toInt() > 0 + ) + ) ) } @@ -64,62 +68,75 @@ VariableAccess getADecrement(Variable var) { result.getTarget() = var and ( result.getParent() instanceof DecrementOperation - or + or exists(AssignSubExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0) - or + or exists(AssignExpr a | a.getLValue() = result | - a.getRValue() = - any(SubExpr ae | ae.getLeftOperand() = var.getAnAccess() and - ae.getRightOperand().getValue().toInt() > 0)) + a.getRValue() = any(SubExpr ae | + ae.getLeftOperand() = var.getAnAccess() and + ae.getRightOperand().getValue().toInt() > 0 + ) + ) ) } -predicate inScope(Loop l, Stmt s) { - l.getAChild*() = s -} +predicate inScope(Loop l, Stmt s) { l.getAChild*() = s } predicate reachesNoInc(VariableAccess source, ControlFlowNode target) { - (upperBoundCheck(_, source) and source.getASuccessor() = target) or - exists(ControlFlowNode mid | reachesNoInc(source, mid) and not mid = getAnIncrement(source.getTarget()) | - target = mid.getASuccessor() and - inScope(source.getEnclosingStmt(), target.getEnclosingStmt())) + upperBoundCheck(_, source) and source.getASuccessor() = target + or + exists(ControlFlowNode mid | + reachesNoInc(source, mid) and not mid = getAnIncrement(source.getTarget()) + | + target = mid.getASuccessor() and + inScope(source.getEnclosingStmt(), target.getEnclosingStmt()) + ) } predicate reachesNoDec(VariableAccess source, ControlFlowNode target) { - (lowerBoundCheck(_, source) and source.getASuccessor() = target) or - exists(ControlFlowNode mid | reachesNoDec(source, mid) and not mid = getADecrement(source.getTarget()) | - target = mid.getASuccessor() and - inScope(source.getEnclosingStmt(), target.getEnclosingStmt())) -} - -predicate hasSafeBound(Loop l) { - exists(VariableAccess bound | upperBoundCheck(l, bound) | - not reachesNoInc(bound, bound) - ) or exists(VariableAccess bound | lowerBoundCheck(l, bound) | - not reachesNoDec(bound, bound) - ) or exists(l.getControllingExpr().getValue()) -} - -predicate markedAsNonterminating(Loop l) { - exists(Comment c | c.getContents().matches("%@non-terminating@%") | - c.getCommentedElement() = l + lowerBoundCheck(_, source) and source.getASuccessor() = target + or + exists(ControlFlowNode mid | + reachesNoDec(source, mid) and not mid = getADecrement(source.getTarget()) + | + target = mid.getASuccessor() and + inScope(source.getEnclosingStmt(), target.getEnclosingStmt()) ) } +predicate hasSafeBound(Loop l) { + exists(VariableAccess bound | upperBoundCheck(l, bound) | not reachesNoInc(bound, bound)) + or + exists(VariableAccess bound | lowerBoundCheck(l, bound) | not reachesNoDec(bound, bound)) + or + exists(l.getControllingExpr().getValue()) +} + +predicate markedAsNonterminating(Loop l) { + exists(Comment c | c.getContents().matches("%@non-terminating@%") | c.getCommentedElement() = l) +} + from Loop loop, string msg -where not hasSafeBound(loop) and - not markedAsNonterminating(loop) and - ( - ( - not upperBoundCheck(loop, _) and - not lowerBoundCheck(loop, _) and - msg = "This loop does not have a fixed bound." - ) or exists(VariableAccess bound | upperBoundCheck(loop, bound) and - reachesNoInc(bound, bound) and - msg = "The loop counter " + bound.getTarget().getName() + " is not always incremented in the loop body." - ) or exists(VariableAccess bound | lowerBoundCheck(loop, bound) and - reachesNoDec(bound, bound) and - msg = "The loop counter " + bound.getTarget().getName() + " is not always decremented in the loop body." - ) +where + not hasSafeBound(loop) and + not markedAsNonterminating(loop) and + ( + not upperBoundCheck(loop, _) and + not lowerBoundCheck(loop, _) and + msg = "This loop does not have a fixed bound." + or + exists(VariableAccess bound | + upperBoundCheck(loop, bound) and + reachesNoInc(bound, bound) and + msg = "The loop counter " + bound.getTarget().getName() + + " is not always incremented in the loop body." ) + or + exists(VariableAccess bound | + lowerBoundCheck(loop, bound) and + reachesNoDec(bound, bound) and + msg = "The loop counter " + bound.getTarget().getName() + + " is not always decremented in the loop body." + ) + ) select loop, msg diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 04/Recursion.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 04/Recursion.ql index 507b93665bf..df8b3ffbf2a 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 04/Recursion.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 04/Recursion.ql @@ -13,14 +13,14 @@ import cpp class RecursiveCall extends FunctionCall { - RecursiveCall() { - this.getTarget().calls*(this.getEnclosingFunction()) - } + RecursiveCall() { this.getTarget().calls*(this.getEnclosingFunction()) } } from RecursiveCall call, string msg -where if (call.getTarget() = call.getEnclosingFunction()) then - msg = "This call directly invokes its containing function $@." - else - msg = "The function " + call.getEnclosingFunction() + " is indirectly recursive via this call to $@." +where + if call.getTarget() = call.getEnclosingFunction() + then msg = "This call directly invokes its containing function $@." + else + msg = "The function " + call.getEnclosingFunction() + + " is indirectly recursive via this call to $@." select call, msg, call.getTarget(), call.getTarget().getName() diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql index 8a240402142..e170c48f4f6 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 05/HeapMemory.ql @@ -23,12 +23,17 @@ class Initialization extends Function { class Allocation extends FunctionCall { Allocation() { exists(string name | name = this.getTarget().getName() | - name = "malloc" or name = "calloc" or name = "alloca" or - name = "sbrk" or name = "valloc") + name = "malloc" or + name = "calloc" or + name = "alloca" or + name = "sbrk" or + name = "valloc" + ) } } from Function f, Allocation a -where not f instanceof Initialization and - a.getEnclosingFunction() = f +where + not f instanceof Initialization and + a.getEnclosingFunction() = f select a, "Dynamic memory allocation is only allowed during initialization." diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql index e26fca86b12..5b9f9cf79d1 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 07/ThreadSafety.ql @@ -14,8 +14,10 @@ import cpp class ForbiddenCall extends FunctionCall { ForbiddenCall() { exists(string name | name = this.getTarget().getName() | - name = "task_delay" or name = "taskDelay" or - name = "sleep" or name = "nanosleep" or + name = "task_delay" or + name = "taskDelay" or + name = "sleep" or + name = "nanosleep" or name = "clock_nanosleep" ) } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidNestedSemaphores.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidNestedSemaphores.ql index fa79d3b7dc5..125f64fee51 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidNestedSemaphores.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidNestedSemaphores.ql @@ -12,20 +12,22 @@ import Semaphores LockOperation maybeLocked(Function f) { - result.getEnclosingFunction() = f or - exists(Function g | f.calls(g) | - result = maybeLocked(g) - ) + result.getEnclosingFunction() = f + or + exists(Function g | f.calls(g) | result = maybeLocked(g)) } predicate intraproc(LockOperation inner, string msg, LockOperation outer) { - inner = outer.getAReachedNode() and outer.getLocked() != inner.getLocked() and + inner = outer.getAReachedNode() and + outer.getLocked() != inner.getLocked() and msg = "This lock operation is nested in a $@." } predicate interproc(FunctionCall inner, string msg, LockOperation outer) { inner = outer.getAReachedNode() and - exists(LockOperation lock | lock = maybeLocked(inner.getTarget()) and lock.getLocked() != outer.getLocked() | + exists(LockOperation lock | + lock = maybeLocked(inner.getTarget()) and lock.getLocked() != outer.getLocked() + | msg = "This call may perform a " + lock.say() + " while under the effect of a $@." ) } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidSemaphores.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidSemaphores.ql index d76b31314e8..01d787f2fae 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidSemaphores.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 09/AvoidSemaphores.ql @@ -11,6 +11,8 @@ import Semaphores from FunctionCall call, string kind -where (call instanceof SemaphoreCreation and kind = "semaphores") or - (call instanceof LockingPrimitive and kind = "locking primitives") +where + call instanceof SemaphoreCreation and kind = "semaphores" + or + call instanceof LockingPrimitive and kind = "locking primitives" select call, "Use of " + kind + " should be avoided." diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 09/OutOfOrderLocks.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 09/OutOfOrderLocks.ql index 7c375edcecf..ed8e8ffad01 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 09/OutOfOrderLocks.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 09/OutOfOrderLocks.ql @@ -18,11 +18,15 @@ predicate lockOrder(LockOperation outer, LockOperation inner) { int orderCount(Declaration outerLock, Declaration innerLock) { result = strictcount(LockOperation outer, LockOperation inner | - outer.getLocked() = outerLock and inner.getLocked() = innerLock and - lockOrder(outer, inner)) + outer.getLocked() = outerLock and + inner.getLocked() = innerLock and + lockOrder(outer, inner) + ) } from LockOperation outer, LockOperation inner -where lockOrder(outer, inner) - and orderCount(outer.getLocked(), inner.getLocked()) <= orderCount(inner.getLocked(), outer.getLocked()) +where + lockOrder(outer, inner) and + orderCount(outer.getLocked(), inner.getLocked()) <= orderCount(inner.getLocked(), + outer.getLocked()) select inner, "Out-of-order locks: A " + inner.say() + " usually precedes a $@.", outer, outer.say() diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll b/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll index d58b240a414..ef32ea83d90 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 09/Semaphores.qll @@ -4,29 +4,31 @@ import cpp - class SemaphoreCreation extends FunctionCall { SemaphoreCreation() { exists(string name | name = this.getTarget().getName() | - name = "semBCreate" or name = "semMCreate" or name = "semCCreate" or + name = "semBCreate" or + name = "semMCreate" or + name = "semCCreate" or name = "semRWCreate" ) } - Variable getSemaphore() { - result.getAnAccess() = this.getParent().(Assignment).getLValue() - } + Variable getSemaphore() { result.getAnAccess() = this.getParent().(Assignment).getLValue() } } abstract class LockOperation extends FunctionCall { abstract UnlockOperation getMatchingUnlock(); + abstract Declaration getLocked(); + abstract string say(); ControlFlowNode getAReachedNode() { - result = this or + result = this + or exists(ControlFlowNode mid | mid = getAReachedNode() | - not(mid != this.getMatchingUnlock()) and + not mid != this.getMatchingUnlock() and result = mid.getASuccessor() ) } @@ -39,24 +41,21 @@ abstract class UnlockOperation extends FunctionCall { class SemaphoreTake extends LockOperation { SemaphoreTake() { exists(string name | name = this.getTarget().getName() | - name = "semTake" or + name = "semTake" + or // '_' is a wildcard, so this matches calls like // semBTakeScalable or semMTake_inline. name.matches("sem_Take%") ) } - override Variable getLocked() { - result.getAnAccess() = this.getArgument(0) - } + override Variable getLocked() { result.getAnAccess() = this.getArgument(0) } override UnlockOperation getMatchingUnlock() { result.(SemaphoreGive).getLocked() = this.getLocked() } - override string say() { - result = "semaphore take of " + getLocked().getName() - } + override string say() { result = "semaphore take of " + getLocked().getName() } } class SemaphoreGive extends UnlockOperation { @@ -67,14 +66,9 @@ class SemaphoreGive extends UnlockOperation { ) } - Variable getLocked() { - result.getAnAccess() = this.getArgument(0) - } - - override LockOperation getMatchingLock() { - this = result.getMatchingUnlock() - } + Variable getLocked() { result.getAnAccess() = this.getArgument(0) } + override LockOperation getMatchingLock() { this = result.getMatchingUnlock() } } class LockingPrimitive extends FunctionCall, LockOperation { @@ -84,18 +78,16 @@ class LockingPrimitive extends FunctionCall, LockOperation { ) } - override Function getLocked() { - result = this.getTarget() - } + override Function getLocked() { result = this.getTarget() } override UnlockOperation getMatchingUnlock() { - result.(UnlockingPrimitive).getTarget().getName() = - this.getTarget().getName().replaceAll("Lock", "Unlock") + result.(UnlockingPrimitive).getTarget().getName() = this + .getTarget() + .getName() + .replaceAll("Lock", "Unlock") } - override string say() { - result = "call to " + getLocked().getName() - } + override string say() { result = "call to " + getLocked().getName() } } class UnlockingPrimitive extends FunctionCall, UnlockOperation { @@ -105,11 +97,7 @@ class UnlockingPrimitive extends FunctionCall, UnlockOperation { ) } - Function getLocked() { - result = getMatchingLock().getLocked() - } + Function getLocked() { result = getMatchingLock().getLocked() } - override LockOperation getMatchingLock() { - this = result.getMatchingUnlock() - } + override LockOperation getMatchingLock() { this = result.getMatchingUnlock() } } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql index 405d9fa0879..7468b6e7174 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 11/SimpleControlFlowJmp.ql @@ -15,8 +15,11 @@ import cpp class ForbiddenFunction extends Function { ForbiddenFunction() { exists(string name | name = this.getName() | - name = "setjmp" or name = "longjmp" or - name = "sigsetjmp" or name = "siglongjmp") + name = "setjmp" or + name = "longjmp" or + name = "sigsetjmp" or + name = "siglongjmp" + ) } } diff --git a/cpp/ql/src/JPL_C/LOC-2/Rule 12/EnumInitialization.ql b/cpp/ql/src/JPL_C/LOC-2/Rule 12/EnumInitialization.ql index 757bdda26ad..4aa712fe1d6 100644 --- a/cpp/ql/src/JPL_C/LOC-2/Rule 12/EnumInitialization.ql +++ b/cpp/ql/src/JPL_C/LOC-2/Rule 12/EnumInitialization.ql @@ -8,15 +8,14 @@ * readability * external/jpl */ + import cpp -predicate hasInitializer(EnumConstant c) { - c.getInitializer().fromSource() -} +predicate hasInitializer(EnumConstant c) { c.getInitializer().fromSource() } /** Does this have an initializer that is not just a ref to another constant in the same enum? */ predicate hasNonReferenceInitializer(EnumConstant c) { - exists (Initializer init | + exists(Initializer init | init = c.getInitializer() and init.fromSource() and not init.getExpr().(EnumConstantAccess).getTarget().getDeclaringEnum() = c.getDeclaringEnum() @@ -24,14 +23,13 @@ predicate hasNonReferenceInitializer(EnumConstant c) { } predicate hasReferenceInitializer(EnumConstant c) { - exists (Initializer init | + exists(Initializer init | init = c.getInitializer() and init.fromSource() and init.getExpr().(EnumConstantAccess).getTarget().getDeclaringEnum() = c.getDeclaringEnum() ) } - // There exists another constant whose value is implicit, but it's // not the last one: the last value is okay to use to get the highest // enum value automatically. It can be followed by aliases though. @@ -48,15 +46,16 @@ predicate enumThatHasConstantWithImplicitValue(Enum e) { } from Enum e, int i -where // e is at position i, and has an explicit value in the source - but - // not just a reference to another enum constant - hasNonReferenceInitializer(e.getEnumConstant(i)) and - // but e is not the first or the last constant of the enum - i != 0 and - exists(e.getEnumConstant(i+1)) and - // and there exists another constant whose value is implicit, but it's - // not the last one: the last value is okay to use to get the highest - // enum value automatically. It can be followed by aliases though. - enumThatHasConstantWithImplicitValue(e) - -select e, "In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized." +where + // e is at position i, and has an explicit value in the source - but + // not just a reference to another enum constant + hasNonReferenceInitializer(e.getEnumConstant(i)) and + // but e is not the first or the last constant of the enum + i != 0 and + exists(e.getEnumConstant(i + 1)) and + // and there exists another constant whose value is implicit, but it's + // not the last one: the last value is okay to use to get the highest + // enum value automatically. It can be followed by aliases though. + enumThatHasConstantWithImplicitValue(e) +select e, + "In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized." diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 13/ExternDeclsInHeader.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 13/ExternDeclsInHeader.ql index 81ca1051409..4eb8b032926 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 13/ExternDeclsInHeader.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 13/ExternDeclsInHeader.ql @@ -11,7 +11,8 @@ import cpp from VariableDeclarationEntry v -where v.getVariable() instanceof GlobalVariable and +where + v.getVariable() instanceof GlobalVariable and v.hasSpecifier("extern") and not v.getFile() instanceof HeaderFile select v, v.getName() + " should be declared only in a header file that is included as needed." diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql index 3c761e3edcf..05d84902085 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFile.ql @@ -13,9 +13,11 @@ import cpp from GlobalVariable v -where forex(VariableAccess va | va.getTarget() = v | va.getFile() = v.getDefinitionLocation().getFile()) - and not v.hasSpecifier("static") - and strictcount(v.getAnAccess().getEnclosingFunction()) > 1 // If = 1, variable should be function-scope. - and not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere -select v, "The global variable " + v.getName() + " is not accessed outside of " + v.getFile().getBaseName() - + " and could be made static." +where + forex(VariableAccess va | va.getTarget() = v | va.getFile() = v.getDefinitionLocation().getFile()) and + not v.hasSpecifier("static") and + strictcount(v.getAnAccess().getEnclosingFunction()) > 1 and // If = 1, variable should be function-scope. + not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere +select v, + "The global variable " + v.getName() + " is not accessed outside of " + v.getFile().getBaseName() + + " and could be made static." diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql index 78273f1d68f..77259da860e 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeFunction.ql @@ -12,8 +12,11 @@ import cpp from GlobalVariable v, Function f -where v.getAnAccess().getEnclosingFunction() = f and - strictcount(v.getAnAccess().getEnclosingFunction()) = 1 and - forall(VariableAccess a | a = v.getAnAccess() | exists(a.getEnclosingFunction())) and - not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere -select v, "The variable " + v.getName() + " is only accessed in $@ and should be scoped accordingly.", f, f.getName() +where + v.getAnAccess().getEnclosingFunction() = f and + strictcount(v.getAnAccess().getEnclosingFunction()) = 1 and + forall(VariableAccess a | a = v.getAnAccess() | exists(a.getEnclosingFunction())) and + not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere +select v, + "The variable " + v.getName() + " is only accessed in $@ and should be scoped accordingly.", f, + f.getName() diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeLocalHidesGlobal.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeLocalHidesGlobal.ql index a82149c0597..5904bce851e 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeLocalHidesGlobal.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 13/LimitedScopeLocalHidesGlobal.ql @@ -8,27 +8,29 @@ * readability * external/jpl */ + import cpp class LocalVariableOrParameter extends Variable { LocalVariableOrParameter() { - this instanceof LocalVariable or + this instanceof LocalVariable + or // A function declaration (i.e. "int foo(int bar);") doesn't usefully // shadow globals; the parameter should be on the version of the function // that has a body. exists(Parameter p | p = this | - p.getFunction().getDefinitionLocation().getFile() = this.getFile() and - exists(p.getFunction().getBlock())) + p.getFunction().getDefinitionLocation().getFile() = this.getFile() and + exists(p.getFunction().getBlock()) + ) } string type() { - if this instanceof Parameter - then result = "Parameter " - else result = "Local variable " + if this instanceof Parameter then result = "Parameter " else result = "Local variable " } } from LocalVariableOrParameter lv, GlobalVariable gv -where lv.getName() = gv.getName() and - lv.getFile() = gv.getFile() +where + lv.getName() = gv.getName() and + lv.getFile() = gv.getFile() select lv, lv.type() + lv.getName() + " hides the global variable $@.", gv, gv.getName() diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 14/CheckingReturnValues.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 14/CheckingReturnValues.ql index 9adb7289920..87215b69e34 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 14/CheckingReturnValues.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 14/CheckingReturnValues.ql @@ -11,7 +11,8 @@ import cpp -/** In its full generality, the rule applies to all functions that +/** + * In its full generality, the rule applies to all functions that * return non-void, including things like 'printf' and 'close', * which are routinely not checked because the behavior on success * is the same as the behavior on failure. The recommendation is @@ -27,13 +28,15 @@ predicate whitelist(Function f) { } from FunctionCall c, string msg -where not c.getTarget().getType() instanceof VoidType - and not whitelist(c.getTarget()) - and - ( - (c instanceof ExprInVoidContext and msg = "The return value of non-void function $@ is not checked.") - or - (definition(_, c.getParent()) and not definitionUsePair(_, c.getParent(), _) and - msg = "$@'s return value is stored but not checked.") - ) +where + not c.getTarget().getType() instanceof VoidType and + not whitelist(c.getTarget()) and + ( + c instanceof ExprInVoidContext and + msg = "The return value of non-void function $@ is not checked." + or + definition(_, c.getParent()) and + not definitionUsePair(_, c.getParent(), _) and + msg = "$@'s return value is stored but not checked." + ) select c, msg, c.getTarget() as f, f.getName() diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 15/CheckingParameterValues.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 15/CheckingParameterValues.ql index 5e7f57ecbdc..d9a58f6775b 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 15/CheckingParameterValues.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 15/CheckingParameterValues.ql @@ -12,16 +12,18 @@ import JPL_C.Tasks predicate flow(Parameter p, ControlFlowNode n) { - (exists(p.getAnAccess()) and n = p.getFunction().getBlock()) or - exists(ControlFlowNode mid | flow(p, mid) and not mid = p.getAnAccess() and n = mid.getASuccessor()) + exists(p.getAnAccess()) and n = p.getFunction().getBlock() + or + exists(ControlFlowNode mid | + flow(p, mid) and not mid = p.getAnAccess() and n = mid.getASuccessor() + ) } -VariableAccess firstAccess(Parameter p) { - flow(p, result) and result = p.getAnAccess() -} +VariableAccess firstAccess(Parameter p) { flow(p, result) and result = p.getAnAccess() } from Parameter p, VariableAccess va -where va = firstAccess(p) and p.getFunction() instanceof PublicFunction and - not exists(Expr e | e.isCondition() | e.getAChild*() = va) +where + va = firstAccess(p) and + p.getFunction() instanceof PublicFunction and + not exists(Expr e | e.isCondition() | e.getAChild*() = va) select va, "This use of parameter " + p.getName() + " has not been checked." - diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsConstant.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsConstant.ql index 182d5ff53c4..8634173ccda 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsConstant.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsConstant.ql @@ -12,9 +12,9 @@ import semmle.code.cpp.commons.Assertions from Assertion a, string value, string msg -where value = a.getAsserted().getValue() and - if value.toInt() = 0 then - msg = "This assertion is always false." - else - msg = "This assertion is always true." +where + value = a.getAsserted().getValue() and + if value.toInt() = 0 + then msg = "This assertion is always false." + else msg = "This assertion is always true." select a.getAsserted(), msg diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsDensity.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsDensity.ql index 9e9ff9b73d7..b05848d36b4 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsDensity.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 16/UseOfAssertionsDensity.ql @@ -12,6 +12,7 @@ import semmle.code.cpp.commons.Assertions from Function f -where f.getMetrics().getNumberOfLinesOfCode() > 10 and +where + f.getMetrics().getNumberOfLinesOfCode() > 10 and not exists(Assertion a | a.getAsserted().getEnclosingFunction() = f) select f, "All functions of more than 10 lines should have at least one assertion." diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql index 9a389054f42..72852f0b86c 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql @@ -13,11 +13,16 @@ import cpp predicate allowedTypedefs(TypedefType t) { exists(string name | name = t.getName() | - name = "I64" or name = "U64" or - name = "I32" or name = "U32" or - name = "I16" or name = "U16" or - name = "I8" or name = "U8" or - name = "F64" or name = "F32" + name = "I64" or + name = "U64" or + name = "I32" or + name = "U32" or + name = "I16" or + name = "U16" or + name = "I8" or + name = "U8" or + name = "F64" or + name = "F32" ) } @@ -25,7 +30,8 @@ predicate allowedTypedefs(TypedefType t) { * Gets a type which appears literally in the declaration of `d`. */ Type getAnImmediateUsedType(Declaration d) { - d.isDefined() and ( + d.isDefined() and + ( result = d.(Function).getType() or result = d.(Variable).getType() ) @@ -48,7 +54,11 @@ predicate problematic(IntegralType t) { } from Declaration d, Type usedType -where usedType = getAUsedType*(getAnImmediateUsedType(d)) and problematic(usedType) +where + usedType = getAUsedType*(getAnImmediateUsedType(d)) and + problematic(usedType) and // Ignore violations for which we do not have a valid location. - and not(d.getLocation() instanceof UnknownLocation) -select d, d.getName() + " uses the basic integral type " + usedType.getName() + " rather than a typedef with size and signedness." + not d.getLocation() instanceof UnknownLocation +select d, + d.getName() + " uses the basic integral type " + usedType.getName() + + " rather than a typedef with size and signedness." diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 18/CompoundExpressions.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 18/CompoundExpressions.ql index 364b542274a..bf2367ef5c5 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 18/CompoundExpressions.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 18/CompoundExpressions.ql @@ -12,7 +12,9 @@ import cpp from BinaryOperation parent, BinaryOperation child -where parent.getAnOperand() = child and not child.isParenthesised() and +where + parent.getAnOperand() = child and + not child.isParenthesised() and (parent instanceof BinaryBitwiseOperation or child instanceof BinaryBitwiseOperation) and // Some benign cases... not (parent instanceof BitwiseAndExpr and child instanceof BitwiseAndExpr) and diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 19/NoBooleanSideEffects.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 19/NoBooleanSideEffects.ql index 674c4d6d1f9..a3b0ed3b2b9 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 19/NoBooleanSideEffects.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 19/NoBooleanSideEffects.ql @@ -46,10 +46,9 @@ predicate inherentlyUnsafe(Function f) { exists(Variable v | v.getAnAssignedValue().getEnclosingFunction() = f | v instanceof GlobalVariable or v.isStatic() - ) or - exists(FunctionCall c | c.getEnclosingFunction() = f | - inherentlyUnsafe(c.getTarget()) ) + or + exists(FunctionCall c | c.getEnclosingFunction() = f | inherentlyUnsafe(c.getTarget())) } /** @@ -59,7 +58,9 @@ predicate inherentlyUnsafe(Function f) { * not inherently unsafe. */ predicate safeToCall(Function f) { - forall(PointerType paramPointerType | paramPointerType = getAPointerType(f.getAParameter().getType()) | + forall(PointerType paramPointerType | + paramPointerType = getAPointerType(f.getAParameter().getType()) + | paramPointerType.getBaseType().isConst() ) and not inherentlyUnsafe(f) @@ -78,12 +79,16 @@ class BooleanExpression extends Expr { } predicate hasSideEffect(Expr e) { - e instanceof Assignment or - e instanceof CrementOperation or - e instanceof ExprCall or + e instanceof Assignment + or + e instanceof CrementOperation + or + e instanceof ExprCall + or exists(Function f | f = e.(FunctionCall).getTarget() and not safeFunctionWhitelist(f) | inherentlyUnsafe(f) or not safeToCall(f) - ) or + ) + or hasSideEffect(e.getAChild()) } diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUse.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUse.ql index a2b5496998e..826534761d7 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUse.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUse.ql @@ -12,12 +12,13 @@ import cpp from PreprocessorDirective p -where not p instanceof Include and - not p instanceof Macro and - not p instanceof PreprocessorIf and - not p instanceof PreprocessorElif and - not p instanceof PreprocessorElse and - not p instanceof PreprocessorIfdef and - not p instanceof PreprocessorIfndef and - not p instanceof PreprocessorEndif +where + not p instanceof Include and + not p instanceof Macro and + not p instanceof PreprocessorIf and + not p instanceof PreprocessorElif and + not p instanceof PreprocessorElse and + not p instanceof PreprocessorIfdef and + not p instanceof PreprocessorIfndef and + not p instanceof PreprocessorEndif select p, "This preprocessor directive is not allowed." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseIfdef.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseIfdef.ql index 2ecd1d4c6f2..6af58a7d09f 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseIfdef.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseIfdef.ql @@ -12,6 +12,7 @@ import cpp from PreprocessorDirective i -where (i instanceof PreprocessorIf or i instanceof PreprocessorIfdef or i instanceof PreprocessorIfndef) - and not i.getFile() instanceof HeaderFile +where + (i instanceof PreprocessorIf or i instanceof PreprocessorIfdef or i instanceof PreprocessorIfndef) and + not i.getFile() instanceof HeaderFile select i, "Use of conditional compilation must be kept to a minimum." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseUndisciplined.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseUndisciplined.ql index 93dba91e442..21983ebda64 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseUndisciplined.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 20/PreprocessorUseUndisciplined.ql @@ -12,6 +12,10 @@ import cpp from Macro m, string msg -where (m.getHead().matches("%...%") and msg = "The macro " + m.getHead() + " is variadic, and hence not allowed.") or - (m.getBody().matches("%##%") and msg = "The macro " + m.getHead() + " uses token pasting and is not allowed.") +where + m.getHead().matches("%...%") and + msg = "The macro " + m.getHead() + " is variadic, and hence not allowed." + or + m.getBody().matches("%##%") and + msg = "The macro " + m.getHead() + " uses token pasting and is not allowed." select m, msg diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 21/MacroInBlock.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 21/MacroInBlock.ql index ec6b5339572..602be971763 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 21/MacroInBlock.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 21/MacroInBlock.ql @@ -12,8 +12,10 @@ import cpp int lineInBlock(File f) { - exists(Block block, Location blockLocation | block.getFile() = f and blockLocation = block.getLocation()| - result in [blockLocation.getStartLine()..blockLocation.getEndLine()] + exists(Block block, Location blockLocation | + block.getFile() = f and blockLocation = block.getLocation() + | + result in [blockLocation.getStartLine() .. blockLocation.getEndLine()] ) } diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 23/MismatchedIfdefs.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 23/MismatchedIfdefs.ql index f8a605bbf63..e9c619167de 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 23/MismatchedIfdefs.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 23/MismatchedIfdefs.ql @@ -12,43 +12,35 @@ import cpp class FileWithDirectives extends File { - FileWithDirectives() { - exists(Directive d | d.getFile() = this) - } + FileWithDirectives() { exists(Directive d | d.getFile() = this) } int getDirectiveLine(Directive d) { d.getFile() = this and d.getLocation().getStartLine() = result } int getDirectiveIndex(Directive d) { - exists(int line | line = getDirectiveLine(d) | - line = rank[result](getDirectiveLine(_)) - ) + exists(int line | line = getDirectiveLine(d) | line = rank[result](getDirectiveLine(_))) } int depth(Directive d) { exists(int index | index = getDirectiveIndex(d) | - (index = 1 and result = d.depthChange()) or - exists(Directive prev | getDirectiveIndex(prev) = index-1 | + index = 1 and result = d.depthChange() + or + exists(Directive prev | getDirectiveIndex(prev) = index - 1 | result = d.depthChange() + depth(prev) ) ) } - Directive lastDirective() { - getDirectiveIndex(result) = max(getDirectiveIndex(_)) - } + Directive lastDirective() { getDirectiveIndex(result) = max(getDirectiveIndex(_)) } } abstract class Directive extends PreprocessorDirective { abstract int depthChange(); + abstract predicate mismatched(); - int depth() { - exists(FileWithDirectives f | - f.depth(this) = result - ) - } + int depth() { exists(FileWithDirectives f | f.depth(this) = result) } } class IfDirective extends Directive { @@ -59,6 +51,7 @@ class IfDirective extends Directive { } override int depthChange() { result = 1 } + override predicate mismatched() { none() } } @@ -69,24 +62,26 @@ class ElseDirective extends Directive { } override int depthChange() { result = 0 } + override predicate mismatched() { depth() < 1 } } class EndifDirective extends Directive { - EndifDirective() { - this instanceof PreprocessorEndif - } + EndifDirective() { this instanceof PreprocessorEndif } override int depthChange() { result = -1 } + override predicate mismatched() { depth() < 0 } } from FileWithDirectives f, Directive d, string msg -where d.getFile() = f and - if d.mismatched() then ( - msg = "'" + d + "' has no matching #if in file " + f.getBaseName() + "." - ) else ( - d = f.lastDirective() and d.depth() > 0 and msg = "File " + f.getBaseName() + - " ends with " + d.depth() + " unterminated #if directives." +where + d.getFile() = f and + if d.mismatched() + then msg = "'" + d + "' has no matching #if in file " + f.getBaseName() + "." + else ( + d = f.lastDirective() and + d.depth() > 0 and + msg = "File " + f.getBaseName() + " ends with " + d.depth() + " unterminated #if directives." ) select d, msg diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql index 2940f493d87..03b7bb1c5da 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleStmtsPerLine.ql @@ -22,16 +22,16 @@ class OneLineStmt extends Stmt { } } -int numStmt(File f, int line) { - result = strictcount(OneLineStmt o | o.onLine(f, line)) -} +int numStmt(File f, int line) { result = strictcount(OneLineStmt o | o.onLine(f, line)) } from File f, int line, OneLineStmt o, int cnt -where numStmt(f, line) = cnt - and cnt > 1 - and o.onLine(f, line) - and o.getLocation().getStartColumn() = - min(OneLineStmt other, int toMin - | other.onLine(f, line) and toMin = other.getLocation().getStartColumn() - | toMin) +where + numStmt(f, line) = cnt and + cnt > 1 and + o.onLine(f, line) and + o.getLocation().getStartColumn() = min(OneLineStmt other, int toMin | + other.onLine(f, line) and toMin = other.getLocation().getStartColumn() + | + toMin + ) select o, "This line contains " + cnt + " statements; only one is allowed." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql index 625c86bef6d..fcdb2471b76 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 24/MultipleVarDeclsPerLine.ql @@ -12,7 +12,8 @@ import cpp from DeclStmt d -where exists(Variable v1, Variable v2 | v1 = d.getADeclaration() and v2 = d.getADeclaration() | +where + exists(Variable v1, Variable v2 | v1 = d.getADeclaration() and v2 = d.getADeclaration() | v1 != v2 and v1.getLocation().getStartLine() = v2.getLocation().getStartLine() ) diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 25/FunctionSizeLimits.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 25/FunctionSizeLimits.ql index 19eb0be0e89..ef84add2be2 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 25/FunctionSizeLimits.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 25/FunctionSizeLimits.ql @@ -26,6 +26,7 @@ string paramWarning(Function f) { } from Function f, string msg -where msg = lengthWarning(f) or - msg = paramWarning(f) +where + msg = lengthWarning(f) or + msg = paramWarning(f) select f, msg diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 26/DeclarationPointerNesting.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 26/DeclarationPointerNesting.ql index e39c9e56a85..5f59fa80d10 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 26/DeclarationPointerNesting.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 26/DeclarationPointerNesting.ql @@ -15,7 +15,7 @@ string var(Variable v) { exists(int level | level = v.getType().getPointerIndirectionLevel() | level > 2 and result = "The type of " + v.getName() + " uses " + level + - " levels of pointer indirection -- maximum allowed is 2." + " levels of pointer indirection -- maximum allowed is 2." ) } @@ -23,7 +23,7 @@ string fun(Function f) { exists(int level | level = f.getType().getPointerIndirectionLevel() | level > 2 and result = "The return type of " + f.getName() + " uses " + level + - " levels of pointer indirection -- maximum allowed is 2." + " levels of pointer indirection -- maximum allowed is 2." ) } diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 27/PointerDereferenceInStmt.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 27/PointerDereferenceInStmt.ql index 3c197051fbe..f5eb7c6463c 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 27/PointerDereferenceInStmt.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 27/PointerDereferenceInStmt.ql @@ -12,7 +12,8 @@ import cpp from PointerDereferenceExpr e, int n -where not e.getParent+() instanceof PointerDereferenceExpr - and n = strictcount(PointerDereferenceExpr child | child.getParent+() = e) - and n > 1 +where + not e.getParent+() instanceof PointerDereferenceExpr and + n = strictcount(PointerDereferenceExpr child | child.getParent+() = e) and + n > 1 select e, "This expression involves " + n + " levels of pointer dereference; 2 are allowed." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 28/HiddenPointerDereferenceMacro.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 28/HiddenPointerDereferenceMacro.ql index abf8a9a5171..864be97c43f 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 28/HiddenPointerDereferenceMacro.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 28/HiddenPointerDereferenceMacro.ql @@ -12,9 +12,11 @@ import cpp from Macro m -where forex(MacroInvocation mi | mi.getMacro() = m | +where + forex(MacroInvocation mi | mi.getMacro() = m | exists(PointerDereferenceExpr e, Location miLoc, Location eLoc | e = mi.getAGeneratedElement() | - miLoc = mi.getLocation() and eLoc = e.getLocation() and + miLoc = mi.getLocation() and + eLoc = e.getLocation() and eLoc.getStartColumn() = miLoc.getStartColumn() and eLoc.getStartLine() = miLoc.getStartLine() ) diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 30/FunctionPointerConversions.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 30/FunctionPointerConversions.ql index fba27480c32..5771c94ce02 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 30/FunctionPointerConversions.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 30/FunctionPointerConversions.ql @@ -20,7 +20,9 @@ predicate permissibleConversion(Type t) { } from Expr e, Type converted -where e.getType() instanceof FunctionPointerType and +where + e.getType() instanceof FunctionPointerType and e.getFullyConverted().getType() = converted and not permissibleConversion(converted) -select e, "Function pointer converted to " + converted.getName() + ", which is not an integral type." +select e, + "Function pointer converted to " + converted.getName() + ", which is not an integral type." diff --git a/cpp/ql/src/JPL_C/LOC-4/Rule 31/IncludesFirst.ql b/cpp/ql/src/JPL_C/LOC-4/Rule 31/IncludesFirst.ql index aa796cd1795..12f17106fbc 100644 --- a/cpp/ql/src/JPL_C/LOC-4/Rule 31/IncludesFirst.ql +++ b/cpp/ql/src/JPL_C/LOC-4/Rule 31/IncludesFirst.ql @@ -12,8 +12,16 @@ import cpp int firstCodeLine(File f) { - result = min(Declaration d, Location l, int toMin | (l = d.getLocation() and - l.getFile() = f and not d.isInMacroExpansion()) and (toMin = l.getStartLine()) | toMin) + result = min(Declaration d, Location l, int toMin | + ( + l = d.getLocation() and + l.getFile() = f and + not d.isInMacroExpansion() + ) and + toMin = l.getStartLine() + | + toMin + ) } int badIncludeLine(File f, Include i) { @@ -23,7 +31,9 @@ int badIncludeLine(File f, Include i) { } from File f, Include i, int line -where line = badIncludeLine(f, i) and +where + line = badIncludeLine(f, i) and line = min(badIncludeLine(f, _)) -select i, "'" + i.toString() + "' is preceded by code -- it should be moved above line " + - firstCodeLine(f) + " in " + f.getBaseName() + "." +select i, + "'" + i.toString() + "' is preceded by code -- it should be moved above line " + firstCodeLine(f) + + " in " + f.getBaseName() + "." diff --git a/cpp/ql/src/JPL_C/Tasks.qll b/cpp/ql/src/JPL_C/Tasks.qll index 9f582585c20..51eb0477c03 100644 --- a/cpp/ql/src/JPL_C/Tasks.qll +++ b/cpp/ql/src/JPL_C/Tasks.qll @@ -22,7 +22,8 @@ class Task extends Function { */ class PublicFunction extends Function { PublicFunction() { - not this.isStatic() and ( + not this.isStatic() and + ( strictcount(Task t | t.calls+(this)) > 1 or not exists(Task t | t.getFile() = this.getFile()) ) diff --git a/cpp/ql/src/Likely Bugs/AmbiguouslySignedBitField.ql b/cpp/ql/src/Likely Bugs/AmbiguouslySignedBitField.ql index 0c8319e8f43..a2f3ec1d119 100644 --- a/cpp/ql/src/Likely Bugs/AmbiguouslySignedBitField.ql +++ b/cpp/ql/src/Likely Bugs/AmbiguouslySignedBitField.ql @@ -14,17 +14,21 @@ * language-features * external/cwe/cwe-190 */ + import cpp from BitField bf -where not bf.getUnspecifiedType().(IntegralType).isExplicitlySigned() - and not bf.getUnspecifiedType().(IntegralType).isExplicitlyUnsigned() - and not bf.getUnspecifiedType() instanceof Enum - and not bf.getUnspecifiedType() instanceof BoolType +where + not bf.getUnspecifiedType().(IntegralType).isExplicitlySigned() and + not bf.getUnspecifiedType().(IntegralType).isExplicitlyUnsigned() and + not bf.getUnspecifiedType() instanceof Enum and + not bf.getUnspecifiedType() instanceof BoolType and // At least for C programs on Windows, BOOL is a common typedef for a type // representing BoolType. - and not bf.getType().hasName("BOOL") + not bf.getType().hasName("BOOL") and // If this is true, then there cannot be unsigned sign extension or overflow. - and not bf.getDeclaredNumBits() = bf.getType().getSize() * 8 - and not bf.isAnonymous() -select bf, "Bit field " + bf.getName() + " of type " + bf.getUnderlyingType().getName() + " should have explicitly unsigned integral, explicitly signed integral, or enumeration type." + not bf.getDeclaredNumBits() = bf.getType().getSize() * 8 and + not bf.isAnonymous() +select bf, + "Bit field " + bf.getName() + " of type " + bf.getUnderlyingType().getName() + + " should have explicitly unsigned integral, explicitly signed integral, or enumeration type." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.qll b/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.qll index e2b1b2579b3..56fa74d3aab 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.qll +++ b/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.qll @@ -13,8 +13,9 @@ private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils * swapping the operands both ways round. */ private predicate addExpr(AddExpr plus, Expr a, Expr b) { - (a = plus.getLeftOperand() and b = plus.getRightOperand()) or - (b = plus.getLeftOperand() and a = plus.getRightOperand()) + a = plus.getLeftOperand() and b = plus.getRightOperand() + or + b = plus.getLeftOperand() and a = plus.getRightOperand() } /** @@ -29,12 +30,12 @@ private predicate addExpr(AddExpr plus, Expr a, Expr b) { * false. */ predicate badAdditionOverflowCheck(RelationalOperation cmp, AddExpr plus) { - exists (Variable v, VariableAccess a1, VariableAccess a2, Expr b - | addExpr(plus, a1, b) and + exists(Variable v, VariableAccess a1, VariableAccess a2, Expr b | + addExpr(plus, a1, b) and a1 = v.getAnAccess() and a2 = v.getAnAccess() and - not exists (a1.getQualifier()) and // Avoid structure fields - not exists (a2.getQualifier()) and // Avoid structure fields + not exists(a1.getQualifier()) and // Avoid structure fields + not exists(a2.getQualifier()) and // Avoid structure fields // Simple type-based check that the addition cannot overflow. exprMinVal(plus) <= exprMinVal(a1) + exprMinVal(b) and exprMaxVal(plus) > exprMaxVal(a1) and @@ -43,5 +44,6 @@ predicate badAdditionOverflowCheck(RelationalOperation cmp, AddExpr plus) { exprMinVal(plus.getExplicitlyConverted()) <= exprMinVal(plus) and exprMaxVal(plus.getExplicitlyConverted()) >= exprMaxVal(plus) and cmp.getAnOperand() = plus and - cmp.getAnOperand() = a2) + cmp.getAnOperand() = a2 + ) } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.ql b/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.ql index fed102e2d1d..bff2492a70a 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/BadCheckOdd.ql @@ -10,12 +10,14 @@ * correctness * types */ + import cpp from EqualityOperation t, RemExpr lhs, Literal rhs -where t.getLeftOperand() = lhs and - t.getRightOperand() = rhs and - lhs.getLeftOperand().getUnspecifiedType().(IntegralType).isSigned() and - lhs.getRightOperand().getValue() = "2" and - rhs.getValue() = "1" +where + t.getLeftOperand() = lhs and + t.getRightOperand() = rhs and + lhs.getLeftOperand().getUnspecifiedType().(IntegralType).isSigned() and + lhs.getRightOperand().getValue() = "2" and + rhs.getValue() = "1" select t, "Possibly invalid test for oddness. This will fail for negative numbers." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql index 2e8c10df1d7..1e29e77742f 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql @@ -9,12 +9,14 @@ * @tags reliability * correctness */ + import cpp from RelationalOperation e, BinaryBitwiseOperation lhs -where lhs = e.getGreaterOperand() and - lhs.getActualType().(IntegralType).isSigned() and - forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and - e.getLesserOperand().getValue() = "0" and - not e.isAffectedByMacro() +where + lhs = e.getGreaterOperand() and + lhs.getActualType().(IntegralType).isSigned() and + forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and + e.getLesserOperand().getValue() = "0" and + not e.isAffectedByMacro() select e, "Potential unsafe sign check of a bitwise operation." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.ql b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.ql index 4e0fd8d9eee..16d7925c53f 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.ql @@ -10,8 +10,8 @@ * @tags maintainability * readability */ -import cpp +import cpp from ComparisonOperation co, ComparisonOperation chco where co.getAChild() = chco and not chco.isParenthesised() diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonWithCancelingSubExpr.ql b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonWithCancelingSubExpr.ql index 882e44f83a3..d0e0c269b8e 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonWithCancelingSubExpr.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonWithCancelingSubExpr.ql @@ -25,11 +25,15 @@ import PointlessSelfComparison * `parent = 2 * child` */ private predicate linearChild(Expr parent, Expr child, float multiplier) { - (child = parent.(AddExpr).getAChild() and multiplier = 1.0) or - (child = parent.(SubExpr).getLeftOperand() and multiplier = 1.0) or - (child = parent.(SubExpr).getRightOperand() and multiplier = -1.0) or - (child = parent.(UnaryPlusExpr).getOperand() and multiplier = 1.0) or - (child = parent.(UnaryMinusExpr).getOperand() and multiplier = -1.0) + child = parent.(AddExpr).getAChild() and multiplier = 1.0 + or + child = parent.(SubExpr).getLeftOperand() and multiplier = 1.0 + or + child = parent.(SubExpr).getRightOperand() and multiplier = -1.0 + or + child = parent.(UnaryPlusExpr).getOperand() and multiplier = 1.0 + or + child = parent.(UnaryMinusExpr).getOperand() and multiplier = -1.0 } /** @@ -41,18 +45,19 @@ private predicate linearChild(Expr parent, Expr child, float multiplier) { * In this example, `x` has multiplier 4, `y` has multiplier -1, and `z` * has multiplier -3 (multipliers from the right hand child are negated). */ -private predicate cmpLinearSubExpr( - ComparisonOperation cmp, Expr child, float multiplier) { - not convertedExprMightOverflow(child) - and - ((child = cmp.getLeftOperand() and multiplier = 1.0) - or - (child = cmp.getRightOperand() and multiplier = -1.0) - or - exists (Expr parent, float m1, float m2 - | cmpLinearSubExpr(cmp, parent, m1) and - linearChild(parent, child, m2) and - multiplier = m1 * m2)) +private predicate cmpLinearSubExpr(ComparisonOperation cmp, Expr child, float multiplier) { + not convertedExprMightOverflow(child) and + ( + child = cmp.getLeftOperand() and multiplier = 1.0 + or + child = cmp.getRightOperand() and multiplier = -1.0 + or + exists(Expr parent, float m1, float m2 | + cmpLinearSubExpr(cmp, parent, m1) and + linearChild(parent, child, m2) and + multiplier = m1 * m2 + ) + ) } /** @@ -60,9 +65,10 @@ private predicate cmpLinearSubExpr( * `child` is an access of variable `v`. */ private predicate cmpLinearSubVariable( - ComparisonOperation cmp, Variable v, VariableAccess child, float multiplier) { + ComparisonOperation cmp, Variable v, VariableAccess child, float multiplier +) { v = child.getTarget() and - not exists (child.getQualifier()) and + not exists(child.getQualifier()) and cmpLinearSubExpr(cmp, child, multiplier) } @@ -75,23 +81,19 @@ private predicate cmpLinearSubVariable( * `v + x - v < y` * `v + x + v < y + 2*v` */ -private predicate cancelingSubExprs( - ComparisonOperation cmp, VariableAccess a1, VariableAccess a2) { - exists (Variable v - | exists (float m | m < 0 and cmpLinearSubVariable(cmp, v, a1, m)) and - exists (float m | m > 0 and cmpLinearSubVariable(cmp, v, a2, m))) +private predicate cancelingSubExprs(ComparisonOperation cmp, VariableAccess a1, VariableAccess a2) { + exists(Variable v | + exists(float m | m < 0 and cmpLinearSubVariable(cmp, v, a1, m)) and + exists(float m | m > 0 and cmpLinearSubVariable(cmp, v, a2, m)) + ) } from ComparisonOperation cmp, VariableAccess a1, VariableAccess a2 where - cancelingSubExprs(cmp, a1, a2) - + cancelingSubExprs(cmp, a1, a2) and // Most practical examples found by this query are instances of // BadAdditionOverflowCheck or PointlessSelfComparison. - and not badAdditionOverflowCheck(cmp, _) - and not pointlessSelfComparison(cmp) -select - cmp, - "Comparison can be simplified by canceling $@ with $@.", - a1, a1.getTarget().getName(), + not badAdditionOverflowCheck(cmp, _) and + not pointlessSelfComparison(cmp) +select cmp, "Comparison can be simplified by canceling $@ with $@.", a1, a1.getTarget().getName(), a2, a2.getTarget().getName() diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql index 09cf27de30b..5233f567fa5 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql @@ -10,11 +10,15 @@ * @tags reliability * correctness */ + import cpp from EqualityOperation ro, Expr left, Expr right -where left = ro.getLeftOperand() and right = ro.getRightOperand() and - ro.getAnOperand().getExplicitlyConverted().getType().getUnderlyingType() instanceof FloatingPointType and - not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives - not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison +where + left = ro.getLeftOperand() and + right = ro.getRightOperand() and + ro.getAnOperand().getExplicitlyConverted().getType().getUnderlyingType() instanceof + FloatingPointType and + not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives + not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison select ro, "Equality test on floating point values may not behave as expected." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql b/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql index 885039e9d58..af4e1ccce8f 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql @@ -15,6 +15,7 @@ * external/cwe/cwe-197 * external/cwe/cwe-681 */ + import cpp import semmle.code.cpp.controlflow.SSA @@ -28,9 +29,12 @@ import semmle.code.cpp.controlflow.SSA * controlled, so we consider it less likely to cause an overflow. */ predicate likelySmall(Expr e) { - e.isConstant() or - e.getType().getSize() <= 1 or - e.(ArrayExpr).getArrayBase().getType().(ArrayType).getBaseType().isConst() or + 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 likelySmall(def.getDefiningValue(v)) @@ -41,9 +45,7 @@ predicate likelySmall(Expr e) { * Gets an operand of a multiply expression (we need the restriction * to multiply expressions to get the correct transitive closure). */ -Expr getMulOperand(MulExpr me) { - result = me.getAnOperand() -} +Expr getMulOperand(MulExpr me) { result = me.getAnOperand() } /** * Gets the number of non-constant operands of a multiply expression, @@ -56,53 +58,50 @@ Expr getMulOperand(MulExpr me) { */ int getEffectiveMulOperands(MulExpr me) { result = count(Expr op | - op = getMulOperand*(me) and - not op instanceof MulExpr and - not likelySmall(op) - ) + op = getMulOperand*(me) and + not op instanceof MulExpr and + not likelySmall(op) + ) } from MulExpr me, Type t1, Type t2 -where t1 = me.getType().getUnderlyingType() and - t2 = me.getConversion().getType().getUnderlyingType() and - t1.getSize() < t2.getSize() and - ( - ( - t1.getUnspecifiedType() instanceof IntegralType and - t2.getUnspecifiedType() instanceof IntegralType - ) or ( - t1.getUnspecifiedType() instanceof FloatingPointType and - t2.getUnspecifiedType() instanceof FloatingPointType - ) - ) and - - // exclude explicit conversions - me.getConversion().isCompilerGenerated() and - - // require the multiply to have two non-constant operands - // (the intuition here is that multiplying two unknowns is - // much more likely to produce a result that needs significantly - // more bits than the operands did, and thus requires a larger - // type). - getEffectiveMulOperands(me) >= 2 and - - // exclude varargs promotions - not exists(FunctionCall fc, int vararg | - fc.getArgument(vararg) = me and - vararg >= fc.getTarget().getNumberOfParameters() - ) and - - // exclude cases where the type was made bigger by a literal - // (compared to other cases such as assignment, this is more - // likely to be a trivial accident rather than suggesting a - // larger type is needed for the result). - not exists(Expr other, Expr e | - other = me.getParent().(BinaryOperation).getAnOperand() and - not other = me and - ( - e = other or - e = other.(BinaryOperation).getAnOperand*() - ) and - e.(Literal).getType().getSize() = t2.getSize() - ) -select me, "Multiplication result may overflow '" + me.getType().toString() + "' before it is converted to '" + me.getFullyConverted().getType().toString() + "'." +where + t1 = me.getType().getUnderlyingType() and + t2 = me.getConversion().getType().getUnderlyingType() and + t1.getSize() < t2.getSize() and + ( + t1.getUnspecifiedType() instanceof IntegralType and + t2.getUnspecifiedType() instanceof IntegralType + or + t1.getUnspecifiedType() instanceof FloatingPointType and + t2.getUnspecifiedType() instanceof FloatingPointType + ) and + // exclude explicit conversions + me.getConversion().isCompilerGenerated() and + // require the multiply to have two non-constant operands + // (the intuition here is that multiplying two unknowns is + // much more likely to produce a result that needs significantly + // more bits than the operands did, and thus requires a larger + // type). + getEffectiveMulOperands(me) >= 2 and + // exclude varargs promotions + not exists(FunctionCall fc, int vararg | + fc.getArgument(vararg) = me and + vararg >= fc.getTarget().getNumberOfParameters() + ) and + // exclude cases where the type was made bigger by a literal + // (compared to other cases such as assignment, this is more + // likely to be a trivial accident rather than suggesting a + // larger type is needed for the result). + not exists(Expr other, Expr e | + other = me.getParent().(BinaryOperation).getAnOperand() and + not other = me and + ( + e = other or + e = other.(BinaryOperation).getAnOperand*() + ) and + e.(Literal).getType().getSize() = t2.getSize() + ) +select me, + "Multiplication result may overflow '" + me.getType().toString() + "' before it is converted to '" + + me.getFullyConverted().getType().toString() + "'." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql index 41a1757bb2a..94a6c403937 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql @@ -11,6 +11,7 @@ * @tags maintainability * readability */ + import cpp private import semmle.code.cpp.commons.Exclusions private import semmle.code.cpp.rangeanalysis.PointlessComparison @@ -25,38 +26,40 @@ import UnsignedGEZero // So to reduce the number of false positives, we do not report a result if // the comparison is in a macro expansion. Similarly for template // instantiations. -from - ComparisonOperation cmp, SmallSide ss, - float left, float right, boolean value, - string reason +from ComparisonOperation cmp, SmallSide ss, float left, float right, boolean value, string reason where not cmp.isInMacroExpansion() and not cmp.isFromTemplateInstantiation(_) and not functionContainsDisabledCode(cmp.getEnclosingFunction()) and reachablePointlessComparison(cmp, left, right, value, ss) and - // a comparison between an enum and zero is always valid because whether // the underlying type of an enum is signed is compiler-dependent - not exists (Expr e, ConstantZero z - | relOpWithSwap(cmp, e.getFullyConverted(), z, _, _) and - e.getUnderlyingType() instanceof Enum) and - + not exists(Expr e, ConstantZero z | + relOpWithSwap(cmp, e.getFullyConverted(), z, _, _) and + e.getUnderlyingType() instanceof Enum + ) and // Construct a reason for the message. Something like: x >= 5 and 3 >= y. - exists (string cmpOp, string leftReason, string rightReason - | ((ss = LeftIsSmaller() and cmpOp = " <= ") or - (ss = RightIsSmaller() and cmpOp = " >= ")) and + exists(string cmpOp, string leftReason, string rightReason | + ( + ss = LeftIsSmaller() and cmpOp = " <= " + or + ss = RightIsSmaller() and cmpOp = " >= " + ) and leftReason = cmp.getLeftOperand().toString() + cmpOp + left.toString() and rightReason = right.toString() + cmpOp + cmp.getRightOperand().toString() and // If either of the operands is constant, then don't include it. - (if cmp.getLeftOperand().isConstant() - then if cmp.getRightOperand().isConstant() - then none() // Both operands are constant so don't create a message. - else reason = rightReason - else if cmp.getRightOperand().isConstant() - then reason = leftReason - else reason = leftReason + " and " + rightReason)) and - + ( + if cmp.getLeftOperand().isConstant() + then + if cmp.getRightOperand().isConstant() + then none() // Both operands are constant so don't create a message. + else reason = rightReason + else + if cmp.getRightOperand().isConstant() + then reason = leftReason + else reason = leftReason + " and " + rightReason + ) + ) and // Don't report results which have already been reported by UnsignedGEZero. not unsignedGEZero(cmp, _) -select - cmp, "Comparison is always " + value.toString() + " because " + reason + "." +select cmp, "Comparison is always " + value.toString() + " because " + reason + "." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql index c25a7b7550e..afe49a1053b 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql @@ -15,15 +15,15 @@ import cpp import PointlessSelfComparison from ComparisonOperation cmp -where pointlessSelfComparison(cmp) - and not nanTest(cmp) - and not overflowTest(cmp) - and not exists(MacroInvocation mi | - // cmp is in mi - mi.getAnExpandedElement() = cmp and - - // and cmp was apparently not passed in as a macro parameter - cmp.getLocation().getStartLine() = mi.getLocation().getStartLine() and - cmp.getLocation().getStartColumn() = mi.getLocation().getStartColumn() - ) +where + pointlessSelfComparison(cmp) and + not nanTest(cmp) and + not overflowTest(cmp) and + not exists(MacroInvocation mi | + // cmp is in mi + mi.getAnExpandedElement() = cmp and + // and cmp was apparently not passed in as a macro parameter + cmp.getLocation().getStartLine() = mi.getLocation().getStartLine() and + cmp.getLocation().getStartColumn() = mi.getLocation().getStartColumn() + ) select cmp, "Self comparison." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.qll b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.qll index caf0ea61d7f..0504aad0642 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.qll +++ b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.qll @@ -21,15 +21,16 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis * `<=`, `>=`). */ predicate pointlessSelfComparison(ComparisonOperation cmp) { - exists (Variable v, VariableAccess lhs, VariableAccess rhs - | lhs = cmp.getLeftOperand() and + exists(Variable v, VariableAccess lhs, VariableAccess rhs | + lhs = cmp.getLeftOperand() and rhs = cmp.getRightOperand() and lhs = v.getAnAccess() and rhs = v.getAnAccess() and - not exists (lhs.getQualifier()) and // Avoid structure fields - not exists (rhs.getQualifier()) and // Avoid structure fields + not exists(lhs.getQualifier()) and // Avoid structure fields + not exists(rhs.getQualifier()) and // Avoid structure fields not convertedExprMightOverflow(lhs) and - not convertedExprMightOverflow(rhs)) + not convertedExprMightOverflow(rhs) + ) } /** @@ -44,10 +45,10 @@ predicate pointlessSelfComparison(ComparisonOperation cmp) { */ predicate nanTest(EqualityOperation cmp) { pointlessSelfComparison(cmp) and - exists (Type t - | t = cmp.getLeftOperand().getUnspecifiedType() - | t instanceof FloatingPointType or - t instanceof TemplateParameter) + exists(Type t | t = cmp.getLeftOperand().getUnspecifiedType() | + t instanceof FloatingPointType or + t instanceof TemplateParameter + ) } /** diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.ql b/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.ql index 21f188d8f43..7f89569c3ba 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.ql @@ -10,6 +10,7 @@ * @tags maintainability * readability */ + import cpp import UnsignedGEZero diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.qll b/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.qll index 8ee3e9f6fc2..4ca68fb27c4 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.qll +++ b/cpp/ql/src/Likely Bugs/Arithmetic/UnsignedGEZero.qll @@ -18,20 +18,16 @@ class ConstantZero extends Expr { class UnsignedGEZero extends GEExpr { UnsignedGEZero() { this.getRightOperand() instanceof ConstantZero and - // left operand was a signed or unsigned IntegralType before conversions // (not a pointer, checking a pointer >= 0 is an entirely different mistake) // (not an enum, as the fully converted type of an enum is compiler dependent // so checking an enum >= 0 is always reasonable) getLeftOperand().getUnderlyingType() instanceof IntegralType and - exists(Expr ue | // ue is some conversion of the left operand ue = getLeftOperand().getConversion*() and - // ue is unsigned ue.getUnderlyingType().(IntegralType).isUnsigned() and - // ue may be converted to zero or more strictly larger possibly signed types // before it is fully converted forall(Expr following | following = ue.getConversion+() | @@ -45,7 +41,6 @@ predicate unsignedGEZero(UnsignedGEZero ugez, string msg) { not exists(MacroInvocation mi | // ugez is in mi mi.getAnExpandedElement() = ugez and - // and ugez was apparently not passed in as a macro parameter ugez.getLocation().getStartLine() = mi.getLocation().getStartLine() and ugez.getLocation().getStartColumn() = mi.getLocation().getStartColumn() diff --git a/cpp/ql/src/Likely Bugs/ContinueInFalseLoop.ql b/cpp/ql/src/Likely Bugs/ContinueInFalseLoop.ql index 23249564a38..293595d60d8 100644 --- a/cpp/ql/src/Likely Bugs/ContinueInFalseLoop.ql +++ b/cpp/ql/src/Likely Bugs/ContinueInFalseLoop.ql @@ -16,8 +16,8 @@ import cpp * Gets a `do` ... `while` loop with a constant false condition. */ DoStmt getAFalseLoop() { - result.getControllingExpr().getValue() = "0" - and not result.getControllingExpr().isAffectedByMacro() + result.getControllingExpr().getValue() = "0" and + not result.getControllingExpr().isAffectedByMacro() } /** @@ -30,22 +30,19 @@ DoStmt enclosingLoop(Stmt s) { exists(Stmt parent | parent = s.getParent() and ( - ( - parent instanceof Loop and - result = parent - ) or ( - not parent instanceof Loop and - not parent instanceof SwitchStmt and - result = enclosingLoop(parent) - ) + parent instanceof Loop and + result = parent + or + not parent instanceof Loop and + not parent instanceof SwitchStmt and + result = enclosingLoop(parent) ) ) } from DoStmt loop, ContinueStmt continue -where loop = getAFalseLoop() - and loop = enclosingLoop(continue) -select continue, - "This 'continue' never re-runs the loop - the $@ is always false.", - loop.getControllingExpr(), - "loop condition" +where + loop = getAFalseLoop() and + loop = enclosingLoop(continue) +select continue, "This 'continue' never re-runs the loop - the $@ is always false.", + loop.getControllingExpr(), "loop condition" diff --git a/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.ql b/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.ql index af258c03b9f..924b5d87f90 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.ql @@ -8,20 +8,21 @@ * @precision high * @tags reliability */ + import cpp import semmle.code.cpp.commons.Buffer from Function f, FunctionCall c, int i, ArrayType argType, ArrayType paramType, int a, int b -where f = c.getTarget() and - argType = c.getArgument(i).getType() and - paramType = f.getParameter(i).getType() and - a = argType.getArraySize() and - b = paramType.getArraySize() and - argType.getBaseType().getSize() = paramType.getBaseType().getSize() and - a < b and - not memberMayBeVarSize(_, c.getArgument(i).(VariableAccess).getTarget()) and - // filter out results for inconsistent declarations - strictcount(f.getParameter(i).getType().getSize()) = 1 -select c.getArgument(i), "Array of size " + a + - " passed to $@ which expects an array of size " + b + ".", - f, f.getName() +where + f = c.getTarget() and + argType = c.getArgument(i).getType() and + paramType = f.getParameter(i).getType() and + a = argType.getArraySize() and + b = paramType.getArraySize() and + argType.getBaseType().getSize() = paramType.getBaseType().getSize() and + a < b and + not memberMayBeVarSize(_, c.getArgument(i).(VariableAccess).getTarget()) and + // filter out results for inconsistent declarations + strictcount(f.getParameter(i).getType().getSize()) = 1 +select c.getArgument(i), + "Array of size " + a + " passed to $@ which expects an array of size " + b + ".", f, f.getName() diff --git a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql index 93ac580a613..3a0ddb612be 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql @@ -20,26 +20,17 @@ import semmle.code.cpp.dataflow.DataFlow import DataFlow::PathGraph class CastToPointerArithFlow extends DataFlow::Configuration { - CastToPointerArithFlow() { - this = "CastToPointerArithFlow" - } + CastToPointerArithFlow() { this = "CastToPointerArithFlow" } override predicate isSource(DataFlow::Node node) { not node.asExpr() instanceof Conversion and - introducesNewField( - node.asExpr().getType().(DerivedType).getBaseType(), - node.asExpr().getConversion*().getType().(DerivedType).getBaseType() - - ) + introducesNewField(node.asExpr().getType().(DerivedType).getBaseType(), + node.asExpr().getConversion*().getType().(DerivedType).getBaseType()) } override predicate isSink(DataFlow::Node node) { - exists(PointerAddExpr pae | - pae.getAnOperand() = node.asExpr() - ) or - exists(ArrayExpr ae | - ae.getArrayBase() = node.asExpr() - ) + exists(PointerAddExpr pae | pae.getAnOperand() = node.asExpr()) or + exists(ArrayExpr ae | ae.getArrayBase() = node.asExpr()) } } @@ -52,12 +43,19 @@ predicate introducesNewField(Class derived, Class base) { exists(Field f | f.getDeclaringType() = derived and derived.getABaseClass+() = base - ) or + ) + or introducesNewField(derived.getABaseClass(), base) ) } from DataFlow::PathNode source, DataFlow::PathNode sink, CastToPointerArithFlow cfg -where cfg.hasFlowPath(source, sink) - and source.getNode().asExpr().getFullyConverted().getUnspecifiedType() = sink.getNode().asExpr().getFullyConverted().getUnspecifiedType() -select sink, source, sink, "Pointer arithmetic here may be done with the wrong type because of the cast $@.", source, "here" +where + cfg.hasFlowPath(source, sink) and + source.getNode().asExpr().getFullyConverted().getUnspecifiedType() = sink + .getNode() + .asExpr() + .getFullyConverted() + .getUnspecifiedType() +select sink, source, sink, + "Pointer arithmetic here may be done with the wrong type because of the cast $@.", source, "here" diff --git a/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.ql b/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.ql index 44fee5fb133..c89c71fb50b 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.ql @@ -6,18 +6,25 @@ * @problem.severity warning * @tags reliability */ + import cpp from Expr e1, Cast e2, IntegralType it1, IntegralType it2 -where e2 = e1.getConversion() and - e2.isImplicit() and - it1 = e1.getUnderlyingType() and - it2 = e2.getUnderlyingType() and - ( - it1.isUnsigned() and it2.isSigned() and it1.getSize() >= it2.getSize() - or it1.isSigned() and it2.isUnsigned() - ) and - not (e1.isConstant() and 0 <= e1.getValue().toInt() and - e1.getValue().toInt() <= ((it2.getSize()*8-1)*(2.log())).exp()) - and not e1.isConstant() -select e1, "Conversion between signed and unsigned types "+it1.toString()+" and "+it2.toString()+"." +where + e2 = e1.getConversion() and + e2.isImplicit() and + it1 = e1.getUnderlyingType() and + it2 = e2.getUnderlyingType() and + ( + it1.isUnsigned() and it2.isSigned() and it1.getSize() >= it2.getSize() + or + it1.isSigned() and it2.isUnsigned() + ) and + not ( + e1.isConstant() and + 0 <= e1.getValue().toInt() and + e1.getValue().toInt() <= ((it2.getSize() * 8 - 1) * 2.log()).exp() + ) and + not e1.isConstant() +select e1, + "Conversion between signed and unsigned types " + it1.toString() + " and " + it2.toString() + "." diff --git a/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql b/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql index 6670a135b98..8ad98ed8d88 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/ImplicitDowncastFromBitfield.ql @@ -14,10 +14,9 @@ import cpp from BitField fi, VariableAccess va - -where fi.getNumBits() > va.getFullyConverted().getType().getSize() * 8 - and va.getExplicitlyConverted().getType().getSize() > va.getFullyConverted().getType().getSize() - and va.getTarget() = fi - and not va.getActualType() instanceof BoolType - +where + fi.getNumBits() > va.getFullyConverted().getType().getSize() * 8 and + va.getExplicitlyConverted().getType().getSize() > va.getFullyConverted().getType().getSize() and + va.getTarget() = fi and + not va.getActualType() instanceof BoolType select va, "Implicit downcast of bitfield $@", fi, fi.toString() diff --git a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql index 0b844bdcbf5..27f2000692c 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql @@ -44,15 +44,18 @@ predicate whitelistPow(FunctionCall fc) { fc.getTarget().getName() = "pow" or fc.getTarget().getName() = "powf" or fc.getTarget().getName() = "powl" - ) and exists(float value | + ) and + exists(float value | value = fc.getArgument(0).getValue().toFloat() and (value.floor() - value).abs() < 0.001 ) } predicate whiteListWrapped(FunctionCall fc) { - whitelist(fc.getTarget()) or - whitelistPow(fc) or + whitelist(fc.getTarget()) + or + whitelistPow(fc) + or exists(Expr e, ReturnStmt rs | whiteListWrapped(e) and DataFlow::localExprFlow(e, rs.getExpr()) and @@ -61,8 +64,11 @@ predicate whiteListWrapped(FunctionCall fc) { } from FunctionCall c, FloatingPointType t1, IntegralType t2 -where t1 = c.getTarget().getType().getUnderlyingType() and - t2 = c.getActualType() and - c.hasImplicitConversion() and - not whiteListWrapped(c) -select c, "Return value of type " + t1.toString() + " is implicitly converted to " + t2.toString() + " here." +where + t1 = c.getTarget().getType().getUnderlyingType() and + t2 = c.getActualType() and + c.hasImplicitConversion() and + not whiteListWrapped(c) +select c, + "Return value of type " + t1.toString() + " is implicitly converted to " + t2.toString() + + " here." diff --git a/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.ql b/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.ql index 67f27bac6bd..ce130c6f199 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.ql @@ -11,6 +11,7 @@ * correctness * types */ + import cpp predicate lossyPointerCast(Expr e, PointerType pt, IntegralType it) { @@ -25,4 +26,4 @@ predicate lossyPointerCast(Expr e, PointerType pt, IntegralType it) { from Expr e, PointerType pt, IntegralType it where lossyPointerCast(e, pt, it) -select e, "Converted from " + pt.getName() + " to smaller type "+it.getName() +select e, "Converted from " + pt.getName() + " to smaller type " + it.getName() diff --git a/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql b/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql index ba6c2587728..87f52198b0d 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/NonzeroValueCastToPointer.ql @@ -9,22 +9,26 @@ * correctness * types */ + import cpp predicate commonErrorCode(string value) { - value = "0" or value = "1" or value = "-1" - or value = "18446744073709551615" // 2^64-1, i.e. -1 as an unsigned int64 - or value = "4294967295" // 2^32-1, i.e. -1 as an unsigned int32 - or value = "3735928559" // 0xdeadbeef - or value = "3735929054" // 0xdeadc0de - or value = "3405691582" // 0xcafebabe + value = "0" or + value = "1" or + value = "-1" or + value = "18446744073709551615" or // 2^64-1, i.e. -1 as an unsigned int64 + value = "4294967295" or // 2^32-1, i.e. -1 as an unsigned int32 + value = "3735928559" or // 0xdeadbeef + value = "3735929054" or // 0xdeadc0de + value = "3405691582" // 0xcafebabe } from Expr e -where e.isConstant() and - not commonErrorCode(e.getValue()) and - e.getFullyConverted().getType() instanceof PointerType and - not e.getType() instanceof ArrayType and - not e.getType() instanceof PointerType and - not e.isInMacroExpansion() +where + e.isConstant() and + not commonErrorCode(e.getValue()) and + e.getFullyConverted().getType() instanceof PointerType and + not e.getType() instanceof ArrayType and + not e.getType() instanceof PointerType and + not e.isInMacroExpansion() select e, "Nonzero value " + e.getValueText() + " cast to pointer." diff --git a/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql b/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql index c5e933fc200..6a0098df131 100644 --- a/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql +++ b/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql @@ -33,11 +33,9 @@ predicate flowsToExpr(Expr source, Expr sink, boolean pathMightOverflow) { * checking whether the current expression might overflow. */ predicate flowsToExprImpl(Expr source, Expr sink, boolean pathMightOverflow) { - ( - source = sink and - pathMightOverflow = false and - source.(FunctionCall).getTarget().(Snprintf).returnsFullFormatLength() - ) + source = sink and + pathMightOverflow = false and + source.(FunctionCall).getTarget().(Snprintf).returnsFullFormatLength() or exists(RangeSsaDefinition def, LocalScopeVariable v | flowsToDef(source, def, v, pathMightOverflow) and diff --git a/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.ql index 4c06b13630b..f9aa87c684a 100644 --- a/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.ql @@ -10,12 +10,14 @@ * @tags reliability * correctness */ + import cpp from FormatLiteral fl, FormattingFunctionCall ffc, int expected, int given -where ffc = fl.getUse() - and expected = fl.getNumArgNeeded() - and given = ffc.getNumFormatArgument() - and expected < given - and fl.specsAreKnown() -select ffc, "Format expects "+expected.toString()+" arguments but given "+given.toString() +where + ffc = fl.getUse() and + expected = fl.getNumArgNeeded() and + given = ffc.getNumFormatArgument() and + expected < given and + fl.specsAreKnown() +select ffc, "Format expects " + expected.toString() + " arguments but given " + given.toString() diff --git a/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql index 9e1ed30332a..0f112e1ca6f 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql @@ -11,12 +11,14 @@ * security * external/cwe/cwe-685 */ + import cpp from FormatLiteral fl, FormattingFunctionCall ffc, int expected, int given -where ffc = fl.getUse() - and expected = fl.getNumArgNeeded() - and given = ffc.getNumFormatArgument() - and expected > given - and fl.specsAreKnown() -select ffc, "Format expects "+expected.toString()+" arguments but given "+given.toString() +where + ffc = fl.getUse() and + expected = fl.getNumArgNeeded() and + given = ffc.getNumFormatArgument() and + expected > given and + fl.specsAreKnown() +select ffc, "Format expects " + expected.toString() + " arguments but given " + given.toString() diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql index 2172b3dc3e5..75c5bc73029 100644 --- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql +++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql @@ -16,17 +16,19 @@ import cpp /** * Holds if the argument corresponding to the `pos` conversion specifier - * of `ffc` is expected to have type `expected`. + * of `ffc` is expected to have type `expected`. */ pragma[noopt] -private predicate formattingFunctionCallExpectedType(FormattingFunctionCall ffc, int pos, Type expected) { - exists(FormattingFunction f, int i, FormatLiteral fl | - ffc instanceof FormattingFunctionCall and - ffc.getTarget() = f and - f.getFormatParameterIndex() = i and - ffc.getArgument(i) = fl and - fl.getConversionType(pos) = expected - ) +private predicate formattingFunctionCallExpectedType( + FormattingFunctionCall ffc, int pos, Type expected +) { + exists(FormattingFunction f, int i, FormatLiteral fl | + ffc instanceof FormattingFunctionCall and + ffc.getTarget() = f and + f.getFormatParameterIndex() = i and + ffc.getArgument(i) = fl and + fl.getConversionType(pos) = expected + ) } /** @@ -50,7 +52,9 @@ predicate formatArgType(FormattingFunctionCall ffc, int pos, Type expected, Expr * `expected` and the corresponding argument `arg` has type `actual`. */ pragma[noopt] -predicate formatOtherArgType(FormattingFunctionCall ffc, int pos, Type expected, Expr arg, Type actual) { +predicate formatOtherArgType( + FormattingFunctionCall ffc, int pos, Type expected, Expr arg, Type actual +) { exists(Expr argConverted | (arg = ffc.getMinFieldWidthArgument(pos) or arg = ffc.getPrecisionArgument(pos)) and argConverted = arg.getFullyConverted() and @@ -63,14 +67,14 @@ predicate formatOtherArgType(FormattingFunctionCall ffc, int pos, Type expected, * A type that may be expected by a printf format parameter, or that may * be pointed to by such a type (e.g. `wchar_t`, from `wchar_t *`). */ -class ExpectedType extends Type -{ +class ExpectedType extends Type { ExpectedType() { - exists(Type t | + exists(Type t | ( formatArgType(_, _, t, _, _) or formatOtherArgType(_, _, t, _, _) - ) and this = t.getUnspecifiedType() + ) and + this = t.getUnspecifiedType() ) } } @@ -78,7 +82,7 @@ class ExpectedType extends Type /** * Holds if it is safe to display a value of type `actual` when `printf` * expects a value of type `expected`. - * + * * Note that variadic arguments undergo default argument promotions before * they reach `printf`, notably `bool`, `char`, `short` and `enum` types * are promoted to `int` (or `unsigned int`, as appropriate) and `float`s @@ -89,69 +93,71 @@ predicate trivialConversion(ExpectedType expected, Type actual) { formatArgType(_, _, exp, _, act) and expected = exp.getUnspecifiedType() and actual = act.getUnspecifiedType() - ) and ( - ( - // allow a pointer type to be displayed with `%p` - expected instanceof VoidPointerType and actual instanceof PointerType - ) or ( - // allow a function pointer type to be displayed with `%p` - expected instanceof VoidPointerType and actual instanceof FunctionPointerType and expected.getSize() = actual.getSize() - ) or ( - // allow an `enum` type to be displayed with `%i`, `%c` etc - expected instanceof IntegralType and actual instanceof Enum - ) or ( - // allow any `char *` type to be displayed with `%s` - expected instanceof CharPointerType and actual instanceof CharPointerType - ) or ( - // allow `wchar_t *`, or any pointer to an integral type of the same size, to be displayed - // with `%ws` - expected.(PointerType).getBaseType().hasName("wchar_t") and - exists(Wchar_t t | - actual.getUnspecifiedType().(PointerType).getBaseType().(IntegralType).getSize() = t.getSize() - ) - ) or ( - // allow an `int` (or anything promoted to `int`) to be displayed with `%c` - expected instanceof CharType and actual instanceof IntType - ) or ( - // allow an `int` (or anything promoted to `int`) to be displayed with `%wc` - expected instanceof Wchar_t and actual instanceof IntType - ) or ( - expected instanceof UnsignedCharType and actual instanceof IntType - ) or ( - // allow any integral type of the same size - // (this permits signedness changes) - expected.(IntegralType).getSize() = actual.(IntegralType).getSize() - ) or ( - // allow a pointer to any integral type of the same size - // (this permits signedness changes) - expected.(PointerType).getBaseType().(IntegralType).getSize() = actual.(PointerType).getBaseType().(IntegralType).getSize() - ) or ( - expected = actual + ) and + ( + // allow a pointer type to be displayed with `%p` + expected instanceof VoidPointerType and actual instanceof PointerType + or + // allow a function pointer type to be displayed with `%p` + expected instanceof VoidPointerType and + actual instanceof FunctionPointerType and + expected.getSize() = actual.getSize() + or + // allow an `enum` type to be displayed with `%i`, `%c` etc + expected instanceof IntegralType and actual instanceof Enum + or + // allow any `char *` type to be displayed with `%s` + expected instanceof CharPointerType and actual instanceof CharPointerType + or + // allow `wchar_t *`, or any pointer to an integral type of the same size, to be displayed + // with `%ws` + expected.(PointerType).getBaseType().hasName("wchar_t") and + exists(Wchar_t t | + actual.getUnspecifiedType().(PointerType).getBaseType().(IntegralType).getSize() = t.getSize() ) + or + // allow an `int` (or anything promoted to `int`) to be displayed with `%c` + expected instanceof CharType and actual instanceof IntType + or + // allow an `int` (or anything promoted to `int`) to be displayed with `%wc` + expected instanceof Wchar_t and actual instanceof IntType + or + expected instanceof UnsignedCharType and actual instanceof IntType + or + // allow any integral type of the same size + // (this permits signedness changes) + expected.(IntegralType).getSize() = actual.(IntegralType).getSize() + or + // allow a pointer to any integral type of the same size + // (this permits signedness changes) + expected.(PointerType).getBaseType().(IntegralType).getSize() = actual + .(PointerType) + .getBaseType() + .(IntegralType) + .getSize() + or + expected = actual ) } /** * Gets the size of the `int` type. */ -int sizeof_IntType() { - exists(IntType it | result = it.getSize()) -} +int sizeof_IntType() { exists(IntType it | result = it.getSize()) } from FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual -where ( - ( - formatArgType(ffc, n, expected, arg, actual) and - not exists(Type anyExpected | - formatArgType(ffc, n, anyExpected, arg, actual) and - trivialConversion(anyExpected.getUnspecifiedType(), actual.getUnspecifiedType()) - ) - ) - or - ( - formatOtherArgType(ffc, n, expected, arg, actual) and - not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType() - ) - ) - and not arg.isAffectedByMacro() -select arg, "This argument should be of type '"+expected.getName()+"' but is of type '"+actual.getUnspecifiedType().getName() + "'" +where + ( + formatArgType(ffc, n, expected, arg, actual) and + not exists(Type anyExpected | + formatArgType(ffc, n, anyExpected, arg, actual) and + trivialConversion(anyExpected.getUnspecifiedType(), actual.getUnspecifiedType()) + ) + or + formatOtherArgType(ffc, n, expected, arg, actual) and + not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType() + ) and + not arg.isAffectedByMacro() +select arg, + "This argument should be of type '" + expected.getName() + "' but is of type '" + + actual.getUnspecifiedType().getName() + "'" diff --git a/cpp/ql/src/Likely Bugs/InconsistentCallOnResult.ql b/cpp/ql/src/Likely Bugs/InconsistentCallOnResult.ql index 26da76a31dd..719a4cf48fa 100644 --- a/cpp/ql/src/Likely Bugs/InconsistentCallOnResult.ql +++ b/cpp/ql/src/Likely Bugs/InconsistentCallOnResult.ql @@ -11,6 +11,7 @@ * non-attributable * external/cwe/cwe-252 */ + import cpp predicate exclude(Function f) { @@ -39,7 +40,7 @@ predicate checkExpr(Expr e, string operation, Variable v) { predicate checkedFunctionCall(FunctionCall fc, string operation) { relevantFunctionCall(fc, _) and - exists (Variable v, Expr check | v.getAnAssignedValue() = fc | + exists(Variable v, Expr check | v.getAnAssignedValue() = fc | checkExpr(check, operation, v) and check != fc ) @@ -47,13 +48,11 @@ predicate checkedFunctionCall(FunctionCall fc, string operation) { predicate relevantFunctionCall(FunctionCall fc, Function f) { fc.getTarget() = f and - exists (Variable v | v.getAnAssignedValue() = fc) and + exists(Variable v | v.getAnAssignedValue() = fc) and not okToIgnore(fc) } -predicate okToIgnore(FunctionCall fc) { - fc.isInMacroExpansion() -} +predicate okToIgnore(FunctionCall fc) { fc.isInMacroExpansion() } predicate functionStats(Function f, string operation, int used, int total, int percentage) { exists(PointerType pt | pt.getATypeNameUse() = f.getADeclarationEntry()) and @@ -67,7 +66,9 @@ where relevantFunctionCall(unchecked, f) and not checkedFunctionCall(unchecked, operation) and functionStats(f, operation, _, _, percent) and - percent >= 70 - and unchecked.getFile().getAbsolutePath().matches("%fbcode%") - and not unchecked.getFile().getAbsolutePath().matches("%\\_build%") -select unchecked, "After " + percent.toString() + "% of calls to " + f.getName() + " there is a call to " + operation + " on the return value. The call may be missing in this case." + percent >= 70 and + unchecked.getFile().getAbsolutePath().matches("%fbcode%") and + not unchecked.getFile().getAbsolutePath().matches("%\\_build%") +select unchecked, + "After " + percent.toString() + "% of calls to " + f.getName() + " there is a call to " + + operation + " on the return value. The call may be missing in this case." diff --git a/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.ql b/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.ql index 71e38099c6b..f0bc9b09b38 100644 --- a/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.ql +++ b/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.ql @@ -14,11 +14,10 @@ * non-attributable * external/cwe/cwe-476 */ + import cpp -predicate assertMacro(Macro m) { - m.getHead().toLowerCase().matches("%assert%") -} +predicate assertMacro(Macro m) { m.getHead().toLowerCase().matches("%assert%") } predicate assertInvocation(File f, int line) { exists(MacroInvocation i, Location l | assertMacro(i.getMacro()) and l = i.getLocation() | @@ -28,61 +27,92 @@ predicate assertInvocation(File f, int line) { predicate nullCheckAssert(Expr e, Variable v, Declaration qualifier) { nullCheckInCondition(e, v, qualifier) and - exists(File f, int i | e.getLocation().getStartLine() = i and e.getFile() = f and assertInvocation(f, i)) + exists(File f, int i | + e.getLocation().getStartLine() = i and e.getFile() = f and assertInvocation(f, i) + ) } VariableAccess qualifiedAccess(Variable v, Declaration qualifier) { result = v.getAnAccess() and ( - result.getQualifier().(VariableAccess).getTarget() = qualifier - or exists(PointerDereferenceExpr e, VariableAccess va - | result.getQualifier() = e - | e.getOperand() = va and va.getTarget() = qualifier) - or (not exists(result.getQualifier()) and qualifier = result.getEnclosingFunction()) - or (result.getQualifier() instanceof ThisExpr and qualifier = result.getEnclosingFunction()) + result.getQualifier().(VariableAccess).getTarget() = qualifier + or + exists(PointerDereferenceExpr e, VariableAccess va | result.getQualifier() = e | + e.getOperand() = va and va.getTarget() = qualifier + ) + or + not exists(result.getQualifier()) and qualifier = result.getEnclosingFunction() + or + result.getQualifier() instanceof ThisExpr and qualifier = result.getEnclosingFunction() ) } predicate nullCheckInCondition(Expr e, Variable v, Declaration qualifier) { - // if(v) - exists(FunctionCall fc | relevantFunctionCall(fc, _) and fc = assignedValueForVariableAndQualifier(v, qualifier) | - e = qualifiedAccess(v, qualifier) - ) - or exists(AssignExpr a | a = e and a.getLValue() = qualifiedAccess(v, qualifier)) - // if(v == NULL), if(v != NULL), if(NULL != v), if(NULL == v) - or exists(EqualityOperation eq | eq = e and nullCheckInCondition(eq.getAnOperand(), v, qualifier) and - eq.getAnOperand().getValue() = "0") - // if(v && something) - or exists(LogicalAndExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier)) - // if(v || something) - or exists(LogicalOrExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier)) - // if(!v) - or exists(NotExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier)) - or exists(FunctionCall c | c = e and nullCheckInCondition(c.getAnArgument(), v, qualifier) and - c.getTarget().getName() = "__builtin_expect") - or exists(ConditionDeclExpr d | d = e and nullCheckInCondition(d.getVariableAccess(), v, qualifier)) + // if(v) + exists(FunctionCall fc | + relevantFunctionCall(fc, _) and fc = assignedValueForVariableAndQualifier(v, qualifier) + | + e = qualifiedAccess(v, qualifier) + ) + or + exists(AssignExpr a | a = e and a.getLValue() = qualifiedAccess(v, qualifier)) + or + // if(v == NULL), if(v != NULL), if(NULL != v), if(NULL == v) + exists(EqualityOperation eq | + eq = e and + nullCheckInCondition(eq.getAnOperand(), v, qualifier) and + eq.getAnOperand().getValue() = "0" + ) + or + // if(v && something) + exists(LogicalAndExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier)) + or + // if(v || something) + exists(LogicalOrExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier)) + or + // if(!v) + exists(NotExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier)) + or + exists(FunctionCall c | + c = e and + nullCheckInCondition(c.getAnArgument(), v, qualifier) and + c.getTarget().getName() = "__builtin_expect" + ) + or + exists(ConditionDeclExpr d | d = e and nullCheckInCondition(d.getVariableAccess(), v, qualifier)) } predicate hasNullCheck(Function enclosing, Variable v, Declaration qualifier) { - exists(Expr exp | nullCheckInCondition(exp, v, qualifier) and exp.getEnclosingFunction() = enclosing | - exists(ControlStructure s | exp = s.getControllingExpr()) - or exists(ConditionalExpr e | exp = e.getCondition()) - or exists(ReturnStmt s | exp = s.getExpr() and not exp instanceof VariableAccess) - or exists(AssignExpr e | exp = e.getRValue() and not exp instanceof VariableAccess) - or exists(AggregateLiteral al | exp = al.getAChild() and not exp instanceof VariableAccess) - or exists(Variable other | exp = other.getInitializer().getExpr() and not exp instanceof VariableAccess) + exists(Expr exp | + nullCheckInCondition(exp, v, qualifier) and exp.getEnclosingFunction() = enclosing + | + exists(ControlStructure s | exp = s.getControllingExpr()) + or + exists(ConditionalExpr e | exp = e.getCondition()) + or + exists(ReturnStmt s | exp = s.getExpr() and not exp instanceof VariableAccess) + or + exists(AssignExpr e | exp = e.getRValue() and not exp instanceof VariableAccess) + or + exists(AggregateLiteral al | exp = al.getAChild() and not exp instanceof VariableAccess) + or + exists(Variable other | + exp = other.getInitializer().getExpr() and not exp instanceof VariableAccess + ) ) } Expr assignedValueForVariableAndQualifier(Variable v, Declaration qualifier) { - (result = v.getInitializer().getExpr() and qualifier = result.getEnclosingFunction()) - or exists(AssignExpr e | e.getLValue() = qualifiedAccess(v, qualifier) and result = e.getRValue()) + result = v.getInitializer().getExpr() and qualifier = result.getEnclosingFunction() + or + exists(AssignExpr e | e.getLValue() = qualifiedAccess(v, qualifier) and result = e.getRValue()) } - predicate checkedFunctionCall(FunctionCall fc) { relevantFunctionCall(fc, _) and - exists (Variable v, Declaration qualifier | fc = assignedValueForVariableAndQualifier(v, qualifier) | + exists(Variable v, Declaration qualifier | + fc = assignedValueForVariableAndQualifier(v, qualifier) + | hasNullCheck(fc.getEnclosingFunction(), v, qualifier) ) } @@ -91,27 +121,33 @@ predicate uncheckedFunctionCall(FunctionCall fc) { relevantFunctionCall(fc, _) and not checkedFunctionCall(fc) and not exists(File f, int line | f = fc.getFile() and line = fc.getLocation().getEndLine() | - assertInvocation(f, line+1) or assertInvocation(f, line) + assertInvocation(f, line + 1) or assertInvocation(f, line) ) and - not exists(Variable v, Declaration qualifier - | fc = assignedValueForVariableAndQualifier(v, qualifier) - | nullCheckAssert(_, v, qualifier)) and - not exists(ControlStructure s - | callResultNullCheckInCondition(s.getControllingExpr(), fc)) and - not exists(FunctionCall other, Variable v, Declaration qualifier, Expr arg - | fc = assignedValueForVariableAndQualifier(v, qualifier) - | arg = other.getAnArgument() and - nullCheckInCondition(arg, v, qualifier) and - not arg instanceof VariableAccess) + not exists(Variable v, Declaration qualifier | + fc = assignedValueForVariableAndQualifier(v, qualifier) + | + nullCheckAssert(_, v, qualifier) + ) and + not exists(ControlStructure s | callResultNullCheckInCondition(s.getControllingExpr(), fc)) and + not exists(FunctionCall other, Variable v, Declaration qualifier, Expr arg | + fc = assignedValueForVariableAndQualifier(v, qualifier) + | + arg = other.getAnArgument() and + nullCheckInCondition(arg, v, qualifier) and + not arg instanceof VariableAccess + ) } - Declaration functionQualifier(FunctionCall fc) { - fc.getQualifier().(VariableAccess).getTarget() = result - or exists(PointerDereferenceExpr e, VariableAccess va - | fc.getQualifier() = e and e.getOperand() = va and va.getTarget() = result) - or (not exists(fc.getQualifier()) and result = fc.getEnclosingFunction()) - or (fc.getQualifier() instanceof ThisExpr and result = fc.getEnclosingFunction()) + fc.getQualifier().(VariableAccess).getTarget() = result + or + exists(PointerDereferenceExpr e, VariableAccess va | + fc.getQualifier() = e and e.getOperand() = va and va.getTarget() = result + ) + or + not exists(fc.getQualifier()) and result = fc.getEnclosingFunction() + or + fc.getQualifier() instanceof ThisExpr and result = fc.getEnclosingFunction() } predicate callTargetAndEnclosing(FunctionCall fc, Function target, Function enclosing) { @@ -123,28 +159,38 @@ predicate callArgumentVariable(FunctionCall fc, Variable v, int i) { } predicate callResultNullCheckInCondition(Expr e, FunctionCall fc) { - // if(v) - exists(FunctionCall other | e = other and - relevantFunctionCall(fc,_) and not checkedFunctionCall(fc) - and exists(Function called, Function enclosing | - callTargetAndEnclosing(fc, called, enclosing) and - callTargetAndEnclosing(other, called, enclosing)) and - forall(Variable v, int i | callArgumentVariable(fc, v, i) | callArgumentVariable(other, v, i)) and - ( - functionQualifier(fc) = functionQualifier(other) - or - (not exists(functionQualifier(fc)) and not exists(functionQualifier(other))) - ) + // if(v) + exists(FunctionCall other | + e = other and + relevantFunctionCall(fc, _) and + not checkedFunctionCall(fc) and + exists(Function called, Function enclosing | + callTargetAndEnclosing(fc, called, enclosing) and + callTargetAndEnclosing(other, called, enclosing) + ) and + forall(Variable v, int i | callArgumentVariable(fc, v, i) | callArgumentVariable(other, v, i)) and + ( + functionQualifier(fc) = functionQualifier(other) + or + not exists(functionQualifier(fc)) and not exists(functionQualifier(other)) ) - // if(v == NULL), if(v != NULL), if(NULL != v), if(NULL == v) - or exists(EqualityOperation eq | eq = e and callResultNullCheckInCondition(eq.getAnOperand(), fc) and - eq.getAnOperand().getValue() = "0") - // if(v && something) - or exists(LogicalAndExpr exp | exp = e and callResultNullCheckInCondition(exp.getAnOperand(), fc)) - // if(v || something) - or exists(LogicalOrExpr exp | exp = e and callResultNullCheckInCondition(exp.getAnOperand(), fc)) - // if(!v) - or exists(NotExpr exp | exp = e and callResultNullCheckInCondition(exp.getAnOperand(), fc)) + ) + or + // if(v == NULL), if(v != NULL), if(NULL != v), if(NULL == v) + exists(EqualityOperation eq | + eq = e and + callResultNullCheckInCondition(eq.getAnOperand(), fc) and + eq.getAnOperand().getValue() = "0" + ) + or + // if(v && something) + exists(LogicalAndExpr exp | exp = e and callResultNullCheckInCondition(exp.getAnOperand(), fc)) + or + // if(v || something) + exists(LogicalOrExpr exp | exp = e and callResultNullCheckInCondition(exp.getAnOperand(), fc)) + or + // if(!v) + exists(NotExpr exp | exp = e and callResultNullCheckInCondition(exp.getAnOperand(), fc)) } predicate dereferenced(Variable v, Declaration qualifier, Function f) { @@ -152,11 +198,13 @@ predicate dereferenced(Variable v, Declaration qualifier, Function f) { e.getOperand() = qualifiedAccess(v, qualifier) and e.getEnclosingFunction() = f and not exists(SizeofExprOperator s | s.getExprOperand() = e) - ) or + ) + or exists(FunctionCall c | c.getQualifier() = qualifiedAccess(v, qualifier) and c.getEnclosingFunction() = f - ) or + ) + or exists(VariableAccess va | va.getQualifier() = qualifiedAccess(v, qualifier) and va.getEnclosingFunction() = f @@ -165,15 +213,15 @@ predicate dereferenced(Variable v, Declaration qualifier, Function f) { predicate relevantFunctionCall(FunctionCall fc, Function f) { fc.getTarget() = f and - exists (Variable v, Declaration qualifier - | fc = assignedValueForVariableAndQualifier(v, qualifier) - | dereferenced(v, qualifier, fc.getEnclosingFunction())) and + exists(Variable v, Declaration qualifier | + fc = assignedValueForVariableAndQualifier(v, qualifier) + | + dereferenced(v, qualifier, fc.getEnclosingFunction()) + ) and not okToIgnore(fc) } -predicate okToIgnore(FunctionCall fc) { - fc.isInMacroExpansion() -} +predicate okToIgnore(FunctionCall fc) { fc.isInMacroExpansion() } predicate functionStats(Function f, int percentage) { exists(int used, int total | @@ -190,4 +238,6 @@ where uncheckedFunctionCall(unchecked) and functionStats(f, percent) and percent >= 70 -select unchecked, "The result of this call to " + f.getName() + " is not checked for null, but " + percent + "% of calls to " + f.getName() + " check for null." +select unchecked, + "The result of this call to " + f.getName() + " is not checked for null, but " + percent + + "% of calls to " + f.getName() + " check for null." diff --git a/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql b/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql index fe924954d99..f05a0351a12 100644 --- a/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql +++ b/cpp/ql/src/Likely Bugs/JapaneseEra/StructWithExactEraDate.ql @@ -15,8 +15,7 @@ import cpp import semmle.code.cpp.commons.DateTime -predicate assignedYear(Struct s, YearFieldAccess year, int value) -{ +predicate assignedYear(Struct s, YearFieldAccess year, int value) { exists(Operation yearAssignment | s.getAField().getAnAccess() = year and yearAssignment.getAnOperand() = year and @@ -24,8 +23,7 @@ predicate assignedYear(Struct s, YearFieldAccess year, int value) ) } -predicate assignedMonth(Struct s, MonthFieldAccess month, int value) -{ +predicate assignedMonth(Struct s, MonthFieldAccess month, int value) { exists(Operation monthAssignment | s.getAField().getAnAccess() = month and monthAssignment.getAnOperand() = month and @@ -33,8 +31,7 @@ predicate assignedMonth(Struct s, MonthFieldAccess month, int value) ) } -predicate assignedDay(Struct s, DayFieldAccess day, int value) -{ +predicate assignedDay(Struct s, DayFieldAccess day, int value) { exists(Operation dayAssignment | s.getAField().getAnAccess() = day and dayAssignment.getAnOperand() = day and @@ -42,8 +39,7 @@ predicate assignedDay(Struct s, DayFieldAccess day, int value) ) } -from - StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day +from StructLikeClass s, YearFieldAccess year, MonthFieldAccess month, DayFieldAccess day where assignedYear(s, year, 1989) and assignedMonth(s, month, 1) and diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index 0f1a37d4813..f75305dbf2a 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -197,18 +197,14 @@ class StructTmLeapYearFieldAccess extends LeapYearFieldAccess { * `Function` that includes an operation that is checking for leap year. */ class ChecksForLeapYearFunction extends Function { - ChecksForLeapYearFunction() { - this = any(CheckForLeapYearOperation clyo).getEnclosingFunction() - } + ChecksForLeapYearFunction() { this = any(CheckForLeapYearOperation clyo).getEnclosingFunction() } } /** * `FunctionCall` that includes an operation that is checking for leap year. */ class ChecksForLeapYearFunctionCall extends FunctionCall { - ChecksForLeapYearFunctionCall() { - this.getTarget() instanceof ChecksForLeapYearFunction - } + ChecksForLeapYearFunctionCall() { this.getTarget() instanceof ChecksForLeapYearFunction } } /** diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/AssignWhereCompareMeant.ql b/cpp/ql/src/Likely Bugs/Likely Typos/AssignWhereCompareMeant.ql index 22b0753e638..368171a1359 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/AssignWhereCompareMeant.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/AssignWhereCompareMeant.ql @@ -10,26 +10,25 @@ * correctness * external/cwe/cwe-481 */ + import cpp import semmle.code.cpp.controlflow.LocalScopeVariableReachability class UndefReachability extends LocalScopeVariableReachability { - UndefReachability() { - this = "UndefReachability" - } - + UndefReachability() { this = "UndefReachability" } + override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { candidateVariable(v) and node = v.getParentScope() and not v instanceof Parameter and not v.hasInitializer() } - + override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { candidateVariable(v) and node = v.getAnAccess() } - + override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) { node.(AssignExpr).getLValue() = v.getAnAccess() } @@ -41,27 +40,23 @@ abstract class BooleanControllingAssignment extends AssignExpr { class BooleanControllingAssignmentInExpr extends BooleanControllingAssignment { BooleanControllingAssignmentInExpr() { - this.getParent() instanceof UnaryLogicalOperation - or this.getParent() instanceof BinaryLogicalOperation - or exists(ConditionalExpr c | c.getCondition() = this) + this.getParent() instanceof UnaryLogicalOperation or + this.getParent() instanceof BinaryLogicalOperation or + exists(ConditionalExpr c | c.getCondition() = this) } - override predicate isWhitelisted() { - this.getConversion().(ParenthesisExpr).isParenthesised() - } + override predicate isWhitelisted() { this.getConversion().(ParenthesisExpr).isParenthesised() } } class BooleanControllingAssignmentInStmt extends BooleanControllingAssignment { BooleanControllingAssignmentInStmt() { - exists(IfStmt i | i.getCondition() = this) - or exists(ForStmt f | f.getCondition() = this) - or exists(WhileStmt w | w.getCondition() = this) - or exists(DoStmt d | d.getCondition() = this) + exists(IfStmt i | i.getCondition() = this) or + exists(ForStmt f | f.getCondition() = this) or + exists(WhileStmt w | w.getCondition() = this) or + exists(DoStmt d | d.getCondition() = this) } - override predicate isWhitelisted() { - this.isParenthesised() - } + override predicate isWhitelisted() { this.isParenthesised() } } /** @@ -84,6 +79,7 @@ predicate candidateVariable(Variable v) { } from BooleanControllingAssignment ae, UndefReachability undef -where candidateResult(ae) - and not undef.reaches(_, ae.getLValue().(VariableAccess).getTarget(), ae.getLValue()) +where + candidateResult(ae) and + not undef.reaches(_, ae.getLValue().(VariableAccess).getTarget(), ae.getLValue()) select ae, "Use of '=' where '==' may have been intended." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.ql b/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.ql index 6ac9241afa6..3ece1f844d3 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.ql @@ -39,8 +39,9 @@ predicate nonShortCircuitLogic2(BinaryBitwiseOperation op) { } from LogicalOperation o -where o.getParent() instanceof BitwiseOperation and - not nonShortCircuitLogic2(o.getParent()) and - not o.getParent().isInMacroExpansion() and // It's ok if o itself is in a macro expansion. - not o.getParent().(LShiftExpr).getLeftOperand() = o // Common pattern for producing bit masks: "(a && b) << 16". +where + o.getParent() instanceof BitwiseOperation and + not nonShortCircuitLogic2(o.getParent()) and + not o.getParent().isInMacroExpansion() and // It's ok if o itself is in a macro expansion. + not o.getParent().(LShiftExpr).getLeftOperand() = o // Common pattern for producing bit masks: "(a && b) << 16". select o, "The result of this expression is Boolean, but it is used in a bitwise context." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql b/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql index 3e2758c4efa..eb60eebeeb8 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/CompareWhereAssignMeant.ql @@ -10,10 +10,12 @@ * correctness * external/cwe/cwe-482 */ + import cpp from ExprInVoidContext op -where op instanceof EQExpr - or - op.(FunctionCall).getTarget().hasName("operator==") +where + op instanceof EQExpr + or + op.(FunctionCall).getTarget().hasName("operator==") select op, "This '==' operator has no effect. The assignment ('=') operator was probably intended." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/DubiousNullCheck.ql b/cpp/ql/src/Likely Bugs/Likely Typos/DubiousNullCheck.ql index b6b1f60fdf8..819ecbae8ec 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/DubiousNullCheck.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/DubiousNullCheck.ql @@ -21,8 +21,10 @@ predicate zeroComparison(EqualityOperation e) { predicate inNullContext(AddressOfExpr e) { e.getFullyConverted().getUnderlyingType() instanceof BoolType - or exists(ControlStructure c | c.getControllingExpr() = e) - or exists(EqualityOperation cmp | zeroComparison(cmp) | + or + exists(ControlStructure c | c.getControllingExpr() = e) + or + exists(EqualityOperation cmp | zeroComparison(cmp) | e = cmp.getLeftOperand() or e = cmp.getRightOperand() ) @@ -34,11 +36,12 @@ FieldAccess chainedFields(FieldAccess fa) { } from AddressOfExpr addrof, FieldAccess fa, Variable v, int offset -where fa = addrof.getOperand() - and inNullContext(addrof) - and not addrof.isInMacroExpansion() - and v.getAnAccess() = chainedFields(fa).getQualifier() - and not v instanceof MemberVariable - and offset = strictsum(chainedFields(fa).getTarget().getByteOffset()) - and offset != 0 +where + fa = addrof.getOperand() and + inNullContext(addrof) and + not addrof.isInMacroExpansion() and + v.getAnAccess() = chainedFields(fa).getQualifier() and + not v instanceof MemberVariable and + offset = strictsum(chainedFields(fa).getTarget().getByteOffset()) and + offset != 0 select addrof, "This will only be NULL if " + v.getName() + " == -" + offset + "." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql b/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql index a229bd58520..96279c398fd 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql @@ -10,6 +10,7 @@ * correctness * external/cwe/cwe-561 */ + import cpp private import semmle.code.cpp.commons.Exclusions @@ -20,8 +21,10 @@ class PureExprInVoidContext extends ExprInVoidContext { // loop variable mentioned in the init stmt of a for predicate accessInInitOfForStmt(Expr e) { e instanceof Access and - exists(ForStmt f, ExprStmt s | f.getInitialization() = s and - s.getExpr() = e) + exists(ForStmt f, ExprStmt s | + f.getInitialization() = s and + s.getExpr() = e + ) } /** @@ -29,7 +32,8 @@ predicate accessInInitOfForStmt(Expr e) { * code excluded by the preprocessor. */ predicate functionContainsDisabledCodeRecursive(Function f) { - functionContainsDisabledCode(f) or + functionContainsDisabledCode(f) + or // recurse into function calls exists(FunctionCall fc | fc.getEnclosingFunction() = f and @@ -42,7 +46,8 @@ predicate functionContainsDisabledCodeRecursive(Function f) { * preprocessor branch that may have code in another arm */ predicate functionDefinedInIfDefRecursive(Function f) { - functionDefinedInIfDef(f) or + functionDefinedInIfDef(f) + or // recurse into function calls exists(FunctionCall fc | fc.getEnclosingFunction() = f and @@ -60,36 +65,41 @@ predicate functionDefinedInIfDefRecursive(Function f) { * break encapsulation. */ predicate baseCall(FunctionCall call) { - call.getNameQualifier().getQualifyingElement() = - call.getEnclosingFunction().getDeclaringType().(Class).getABaseClass+() + call.getNameQualifier().getQualifyingElement() = call + .getEnclosingFunction() + .getDeclaringType() + .(Class) + .getABaseClass+() } -from PureExprInVoidContext peivc, Locatable parent, - Locatable info, string info_text, string tail -where // EQExprs are covered by CompareWhereAssignMeant.ql - not peivc instanceof EQExpr and - // as is operator== - not peivc.(FunctionCall).getTarget().hasName("operator==") and - not baseCall(peivc) and - not accessInInitOfForStmt(peivc) and - not peivc.isCompilerGenerated() and - not peivc.getEnclosingFunction().isDefaulted() and - not exists(Macro m | peivc = m.getAnInvocation().getAnExpandedElement()) and - not peivc.isFromTemplateInstantiation(_) and - parent = peivc.getParent() and - not parent.isInMacroExpansion() and - not parent instanceof PureExprInVoidContext and - not peivc.getEnclosingFunction().isCompilerGenerated() and - not peivc.getType() instanceof UnknownType and - not functionContainsDisabledCodeRecursive(peivc.(FunctionCall).getTarget()) and - not functionDefinedInIfDefRecursive(peivc.(FunctionCall).getTarget()) and - if peivc instanceof FunctionCall then - exists(Function target | - target = peivc.(FunctionCall).getTarget() and - info = target and - info_text = target.getName() and - tail = " (because $@ has no external side effects).") - else - (tail = "." and info = peivc and info_text = "") -select peivc, "This expression has no effect" + tail, - info, info_text +from PureExprInVoidContext peivc, Locatable parent, Locatable info, string info_text, string tail +where + // EQExprs are covered by CompareWhereAssignMeant.ql + not peivc instanceof EQExpr and + // as is operator== + not peivc.(FunctionCall).getTarget().hasName("operator==") and + not baseCall(peivc) and + not accessInInitOfForStmt(peivc) and + not peivc.isCompilerGenerated() and + not peivc.getEnclosingFunction().isDefaulted() and + not exists(Macro m | peivc = m.getAnInvocation().getAnExpandedElement()) and + not peivc.isFromTemplateInstantiation(_) and + parent = peivc.getParent() and + not parent.isInMacroExpansion() and + not parent instanceof PureExprInVoidContext and + not peivc.getEnclosingFunction().isCompilerGenerated() and + not peivc.getType() instanceof UnknownType and + not functionContainsDisabledCodeRecursive(peivc.(FunctionCall).getTarget()) and + not functionDefinedInIfDefRecursive(peivc.(FunctionCall).getTarget()) and + if peivc instanceof FunctionCall + then + exists(Function target | + target = peivc.(FunctionCall).getTarget() and + info = target and + info_text = target.getName() and + tail = " (because $@ has no external side effects)." + ) + else ( + tail = "." and info = peivc and info_text = "" + ) +select peivc, "This expression has no effect" + tail, info, info_text diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/FutileConditional.ql b/cpp/ql/src/Likely Bugs/Likely Typos/FutileConditional.ql index 50bb19aee24..4f23ed50b36 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/FutileConditional.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/FutileConditional.ql @@ -9,6 +9,7 @@ * @tags reliability * readability */ + import cpp predicate macroUse(Locatable l) { @@ -28,12 +29,12 @@ predicate macroUseLocation(File f, int start, int end) { pragma[noopt] predicate emptyIf(IfStmt s, Block b, File f, int start, int end) { s instanceof IfStmt and - not exists (s.getElse()) and + not exists(s.getElse()) and b = s.getThen() and b instanceof Block and not exists(b.getAChild()) and f = b.getFile() and - exists (Location l | + exists(Location l | l = b.getLocation() and start = l.getStartLine() and end = l.getEndLine() @@ -53,6 +54,7 @@ predicate query(IfStmt s, Block b) { } from IfStmt s, Block b -where query(s, b) and - not b.isInMacroExpansion() +where + query(s, b) and + not b.isInMacroExpansion() select s, "If-statement with an empty then-branch and no else-branch." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.ql b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.ql index a3dc2e6d571..bb20c220186 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.ql @@ -17,19 +17,19 @@ import cpp /** * It's common in some projects to use "a double negation" to normalize the boolean * result to either 1 or 0. - * This predciate is intended to filter explicit usage of a double negation as it typically - * indicates the explicit purpose to normalize the result for bit-wise or arithmetic purposes. + * This predciate is intended to filter explicit usage of a double negation as it typically + * indicates the explicit purpose to normalize the result for bit-wise or arithmetic purposes. */ -predicate doubleNegationNormalization( NotExpr notexpr ){ - notexpr.getAnOperand() instanceof NotExpr -} +predicate doubleNegationNormalization(NotExpr notexpr) { notexpr.getAnOperand() instanceof NotExpr } from BinaryBitwiseOperation binbitwop -where exists( NotExpr notexpr | - binbitwop.getAnOperand() = notexpr - and not doubleNegationNormalization(notexpr) - and ( binbitwop instanceof BitwiseAndExpr - or binbitwop instanceof BitwiseOrExpr ) -) +where + exists(NotExpr notexpr | + binbitwop.getAnOperand() = notexpr and + not doubleNegationNormalization(notexpr) and + ( + binbitwop instanceof BitwiseAndExpr or + binbitwop instanceof BitwiseOrExpr + ) + ) select binbitwop, "Usage of a logical not (!) expression as a bitwise operator." - diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql b/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql index ec3eb804a28..554937127c0 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql @@ -10,11 +10,13 @@ * correctness * external/cwe/cwe-478 */ + import cpp from EnumSwitch es, float missing, float total -where not es.hasDefaultCase() - and missing = count(es.getAMissingCase()) - and total = missing + count(es.getASwitchCase()) - and missing/total < 0.30 -select es, "Switch statement is missing case for "+es.getAMissingCase().getName() +where + not es.hasDefaultCase() and + missing = count(es.getAMissingCase()) and + total = missing + count(es.getASwitchCase()) and + missing / total < 0.3 +select es, "Switch statement is missing case for " + es.getAMissingCase().getName() diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql b/cpp/ql/src/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql index b3aae5ff2dd..b562fb40c62 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/ShortCircuitBitMask.ql @@ -10,6 +10,7 @@ * correctness * external/cwe/cwe-480 */ + import cpp /** @@ -21,12 +22,10 @@ float candidateExpr(Expr e) { e = blo.getAnOperand() and e.isConstant() and result = e.getValue().toFloat() and - // exclusions not e.isFromTemplateInstantiation(_) and not e instanceof SizeofOperator and not inMacroExpansion(blo) and - // exclude values 0 and 1 result != 0.0 and result != 1.0 @@ -36,15 +35,21 @@ float candidateExpr(Expr e) { from Expr e, float v, int l, string msg where v = candidateExpr(e) and - // before reporting an error, we check that the candidate is either a hex/octal - // literal, or its value is a power of two. + // literal, or its value is a power of two. l = v.log2().floor() and - if v = 2.pow(l) then - msg = "Operand to short-circuiting operator looks like a flag ("+v+" = 2 ^ "+l+"), may be typo for bitwise operator." - else exists(string kind | - ((e instanceof HexLiteral and kind = "a hexadecimal literal") or - (e instanceof OctalLiteral and kind = "an octal literal")) and - msg = "Operand to short-circuiting operator is " + kind + ", and therefore likely a flag; a bitwise operator may be intended." - ) + if v = 2.pow(l) + then + msg = "Operand to short-circuiting operator looks like a flag (" + v + " = 2 ^ " + l + + "), may be typo for bitwise operator." + else + exists(string kind | + ( + e instanceof HexLiteral and kind = "a hexadecimal literal" + or + e instanceof OctalLiteral and kind = "an octal literal" + ) and + msg = "Operand to short-circuiting operator is " + kind + + ", and therefore likely a flag; a bitwise operator may be intended." + ) select e, msg diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql b/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql index ddc74cc6205..5722f45f07b 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql @@ -70,10 +70,8 @@ predicate isStringCopyUsedInLogicalOperationOrCondition(FunctionCall func, Expr from FunctionCall func, Expr expr1, string msg where - ( - isStringCopyCastedAsBoolean(func, expr1, msg) and - not isStringCopyUsedInLogicalOperationOrCondition(func, _, _) - ) + isStringCopyCastedAsBoolean(func, expr1, msg) and + not isStringCopyUsedInLogicalOperationOrCondition(func, _, _) or isStringCopyUsedInLogicalOperationOrCondition(func, expr1, msg) select expr1, msg diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql b/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql index d3e9129d829..8761fd7bcda 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql @@ -6,10 +6,11 @@ * @precision high * @id cpp/inconsistent-loop-direction * @tags correctness - * external/cwe/cwe-835 + * external/cwe/cwe-835 * external/microsoft/6293 * @msrc.severity important */ + import cpp import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import semmle.code.cpp.dataflow.DataFlow @@ -17,17 +18,20 @@ import semmle.code.cpp.dataflow.DataFlow /** * A `for` statement whose update is a crement operation on a variable. */ -predicate candidateForStmt(ForStmt forStmt, Variable v, CrementOperation update, RelationalOperation rel) { +predicate candidateForStmt( + ForStmt forStmt, Variable v, CrementOperation update, RelationalOperation rel +) { update = forStmt.getUpdate() and update.getAnOperand() = v.getAnAccess() and rel = forStmt.getCondition() } pragma[noinline] -predicate candidateDecrForStmt(ForStmt forStmt, Variable v, VariableAccess lesserOperand, Expr terminalCondition) { +predicate candidateDecrForStmt( + ForStmt forStmt, Variable v, VariableAccess lesserOperand, Expr terminalCondition +) { exists(DecrementOperation update, RelationalOperation rel | candidateForStmt(forStmt, v, update, rel) and - // condition is `v < terminalCondition` terminalCondition = rel.getGreaterOperand() and lesserOperand = rel.getLesserOperand() and @@ -35,29 +39,30 @@ predicate candidateDecrForStmt(ForStmt forStmt, Variable v, VariableAccess lesse ) } -predicate illDefinedDecrForStmt( ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition ) { +predicate illDefinedDecrForStmt( + ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition +) { exists(VariableAccess lesserOperand | // decrementing for loop candidateDecrForStmt(forstmt, v, lesserOperand, terminalCondition) and - // `initialCondition` is a value of `v` in the for loop v.getAnAssignedValue() = initialCondition and DataFlow::localFlowStep(DataFlow::exprNode(initialCondition), DataFlow::exprNode(lesserOperand)) and - // `initialCondition` < `terminalCondition` ( - ( upperBound(initialCondition) < lowerBound(terminalCondition) ) + upperBound(initialCondition) < lowerBound(terminalCondition) or - ( forstmt.conditionAlwaysFalse() or forstmt.conditionAlwaysTrue() ) + (forstmt.conditionAlwaysFalse() or forstmt.conditionAlwaysTrue()) ) ) } pragma[noinline] -predicate candidateIncrForStmt(ForStmt forStmt, Variable v, VariableAccess greaterOperand, Expr terminalCondition) { +predicate candidateIncrForStmt( + ForStmt forStmt, Variable v, VariableAccess greaterOperand, Expr terminalCondition +) { exists(IncrementOperation update, RelationalOperation rel | candidateForStmt(forStmt, v, update, rel) and - // condition is `v > terminalCondition` terminalCondition = rel.getLesserOperand() and greaterOperand = rel.getGreaterOperand() and @@ -65,71 +70,64 @@ predicate candidateIncrForStmt(ForStmt forStmt, Variable v, VariableAccess great ) } -predicate illDefinedIncrForStmt( ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition ) { +predicate illDefinedIncrForStmt( + ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition +) { exists(VariableAccess greaterOperand | // incrementing for loop candidateIncrForStmt(forstmt, v, greaterOperand, terminalCondition) and - // `initialCondition` is a value of `v` in the for loop v.getAnAssignedValue() = initialCondition and DataFlow::localFlowStep(DataFlow::exprNode(initialCondition), DataFlow::exprNode(greaterOperand)) and - // `terminalCondition` < `initialCondition` ( - ( upperBound(terminalCondition) < lowerBound(initialCondition) ) + upperBound(terminalCondition) < lowerBound(initialCondition) or - ( forstmt.conditionAlwaysFalse() or forstmt.conditionAlwaysTrue() ) + (forstmt.conditionAlwaysFalse() or forstmt.conditionAlwaysTrue()) ) ) } - -predicate illDefinedForStmtWrongDirection( ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition - , boolean isIncr ) { - ( illDefinedDecrForStmt( forstmt, v, initialCondition, terminalCondition) and isIncr = false ) + +predicate illDefinedForStmtWrongDirection( + ForStmt forstmt, Variable v, Expr initialCondition, Expr terminalCondition, boolean isIncr +) { + illDefinedDecrForStmt(forstmt, v, initialCondition, terminalCondition) and isIncr = false or - ( illDefinedIncrForStmt( forstmt, v, initialCondition, terminalCondition) and isIncr = true) -} - -bindingset[b] -private string forLoopdirection(boolean b){ - if( b = true ) then result = "upward" - else result = "downward" + illDefinedIncrForStmt(forstmt, v, initialCondition, terminalCondition) and isIncr = true } bindingset[b] -private string forLoopTerminalConditionRelationship(boolean b){ - if( b = true ) then result = "lower" - else result = "higher" +private string forLoopdirection(boolean b) { + if b = true then result = "upward" else result = "downward" } - predicate illDefinedForStmt( ForStmt for, string message ) { - exists( - boolean isIncr, - Variable v, - Expr initialCondition, - Expr terminalCondition | - illDefinedForStmtWrongDirection(for, v, initialCondition, terminalCondition, isIncr) - and - if( for.conditionAlwaysFalse() ) then - ( - message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " - + forLoopdirection(isIncr) + " from a value ("+ initialCondition +"), but the terminal condition is always false." - ) - else if - ( - for.conditionAlwaysTrue() ) then ( - message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " - + forLoopdirection(isIncr) + " from a value ("+ initialCondition +"), but the terminal condition is always true." - ) - else - ( - message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " - + forLoopdirection(isIncr) + " from a value ("+ initialCondition +"), but the terminal condition is " - + forLoopTerminalConditionRelationship(isIncr) + " (" + terminalCondition + ")." - ) +bindingset[b] +private string forLoopTerminalConditionRelationship(boolean b) { + if b = true then result = "lower" else result = "higher" +} + +predicate illDefinedForStmt(ForStmt for, string message) { + exists(boolean isIncr, Variable v, Expr initialCondition, Expr terminalCondition | + illDefinedForStmtWrongDirection(for, v, initialCondition, terminalCondition, isIncr) and + if for.conditionAlwaysFalse() + then + message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " + + forLoopdirection(isIncr) + " from a value (" + initialCondition + + "), but the terminal condition is always false." + else + if for.conditionAlwaysTrue() + then + message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " + + forLoopdirection(isIncr) + " from a value (" + initialCondition + + "), but the terminal condition is always true." + else + message = "Ill-defined for-loop: a loop using variable \"" + v + "\" counts " + + forLoopdirection(isIncr) + " from a value (" + initialCondition + + "), but the terminal condition is " + forLoopTerminalConditionRelationship(isIncr) + + " (" + terminalCondition + ")." ) } - -from ForStmt forstmt, string message - where illDefinedForStmt(forstmt, message) + +from ForStmt forstmt, string message +where illDefinedForStmt(forstmt, message) select forstmt, message diff --git a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql index 5a5a886e3bd..e684cb525e7 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql @@ -328,5 +328,4 @@ where not l.isTightlyBounded() and alloc = l.getAnAllocaCall() and alloc.getASuccessor*() = l.(Loop).getStmt() -select alloc, "Stack allocation is inside a $@ loop.", l, - l.toString() +select alloc, "Stack allocation is inside a $@ loop.", l, l.toString() diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql b/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql index da5be6e494f..2948ffb00d1 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/Padding/More64BitWaste.ql @@ -11,8 +11,10 @@ import semmle.code.cpp.padding.Padding from PaddedType t, ILP32 ilp32, LP64 lp64, int w32, int w64 -where w32 = t.wastedSpace(ilp32) - t.trailingPadding(ilp32) and +where + w32 = t.wastedSpace(ilp32) - t.trailingPadding(ilp32) and w64 = t.wastedSpace(lp64) - t.trailingPadding(lp64) and w64 > w32 and t.isPrecise() -select t, t.getName() + " includes " + w32 + " bits of padding on ILP32, but " + w64 + " bits on LP64." +select t, + t.getName() + " includes " + w32 + " bits of padding on ILP32, but " + w64 + " bits on LP64." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql b/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql index 579df397362..fd0bfee91bb 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/Padding/NonPortablePrintf.ql @@ -12,7 +12,8 @@ import cpp import semmle.code.cpp.padding.Padding -/** Used to avoid reporting conflicts between a char +/** + * Used to avoid reporting conflicts between a char * pointer type with specified signedness and an unspecified * char pointer (whose signedness is compiler-dependent). */ @@ -24,14 +25,16 @@ class SignedOrUnsignedCharPointerType extends CharPointerType { } pragma[noopt] -private predicate formattingFunctionCallExpectedType(FormattingFunctionCall ffc, int pos, Type expected) { - exists(FormattingFunction f, int i, FormatLiteral fl | - ffc.getTarget() = f and - ffc instanceof FormattingFunctionCall and - f.getFormatParameterIndex() = i and - ffc.getArgument(i) = fl and - fl.getConversionType(pos) = expected - ) +private predicate formattingFunctionCallExpectedType( + FormattingFunctionCall ffc, int pos, Type expected +) { + exists(FormattingFunction f, int i, FormatLiteral fl | + ffc.getTarget() = f and + ffc instanceof FormattingFunctionCall and + f.getFormatParameterIndex() = i and + ffc.getArgument(i) = fl and + fl.getConversionType(pos) = expected + ) } pragma[noopt] @@ -42,7 +45,9 @@ predicate formatArgType(FormattingFunctionCall ffc, int pos, Type expected, Expr } pragma[noopt] -predicate formatOtherArgType(FormattingFunctionCall ffc, int pos, Type expected, Expr arg, Type actual) { +predicate formatOtherArgType( + FormattingFunctionCall ffc, int pos, Type expected, Expr arg, Type actual +) { (arg = ffc.getMinFieldWidthArgument(pos) or arg = ffc.getPrecisionArgument(pos)) and actual = arg.getActualType() and exists(IntType it | it instanceof IntType and it.isImplicitlySigned() and expected = it) @@ -52,37 +57,38 @@ predicate trivialConversion(Type expected, Type actual) { formatArgType(_, _, expected, _, actual) and ( expected instanceof VoidPointerType and actual instanceof PointerType - or + or expected instanceof IntegralType and actual instanceof Enum - or + or expected instanceof CharPointerType and actual instanceof SignedOrUnsignedCharPointerType - or + or expected instanceof SignedOrUnsignedCharPointerType and actual instanceof CharPointerType - or + or expected instanceof CharType and actual instanceof IntType - or + or expected instanceof UnsignedCharType and actual instanceof IntType - or + or expected.(IntegralType).getUnsigned() = actual.(IntegralType).getUnsigned() - or + or expected = actual ) } -from FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual, ILP32 ilp32, LP64 lp64, int size32, int size64 -where ( - ( - formatArgType(ffc, n, expected, arg, actual) and - not trivialConversion(expected, actual) - ) - or - ( - formatOtherArgType(ffc, n, expected, arg, actual) and - not actual instanceof IntType - ) - ) - and not arg.isAffectedByMacro() - and size32 = ilp32.paddedSize(actual) and size64 = lp64.paddedSize(actual) - and size64 != size32 -select arg, "This argument should be of type '" + expected.getName() + "' but is of type '" + actual.getName() + - "' (which changes size from " + size32 + " to " + size64 + " on 64-bit systems)." +from + FormattingFunctionCall ffc, int n, Expr arg, Type expected, Type actual, ILP32 ilp32, LP64 lp64, + int size32, int size64 +where + ( + formatArgType(ffc, n, expected, arg, actual) and + not trivialConversion(expected, actual) + or + formatOtherArgType(ffc, n, expected, arg, actual) and + not actual instanceof IntType + ) and + not arg.isAffectedByMacro() and + size32 = ilp32.paddedSize(actual) and + size64 = lp64.paddedSize(actual) and + size64 != size32 +select arg, + "This argument should be of type '" + expected.getName() + "' but is of type '" + actual.getName() + + "' (which changes size from " + size32 + " to " + size64 + " on 64-bit systems)." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql b/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql index 1f52a265d0a..f2cf4367d86 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/Padding/Suboptimal64BitType.ql @@ -10,15 +10,17 @@ import semmle.code.cpp.padding.Padding -from PaddedType t, Architecture arch, WideCharType wc, int holes, int size, int percentage, int optimum +from + PaddedType t, Architecture arch, WideCharType wc, int holes, int size, int percentage, int optimum where - arch.pointerSize() = 64 and // Select 64-bit architecture - arch.wideCharSize() = (wc.getSize() * 8) and // Select Windows(sizeof(wchar_t == 2)) or non-Windows(sizeof(wchar_t == 4)) + arch.pointerSize() = 64 and // Select 64-bit architecture + arch.wideCharSize() = (wc.getSize() * 8) and // Select Windows(sizeof(wchar_t == 2)) or non-Windows(sizeof(wchar_t == 4)) t.isPrecise() and optimum = t.optimalSize(arch) and size = arch.paddedSize(t) and holes = size - optimum and holes > 0 and - percentage = (holes*100.0/(float)size).ceil() -select t, t.getName() + " could be optimized to save " + holes + "/" + t.wastedSpace(arch) + - " bits of padding (or " + percentage + "% of its size)." + percentage = (holes * 100.0 / size.(float)).ceil() +select t, + t.getName() + " could be optimized to save " + holes + "/" + t.wastedSpace(arch) + + " bits of padding (or " + percentage + "% of its size)." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql b/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql index 74d87182380..8d075470449 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.ql @@ -14,29 +14,25 @@ * Potentially overrunning write with float to string conversion * (`cpp/overrunning-write-with-float) instead. */ + import cpp import semmle.code.cpp.commons.Buffer class SprintfCall extends FunctionCall { - SprintfCall() { - this.getTarget().hasName("sprintf") or this.getTarget().hasName("vsprintf") - } + SprintfCall() { this.getTarget().hasName("sprintf") or this.getTarget().hasName("vsprintf") } - int getBufferSize() { - result = getBufferSize(this.getArgument(0), _) - } + int getBufferSize() { result = getBufferSize(this.getArgument(0), _) } int getMaxConvertedLength() { result = this.getArgument(1).(FormatLiteral).getMaxConvertedLength() } - predicate isDangerous() { - this.getMaxConvertedLength() > this.getBufferSize() - } + predicate isDangerous() { this.getMaxConvertedLength() > this.getBufferSize() } string getDescription() { - result = "This conversion may yield a string of length "+this.getMaxConvertedLength().toString()+ - ", which exceeds the allocated buffer size of "+this.getBufferSize().toString() + result = "This conversion may yield a string of length " + + this.getMaxConvertedLength().toString() + ", which exceeds the allocated buffer size of " + + this.getBufferSize().toString() } } diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql b/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql index ea198567c53..3888e9a4ef5 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql @@ -21,13 +21,14 @@ class StdString extends Class { StdString() { // `std::string` is usually a typedef and the actual class // is called something like `string std::__cxx11::basic_string`. - exists (Type stdstring, Namespace std - | stdstring.getName() = "string" and + exists(Type stdstring, Namespace std | + stdstring.getName() = "string" and this = stdstring.getUnspecifiedType() and // Make sure that the class is in the `std` namespace. std = this.getNamespace().getParentNamespace*() and std.getName() = "std" and - std.getParentNamespace() instanceof GlobalNamespace) + std.getParentNamespace() instanceof GlobalNamespace + ) } } @@ -36,17 +37,20 @@ class StdString extends Class { * allocated `std::string`. */ predicate refToStdString(Expr e, ConstructorCall source) { - exists (StdString stdstring - | stdstring.getAMemberFunction() = source.getTarget() and - not exists(LocalVariable v - | source = v.getInitializer().getExpr() and - v.isStatic()) and - e = source) + exists(StdString stdstring | + stdstring.getAMemberFunction() = source.getTarget() and + not exists(LocalVariable v | + source = v.getInitializer().getExpr() and + v.isStatic() + ) and + e = source + ) or // Indirect use. - exists(Expr prev - | refToStdString(prev, source) and - DataFlow::localFlowStep(DataFlow::exprNode(prev), DataFlow::exprNode(e))) + exists(Expr prev | + refToStdString(prev, source) and + DataFlow::localFlowStep(DataFlow::exprNode(prev), DataFlow::exprNode(e)) + ) } /** @@ -58,12 +62,11 @@ predicate refToStdString(Expr e, ConstructorCall source) { * will also become invalid. */ predicate flowFunction(Function fcn, int argIndex) { - (fcn.hasQualifiedName("", "_JNIEnv", "NewStringUTF") and argIndex = 0) + fcn.hasQualifiedName("", "_JNIEnv", "NewStringUTF") and argIndex = 0 or - (fcn.hasQualifiedName("art", "JNI", "NewStringUTF") and argIndex = 1) + fcn.hasQualifiedName("art", "JNI", "NewStringUTF") and argIndex = 1 or - (fcn.hasQualifiedName("art", "CheckJNI", "NewStringUTF") and argIndex = 1) - + fcn.hasQualifiedName("art", "CheckJNI", "NewStringUTF") and argIndex = 1 // Add other functions that behave like NewStringUTF here. } @@ -72,27 +75,28 @@ predicate flowFunction(Function fcn, int argIndex) { * `c_str` on a locally allocated `std::string`. */ predicate refToCStr(Expr e, ConstructorCall source) { - exists (MemberFunction f, FunctionCall call - | f.getName() = "c_str" and + exists(MemberFunction f, FunctionCall call | + f.getName() = "c_str" and call = e and call.getTarget() = f and - refToStdString(call.getQualifier(), source)) + refToStdString(call.getQualifier(), source) + ) or // Indirect use. - exists(Expr prev - | refToCStr(prev, source) and - DataFlow::localFlowStep(DataFlow::exprNode(prev), DataFlow::exprNode(e))) + exists(Expr prev | + refToCStr(prev, source) and + DataFlow::localFlowStep(DataFlow::exprNode(prev), DataFlow::exprNode(e)) + ) or // Some functions, such as `JNIEnv::NewStringUTF()` (from Java's JNI) // embed return a structure containing a reference to the C-style string. - exists (Function f, int argIndex - | flowFunction(f, argIndex) and + exists(Function f, int argIndex | + flowFunction(f, argIndex) and f = e.(Call).getTarget() and - refToCStr(e.(Call).getArgument(argIndex), source)) + refToCStr(e.(Call).getArgument(argIndex), source) + ) } from ReturnStmt r, ConstructorCall source where refToCStr(r.getExpr(), source) -select - r, "Return value may contain a dangling pointer to $@.", - source, "this local std::string" +select r, "Return value may contain a dangling pointer to $@.", source, "this local std::string" diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql index 838e1ef74c1..d10addadca9 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql @@ -32,8 +32,8 @@ predicate conservativeDataFlowStep(DataFlow::Node n1, DataFlow::Node n2) { * data flow through such expressions. */ predicate hasNontrivialConversion(Expr e) { - e instanceof Conversion and not - ( + e instanceof Conversion and + not ( e instanceof Cast or e instanceof ParenthesisExpr @@ -61,10 +61,7 @@ where exists(Expr pointerToLocal | variableAddressEscapesTree(va, pointerToLocal.getFullyConverted()) and not hasNontrivialConversion(pointerToLocal) and - conservativeDataFlowStep+( - DataFlow::exprNode(pointerToLocal), - DataFlow::exprNode(r.getExpr()) - ) + conservativeDataFlowStep+(DataFlow::exprNode(pointerToLocal), DataFlow::exprNode(r.getExpr())) ) ) select r, "May return stack-allocated memory from $@.", va, va.toString() diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StackAddressEscapes.ql b/cpp/ql/src/Likely Bugs/Memory Management/StackAddressEscapes.ql index 97701d4a6e1..f9a4e3b8a7a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/StackAddressEscapes.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/StackAddressEscapes.ql @@ -9,6 +9,7 @@ * @id cpp/stack-address-escape * @tags reliability */ + import cpp import semmle.code.cpp.dataflow.StackAddress @@ -18,7 +19,7 @@ import semmle.code.cpp.dataflow.StackAddress * escape. */ predicate stackAddressEscapes(AssignExpr assignExpr, Expr source, boolean isLocal) { - stackPointerFlowsToUse(assignExpr.getRValue(), _, source, isLocal) and + stackPointerFlowsToUse(assignExpr.getRValue(), _, source, isLocal) and not stackReferenceFlowsToUse(assignExpr.getLValue(), _, _, _) } @@ -26,9 +27,11 @@ from Expr use, Expr source, boolean isLocal, string msg, string srcStr where stackAddressEscapes(use, source, isLocal) and if isLocal = true - then (msg = "A stack address ($@) may be assigned to a non-local variable." and - srcStr = "source") - else (msg = "A stack address which arrived via a $@ may be assigned to a non-local variable." and - srcStr = "parameter") -select - use, msg, source, srcStr + then ( + msg = "A stack address ($@) may be assigned to a non-local variable." and + srcStr = "source" + ) else ( + msg = "A stack address which arrived via a $@ may be assigned to a non-local variable." and + srcStr = "parameter" + ) +select use, msg, source, srcStr diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql index 6e035cf9c9c..87120de0603 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.ql @@ -13,16 +13,16 @@ * external/cwe/cwe-119 * external/cwe/cwe-251 */ + import cpp import Buffer private import semmle.code.cpp.valuenumbering.GlobalValueNumbering -predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) -{ - ( - // baseSize - e = baseSize and plus = 0 - ) or exists(AddExpr ae, Expr operand1, Expr operand2, int plusSub | +predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) { + // baseSize + e = baseSize and plus = 0 + or + exists(AddExpr ae, Expr operand1, Expr operand2, int plusSub | // baseSize + n or n + baseSize ae = e and operand1 = ae.getAnOperand() and @@ -30,7 +30,9 @@ predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) operand1 != operand2 and isSizePlus(operand1, baseSize, plusSub) and plus = plusSub + operand2.getValue().toInt() - ) or exists(SubExpr se, int plusSub | + ) + or + exists(SubExpr se, int plusSub | // baseSize - n se = e and isSizePlus(se.getLeftOperand(), baseSize, plusSub) and @@ -38,45 +40,40 @@ predicate isSizePlus(Expr e, BufferSizeExpr baseSize, int plus) ) } -predicate strncpyFunction(Function f, int argDest, int argSrc, int argLimit) -{ +predicate strncpyFunction(Function f, int argDest, int argSrc, int argLimit) { exists(string name | name = f.getName() | ( - ( - name = "strcpy_s" or // strcpy_s(dst, max_amount, src) - name = "wcscpy_s" or // wcscpy_s(dst, max_amount, src) - name = "_mbscpy_s" // _mbscpy_s(dst, max_amount, src) - ) and - argDest = 0 and - argSrc = 2 and - argLimit = 1 - ) or ( - ( - name = "strncpy" or // strncpy(dst, src, max_amount) - name = "strncpy_l" or // strncpy_l(dst, src, max_amount, locale) - name = "wcsncpy" or // wcsncpy(dst, src, max_amount) - name = "_wcsncpy_l" or // _wcsncpy_l(dst, src, max_amount, locale) - name = "_mbsncpy" or // _mbsncpy(dst, src, max_amount) - name = "_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale) - ) and - argDest = 0 and - argSrc = 1 and - argLimit = 2 - ) + name = "strcpy_s" or // strcpy_s(dst, max_amount, src) + name = "wcscpy_s" or // wcscpy_s(dst, max_amount, src) + name = "_mbscpy_s" // _mbscpy_s(dst, max_amount, src) + ) and + argDest = 0 and + argSrc = 2 and + argLimit = 1 + or + ( + name = "strncpy" or // strncpy(dst, src, max_amount) + name = "strncpy_l" or // strncpy_l(dst, src, max_amount, locale) + name = "wcsncpy" or // wcsncpy(dst, src, max_amount) + name = "_wcsncpy_l" or // _wcsncpy_l(dst, src, max_amount, locale) + name = "_mbsncpy" or // _mbsncpy(dst, src, max_amount) + name = "_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale) + ) and + argDest = 0 and + argSrc = 1 and + argLimit = 2 ) } -string nthString (int num) { - ( - num = 0 and - result = "first" - ) or ( - num = 1 and - result = "second" - ) or ( - num = 2 and - result = "third" - ) +string nthString(int num) { + num = 0 and + result = "first" + or + num = 1 and + result = "second" + or + num = 2 and + result = "third" } /** @@ -88,14 +85,16 @@ int arrayExprFixedSize(Expr e) { or result = e.(NewArrayExpr).getAllocatedType().(ArrayType).getSize() or - exists (SsaDefinition def, LocalVariable v - | not (e.getUnspecifiedType() instanceof ArrayType) and + exists(SsaDefinition def, LocalVariable v | + not e.getUnspecifiedType() instanceof ArrayType and e = def.getAUse(v) and - result = arrayExprFixedSize(def.getDefiningValue(v))) + result = arrayExprFixedSize(def.getDefiningValue(v)) + ) } -from Function f, FunctionCall fc, int argDest, int argSrc, int argLimit, int charSize, - Access copyDest, Access copySource, string name, string nth +from + Function f, FunctionCall fc, int argDest, int argSrc, int argLimit, int charSize, Access copyDest, + Access copySource, string name, string nth where f = fc.getTarget() and strncpyFunction(f, argDest, argSrc, argLimit) and @@ -104,22 +103,27 @@ where // Some of the functions operate on a larger char type, like `wchar_t`, so we // need to take this into account in the fixed size case. charSize = f.getParameter(argDest).getUnspecifiedType().(PointerType).getBaseType().getSize() and - if exists(fc.getArgument(argLimit).getValue().toInt()) then ( - // Fixed sized case - exists(int size | - size = arrayExprFixedSize(copyDest) and - size < charSize * fc.getArgument(argLimit).getValue().toInt() and - size != 0 // if the array has zero size, something special is going on - ) - ) else exists (Access takenSizeOf, BufferSizeExpr sizeExpr, int plus | - // Variable sized case - sizeExpr = fc.getArgument(argLimit).getAChild*() and - isSizePlus(fc.getArgument(argLimit), sizeExpr, plus) and - plus >= 0 and - takenSizeOf = sizeExpr.getArg() and - globalValueNumber(copySource) = globalValueNumber(takenSizeOf) and // e.g. strncpy(x, y, strlen(y)) - globalValueNumber(copyDest) != globalValueNumber(takenSizeOf) // e.g. strncpy(y, y, strlen(y)) - ) - and name = fc.getTarget().getName() - and nth = nthString(argLimit) -select fc, "Potentially unsafe call to " + name + "; " + nth + " argument should be size of destination." + ( + if exists(fc.getArgument(argLimit).getValue().toInt()) + then + // Fixed sized case + exists(int size | + size = arrayExprFixedSize(copyDest) and + size < charSize * fc.getArgument(argLimit).getValue().toInt() and + size != 0 // if the array has zero size, something special is going on + ) + else + exists(Access takenSizeOf, BufferSizeExpr sizeExpr, int plus | + // Variable sized case + sizeExpr = fc.getArgument(argLimit).getAChild*() and + isSizePlus(fc.getArgument(argLimit), sizeExpr, plus) and + plus >= 0 and + takenSizeOf = sizeExpr.getArg() and + globalValueNumber(copySource) = globalValueNumber(takenSizeOf) and // e.g. strncpy(x, y, strlen(y)) + globalValueNumber(copyDest) != globalValueNumber(takenSizeOf) // e.g. strncpy(y, y, strlen(y)) + ) + ) and + name = fc.getTarget().getName() and + nth = nthString(argLimit) +select fc, + "Potentially unsafe call to " + name + "; " + nth + " argument should be size of destination." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql index 45ba293867c..2ccdda23bfd 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToMemset.ql @@ -13,6 +13,7 @@ * security * external/cwe/cwe-676 */ + import cpp /** @@ -20,36 +21,37 @@ import cpp * optional multiplication by a constant. */ predicate sizeOfExpr(Expr e, Type t) { - ( - t = e.(SizeofTypeOperator).getTypeOperand() - ) or ( - t = e.(SizeofExprOperator).getExprOperand().getType() - ) or ( - sizeOfExpr(e.(MulExpr).getAnOperand(), t) and - e.(MulExpr).getAnOperand() instanceof Literal - ) + t = e.(SizeofTypeOperator).getTypeOperand() + or + t = e.(SizeofExprOperator).getExprOperand().getType() + or + sizeOfExpr(e.(MulExpr).getAnOperand(), t) and + e.(MulExpr).getAnOperand() instanceof Literal } /** * Gets the type `t` with typedefs, array types and references removed. - * + * * This is similar to `Type.stripType` except that it doesn't remove * a `PointerType`. */ Type stripType(Type t) { - result = stripType(t.(TypedefType).getBaseType()) or - result = stripType(t.(ArrayType).getBaseType()) or - result = stripType(t.(ReferenceType).getBaseType()) or - result = stripType(t.(SpecifiedType).getBaseType()) or - result = stripType(t.(Decltype).getBaseType()) or - ( - not t instanceof TypedefType and - not t instanceof ArrayType and - not t instanceof ReferenceType and - not t instanceof SpecifiedType and - not t instanceof Decltype and - result = t - ) + result = stripType(t.(TypedefType).getBaseType()) + or + result = stripType(t.(ArrayType).getBaseType()) + or + result = stripType(t.(ReferenceType).getBaseType()) + or + result = stripType(t.(SpecifiedType).getBaseType()) + or + result = stripType(t.(Decltype).getBaseType()) + or + not t instanceof TypedefType and + not t instanceof ArrayType and + not t instanceof ReferenceType and + not t instanceof SpecifiedType and + not t instanceof Decltype and + result = t } /** @@ -58,13 +60,11 @@ Type stripType(Type t) { * `base` is a stripped type (via `stripType`). */ predicate pointerIndirection(Type t, int indirection, Type base) { - ( - base = stripType(t) and - not base instanceof PointerType and - indirection = 0 - ) or ( - pointerIndirection(stripType(t).(PointerType).getBaseType(), indirection - 1, base) - ) + base = stripType(t) and + not base instanceof PointerType and + indirection = 0 + or + pointerIndirection(stripType(t).(PointerType).getBaseType(), indirection - 1, base) } /** @@ -73,12 +73,10 @@ predicate pointerIndirection(Type t, int indirection, Type base) { * allowed. */ predicate pointerIndirection2(Type t, int indirection) { - ( - not stripType(t) instanceof PointerType and - indirection = 0 - ) or ( - pointerIndirection2(stripType(t).(PointerType).getBaseType(), indirection - 1) - ) + not stripType(t) instanceof PointerType and + indirection = 0 + or + pointerIndirection2(stripType(t).(PointerType).getBaseType(), indirection - 1) } /** @@ -87,29 +85,38 @@ predicate pointerIndirection2(Type t, int indirection) { */ predicate reasonableMemset(FunctionCall fc) { exists(Expr dataArg, Expr sizeArg | - dataArg = fc.getArgument(0) and sizeArg = fc.getArgument(2) and + dataArg = fc.getArgument(0) and + sizeArg = fc.getArgument(2) and exists(Type dataType, Type sizeOfType | dataType = dataArg.getType() and sizeOfExpr(sizeArg, sizeOfType) and - exists (int i | + exists(int i | exists(Type base | // memset(&t, _, sizeof(t)) pointerIndirection(dataType, i + 1, base) and pointerIndirection(sizeOfType, i, base) - ) or exists(Type base | + ) + or + exists(Type base | // memset(t[n], _, sizeof(t)) pointerIndirection(dataType.getUnspecifiedType().(ArrayType), i, base) and pointerIndirection(sizeOfType, i, base) - ) or exists(VoidType vt | + ) + or + exists(VoidType vt | // memset(void *, _, sizeof(t)) pointerIndirection(dataType, i + 1, vt) and pointerIndirection2(sizeOfType, i) - ) or exists(Type ct | + ) + or + exists(Type ct | // memset(char *, _, sizeof(t)) and similar ct.getSize() = 1 and pointerIndirection(dataType, i + 1, ct) and pointerIndirection2(sizeOfType, i) - ) or exists(Type ct | + ) + or + exists(Type ct | // memset(char [], _, sizeof(t)) and similar ct.getSize() = 1 and pointerIndirection(dataType.getUnspecifiedType().(ArrayType), i, ct) and @@ -125,4 +132,6 @@ where fc.getTarget().hasName("memset") and sizeOfExpr(fc.getArgument(2), t) and not reasonableMemset(fc) -select fc, "The size of the memory area set by memset should not be the size of the type " + t.getName() + "." +select fc, + "The size of the memory area set by memset should not be the size of the type " + t.getName() + + "." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql index 31cc6045799..eae20876e35 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql @@ -13,12 +13,14 @@ * external/cwe/cwe-119 * external/cwe/cwe-251 */ + import cpp import Buffer from FunctionCall fc, VariableAccess va1, VariableAccess va2 -where fc.getTarget().(Function).hasName("strncat") and - va1 = fc.getArgument(0) and - va2 = fc.getArgument(2).(BufferSizeExpr).getArg() and - va1.getTarget() = va2.getTarget() +where + fc.getTarget().(Function).hasName("strncat") and + va1 = fc.getArgument(0) and + va2 = fc.getArgument(2).(BufferSizeExpr).getArg() and + va1.getTarget() = va2.getTarget() select fc, "Potentially unsafe call to strncat." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.ql b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.ql index 61baf081cc7..b887894707c 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.ql @@ -12,27 +12,26 @@ * security * external/cwe/cwe-467 */ + import cpp class CandidateParameter extends Parameter { CandidateParameter() { - // an array parameter - getUnspecifiedType() instanceof ArrayType - or - ( - // a pointer parameter - getUnspecifiedType() instanceof PointerType and - - // whose address is never taken (rules out common - // false positive patterns) - not exists(AddressOfExpr aoe | aoe.getAddressable() = this) - ) + // an array parameter + getUnspecifiedType() instanceof ArrayType + or + // a pointer parameter + getUnspecifiedType() instanceof PointerType and + // whose address is never taken (rules out common + // false positive patterns) + not exists(AddressOfExpr aoe | aoe.getAddressable() = this) } } from SizeofExprOperator seo, VariableAccess va -where seo.getExprOperand() = va and - va.getTarget() instanceof CandidateParameter and - not va.isAffectedByMacro() and - not va.isCompilerGenerated() +where + seo.getExprOperand() = va and + va.getTarget() instanceof CandidateParameter and + not va.isAffectedByMacro() and + not va.isCompilerGenerated() select seo, "This evaluates to the size of the pointer type, which may not be what you want." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql b/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql index f0dc377d1c6..e213e9e461d 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/UninitializedLocal.ql @@ -20,11 +20,14 @@ import semmle.code.cpp.controlflow.LocalScopeVariableReachability */ predicate allocatedType(Type t) { /* Arrays: "int foo[1]; foo[0] = 42;" is ok. */ - t instanceof ArrayType or + t instanceof ArrayType + or /* Structs: "struct foo bar; bar.baz = 42" is ok. */ - t instanceof Class or + t instanceof Class + or /* Typedefs to other allocated types are fine. */ - allocatedType(t.(TypedefType).getUnderlyingType()) or + allocatedType(t.(TypedefType).getUnderlyingType()) + or /* Type specifiers don't affect whether or not a type is allocated. */ allocatedType(t.getUnspecifiedType()) } @@ -51,9 +54,7 @@ class UninitialisedLocalReachability extends LocalScopeVariableReachability { node = declWithNoInit(v) } - override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { - useOfVarActual(v, node) - } + override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { useOfVarActual(v, node) } override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) { // only report the _first_ possibly uninitialized use @@ -63,9 +64,7 @@ class UninitialisedLocalReachability extends LocalScopeVariableReachability { } pragma[noinline] -predicate containsInlineAssembly(Function f) { - exists(AsmStmt s | s.getEnclosingFunction() = f) -} +predicate containsInlineAssembly(Function f) { exists(AsmStmt s | s.getEnclosingFunction() = f) } /** * Auxiliary predicate: List common exceptions or false positives diff --git a/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql b/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql index 51302b710f2..2d595c0c050 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql @@ -13,6 +13,7 @@ * external/cwe/cwe-120 * external/cwe/cwe-251 */ + import cpp import Buffer @@ -20,8 +21,7 @@ import Buffer * An access to a variable that is initialized by a constant * expression, and is never used as an lvalue anywhere else. */ -predicate isEffectivelyConstAccess(VariableAccess a) -{ +predicate isEffectivelyConstAccess(VariableAccess a) { exists(Variable v | a.getTarget() = v and v.getInitializer().getExpr().isConstant() and @@ -41,8 +41,8 @@ class StrcatSource extends VariableAccess { } from StrcatSource src -where not src.getType() instanceof ArrayType and - not exists(BufferSizeExpr bse | - bse.getArg().(VariableAccess).getTarget() = src.getTarget()) and - not isEffectivelyConstAccess(src) +where + not src.getType() instanceof ArrayType and + not exists(BufferSizeExpr bse | bse.getArg().(VariableAccess).getTarget() = src.getTarget()) and + not isEffectivelyConstAccess(src) select src.getStrcatCall(), "Always check the size of the source buffer when using strcat." diff --git a/cpp/ql/src/Likely Bugs/NestedLoopSameVar.ql b/cpp/ql/src/Likely Bugs/NestedLoopSameVar.ql index 4edf3d0706e..7947472259e 100644 --- a/cpp/ql/src/Likely Bugs/NestedLoopSameVar.ql +++ b/cpp/ql/src/Likely Bugs/NestedLoopSameVar.ql @@ -10,8 +10,10 @@ * @tags maintainability * correctness */ + import NestedLoopSameVar from ForStmt inner, Variable iteration, ForStmt outer where nestedForViolation(inner, iteration, outer) -select inner.getCondition(), "Nested for statement uses loop variable $@ of enclosing $@.", iteration, iteration.getName(), outer, "for statement" +select inner.getCondition(), "Nested for statement uses loop variable $@ of enclosing $@.", + iteration, iteration.getName(), outer, "for statement" diff --git a/cpp/ql/src/Likely Bugs/NestedLoopSameVar.qll b/cpp/ql/src/Likely Bugs/NestedLoopSameVar.qll index 0dbe236d418..09ac2055fa2 100644 --- a/cpp/ql/src/Likely Bugs/NestedLoopSameVar.qll +++ b/cpp/ql/src/Likely Bugs/NestedLoopSameVar.qll @@ -14,22 +14,21 @@ predicate simpleFieldAccess(Variable object, Variable field, VariableAccess acce /** * Holds if `inner` and `outer` are nested for statements that - * use the same loop variable `iteration`. + * use the same loop variable `iteration`. */ predicate nestedForViolation(ForStmt inner, Variable iteration, ForStmt outer) { // same variable iteration = inner.getAnIterationVariable() and iteration = outer.getAnIterationVariable() and - // field accesses must have the same object ( - iteration instanceof Field implies + iteration instanceof Field + implies exists(Variable obj | simpleFieldAccess(obj, iteration, inner.getCondition().getAChild*()) and simpleFieldAccess(obj, iteration, outer.getCondition().getAChild*()) ) ) and - // ordinary nested loops exists(inner.getInitialization()) and inner.getParent+() = outer and diff --git a/cpp/ql/src/Likely Bugs/OO/IncorrectConstructorDelegation.ql b/cpp/ql/src/Likely Bugs/OO/IncorrectConstructorDelegation.ql index 5399c0afc9c..38cd86a594d 100644 --- a/cpp/ql/src/Likely Bugs/OO/IncorrectConstructorDelegation.ql +++ b/cpp/ql/src/Likely Bugs/OO/IncorrectConstructorDelegation.ql @@ -15,7 +15,9 @@ import cpp from FunctionCall call -where call.getTarget() = call.getEnclosingFunction().(Constructor).getDeclaringType().getAConstructor() - and call.getParent() instanceof ExprStmt -select call, "The constructor " + call.getTarget().getName() + - " may leave the instance uninitialized, as it tries to delegate to another constructor." +where + call.getTarget() = call.getEnclosingFunction().(Constructor).getDeclaringType().getAConstructor() and + call.getParent() instanceof ExprStmt +select call, + "The constructor " + call.getTarget().getName() + + " may leave the instance uninitialized, as it tries to delegate to another constructor." diff --git a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql index e4284bbd804..e5c364bc855 100644 --- a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql +++ b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.ql @@ -15,8 +15,9 @@ import cpp from Class base, Destructor d1, Class derived, Destructor d2 -where derived.getABaseClass+() = base and - d1.getDeclaringType() = base and - not d1.isVirtual() and - d2.getDeclaringType() = derived +where + derived.getABaseClass+() = base and + d1.getDeclaringType() = base and + not d1.isVirtual() and + d2.getDeclaringType() = derived select d1, "This destructor should probably be virtual." diff --git a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructorInBaseClass.ql b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructorInBaseClass.ql index 2236d5121b0..7a223f56f57 100644 --- a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructorInBaseClass.ql +++ b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructorInBaseClass.ql @@ -9,6 +9,7 @@ * readability * language-features */ + import cpp /* @@ -17,13 +18,16 @@ import cpp */ from Class c -where exists(VirtualFunction f | f.getDeclaringType() = c) - and exists(Destructor d | d.getDeclaringType() = c and - // Ignore non-public destructors, which prevent an object of the declaring class from being deleted - // directly (except from within the class itself). This is a common pattern in real-world code. - d.hasSpecifier("public") and - not d.isVirtual() and - not d.isDeleted() and - not d.isCompilerGenerated()) - and exists(ClassDerivation d | d.getBaseClass() = c) +where + exists(VirtualFunction f | f.getDeclaringType() = c) and + exists(Destructor d | + d.getDeclaringType() = c and + // Ignore non-public destructors, which prevent an object of the declaring class from being deleted + // directly (except from within the class itself). This is a common pattern in real-world code. + d.hasSpecifier("public") and + not d.isVirtual() and + not d.isDeleted() and + not d.isCompilerGenerated() + ) and + exists(ClassDerivation d | d.getBaseClass() = c) select c, "A base class with a virtual function should define a virtual destructor." diff --git a/cpp/ql/src/Likely Bugs/OO/SelfAssignmentCheck.ql b/cpp/ql/src/Likely Bugs/OO/SelfAssignmentCheck.ql index d8c5473724e..c8e10709f1c 100644 --- a/cpp/ql/src/Likely Bugs/OO/SelfAssignmentCheck.ql +++ b/cpp/ql/src/Likely Bugs/OO/SelfAssignmentCheck.ql @@ -10,12 +10,16 @@ * security * external/cwe/cwe-826 */ + import cpp // find copy assignment operators that deallocate memory but do not check for self assignment from CopyAssignmentOperator cao -where exists(DestructorCall d | d.getEnclosingFunction() = cao) and - not exists(EqualityOperation eq | eq.getEnclosingFunction() = cao and - eq.getAChild() instanceof ThisExpr and - eq.getAChild().(AddressOfExpr).getAddressable() = cao.getParameter(0)) +where + exists(DestructorCall d | d.getEnclosingFunction() = cao) and + not exists(EqualityOperation eq | + eq.getEnclosingFunction() = cao and + eq.getAChild() instanceof ThisExpr and + eq.getAChild().(AddressOfExpr).getAddressable() = cao.getParameter(0) + ) select cao, "Copy assignment operator does not check for self assignment." diff --git a/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.ql b/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.ql index bda34dbb8e3..75252eb4509 100644 --- a/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.ql +++ b/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.ql @@ -10,49 +10,50 @@ * readability * language-features */ + import cpp // This predicate finds the catch block enclosing a rethrow expression. -predicate bindEnclosingCatch(ReThrowExpr te, CatchBlock cb) -{ - te.getEnclosingBlock().getEnclosingBlock*() = cb - and not exists(CatchBlock other | te.getEnclosingBlock().getEnclosingBlock*() = other and other.getEnclosingBlock+() = cb) +predicate bindEnclosingCatch(ReThrowExpr te, CatchBlock cb) { + te.getEnclosingBlock().getEnclosingBlock*() = cb and + not exists(CatchBlock other | + te.getEnclosingBlock().getEnclosingBlock*() = other and other.getEnclosingBlock+() = cb + ) } // This predicate strips references from types, i.e. T -> T, T* -> T*, T& -> T. -predicate bindStrippedReferenceType(Type qualified, Type unqualified) -{ - (not(qualified instanceof ReferenceType) and unqualified = qualified) - or unqualified = qualified.(ReferenceType).getBaseType() +predicate bindStrippedReferenceType(Type qualified, Type unqualified) { + not qualified instanceof ReferenceType and unqualified = qualified + or + unqualified = qualified.(ReferenceType).getBaseType() } // This predicate determines (to a first approximation) the type thrown by a throw or rethrow expression. -predicate bindThrownType(ThrowExpr te, Type thrown) -{ +predicate bindThrownType(ThrowExpr te, Type thrown) { // For normal throws, the thrown type is easily determined as the type of the throw expression. - (not(te instanceof ReThrowExpr) and thrown = te.getActualType()) - + not te instanceof ReThrowExpr and thrown = te.getActualType() + or // For rethrows, we use the unqualified version of the type caught by the enclosing catch block. // Note that this is not precise, but is a reasonable first approximation. - or exists(CatchBlock cb | bindEnclosingCatch(te, cb) and bindStrippedReferenceType(cb.getParameter().getUnspecifiedType(), thrown)) + exists(CatchBlock cb | + bindEnclosingCatch(te, cb) and + bindStrippedReferenceType(cb.getParameter().getUnspecifiedType(), thrown) + ) } // This predicate determines the catch blocks that can catch the exceptions thrown by each throw expression. pragma[inline] -predicate canCatch(ThrowExpr te, CatchBlock cb) -{ +predicate canCatch(ThrowExpr te, CatchBlock cb) { exists(Type thrown, Type caught | - bindThrownType(te, thrown) - and caught = cb.getParameter().getUnspecifiedType() - and not bindEnclosingCatch(te, cb) - - and + bindThrownType(te, thrown) and + caught = cb.getParameter().getUnspecifiedType() and + not bindEnclosingCatch(te, cb) and ( // Catching primitives by value or reference bindStrippedReferenceType(caught, thrown) - + or // Catching class types by value or reference - or exists(Class c | c = thrown and bindStrippedReferenceType(caught, c.getABaseClass*())) + exists(Class c | c = thrown and bindStrippedReferenceType(caught, c.getABaseClass*())) ) ) } @@ -61,14 +62,14 @@ predicate canCatch(ThrowExpr te, CatchBlock cb) // the end of the destructor without an intervening catch block that can catch the type thrown. from Destructor d, ThrowExpr te where - te.getEnclosingFunction() = d - and not exists(CatchBlock cb | - te.getASuccessor+() = cb - and cb.getASuccessor+() = d - | canCatch(te, cb) + te.getEnclosingFunction() = d and + not exists(CatchBlock cb | + te.getASuccessor+() = cb and + cb.getASuccessor+() = d + | + canCatch(te, cb) or // Catch anything -- written as `catch(...)`. not exists(cb.getParameter()) ) select te, "Exception thrown in destructor." - diff --git a/cpp/ql/src/Likely Bugs/OO/VirtualCallInStructor.ql b/cpp/ql/src/Likely Bugs/OO/VirtualCallInStructor.ql index c73f79fb917..f27cad6098d 100644 --- a/cpp/ql/src/Likely Bugs/OO/VirtualCallInStructor.ql +++ b/cpp/ql/src/Likely Bugs/OO/VirtualCallInStructor.ql @@ -8,20 +8,22 @@ * @problem.severity warning * @tags reliability */ + import cpp class Structor extends MemberFunction { Structor() { - this instanceof Constructor - or this instanceof Destructor + this instanceof Constructor or + this instanceof Destructor } } from Structor s, FunctionCall c, VirtualFunction vf -where c.getEnclosingFunction() = s and - vf = c.getTarget() and - exists(VirtualFunction vff | - vff.overrides(vf) and - vff.getDeclaringType().getABaseClass+() = s.getDeclaringType()) +where + c.getEnclosingFunction() = s and + vf = c.getTarget() and + exists(VirtualFunction vff | + vff.overrides(vf) and + vff.getDeclaringType().getABaseClass+() = s.getDeclaringType() + ) select c, "Virtual call in constructor or destructor." - diff --git a/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql b/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql index cc469993e55..cce74e064a2 100644 --- a/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql +++ b/cpp/ql/src/Likely Bugs/RedundantNullCheckSimple.ql @@ -48,8 +48,7 @@ predicate explicitNullTestOfInstruction(Instruction checked, Instruction bool) { } pragma[noinline] -predicate candidateResult(LoadInstruction checked, ValueNumber value, IRBlock dominator) -{ +predicate candidateResult(LoadInstruction checked, ValueNumber value, IRBlock dominator) { explicitNullTestOfInstruction(checked, _) and not checked.getAST().isInMacroExpansion() and value.getAnInstruction() = checked and diff --git a/cpp/ql/src/Likely Bugs/ReturnConstType.ql b/cpp/ql/src/Likely Bugs/ReturnConstType.ql index ab20cef95fc..f4b7b859d49 100644 --- a/cpp/ql/src/Likely Bugs/ReturnConstType.ql +++ b/cpp/ql/src/Likely Bugs/ReturnConstType.ql @@ -9,9 +9,11 @@ * readability * language-features */ + import ReturnConstTypeCommon from Function f -where hasSuperfluousConstReturn(f) - and not f instanceof MemberFunction +where + hasSuperfluousConstReturn(f) and + not f instanceof MemberFunction select f, "The 'const' modifier has no effect on a return type and can be removed." diff --git a/cpp/ql/src/Likely Bugs/ReturnConstTypeCommon.qll b/cpp/ql/src/Likely Bugs/ReturnConstTypeCommon.qll index fdcb0bf5ba2..6d81caed391 100644 --- a/cpp/ql/src/Likely Bugs/ReturnConstTypeCommon.qll +++ b/cpp/ql/src/Likely Bugs/ReturnConstTypeCommon.qll @@ -1,21 +1,21 @@ import cpp private predicate mightHaveConstMethods(Type t) { - t instanceof Class - or t instanceof TemplateParameter + t instanceof Class or + t instanceof TemplateParameter } predicate hasSuperfluousConstReturn(Function f) { exists(Type t | t = f.getType() | // This is the primary thing we're testing for, - t instanceof SpecifiedType - and t.hasSpecifier("const") - and (not affectedByMacro(t)) + t instanceof SpecifiedType and + t.hasSpecifier("const") and + not affectedByMacro(t) and // but "const" is meaningful when applied to user defined types, - and not mightHaveConstMethods(t.getUnspecifiedType()) - ) + not mightHaveConstMethods(t.getUnspecifiedType()) + ) and // and therefore "const T" might be meaningful for other values of "T". - and not exists(TemplateFunction t | f = t.getAnInstantiation() | + not exists(TemplateFunction t | f = t.getAnInstantiation() | t.getType().involvesTemplateParameter() ) } diff --git a/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.ql b/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.ql index 724036c7c1e..bd036211218 100644 --- a/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.ql +++ b/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.ql @@ -9,11 +9,14 @@ * readability * language-features */ + import ReturnConstTypeCommon from MemberFunction f, string message -where hasSuperfluousConstReturn(f) and - if f.hasSpecifier("const") or f.isStatic() then +where + hasSuperfluousConstReturn(f) and + if f.hasSpecifier("const") or f.isStatic() + then message = "The 'const' modifier has no effect on return types. The 'const' modifying the return type can be removed." else message = "The 'const' modifier has no effect on return types. For a const function, the 'const' should go after the parameter list." diff --git a/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql b/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql index 92696cfc870..87dee3c8e30 100644 --- a/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql +++ b/cpp/ql/src/Likely Bugs/ShortLoopVarName.ql @@ -8,11 +8,10 @@ * @tags maintainability * readability */ + import cpp -predicate short(Variable v) { - v.getName().length() = 1 -} +predicate short(Variable v) { v.getName().length() = 1 } predicate forStmtAncestor(Stmt child, ForStmt parent) { child.getParent() = parent or forStmtAncestor(child.getParent(), parent) @@ -21,9 +20,7 @@ predicate forStmtAncestor(Stmt child, ForStmt parent) { /** * Gets an `ArrayExpr` that's nested directly inside `ArrayExpr ae`. */ -ArrayExpr getANestedArrayExpr(ArrayExpr ae) { - result.getArrayBase() = ae -} +ArrayExpr getANestedArrayExpr(ArrayExpr ae) { result.getArrayBase() = ae } /** * Holds if variables `a` and `b` are accessed in a way that looks like they @@ -42,12 +39,14 @@ predicate coordinatePair(Variable a, Variable b) { } from ForStmt outer, ForStmt inner, Variable iterationVar, Variable innerVar -where forStmtAncestor(inner, outer) and short(innerVar) - and iterationVar = outer.getAnIterationVariable() - and innerVar = inner.getAnIterationVariable() - and short(iterationVar) - and not coordinatePair(iterationVar, innerVar) +where + forStmtAncestor(inner, outer) and + short(innerVar) and + iterationVar = outer.getAnIterationVariable() and + innerVar = inner.getAnIterationVariable() and + short(iterationVar) and + not coordinatePair(iterationVar, innerVar) select iterationVar, - "Iteration variable " + iterationVar.getName() + " for $@ should have a descriptive name, since there is $@.", - outer, "this loop", - inner, "a nested loop" + "Iteration variable " + iterationVar.getName() + + " for $@ should have a descriptive name, since there is $@.", outer, "this loop", inner, + "a nested loop" diff --git a/cpp/ql/src/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql b/cpp/ql/src/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql index f4ebf73dceb..1142cc1a45b 100644 --- a/cpp/ql/src/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql +++ b/cpp/ql/src/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql @@ -73,8 +73,7 @@ predicate argTypeMayBeUsed(Type arg, Type parm) { // function parameter `parm` without need for run-time conversion. pragma[inline] predicate argMayBeUsed(Expr arg, Parameter parm) { - argTypeMayBeUsed(arg.getFullyConverted().getUnspecifiedType(), - parm.getUnspecifiedType()) + argTypeMayBeUsed(arg.getFullyConverted().getUnspecifiedType(), parm.getUnspecifiedType()) } // True if function was ()-declared, but not (void)-declared or K&R-defined @@ -104,5 +103,4 @@ where not argMayBeUsed(fc.getArgument(p.getIndex()), p) select fc, "Calling $@: argument $@ of type $@ is incompatible with parameter $@.", f, f.toString(), fc.getArgument(p.getIndex()) as arg, arg.toString(), - arg.getExplicitlyConverted().getUnspecifiedType() as atype, atype.toString(), p, - p.getTypedName() + arg.getExplicitlyConverted().getUnspecifiedType() as atype, atype.toString(), p, p.getTypedName() diff --git a/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql b/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql index 134533313ac..a3e78fe61c4 100644 --- a/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql +++ b/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.ql @@ -2,8 +2,8 @@ * @name Call to function with fewer arguments than declared parameters * @description A function call is passing fewer arguments than the number of * declared parameters of the function. This may indicate - * that the code does not follow the author's intent. It is also - * a vulnerability, since the function is likely to operate on + * that the code does not follow the author's intent. It is also + * a vulnerability, since the function is likely to operate on * undefined data. * @kind problem * @problem.severity error diff --git a/cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql b/cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql index b8d60d84f49..6bb411b7844 100644 --- a/cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql +++ b/cpp/ql/src/Likely Bugs/UseInOwnInitializer.ql @@ -14,6 +14,7 @@ import cpp class VariableAccessInInitializer extends VariableAccess { Variable var; Initializer init; + VariableAccessInInitializer() { init.getDeclaration() = var and init.getExpr().getAChild*() = this @@ -25,21 +26,18 @@ class VariableAccessInInitializer extends VariableAccess { } from Initializer init, Variable v, VariableAccessInInitializer va -where va.initializesItself(v, init) - and ( +where + va.initializesItself(v, init) and + ( va.hasLValueToRValueConversion() or - exists (Assignment assn | assn.getLValue() = va) or - exists (CrementOperation crement | crement.getAnOperand() = va) - ) - and not va.isUnevaluated() - and not v.isConst() - and not ( + exists(Assignment assn | assn.getLValue() = va) or + exists(CrementOperation crement | crement.getAnOperand() = va) + ) and + not va.isUnevaluated() and + not v.isConst() and + not ( va.getParent() = init and - exists(MacroInvocation mi | - va = mi.getExpr() - ) - ) - and not ( - va.getEnclosingStmt().isInMacroExpansion() - ) + exists(MacroInvocation mi | va = mi.getExpr()) + ) and + not va.getEnclosingStmt().isInMacroExpansion() select va, v.getName() + " is used in its own initializer." diff --git a/cpp/ql/src/Metrics/Classes/CAfferentCoupling.ql b/cpp/ql/src/Metrics/Classes/CAfferentCoupling.ql index e2747ecad28..1da834bfdce 100644 --- a/cpp/ql/src/Metrics/Classes/CAfferentCoupling.ql +++ b/cpp/ql/src/Metrics/Classes/CAfferentCoupling.ql @@ -9,9 +9,9 @@ * @tags maintainability * modularity */ + import cpp from Class c where c.fromSource() -select c, c.getMetrics().getAfferentCoupling() as n -order by n desc +select c, c.getMetrics().getAfferentCoupling() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CEfferentCoupling.ql b/cpp/ql/src/Metrics/Classes/CEfferentCoupling.ql index 1c895281069..25ba3cad7bb 100644 --- a/cpp/ql/src/Metrics/Classes/CEfferentCoupling.ql +++ b/cpp/ql/src/Metrics/Classes/CEfferentCoupling.ql @@ -9,9 +9,9 @@ * @tags testability * modularity */ + import cpp from Class c where c.fromSource() -select c, c.getMetrics().getEfferentCoupling() as n -order by n desc +select c, c.getMetrics().getEfferentCoupling() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CHalsteadBugs.ql b/cpp/ql/src/Metrics/Classes/CHalsteadBugs.ql index 15e39096a74..b8467b6b51d 100644 --- a/cpp/ql/src/Metrics/Classes/CHalsteadBugs.ql +++ b/cpp/ql/src/Metrics/Classes/CHalsteadBugs.ql @@ -9,6 +9,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricClass mc diff --git a/cpp/ql/src/Metrics/Classes/CHalsteadDifficulty.ql b/cpp/ql/src/Metrics/Classes/CHalsteadDifficulty.ql index 7b7be9b2aa5..817e1f5334e 100644 --- a/cpp/ql/src/Metrics/Classes/CHalsteadDifficulty.ql +++ b/cpp/ql/src/Metrics/Classes/CHalsteadDifficulty.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricClass mc diff --git a/cpp/ql/src/Metrics/Classes/CHalsteadEffort.ql b/cpp/ql/src/Metrics/Classes/CHalsteadEffort.ql index ad87c50c72e..af6f72e9b77 100644 --- a/cpp/ql/src/Metrics/Classes/CHalsteadEffort.ql +++ b/cpp/ql/src/Metrics/Classes/CHalsteadEffort.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricClass mc diff --git a/cpp/ql/src/Metrics/Classes/CHalsteadLength.ql b/cpp/ql/src/Metrics/Classes/CHalsteadLength.ql index 417ce921996..88d179be9ea 100644 --- a/cpp/ql/src/Metrics/Classes/CHalsteadLength.ql +++ b/cpp/ql/src/Metrics/Classes/CHalsteadLength.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricClass mc diff --git a/cpp/ql/src/Metrics/Classes/CHalsteadVocabulary.ql b/cpp/ql/src/Metrics/Classes/CHalsteadVocabulary.ql index 086b4cec070..b351f918e71 100644 --- a/cpp/ql/src/Metrics/Classes/CHalsteadVocabulary.ql +++ b/cpp/ql/src/Metrics/Classes/CHalsteadVocabulary.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricClass mc diff --git a/cpp/ql/src/Metrics/Classes/CHalsteadVolume.ql b/cpp/ql/src/Metrics/Classes/CHalsteadVolume.ql index a99ddec6d5d..7fc17ed221d 100644 --- a/cpp/ql/src/Metrics/Classes/CHalsteadVolume.ql +++ b/cpp/ql/src/Metrics/Classes/CHalsteadVolume.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricClass mc diff --git a/cpp/ql/src/Metrics/Classes/CInheritanceDepth.ql b/cpp/ql/src/Metrics/Classes/CInheritanceDepth.ql index 77e9414f9fd..e6ae8bb62c7 100644 --- a/cpp/ql/src/Metrics/Classes/CInheritanceDepth.ql +++ b/cpp/ql/src/Metrics/Classes/CInheritanceDepth.ql @@ -8,9 +8,9 @@ * @metricAggregate avg max * @tags modularity */ + import cpp from Class c where c.fromSource() -select c, c.getMetrics().getInheritanceDepth() as n -order by n desc +select c, c.getMetrics().getInheritanceDepth() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.ql b/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.ql index c6dbe2f762e..b41d8f9392b 100644 --- a/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.ql +++ b/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.ql @@ -9,9 +9,9 @@ * @metricAggregate avg max * @tags modularity */ + import cpp from Class c where c.fromSource() -select c, c.getMetrics().getLackOfCohesionCK() as n -order by n desc +select c, c.getMetrics().getLackOfCohesionCK() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CLackOfCohesionHS.ql b/cpp/ql/src/Metrics/Classes/CLackOfCohesionHS.ql index 49812f29183..484213e113a 100644 --- a/cpp/ql/src/Metrics/Classes/CLackOfCohesionHS.ql +++ b/cpp/ql/src/Metrics/Classes/CLackOfCohesionHS.ql @@ -8,9 +8,9 @@ * @metricAggregate avg max * @tags modularity */ + import cpp from Class c where c.fromSource() -select c, c.getMetrics().getLackOfCohesionHS() as n -order by n desc +select c, c.getMetrics().getLackOfCohesionHS() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CLinesOfCode.ql b/cpp/ql/src/Metrics/Classes/CLinesOfCode.ql index f958732e479..8a3ea53b553 100644 --- a/cpp/ql/src/Metrics/Classes/CLinesOfCode.ql +++ b/cpp/ql/src/Metrics/Classes/CLinesOfCode.ql @@ -8,13 +8,12 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from Class c, int n -where c.fromSource() - and n = c.getMetrics().getNumberOfMembers() - + sum(Function f | - c.getACanonicalMemberFunction() = f | - f.getMetrics().getNumberOfLinesOfCode()) -select c, n -order by n desc +where + c.fromSource() and + n = c.getMetrics().getNumberOfMembers() + + sum(Function f | c.getACanonicalMemberFunction() = f | f.getMetrics().getNumberOfLinesOfCode()) +select c, n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CNumberOfFields.ql b/cpp/ql/src/Metrics/Classes/CNumberOfFields.ql index a8338397536..9baf194735b 100644 --- a/cpp/ql/src/Metrics/Classes/CNumberOfFields.ql +++ b/cpp/ql/src/Metrics/Classes/CNumberOfFields.ql @@ -8,9 +8,9 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from Class c -where c.fromSource() -select c, c.getMetrics().getNumberOfFields() as n -order by n desc +where c.fromSource() +select c, c.getMetrics().getNumberOfFields() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.ql b/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.ql index a027f058aa2..cdc6e12e9d4 100644 --- a/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.ql +++ b/cpp/ql/src/Metrics/Classes/CNumberOfFunctions.ql @@ -8,9 +8,9 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from Class c -where c.fromSource() -select c, c.getMetrics().getNumberOfMemberFunctions() as n -order by n desc +where c.fromSource() +select c, c.getMetrics().getNumberOfMemberFunctions() as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CNumberOfStatements.ql b/cpp/ql/src/Metrics/Classes/CNumberOfStatements.ql index 68298357ed2..d7fd8adc2fc 100644 --- a/cpp/ql/src/Metrics/Classes/CNumberOfStatements.ql +++ b/cpp/ql/src/Metrics/Classes/CNumberOfStatements.ql @@ -10,9 +10,11 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from Class c, int n -where c.fromSource() - and n = count(Stmt s | s.getEnclosingFunction() = c.getACanonicalMemberFunction()) +where + c.fromSource() and + n = count(Stmt s | s.getEnclosingFunction() = c.getACanonicalMemberFunction()) select c, n diff --git a/cpp/ql/src/Metrics/Classes/CPercentageOfComplexCode.ql b/cpp/ql/src/Metrics/Classes/CPercentageOfComplexCode.ql index 30d46951ef2..a51fa57ee07 100644 --- a/cpp/ql/src/Metrics/Classes/CPercentageOfComplexCode.ql +++ b/cpp/ql/src/Metrics/Classes/CPercentageOfComplexCode.ql @@ -9,18 +9,22 @@ * @metricAggregate avg max * @tags complexity */ + import cpp from Class c, int ccLoc, int loc -where c.fromSource() - and ccLoc = sum(Function f | - c.getACanonicalMemberFunction() = f and - f.getMetrics().getCyclomaticComplexity() > 18 | - f.getMetrics().getNumberOfLinesOfCode()) - and loc = sum(Function f | - c.getACanonicalMemberFunction() = f | - f.getMetrics().getNumberOfLinesOfCode()) - + c.getMetrics().getNumberOfMembers() - and loc != 0 -select c, (ccLoc * 100).(float) / loc as n -order by n desc +where + c.fromSource() and + ccLoc = sum(Function f | + c.getACanonicalMemberFunction() = f and + f.getMetrics().getCyclomaticComplexity() > 18 + | + f.getMetrics().getNumberOfLinesOfCode() + ) and + loc = sum(Function f | + c.getACanonicalMemberFunction() = f + | + f.getMetrics().getNumberOfLinesOfCode() + ) + c.getMetrics().getNumberOfMembers() and + loc != 0 +select c, (ccLoc * 100).(float) / loc as n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CResponse.ql b/cpp/ql/src/Metrics/Classes/CResponse.ql index 1d3a8b13a3b..cccaa058efb 100644 --- a/cpp/ql/src/Metrics/Classes/CResponse.ql +++ b/cpp/ql/src/Metrics/Classes/CResponse.ql @@ -10,6 +10,7 @@ * @tags maintainability * complexity */ + import cpp from Class c diff --git a/cpp/ql/src/Metrics/Classes/CSizeOfAPI.ql b/cpp/ql/src/Metrics/Classes/CSizeOfAPI.ql index 353896af952..060c19aa122 100644 --- a/cpp/ql/src/Metrics/Classes/CSizeOfAPI.ql +++ b/cpp/ql/src/Metrics/Classes/CSizeOfAPI.ql @@ -8,10 +8,11 @@ * @metricAggregate avg sum max * @tags modularity */ + import cpp from Class c, int n -where c.fromSource() - and n = count(Function f | c.getAPublicCanonicalMember() = f) -select c, n -order by n desc +where + c.fromSource() and + n = count(Function f | c.getAPublicCanonicalMember() = f) +select c, n order by n desc diff --git a/cpp/ql/src/Metrics/Classes/CSpecialisation.ql b/cpp/ql/src/Metrics/Classes/CSpecialisation.ql index 5abaf44cd58..be71f1f0269 100644 --- a/cpp/ql/src/Metrics/Classes/CSpecialisation.ql +++ b/cpp/ql/src/Metrics/Classes/CSpecialisation.ql @@ -9,6 +9,7 @@ * @metricAggregate avg max * @tags modularity */ + import cpp from Class c diff --git a/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql index 7f12184fec4..7062911ca4d 100644 --- a/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -12,8 +12,5 @@ import ExternalDependencies from File file, int num, string encodedDependency -where - encodedDependencies(file, encodedDependency, num) -select - encodedDependency, num -order by num desc +where encodedDependencies(file, encodedDependency, num) +select encodedDependency, num order by num desc diff --git a/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.qll b/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.qll index 6dfb94aaba6..76074a2441a 100644 --- a/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.qll +++ b/cpp/ql/src/Metrics/Dependencies/ExternalDependencies.qll @@ -4,6 +4,7 @@ * This performs a "technology inventory" by associating each source file * with the libraries it uses. */ + import cpp import semmle.code.cpp.commons.Dependency @@ -12,7 +13,9 @@ import semmle.code.cpp.commons.Dependency */ abstract class LibraryElement extends Element { abstract string getName(); + abstract string getVersion(); + abstract File getAFile(); } @@ -39,16 +42,11 @@ class Library extends LibraryT { string version; Library() { - exists(LibraryElement lib | - this = LibraryTElement(lib, name, version) - ) or exists(@external_package ep | - this = LibraryTExternalPackage(ep, name, version) - ) + exists(LibraryElement lib | this = LibraryTElement(lib, name, version)) or + exists(@external_package ep | this = LibraryTExternalPackage(ep, name, version)) } - string getName() { - result = name - } + string getName() { result = name } string getVersion() { // The versions reported for C/C++ dependencies are just the versions that @@ -64,7 +62,9 @@ class Library extends LibraryT { exists(LibraryElement lib | this = LibraryTElement(lib, _, _) and result = lib.getAFile() - ) or exists(@external_package ep | + ) + or + exists(@external_package ep | this = LibraryTExternalPackage(ep, _, _) and header_to_external_package(unresolveElement(result), ep) ) @@ -77,34 +77,31 @@ class Library extends LibraryT { */ predicate libDependencies(File sourceFile, Library destLib, int num) { num = strictcount(Element source, Element dest, File destFile | - // dependency from source -> dest. - dependsOnSimple(source, dest) and - sourceFile = source.getFile() and - destFile = dest.getFile() and - - // destFile is inside destLib, sourceFile is outside. - destFile = destLib.getAFile() and - not sourceFile = destLib.getAFile() and - - // don't include dependencies from template instantiations that - // may depend back on types in the using code. - not source.isFromTemplateInstantiation(_) and - - // exclude very common dependencies - not destLib.getName() = "linux" and - not destLib.getName().regexpMatch("gcc-[0-9]+") and - not destLib.getName() = "glibc" - ) + // dependency from source -> dest. + dependsOnSimple(source, dest) and + sourceFile = source.getFile() and + destFile = dest.getFile() and + // destFile is inside destLib, sourceFile is outside. + destFile = destLib.getAFile() and + not sourceFile = destLib.getAFile() and + // don't include dependencies from template instantiations that + // may depend back on types in the using code. + not source.isFromTemplateInstantiation(_) and + // exclude very common dependencies + not destLib.getName() = "linux" and + not destLib.getName().regexpMatch("gcc-[0-9]+") and + not destLib.getName() = "glibc" + ) } /** * Generate the table of dependencies for the query (with some * packages that basically all projects depend on excluded). */ -predicate encodedDependencies(File source, string encodedDependency, int num) -{ +predicate encodedDependencies(File source, string encodedDependency, int num) { exists(Library destLib | libDependencies(source, destLib, num) and - encodedDependency = "/" + source.getRelativePath() + "<|>" + destLib.getName() + "<|>" + destLib.getVersion() + encodedDependency = "/" + source.getRelativePath() + "<|>" + destLib.getName() + "<|>" + + destLib.getVersion() ) } diff --git a/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index 10263c3021f..f2c110a0ac1 100644 --- a/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/cpp/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -16,8 +16,7 @@ import ExternalDependencies * recover that information once we are in the dashboard database, using the * ExternalEntity.getASourceLink() method. */ + from File file, int num, string encodedDependency -where - encodedDependencies(file, encodedDependency, num) -select - encodedDependency, file +where encodedDependencies(file, encodedDependency, num) +select encodedDependency, file diff --git a/cpp/ql/src/Metrics/External/FileCompilationDisplayStrings.ql b/cpp/ql/src/Metrics/External/FileCompilationDisplayStrings.ql index deed2611196..3c57afa49c2 100644 --- a/cpp/ql/src/Metrics/External/FileCompilationDisplayStrings.ql +++ b/cpp/ql/src/Metrics/External/FileCompilationDisplayStrings.ql @@ -4,8 +4,9 @@ * @id cpp/file-compilation-display-strings * @metricType fileCompilation */ + import cpp from Compilation c, int i -select c.toString() + ":" + i.toString(), c.toString() + ":" + i.toString() + ":" + c.getFileCompiled(i) - +select c.toString() + ":" + i.toString(), + c.toString() + ":" + i.toString() + ":" + c.getFileCompiled(i) diff --git a/cpp/ql/src/Metrics/External/FileCompilationSourceLinks.ql b/cpp/ql/src/Metrics/External/FileCompilationSourceLinks.ql index e3e88296166..6d0137c77d7 100644 --- a/cpp/ql/src/Metrics/External/FileCompilationSourceLinks.ql +++ b/cpp/ql/src/Metrics/External/FileCompilationSourceLinks.ql @@ -4,8 +4,8 @@ * @id cpp/file-compilation-source-links * @metricType fileCompilation */ + import cpp from Compilation c, int i select c.toString() + ":" + i.toString(), c.getFileCompiled(i) - diff --git a/cpp/ql/src/Metrics/Files/AutogeneratedLOC.ql b/cpp/ql/src/Metrics/Files/AutogeneratedLOC.ql index 38e2589686c..7c6ef5c0f10 100644 --- a/cpp/ql/src/Metrics/Files/AutogeneratedLOC.ql +++ b/cpp/ql/src/Metrics/Files/AutogeneratedLOC.ql @@ -10,12 +10,10 @@ * @metricAggregate sum * @tags maintainability */ - + import cpp import semmle.code.cpp.AutogeneratedFile - + from AutogeneratedFile af where af.fromSource() -select af, af.getMetrics().getNumberOfLinesOfCode() as n -order by n desc - +select af, af.getMetrics().getNumberOfLinesOfCode() as n order by n desc diff --git a/cpp/ql/src/Metrics/Files/ConditionalSegmentConditions.ql b/cpp/ql/src/Metrics/Files/ConditionalSegmentConditions.ql index be7d2190757..ea2f6be5cb6 100644 --- a/cpp/ql/src/Metrics/Files/ConditionalSegmentConditions.ql +++ b/cpp/ql/src/Metrics/Files/ConditionalSegmentConditions.ql @@ -10,6 +10,7 @@ * @tags maintainability * readability */ + import cpp predicate preprocessorOpenCondition(PreprocessorDirective d) { @@ -26,10 +27,12 @@ predicate headerGuard(PreprocessorIfndef notdef) { from File f where f.fromSource() -select f, count(string s | - exists(PreprocessorDirective open | - preprocessorOpenCondition(open) - and not headerGuard(open) - and open.getFile() = f - and s = open.getHead())) - +select f, + count(string s | + exists(PreprocessorDirective open | + preprocessorOpenCondition(open) and + not headerGuard(open) and + open.getFile() = f and + s = open.getHead() + ) + ) diff --git a/cpp/ql/src/Metrics/Files/ConditionalSegmentLines.ql b/cpp/ql/src/Metrics/Files/ConditionalSegmentLines.ql index 9c4efae77e8..a44ce27bf7c 100644 --- a/cpp/ql/src/Metrics/Files/ConditionalSegmentLines.ql +++ b/cpp/ql/src/Metrics/Files/ConditionalSegmentLines.ql @@ -11,78 +11,72 @@ * @tags maintainability * readability */ + import cpp import semmle.code.cpp.headers.MultipleInclusion predicate preprocessorOpenCondition(PreprocessorDirective d, File f, int line) { - (d instanceof PreprocessorIf or - d instanceof PreprocessorIfdef or - d instanceof PreprocessorIfndef) - and - exists(Location l | - l = d.getLocation() | - f = l.getFile() and line = l.getStartLine()) + ( + d instanceof PreprocessorIf or + d instanceof PreprocessorIfdef or + d instanceof PreprocessorIfndef + ) and + exists(Location l | l = d.getLocation() | f = l.getFile() and line = l.getStartLine()) } -predicate preprocessorCloseCondition(PreprocessorDirective d, File f, int line) { - d instanceof PreprocessorEndif - and - exists(Location l | - l = d.getLocation() | - f = l.getFile() and line = l.getStartLine()) +predicate preprocessorCloseCondition(PreprocessorDirective d, File f, int line) { + d instanceof PreprocessorEndif and + exists(Location l | l = d.getLocation() | f = l.getFile() and line = l.getStartLine()) } -private -predicate relevantLine(File f, int line) { +private predicate relevantLine(File f, int line) { preprocessorOpenCondition(_, f, line) or preprocessorCloseCondition(_, f, line) } predicate relevantDirective(PreprocessorDirective d, File f, int line) { - preprocessorOpenCondition(d, f, line) or + preprocessorOpenCondition(d, f, line) or preprocessorCloseCondition(d, f, line) } -private -predicate relevantLineWithRank(File f, int rnk, int line) { +private predicate relevantLineWithRank(File f, int rnk, int line) { line = rank[rnk](int l | relevantLine(f, l) | l) } -private -PreprocessorDirective next(PreprocessorDirective ppd) { - exists(File f, int line, int rnk, int nextLine | - relevantDirective(ppd, f, line) and - relevantLineWithRank(f, rnk, line) and - relevantLineWithRank(f, rnk + 1, nextLine) and - relevantDirective(result, f, nextLine) - ) +private PreprocessorDirective next(PreprocessorDirective ppd) { + exists(File f, int line, int rnk, int nextLine | + relevantDirective(ppd, f, line) and + relevantLineWithRank(f, rnk, line) and + relevantLineWithRank(f, rnk + 1, nextLine) and + relevantDirective(result, f, nextLine) + ) } -private -int level(PreprocessorDirective ppd) { - (relevantDirective(ppd, _, _) - and not exists(PreprocessorDirective previous | ppd = next(previous)) - and result = 0) +private int level(PreprocessorDirective ppd) { + relevantDirective(ppd, _, _) and + not exists(PreprocessorDirective previous | ppd = next(previous)) and + result = 0 or exists(PreprocessorDirective previous | - ppd = next(previous) and - preprocessorOpenCondition(previous, _, _) and - result = level(previous) + 1) + ppd = next(previous) and + preprocessorOpenCondition(previous, _, _) and + result = level(previous) + 1 + ) or exists(PreprocessorDirective previous | - ppd = next(previous) and - preprocessorCloseCondition(previous, _, _) and - result = level(previous) - 1) + ppd = next(previous) and + preprocessorCloseCondition(previous, _, _) and + result = level(previous) - 1 + ) } -private -predicate openWithDepth(int depth, File f, PreprocessorDirective open, int line) { +private predicate openWithDepth(int depth, File f, PreprocessorDirective open, int line) { preprocessorOpenCondition(open, f, line) and - depth = level(open) and + depth = level(open) and depth < 2 // beyond 2, we don't care about the macros anymore } -private -predicate closeWithDepth(int depth, File f, PreprocessorDirective close, int line) { + +private predicate closeWithDepth(int depth, File f, PreprocessorDirective close, int line) { preprocessorCloseCondition(close, f, line) and depth = level(close) - 1 and depth < 2 // beyond 2, we don't care about the macros anymore @@ -92,33 +86,39 @@ predicate length(PreprocessorDirective open, int length) { exists(int depth, File f, int start, int end | openWithDepth(depth, f, open, start) and end = min(PreprocessorDirective endif, int closeLine | - closeWithDepth(depth, f, endif, closeLine) and - closeLine > start| - closeLine) and + closeWithDepth(depth, f, endif, closeLine) and + closeLine > start + | + closeLine + ) and length = end - start - 1 ) } predicate headerGuard(PreprocessorDirective notdef, File f) { - exists(CorrectIncludeGuard g | - notdef = g.getIfndef() and f = notdef.getFile()) + exists(CorrectIncludeGuard g | notdef = g.getIfndef() and f = notdef.getFile()) } predicate headerGuardChild(PreprocessorDirective open) { - exists(File f, PreprocessorDirective headerGuard | - headerGuard(headerGuard, f) and - openWithDepth(1, f, open, _)) + exists(File f, PreprocessorDirective headerGuard | + headerGuard(headerGuard, f) and + openWithDepth(1, f, open, _) + ) } predicate topLevelOpen(PreprocessorDirective open) { - (openWithDepth(0, _, open, _) and not headerGuard(open,_)) + openWithDepth(0, _, open, _) and not headerGuard(open, _) or headerGuardChild(open) } from File f where f.fromSource() -select f, sum(PreprocessorDirective open, int length | - open.getFile() = f and - topLevelOpen(open) and length(open, length) | - length) +select f, + sum(PreprocessorDirective open, int length | + open.getFile() = f and + topLevelOpen(open) and + length(open, length) + | + length + ) diff --git a/cpp/ql/src/Metrics/Files/FAfferentCoupling.ql b/cpp/ql/src/Metrics/Files/FAfferentCoupling.ql index 0aab056038e..e3c91035f58 100644 --- a/cpp/ql/src/Metrics/Files/FAfferentCoupling.ql +++ b/cpp/ql/src/Metrics/Files/FAfferentCoupling.ql @@ -9,9 +9,9 @@ * @tags maintainability * modularity */ + import cpp from File f where f.fromSource() -select f, f.getMetrics().getAfferentCoupling() as n -order by n desc +select f, f.getMetrics().getAfferentCoupling() as n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FCommentRatio.ql b/cpp/ql/src/Metrics/Files/FCommentRatio.ql index a5ebb243fba..578c725116e 100644 --- a/cpp/ql/src/Metrics/Files/FCommentRatio.ql +++ b/cpp/ql/src/Metrics/Files/FCommentRatio.ql @@ -9,9 +9,9 @@ * @tags maintainability * documentation */ + import cpp from File f, int comments, int total where f.fromSource() and numlines(unresolveElement(f), total, _, comments) and total > 0 -select f, 100.0 * (comments.(float) / total.(float)) as ratio -order by ratio desc +select f, 100.0 * (comments.(float) / total.(float)) as ratio order by ratio desc diff --git a/cpp/ql/src/Metrics/Files/FCyclomaticComplexity.ql b/cpp/ql/src/Metrics/Files/FCyclomaticComplexity.ql index f07d0b6eba3..8ec22658a38 100644 --- a/cpp/ql/src/Metrics/Files/FCyclomaticComplexity.ql +++ b/cpp/ql/src/Metrics/Files/FCyclomaticComplexity.ql @@ -9,21 +9,20 @@ * @tags testability * complexity */ + import cpp from File f, float complexity, float loc -where f.fromSource() - and loc = sum(FunctionDeclarationEntry fde | - fde.getFile() = f | - fde.getNumberOfLines()).(float) - and if loc > 0 then - // Weighted average of complexity by function length - complexity = - sum(FunctionDeclarationEntry fde | - fde.getFile() = f | - fde.getNumberOfLines() * fde.getCyclomaticComplexity()).(float) - / - loc - else - complexity = 0 +where + f.fromSource() and + loc = sum(FunctionDeclarationEntry fde | fde.getFile() = f | fde.getNumberOfLines()).(float) and + if loc > 0 + then + // Weighted average of complexity by function length + complexity = sum(FunctionDeclarationEntry fde | + fde.getFile() = f + | + fde.getNumberOfLines() * fde.getCyclomaticComplexity() + ).(float) / loc + else complexity = 0 select f, complexity diff --git a/cpp/ql/src/Metrics/Files/FDirectIncludes.ql b/cpp/ql/src/Metrics/Files/FDirectIncludes.ql index a5d6cabf839..35ae06ff9c3 100644 --- a/cpp/ql/src/Metrics/Files/FDirectIncludes.ql +++ b/cpp/ql/src/Metrics/Files/FDirectIncludes.ql @@ -10,9 +10,11 @@ * @tags maintainability * modularity */ + import cpp from File f, int n -where f.fromSource() - and n = count(Include i | i.getFile() = f) +where + f.fromSource() and + n = count(Include i | i.getFile() = f) select f, n diff --git a/cpp/ql/src/Metrics/Files/FEfferentCoupling.ql b/cpp/ql/src/Metrics/Files/FEfferentCoupling.ql index 3e2116ac877..4bf9ba1555f 100644 --- a/cpp/ql/src/Metrics/Files/FEfferentCoupling.ql +++ b/cpp/ql/src/Metrics/Files/FEfferentCoupling.ql @@ -10,9 +10,9 @@ * modularity * maintainability */ + import cpp from File f where f.fromSource() -select f, f.getMetrics().getEfferentCoupling() as n -order by n desc +select f, f.getMetrics().getEfferentCoupling() as n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FHalsteadBugs.ql b/cpp/ql/src/Metrics/Files/FHalsteadBugs.ql index cf2adc20761..6a782a6466a 100644 --- a/cpp/ql/src/Metrics/Files/FHalsteadBugs.ql +++ b/cpp/ql/src/Metrics/Files/FHalsteadBugs.ql @@ -9,6 +9,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricFile mc diff --git a/cpp/ql/src/Metrics/Files/FHalsteadDifficulty.ql b/cpp/ql/src/Metrics/Files/FHalsteadDifficulty.ql index 3bebb9d3b49..c2a69b7f24c 100644 --- a/cpp/ql/src/Metrics/Files/FHalsteadDifficulty.ql +++ b/cpp/ql/src/Metrics/Files/FHalsteadDifficulty.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricFile mc diff --git a/cpp/ql/src/Metrics/Files/FHalsteadEffort.ql b/cpp/ql/src/Metrics/Files/FHalsteadEffort.ql index b61e6ae1b41..5ee2cad6b89 100644 --- a/cpp/ql/src/Metrics/Files/FHalsteadEffort.ql +++ b/cpp/ql/src/Metrics/Files/FHalsteadEffort.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricFile mc diff --git a/cpp/ql/src/Metrics/Files/FHalsteadLength.ql b/cpp/ql/src/Metrics/Files/FHalsteadLength.ql index 3dfef610895..55a6293a3d8 100644 --- a/cpp/ql/src/Metrics/Files/FHalsteadLength.ql +++ b/cpp/ql/src/Metrics/Files/FHalsteadLength.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricFile mc diff --git a/cpp/ql/src/Metrics/Files/FHalsteadVocabulary.ql b/cpp/ql/src/Metrics/Files/FHalsteadVocabulary.ql index 1a4ba70b886..93237473499 100644 --- a/cpp/ql/src/Metrics/Files/FHalsteadVocabulary.ql +++ b/cpp/ql/src/Metrics/Files/FHalsteadVocabulary.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricFile mc diff --git a/cpp/ql/src/Metrics/Files/FHalsteadVolume.ql b/cpp/ql/src/Metrics/Files/FHalsteadVolume.ql index 9bd1501f755..26df8ffbead 100644 --- a/cpp/ql/src/Metrics/Files/FHalsteadVolume.ql +++ b/cpp/ql/src/Metrics/Files/FHalsteadVolume.ql @@ -8,6 +8,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from MetricFile mc diff --git a/cpp/ql/src/Metrics/Files/FLines.ql b/cpp/ql/src/Metrics/Files/FLines.ql index ca1cf5676f5..a4c5895d4c1 100644 --- a/cpp/ql/src/Metrics/Files/FLines.ql +++ b/cpp/ql/src/Metrics/Files/FLines.ql @@ -8,9 +8,9 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from File f where f.fromSource() -select f, f.getMetrics().getNumberOfLines() as n -order by n desc +select f, f.getMetrics().getNumberOfLines() as n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FLinesOfCode.ql b/cpp/ql/src/Metrics/Files/FLinesOfCode.ql index 33d1bfd6b2b..07c8934115c 100644 --- a/cpp/ql/src/Metrics/Files/FLinesOfCode.ql +++ b/cpp/ql/src/Metrics/Files/FLinesOfCode.ql @@ -12,9 +12,9 @@ * @tags maintainability * complexity */ + import cpp from File f where f.fromSource() -select f, f.getMetrics().getNumberOfLinesOfCode() as n -order by n desc +select f, f.getMetrics().getNumberOfLinesOfCode() as n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FLinesOfCommentedOutCode.ql b/cpp/ql/src/Metrics/Files/FLinesOfCommentedOutCode.ql index 6ad0e469a8e..495464d633b 100644 --- a/cpp/ql/src/Metrics/Files/FLinesOfCommentedOutCode.ql +++ b/cpp/ql/src/Metrics/Files/FLinesOfCommentedOutCode.ql @@ -9,12 +9,9 @@ * @id cpp/lines-of-commented-out-code-in-files * @tags documentation */ - + import Documentation.CommentedOutCode from File f, int n -where n = sum(CommentedOutCode comment | - comment.getFile() = f | - comment.numCodeLines()) -select f, n -order by n desc +where n = sum(CommentedOutCode comment | comment.getFile() = f | comment.numCodeLines()) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FLinesOfComments.ql b/cpp/ql/src/Metrics/Files/FLinesOfComments.ql index 05f8ccf9e5b..4787587474e 100644 --- a/cpp/ql/src/Metrics/Files/FLinesOfComments.ql +++ b/cpp/ql/src/Metrics/Files/FLinesOfComments.ql @@ -12,9 +12,9 @@ * @tags maintainability * documentation */ + import cpp from File f where f.fromSource() -select f, f.getMetrics().getNumberOfLinesOfComments() as n -order by n desc +select f, f.getMetrics().getNumberOfLinesOfComments() as n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql b/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql index aae928b9fd1..24b32eed231 100644 --- a/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql +++ b/cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCode.ql @@ -12,12 +12,15 @@ * @tags testability * modularity */ + import external.CodeDuplication from File f, int n -where n = count(int line | - exists(DuplicateBlock d | d.sourceFile() = f | - line in [d.sourceStartLine()..d.sourceEndLine()]) - and not whitelistedLineForDuplication(f, line)) -select f, n -order by n desc +where + n = count(int line | + exists(DuplicateBlock d | d.sourceFile() = f | + line in [d.sourceStartLine() .. d.sourceEndLine()] + ) and + not whitelistedLineForDuplication(f, line) + ) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FMacroRatio.ql b/cpp/ql/src/Metrics/Files/FMacroRatio.ql index 8a224fa7f52..6c07c34d964 100644 --- a/cpp/ql/src/Metrics/Files/FMacroRatio.ql +++ b/cpp/ql/src/Metrics/Files/FMacroRatio.ql @@ -10,20 +10,22 @@ * @tags maintainability * readability */ + import cpp predicate macroLines(File f, int line) { - exists(MacroInvocation mi | + exists(MacroInvocation mi | mi.getFile() = f and - mi.getLocation().getStartLine() = line) + mi.getLocation().getStartLine() = line + ) } -predicate macroLineCount(File f, int num) { - num = count(int line | macroLines(f, line)) -} +predicate macroLineCount(File f, int num) { num = count(int line | macroLines(f, line)) } from MetricFile f, int macroLines, int loc -where f.fromSource() and loc = f.getNumberOfLinesOfCode() and loc > 0 and - macroLineCount(f, macroLines) -select f, 100.0 * (macroLines.(float) / loc.(float)) as ratio -order by ratio desc +where + f.fromSource() and + loc = f.getNumberOfLinesOfCode() and + loc > 0 and + macroLineCount(f, macroLines) +select f, 100.0 * (macroLines.(float) / loc.(float)) as ratio order by ratio desc diff --git a/cpp/ql/src/Metrics/Files/FNumberOfClasses.ql b/cpp/ql/src/Metrics/Files/FNumberOfClasses.ql index 88a2a8dcc9f..845ff5d0994 100644 --- a/cpp/ql/src/Metrics/Files/FNumberOfClasses.ql +++ b/cpp/ql/src/Metrics/Files/FNumberOfClasses.ql @@ -8,10 +8,11 @@ * @tags maintainability * modularity */ + import cpp from File f, int n -where f.fromSource() - and n = count(Class c | c.getAFile() = f) -select f, n -order by n desc +where + f.fromSource() and + n = count(Class c | c.getAFile() = f) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FNumberOfTests.ql b/cpp/ql/src/Metrics/Files/FNumberOfTests.ql index 5ed8230bd99..a474b986203 100644 --- a/cpp/ql/src/Metrics/Files/FNumberOfTests.ql +++ b/cpp/ql/src/Metrics/Files/FNumberOfTests.ql @@ -9,17 +9,17 @@ * @id cpp/tests-in-files * @tags maintainability */ + import cpp Expr getTest() { - // cppunit tests; https://freedesktop.org/wiki/Software/cppunit/ - result.(FunctionCall).getTarget().hasQualifiedName("CppUnit", _, "addTest") - or - // boost tests; http://www.boost.org/ - result.(FunctionCall).getTarget().hasQualifiedName("boost::unit_test", "make_test_case") + // cppunit tests; https://freedesktop.org/wiki/Software/cppunit/ + result.(FunctionCall).getTarget().hasQualifiedName("CppUnit", _, "addTest") + or + // boost tests; http://www.boost.org/ + result.(FunctionCall).getTarget().hasQualifiedName("boost::unit_test", "make_test_case") } from File f, int n where n = strictcount(Expr e | e = getTest() and e.getFile() = f) -select f, n -order by n desc +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/Files/FTimeInFrontend.ql b/cpp/ql/src/Metrics/Files/FTimeInFrontend.ql index 46001cec583..fd6527ee184 100644 --- a/cpp/ql/src/Metrics/Files/FTimeInFrontend.ql +++ b/cpp/ql/src/Metrics/Files/FTimeInFrontend.ql @@ -10,12 +10,14 @@ * @tags maintainability * testability */ + import cpp from string x, float t -where exists(Compilation c, int i | - x = c.toString() + ":" + i.toString() and - t = 1000 * c.getFrontendCpuSeconds(i) and - c.getFileCompiled(i).fromSource()) -select x, t -order by t desc +where + exists(Compilation c, int i | + x = c.toString() + ":" + i.toString() and + t = 1000 * c.getFrontendCpuSeconds(i) and + c.getFileCompiled(i).fromSource() + ) +select x, t order by t desc diff --git a/cpp/ql/src/Metrics/Files/FTodoComments.ql b/cpp/ql/src/Metrics/Files/FTodoComments.ql index 8265f625316..5e869a106c4 100644 --- a/cpp/ql/src/Metrics/Files/FTodoComments.ql +++ b/cpp/ql/src/Metrics/Files/FTodoComments.ql @@ -9,13 +9,17 @@ * @tags maintainability * documentation */ + import cpp from File f, int n -where f.fromSource() - and n = count(Comment c | - c.getFile() = f and - (c.getContents().matches("%TODO%") or - c.getContents().matches("%FIXME%"))) -select f, n -order by n +where + f.fromSource() and + n = count(Comment c | + c.getFile() = f and + ( + c.getContents().matches("%TODO%") or + c.getContents().matches("%FIXME%") + ) + ) +select f, n order by n diff --git a/cpp/ql/src/Metrics/Files/FTransitiveIncludes.ql b/cpp/ql/src/Metrics/Files/FTransitiveIncludes.ql index 7f195627d91..2cde128e4bd 100644 --- a/cpp/ql/src/Metrics/Files/FTransitiveIncludes.ql +++ b/cpp/ql/src/Metrics/Files/FTransitiveIncludes.ql @@ -12,9 +12,11 @@ * @tags maintainability * modularity */ + import cpp from File f, int n -where f.fromSource() - and n = count(File g | g = f.getAnIncludedFile+()) +where + f.fromSource() and + n = count(File g | g = f.getAnIncludedFile+()) select f, n diff --git a/cpp/ql/src/Metrics/Files/FTransitiveSourceIncludes.ql b/cpp/ql/src/Metrics/Files/FTransitiveSourceIncludes.ql index 31461daff31..d480699b8c4 100644 --- a/cpp/ql/src/Metrics/Files/FTransitiveSourceIncludes.ql +++ b/cpp/ql/src/Metrics/Files/FTransitiveSourceIncludes.ql @@ -14,15 +14,17 @@ * @tags maintainability * modularity */ + import cpp predicate isInCodebase(File f) { - exists(string prefix | - sourceLocationPrefix(prefix) | - f.getAbsolutePath().prefix(prefix.length()) = prefix) + exists(string prefix | sourceLocationPrefix(prefix) | + f.getAbsolutePath().prefix(prefix.length()) = prefix + ) } from File f, int n -where f.fromSource() - and n = count(File g | g = f.getAnIncludedFile+() and isInCodebase(g)) +where + f.fromSource() and + n = count(File g | g = f.getAnIncludedFile+() and isInCodebase(g)) select f, n diff --git a/cpp/ql/src/Metrics/Files/FunctionLength.ql b/cpp/ql/src/Metrics/Files/FunctionLength.ql index 8fb4be15b69..d753e5b5ddc 100644 --- a/cpp/ql/src/Metrics/Files/FunctionLength.ql +++ b/cpp/ql/src/Metrics/Files/FunctionLength.ql @@ -9,11 +9,15 @@ * @tags maintainability * readability */ + import cpp from File f where f.fromSource() -select f, avg(MetricFunction fn | - fn.getFile() = f - and not fn instanceof MemberFunction | - fn.getNumberOfLinesOfCode()) +select f, + avg(MetricFunction fn | + fn.getFile() = f and + not fn instanceof MemberFunction + | + fn.getNumberOfLinesOfCode() + ) diff --git a/cpp/ql/src/Metrics/Files/NumberOfFunctions.ql b/cpp/ql/src/Metrics/Files/NumberOfFunctions.ql index 28994d42ce8..3fa9387935b 100644 --- a/cpp/ql/src/Metrics/Files/NumberOfFunctions.ql +++ b/cpp/ql/src/Metrics/Files/NumberOfFunctions.ql @@ -8,10 +8,13 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from File f where f.fromSource() -select f, count(Function fn | - fn.getFile() = f - and not fn instanceof MemberFunction) +select f, + count(Function fn | + fn.getFile() = f and + not fn instanceof MemberFunction + ) diff --git a/cpp/ql/src/Metrics/Files/NumberOfGlobals.ql b/cpp/ql/src/Metrics/Files/NumberOfGlobals.ql index affed3116a2..36ebfcf4d8a 100644 --- a/cpp/ql/src/Metrics/Files/NumberOfGlobals.ql +++ b/cpp/ql/src/Metrics/Files/NumberOfGlobals.ql @@ -8,10 +8,11 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp predicate macroLocation(File f, int startLine, int endLine) { - exists(MacroInvocation mi, Location l | + exists(MacroInvocation mi, Location l | l = mi.getLocation() and l.getFile() = f and l.getStartLine() = startLine and @@ -20,19 +21,17 @@ predicate macroLocation(File f, int startLine, int endLine) { } pragma[nomagic] -Location getVariableLocation(Variable v) { - result = v.getLocation() -} +Location getVariableLocation(Variable v) { result = v.getLocation() } predicate globalLocation(GlobalVariable gv, File f, int startLine, int endLine) { - exists(Location l | + exists(Location l | l = getVariableLocation(gv) and l.hasLocationInfo(f.getAbsolutePath(), startLine, _, endLine, _) ) } predicate inMacro(GlobalVariable gv) { - exists(File f, int macroStart, int macroEnd, int varStart, int varEnd | + exists(File f, int macroStart, int macroEnd, int varStart, int varEnd | macroLocation(f, macroStart, macroEnd) and globalLocation(gv, f, varStart, varEnd) and varStart >= macroStart and diff --git a/cpp/ql/src/Metrics/Files/NumberOfParameters.ql b/cpp/ql/src/Metrics/Files/NumberOfParameters.ql index 6c64eaebfe2..447c2af0e88 100644 --- a/cpp/ql/src/Metrics/Files/NumberOfParameters.ql +++ b/cpp/ql/src/Metrics/Files/NumberOfParameters.ql @@ -9,10 +9,14 @@ * @tags testability * complexity */ + import cpp from File f where f.fromSource() -select f, avg(Function fn | - fn.getFile() = f and not fn instanceof MemberFunction | - fn.getNumberOfParameters()) +select f, + avg(Function fn | + fn.getFile() = f and not fn instanceof MemberFunction + | + fn.getNumberOfParameters() + ) diff --git a/cpp/ql/src/Metrics/Files/NumberOfPublicFunctions.ql b/cpp/ql/src/Metrics/Files/NumberOfPublicFunctions.ql index 8643f55862b..f3cfee52e93 100644 --- a/cpp/ql/src/Metrics/Files/NumberOfPublicFunctions.ql +++ b/cpp/ql/src/Metrics/Files/NumberOfPublicFunctions.ql @@ -9,11 +9,14 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from File f where f.fromSource() -select f, count(Function fn | - fn.getFile() = f - and not fn instanceof MemberFunction - and not fn.isStatic()) +select f, + count(Function fn | + fn.getFile() = f and + not fn instanceof MemberFunction and + not fn.isStatic() + ) diff --git a/cpp/ql/src/Metrics/Files/NumberOfPublicGlobals.ql b/cpp/ql/src/Metrics/Files/NumberOfPublicGlobals.ql index 2abef690d82..953f4a4366e 100644 --- a/cpp/ql/src/Metrics/Files/NumberOfPublicGlobals.ql +++ b/cpp/ql/src/Metrics/Files/NumberOfPublicGlobals.ql @@ -10,10 +10,11 @@ * @tags maintainability * modularity */ + import cpp predicate macroLocation(File f, int startLine, int endLine) { - exists(MacroInvocation mi, Location l | + exists(MacroInvocation mi, Location l | l = mi.getLocation() and l.getFile() = f and l.getStartLine() = startLine and @@ -22,18 +23,17 @@ predicate macroLocation(File f, int startLine, int endLine) { } pragma[nomagic] -Location getVariableLocation(Variable v) { - result = v.getLocation() -} +Location getVariableLocation(Variable v) { result = v.getLocation() } predicate globalLocation(GlobalVariable gv, File f, int startLine, int endLine) { - exists(Location l | - l = getVariableLocation(gv) and - l.hasLocationInfo(f.getAbsolutePath(), startLine, _, endLine, _)) + exists(Location l | + l = getVariableLocation(gv) and + l.hasLocationInfo(f.getAbsolutePath(), startLine, _, endLine, _) + ) } predicate inMacro(GlobalVariable gv) { - exists(File f, int macroStart, int macroEnd, int varStart, int varEnd | + exists(File f, int macroStart, int macroEnd, int varStart, int varEnd | macroLocation(f, macroStart, macroEnd) and globalLocation(gv, f, varStart, varEnd) and varStart >= macroStart and @@ -43,7 +43,9 @@ predicate inMacro(GlobalVariable gv) { from File f where f.fromSource() -select f, count(GlobalVariable gv | - gv.getFile() = f - and not gv.isStatic() - and not inMacro(gv)) +select f, + count(GlobalVariable gv | + gv.getFile() = f and + not gv.isStatic() and + not inMacro(gv) + ) diff --git a/cpp/ql/src/Metrics/Functions/FunCyclomaticComplexity.ql b/cpp/ql/src/Metrics/Functions/FunCyclomaticComplexity.ql index 30b24868d45..44b64a46809 100644 --- a/cpp/ql/src/Metrics/Functions/FunCyclomaticComplexity.ql +++ b/cpp/ql/src/Metrics/Functions/FunCyclomaticComplexity.ql @@ -12,6 +12,7 @@ * maintainability * complexity */ + import cpp from Function f diff --git a/cpp/ql/src/Metrics/Functions/FunIterationNestingDepth.ql b/cpp/ql/src/Metrics/Functions/FunIterationNestingDepth.ql index 7cf3dd94808..bc1cb095fd1 100644 --- a/cpp/ql/src/Metrics/Functions/FunIterationNestingDepth.ql +++ b/cpp/ql/src/Metrics/Functions/FunIterationNestingDepth.ql @@ -9,13 +9,13 @@ * @tags maintainability * complexity */ + import cpp -int iterationDepth(Stmt l) { - result = count(Loop other | l.getParent*() = other) -} +int iterationDepth(Stmt l) { result = count(Loop other | l.getParent*() = other) } from Function f, int depth -where depth = max(Stmt s | s.getEnclosingFunction() = f | iterationDepth(s)) - and strictcount(f.getEntryPoint()) = 1 +where + depth = max(Stmt s | s.getEnclosingFunction() = f | iterationDepth(s)) and + strictcount(f.getEntryPoint()) = 1 select f, depth order by depth desc diff --git a/cpp/ql/src/Metrics/Functions/FunLinesOfCode.ql b/cpp/ql/src/Metrics/Functions/FunLinesOfCode.ql index dd458edb10b..979640a9626 100644 --- a/cpp/ql/src/Metrics/Functions/FunLinesOfCode.ql +++ b/cpp/ql/src/Metrics/Functions/FunLinesOfCode.ql @@ -10,6 +10,7 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from Function f diff --git a/cpp/ql/src/Metrics/Functions/FunLinesOfComments.ql b/cpp/ql/src/Metrics/Functions/FunLinesOfComments.ql index 98440e505d1..283c2085a41 100644 --- a/cpp/ql/src/Metrics/Functions/FunLinesOfComments.ql +++ b/cpp/ql/src/Metrics/Functions/FunLinesOfComments.ql @@ -11,6 +11,7 @@ * @tags maintainability * documentation */ + import cpp from Function f diff --git a/cpp/ql/src/Metrics/Functions/FunNumberOfCalls.ql b/cpp/ql/src/Metrics/Functions/FunNumberOfCalls.ql index ee972222c36..bfff5f160b6 100644 --- a/cpp/ql/src/Metrics/Functions/FunNumberOfCalls.ql +++ b/cpp/ql/src/Metrics/Functions/FunNumberOfCalls.ql @@ -9,6 +9,7 @@ * @tags maintainability * complexity */ + import cpp predicate callToOperator(FunctionCall fc) { @@ -17,11 +18,13 @@ predicate callToOperator(FunctionCall fc) { } from Function f, int n, int o -where strictcount(f.getEntryPoint()) = 1 - and o = count(FunctionCall c | - c.getEnclosingFunction() = f and - not c.isInMacroExpansion() and - not c.isCompilerGenerated() and - not callToOperator(c)) - and n = o / count(f.getBlock()) +where + strictcount(f.getEntryPoint()) = 1 and + o = count(FunctionCall c | + c.getEnclosingFunction() = f and + not c.isInMacroExpansion() and + not c.isCompilerGenerated() and + not callToOperator(c) + ) and + n = o / count(f.getBlock()) select f, n diff --git a/cpp/ql/src/Metrics/Functions/FunNumberOfParameters.ql b/cpp/ql/src/Metrics/Functions/FunNumberOfParameters.ql index f05191a5237..2e8f8de50ac 100644 --- a/cpp/ql/src/Metrics/Functions/FunNumberOfParameters.ql +++ b/cpp/ql/src/Metrics/Functions/FunNumberOfParameters.ql @@ -9,6 +9,7 @@ * @tags testability * maintainability */ + import cpp from Function f diff --git a/cpp/ql/src/Metrics/Functions/FunNumberOfStatements.ql b/cpp/ql/src/Metrics/Functions/FunNumberOfStatements.ql index 07211dc78f5..565afe71c82 100644 --- a/cpp/ql/src/Metrics/Functions/FunNumberOfStatements.ql +++ b/cpp/ql/src/Metrics/Functions/FunNumberOfStatements.ql @@ -8,9 +8,11 @@ * @metricAggregate avg sum max * @tags maintainability */ + import cpp from Function f, int n -where strictcount(f.getEntryPoint()) = 1 and - n = count(Stmt s | s.getEnclosingFunction() = f) +where + strictcount(f.getEntryPoint()) = 1 and + n = count(Stmt s | s.getEnclosingFunction() = f) select f, n diff --git a/cpp/ql/src/Metrics/Functions/FunPercentageOfComments.ql b/cpp/ql/src/Metrics/Functions/FunPercentageOfComments.ql index ebeefec5b42..f00f8590055 100644 --- a/cpp/ql/src/Metrics/Functions/FunPercentageOfComments.ql +++ b/cpp/ql/src/Metrics/Functions/FunPercentageOfComments.ql @@ -10,6 +10,7 @@ * @tags maintainability * documentation */ + import cpp from MetricFunction f diff --git a/cpp/ql/src/Metrics/Functions/StatementNestingDepth.ql b/cpp/ql/src/Metrics/Functions/StatementNestingDepth.ql index 0e9ce896611..7b5dda4f7b0 100644 --- a/cpp/ql/src/Metrics/Functions/StatementNestingDepth.ql +++ b/cpp/ql/src/Metrics/Functions/StatementNestingDepth.ql @@ -10,10 +10,11 @@ * @tags maintainability * complexity */ + import cpp from MetricFunction f, int depth -where depth = f.getNestingDepth() - and strictcount(f.getEntryPoint()) = 1 -select f, depth -order by depth desc +where + depth = f.getNestingDepth() and + strictcount(f.getEntryPoint()) = 1 +select f, depth order by depth desc diff --git a/cpp/ql/src/Metrics/History/HChurn.ql b/cpp/ql/src/Metrics/History/HChurn.ql index d11f012b310..9e10ec124b3 100644 --- a/cpp/ql/src/Metrics/History/HChurn.ql +++ b/cpp/ql/src/Metrics/History/HChurn.ql @@ -10,14 +10,17 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f, int n -where n = sum(Commit entry, int churn | - churn = entry.getRecentChurnForFile(f) and - not artificialChange(entry) | - churn) - and exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, n -order by n desc +where + n = sum(Commit entry, int churn | + churn = entry.getRecentChurnForFile(f) and + not artificialChange(entry) + | + churn + ) and + exists(f.getMetrics().getNumberOfLinesOfCode()) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/History/HLinesAdded.ql b/cpp/ql/src/Metrics/History/HLinesAdded.ql index d3333ce6f99..3046d125eec 100644 --- a/cpp/ql/src/Metrics/History/HLinesAdded.ql +++ b/cpp/ql/src/Metrics/History/HLinesAdded.ql @@ -10,14 +10,17 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f, int n -where n = sum(Commit entry, int churn | - churn = entry.getRecentAdditionsForFile(f) and - not artificialChange(entry) | - churn) - and exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, n -order by n desc +where + n = sum(Commit entry, int churn | + churn = entry.getRecentAdditionsForFile(f) and + not artificialChange(entry) + | + churn + ) and + exists(f.getMetrics().getNumberOfLinesOfCode()) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/History/HLinesDeleted.ql b/cpp/ql/src/Metrics/History/HLinesDeleted.ql index 4f4faea93a8..becf9f804db 100644 --- a/cpp/ql/src/Metrics/History/HLinesDeleted.ql +++ b/cpp/ql/src/Metrics/History/HLinesDeleted.ql @@ -10,14 +10,17 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f, int n -where n = sum(Commit entry, int churn | - churn = entry.getRecentDeletionsForFile(f) - and not artificialChange(entry) | - churn) - and exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, n -order by n desc +where + n = sum(Commit entry, int churn | + churn = entry.getRecentDeletionsForFile(f) and + not artificialChange(entry) + | + churn + ) and + exists(f.getMetrics().getNumberOfLinesOfCode()) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql b/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql index 5acfc693099..2d8f1f382c3 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfAuthors.ql @@ -9,10 +9,10 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f where exists(f.getMetrics().getNumberOfLinesOfCode()) select f, count(Author author | author.getAnEditedFile() = f) - diff --git a/cpp/ql/src/Metrics/History/HNumberOfChanges.ql b/cpp/ql/src/Metrics/History/HNumberOfChanges.ql index 450d19a0e34..451dc575636 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfChanges.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfChanges.ql @@ -10,10 +10,10 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f where exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, count(Commit svn | - f = svn.getAnAffectedFile() and not artificialChange(svn)) +select f, count(Commit svn | f = svn.getAnAffectedFile() and not artificialChange(svn)) diff --git a/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql b/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql index 9b42b3fe486..ecd5c4ccb0d 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfCoCommits.ql @@ -10,16 +10,12 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS -int committedFiles(Commit commit) { - result = count(commit.getAnAffectedFile()) -} +int committedFiles(Commit commit) { result = count(commit.getAnAffectedFile()) } from File f where exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, avg(Commit commit | - commit.getAnAffectedFile() = f | - committedFiles(commit) - 1) - +select f, avg(Commit commit | commit.getAnAffectedFile() = f | committedFiles(commit) - 1) diff --git a/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql b/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql index 7f60ab7b8dc..73c5d09c249 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfReCommits.ql @@ -10,23 +10,27 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS predicate inRange(Commit first, Commit second) { first.getAnAffectedFile() = second.getAnAffectedFile() and first != second and - exists(int n | n = first.getDate().daysTo(second.getDate()) and - n >= 0 and n < 5) + exists(int n | + n = first.getDate().daysTo(second.getDate()) and + n >= 0 and + n < 5 + ) } int recommitsForFile(File f) { result = count(Commit recommit | - f = recommit.getAnAffectedFile() and - exists(Commit prev | inRange(prev, recommit))) + f = recommit.getAnAffectedFile() and + exists(Commit prev | inRange(prev, recommit)) + ) } from File f where exists(f.getMetrics().getNumberOfLinesOfCode()) select f, recommitsForFile(f) - diff --git a/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql b/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql index 0f645f08060..7f40c8706d9 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfRecentAuthors.ql @@ -10,15 +10,18 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f where exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, count(Author author | - exists(Commit e | - e = author.getACommit() and - f = e.getAnAffectedFile() and - e.daysToNow() <= 180 and - not artificialChange(e))) - +select f, + count(Author author | + exists(Commit e | + e = author.getACommit() and + f = e.getAnAffectedFile() and + e.daysToNow() <= 180 and + not artificialChange(e) + ) + ) diff --git a/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql b/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql index 9ae8912dddc..751449eb5aa 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql @@ -9,14 +9,16 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f -where exists(Commit e | - e.getAnAffectedFile() = f and - e.daysToNow() <= 180 and - not artificialChange(e)) - and exists(f.getMetrics().getNumberOfLinesOfCode()) +where + exists(Commit e | + e.getAnAffectedFile() = f and + e.daysToNow() <= 180 and + not artificialChange(e) + ) and + exists(f.getMetrics().getNumberOfLinesOfCode()) select f, 1 - diff --git a/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql b/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql index 34db4dbd367..dcd3272c418 100644 --- a/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql +++ b/cpp/ql/src/Metrics/History/HNumberOfRecentChanges.ql @@ -9,15 +9,16 @@ * @tags external-data * @deprecated */ + import cpp import external.VCS from File f, int n -where n = count(Commit e | - e.getAnAffectedFile() = f and - e.daysToNow() <= 180 and - not artificialChange(e)) - and exists(f.getMetrics().getNumberOfLinesOfCode()) -select f, n -order by n desc - +where + n = count(Commit e | + e.getAnAffectedFile() = f and + e.daysToNow() <= 180 and + not artificialChange(e) + ) and + exists(f.getMetrics().getNumberOfLinesOfCode()) +select f, n order by n desc diff --git a/cpp/ql/src/Metrics/Internal/CallableDisplayStrings.ql b/cpp/ql/src/Metrics/Internal/CallableDisplayStrings.ql index d02e7f1165d..9923ebc26a4 100644 --- a/cpp/ql/src/Metrics/Internal/CallableDisplayStrings.ql +++ b/cpp/ql/src/Metrics/Internal/CallableDisplayStrings.ql @@ -4,6 +4,7 @@ * @id cpp/callable-display-strings * @metricType callable */ + import cpp from Function f diff --git a/cpp/ql/src/Metrics/Internal/CallableExtents.ql b/cpp/ql/src/Metrics/Internal/CallableExtents.ql index 4f1c5e4ac0f..80c798b19ff 100644 --- a/cpp/ql/src/Metrics/Internal/CallableExtents.ql +++ b/cpp/ql/src/Metrics/Internal/CallableExtents.ql @@ -4,6 +4,7 @@ * @id cpp/callable-extents * @metricType callable */ + import cpp /** @@ -13,18 +14,18 @@ import cpp */ class RangeFunction extends Function { /** - * Holds if this function is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). - */ + * Holds if this function is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - super.getLocation().hasLocationInfo(path, sl, sc, _, _) - and + super.getLocation().hasLocationInfo(path, sl, sc, _, _) and ( - this.getBlock().getLocation().hasLocationInfo(path, _, _, el, ec) or - (not exists(this.getBlock()) and el = sl+1 and ec=1) + this.getBlock().getLocation().hasLocationInfo(path, _, _, el, ec) + or + not exists(this.getBlock()) and el = sl + 1 and ec = 1 ) } } diff --git a/cpp/ql/src/Metrics/Internal/CallableSourceLinks.ql b/cpp/ql/src/Metrics/Internal/CallableSourceLinks.ql index f6d1667b019..7430aa30a07 100644 --- a/cpp/ql/src/Metrics/Internal/CallableSourceLinks.ql +++ b/cpp/ql/src/Metrics/Internal/CallableSourceLinks.ql @@ -4,6 +4,7 @@ * @id cpp/callable-source-links * @metricType callable */ + import cpp from Function f diff --git a/cpp/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql b/cpp/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql index e11fdda6e62..68c966467f2 100644 --- a/cpp/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql +++ b/cpp/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql @@ -4,6 +4,7 @@ * @id cpp/reference-type-display-strings * @metricType reftype */ + import cpp from Class c diff --git a/cpp/ql/src/Metrics/Internal/ReftypeSourceLinks.ql b/cpp/ql/src/Metrics/Internal/ReftypeSourceLinks.ql index d5918eaeb1f..1d03a2b6e64 100644 --- a/cpp/ql/src/Metrics/Internal/ReftypeSourceLinks.ql +++ b/cpp/ql/src/Metrics/Internal/ReftypeSourceLinks.ql @@ -4,6 +4,7 @@ * @id cpp/reference-type-source-links * @metricType reftype */ + import cpp from Class c diff --git a/cpp/ql/src/Metrics/Namespaces/AbstractNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/AbstractNamespaces.ql index 9a9fd5dabc7..2d1440813f4 100644 --- a/cpp/ql/src/Metrics/Namespaces/AbstractNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/AbstractNamespaces.ql @@ -6,11 +6,12 @@ * @chart.type bar * @tags maintainability */ + import cpp from Namespace n, float c -where n.fromSource() - and c = n.getMetrics().getAbstractness() - and c > 0.20 -select n as Namespace, c as Abstractness -order by Abstractness desc +where + n.fromSource() and + c = n.getMetrics().getAbstractness() and + c > 0.2 +select n as Namespace, c as Abstractness order by Abstractness desc diff --git a/cpp/ql/src/Metrics/Namespaces/ConcreteNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/ConcreteNamespaces.ql index b6b9c541959..c71f654f275 100644 --- a/cpp/ql/src/Metrics/Namespaces/ConcreteNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/ConcreteNamespaces.ql @@ -5,11 +5,12 @@ * @id cpp/concrete-namespaces * @tags maintainability */ + import cpp from Namespace n, float c -where n.fromSource() - and c = n.getMetrics().getAbstractness() - and c = 0 -select n as Namespace, c as Abstractness -order by Abstractness desc +where + n.fromSource() and + c = n.getMetrics().getAbstractness() and + c = 0 +select n as Namespace, c as Abstractness order by Abstractness desc diff --git a/cpp/ql/src/Metrics/Namespaces/HighAfferentCouplingNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/HighAfferentCouplingNamespaces.ql index 58cb60142a4..89dae1a3404 100644 --- a/cpp/ql/src/Metrics/Namespaces/HighAfferentCouplingNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/HighAfferentCouplingNamespaces.ql @@ -7,11 +7,12 @@ * @chart.type bar * @tags maintainability */ + import cpp from Namespace n, int c -where n.fromSource() - and c = n.getMetrics().getAfferentCoupling() - and c > 20 -select n as Namespace, c as AfferentCoupling -order by AfferentCoupling desc +where + n.fromSource() and + c = n.getMetrics().getAfferentCoupling() and + c > 20 +select n as Namespace, c as AfferentCoupling order by AfferentCoupling desc diff --git a/cpp/ql/src/Metrics/Namespaces/HighDistanceFromMainLineNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/HighDistanceFromMainLineNamespaces.ql index 85d5064a346..ce5553749d2 100644 --- a/cpp/ql/src/Metrics/Namespaces/HighDistanceFromMainLineNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/HighDistanceFromMainLineNamespaces.ql @@ -7,11 +7,12 @@ * @chart.type bar * @tags maintainability */ + import cpp from Namespace n, float c -where n.fromSource() - and c = n.getMetrics().getDistanceFromMain() - and c > 0.7 -select n as Namespace, c as DistanceFromMainline -order by DistanceFromMainline desc +where + n.fromSource() and + c = n.getMetrics().getDistanceFromMain() and + c > 0.7 +select n as Namespace, c as DistanceFromMainline order by DistanceFromMainline desc diff --git a/cpp/ql/src/Metrics/Namespaces/HighEfferentCouplingNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/HighEfferentCouplingNamespaces.ql index c119ca878b2..1de659f1384 100644 --- a/cpp/ql/src/Metrics/Namespaces/HighEfferentCouplingNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/HighEfferentCouplingNamespaces.ql @@ -7,11 +7,12 @@ * @tags maintainability * modularity */ + import cpp from Namespace n, int c -where n.fromSource() - and c = n.getMetrics().getEfferentCoupling() - and c > 20 -select n as Namespace, c as EfferentCoupling -order by EfferentCoupling desc +where + n.fromSource() and + c = n.getMetrics().getEfferentCoupling() and + c > 20 +select n as Namespace, c as EfferentCoupling order by EfferentCoupling desc diff --git a/cpp/ql/src/Metrics/Namespaces/StableNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/StableNamespaces.ql index 15a079588ad..3fd17ee4066 100644 --- a/cpp/ql/src/Metrics/Namespaces/StableNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/StableNamespaces.ql @@ -6,11 +6,12 @@ * @chart.type bar * @tags maintainability */ + import cpp from Namespace n, float c -where n.fromSource() - and c = n.getMetrics().getInstability() - and c < 0.2 -select n as Namespace, c as Instability -order by Instability desc +where + n.fromSource() and + c = n.getMetrics().getInstability() and + c < 0.2 +select n as Namespace, c as Instability order by Instability desc diff --git a/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.ql b/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.ql index 966988e3c33..8e150d62f03 100644 --- a/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.ql +++ b/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.ql @@ -6,11 +6,12 @@ * @chart.type bar * @tags maintainability */ + import cpp from Namespace n, float c -where n.fromSource() - and c = n.getMetrics().getInstability() - and c > 0.8 -select n as Package, c as Instability -order by Instability desc +where + n.fromSource() and + c = n.getMetrics().getInstability() and + c > 0.8 +select n as Package, c as Instability order by Instability desc diff --git a/cpp/ql/src/Microsoft/CallWithNullSAL.ql b/cpp/ql/src/Microsoft/CallWithNullSAL.ql index a3ba5fd15e0..d5c74547c3e 100644 --- a/cpp/ql/src/Microsoft/CallWithNullSAL.ql +++ b/cpp/ql/src/Microsoft/CallWithNullSAL.ql @@ -7,15 +7,16 @@ * @problem.severity warning * @tags reliability */ + import cpp import SAL from Parameter p, Call c, Expr arg -where any(SALNotNull a).getDeclaration() = p - and c.getTarget() = p.getFunction() - and arg = c.getArgument(p.getIndex()) - and nullValue(arg) -select arg, "Argument ("+ arg.toString() - +") for parameter $@ in call to "+ c.getTarget().getName() + - " may be null, but a SAL annotation forbids this.", - p, p.getName() +where + any(SALNotNull a).getDeclaration() = p and + c.getTarget() = p.getFunction() and + arg = c.getArgument(p.getIndex()) and + nullValue(arg) +select arg, + "Argument (" + arg.toString() + ") for parameter $@ in call to " + c.getTarget().getName() + + " may be null, but a SAL annotation forbids this.", p, p.getName() diff --git a/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql b/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql index b8b06b9146c..64f398fa855 100644 --- a/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql +++ b/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql @@ -8,12 +8,14 @@ * @problem.severity warning * @tags reliability */ + import SAL from Function f, FunctionCall call -where call.getTarget() = f - and call instanceof ExprInVoidContext - and any(SALCheckReturn a).getDeclaration() = f - and not getOptions().okToIgnoreReturnValue(call) -select call, "Return value of $@ discarded although a SAL annotation "+ - "requires inspecting it.", f, f.getName() +where + call.getTarget() = f and + call instanceof ExprInVoidContext and + any(SALCheckReturn a).getDeclaration() = f and + not getOptions().okToIgnoreReturnValue(call) +select call, "Return value of $@ discarded although a SAL annotation " + "requires inspecting it.", + f, f.getName() diff --git a/cpp/ql/src/Microsoft/InconsistentSAL.ql b/cpp/ql/src/Microsoft/InconsistentSAL.ql index 081c7439adb..e5965e62b49 100644 --- a/cpp/ql/src/Microsoft/InconsistentSAL.ql +++ b/cpp/ql/src/Microsoft/InconsistentSAL.ql @@ -6,6 +6,7 @@ * @problem.severity warning * @tags reliability */ + import SAL /** Holds if `e` has SAL annotation `name`. */ @@ -25,16 +26,16 @@ predicate inheritsDeclAnnotations(DeclarationEntry e) { ) or // or is a parameter of a function with such an annotation - inheritsDeclAnnotations(e.(ParameterDeclarationEntry) - .getFunctionDeclarationEntry()) + inheritsDeclAnnotations(e.(ParameterDeclarationEntry).getFunctionDeclarationEntry()) } from DeclarationEntry e1, DeclarationEntry e2, string name -where e1.getDeclaration() = e2.getDeclaration() - and hasAnnotation(e1, name) - and not hasAnnotation(e2, name) - and not name = "_Use_decl_annotations_" - and not inheritsDeclAnnotations(e2) -select e2, "Missing SAL annotation "+ name + - " in "+ e2.toString() +" although it is present on $@.", - e1, e1.toString() +where + e1.getDeclaration() = e2.getDeclaration() and + hasAnnotation(e1, name) and + not hasAnnotation(e2, name) and + not name = "_Use_decl_annotations_" and + not inheritsDeclAnnotations(e2) +select e2, + "Missing SAL annotation " + name + " in " + e2.toString() + " although it is present on $@.", e1, + e1.toString() diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index 545af55bffa..b9f6c2d037d 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -15,14 +15,10 @@ class SALAnnotation extends MacroInvocation { } /** Returns the `Declaration` annotated by `this`. */ - Declaration getDeclaration() { - annotatesAt(this, result.getADeclarationEntry(), _, _) - } + Declaration getDeclaration() { annotatesAt(this, result.getADeclarationEntry(), _, _) } /** Returns the `DeclarationEntry` annotated by `this`. */ - DeclarationEntry getDeclarationEntry() { - annotatesAt(this, result, _, _) - } + DeclarationEntry getDeclarationEntry() { annotatesAt(this, result, _, _) } } /* @@ -47,12 +43,12 @@ class SALNotNull extends SALAnnotation { m.getName().matches("\\_Out%") or m.getName() = "_Ret_notnull_" ) - ) - and - exists(Type t - | t = this.getDeclaration().(Variable).getType() or + ) and + exists(Type t | + t = this.getDeclaration().(Variable).getType() or t = this.getDeclaration().(Function).getType() - | t.getUnspecifiedType() instanceof PointerType + | + t.getUnspecifiedType() instanceof PointerType ) } } @@ -60,9 +56,9 @@ class SALNotNull extends SALAnnotation { class SALMaybeNull extends SALAnnotation { SALMaybeNull() { exists(SALMacro m | m = this.getMacro() | - m.getName().matches("%\\_opt\\_%") or - m.getName().matches("\\_Ret_maybenull\\_%") or - m.getName() = "_Result_nullonfailure_" + m.getName().matches("%\\_opt\\_%") or + m.getName().matches("\\_Ret_maybenull\\_%") or + m.getName() = "_Result_nullonfailure_" ) } } @@ -71,8 +67,7 @@ class SALMaybeNull extends SALAnnotation { * Implementation details */ -private predicate annotatesAt(SALAnnotation a, DeclarationEntry e, - File file, int idx) { +private predicate annotatesAt(SALAnnotation a, DeclarationEntry e, File file, int idx) { a = salElementAt(file, idx) and ( // Base case: `a` right before `e` @@ -95,8 +90,10 @@ private SALElement salElementAt(File file, int idx) { interestingLoc(file, result, interestingStartPos(file, idx)) } -/** Holds if an SALElement element at character `result` comes at - * position `idx` in `file`. */ +/** + * Holds if an SALElement element at character `result` comes at + * position `idx` in `file`. + */ private int interestingStartPos(File file, int idx) { result = rank[idx](int otherStart | interestingLoc(file, _, otherStart)) } diff --git a/cpp/ql/src/Options.qll b/cpp/ql/src/Options.qll index bc56cf3488d..353d012e339 100644 --- a/cpp/ql/src/Options.qll +++ b/cpp/ql/src/Options.qll @@ -13,8 +13,7 @@ import cpp * Customizable predicates that specify information about * the behavior of the program being analyzed. */ -class CustomOptions extends Options -{ +class CustomOptions extends Options { /** * Holds if we wish to override the "may return NULL" inference for this * call. If this holds, then rather than trying to infer whether this @@ -24,9 +23,7 @@ class CustomOptions extends Options * By default, this handles the `Xstrdup` function used by the CVS * project. */ - override predicate overrideReturnsNull(Call call) { - Options.super.overrideReturnsNull(call) - } + override predicate overrideReturnsNull(Call call) { Options.super.overrideReturnsNull(call) } /** * Holds if this call may return NULL. This is only used if @@ -35,9 +32,7 @@ class CustomOptions extends Options * By default, this handles the `Xstrdup` function used by the CVS * project. */ - override predicate returnsNull(Call call) { - Options.super.returnsNull(call) - } + override predicate returnsNull(Call call) { Options.super.returnsNull(call) } /** * Holds if a call to this function will never return. @@ -46,9 +41,7 @@ class CustomOptions extends Options * `longjmp`, `error`, `__builtin_unreachable` and any function with a * `noreturn` attribute. */ - override predicate exits(Function f) { - Options.super.exits(f) - } + override predicate exits(Function f) { Options.super.exits(f) } /** * Holds if evaluating expression `e` will never return, or can be assumed @@ -59,18 +52,14 @@ class CustomOptions extends Options * (note that in this case if the hint is wrong and the expression is reached at * runtime, the program's behaviour is undefined) */ - override predicate exprExits(Expr e) { - Options.super.exprExits(e) - } + override predicate exprExits(Expr e) { Options.super.exprExits(e) } /** * Holds if function `f` should always have its return value checked. * * By default holds only for `fgets`. */ - override predicate alwaysCheckReturnValue(Function f) { - Options.super.alwaysCheckReturnValue(f) - } + override predicate alwaysCheckReturnValue(Function f) { Options.super.alwaysCheckReturnValue(f) } /** * Holds if it is reasonable to ignore the return value of function @@ -89,33 +78,25 @@ class CustomOptions extends Options * A type that acts as a mutex. */ class CustomMutexType extends MutexType { - CustomMutexType() { - none() - } + CustomMutexType() { none() } /** * Holds if `fc` is a call that always locks mutex `arg` * of this type. */ - override predicate mustlockAccess(FunctionCall fc, Expr arg) { - none() - } + override predicate mustlockAccess(FunctionCall fc, Expr arg) { none() } /** * Holds if `fc` is a call that tries to lock mutex `arg` * of this type, but may return without success. - */ - override predicate trylockAccess(FunctionCall fc, Expr arg) { - none() - } + */ + override predicate trylockAccess(FunctionCall fc, Expr arg) { none() } /** * Holds if `fc` is a call that unlocks mutex `arg` * of this type. - */ - override predicate unlockAccess(FunctionCall fc, Expr arg) { - none() - } + */ + override predicate unlockAccess(FunctionCall fc, Expr arg) { none() } } /** @@ -125,9 +106,7 @@ class CustomMutexType extends MutexType { * older `Options.qll` files. It should not be removed or modified by * end users. */ -predicate overrideReturnsNull(Call call) { - none() -} +predicate overrideReturnsNull(Call call) { none() } /** * DEPRECATED: customize `CustomOptions.returnsNull` instead. @@ -136,9 +115,7 @@ predicate overrideReturnsNull(Call call) { * older `Options.qll` files. It should not be removed or modified by * end users. */ -predicate returnsNull(Call call) { - none() -} +predicate returnsNull(Call call) { none() } /** * DEPRECATED: customize `CustomOptions.exits` instead. @@ -147,9 +124,7 @@ predicate returnsNull(Call call) { * older `Options.qll` files. It should not be removed or modified by * end users. */ -predicate exits(Function f) { - none() -} +predicate exits(Function f) { none() } /** * DEPRECATED: customize `CustomOptions.exprExits` instead. @@ -158,9 +133,7 @@ predicate exits(Function f) { * older `Options.qll` files. It should not be removed or modified by * end users. */ -predicate exprExits(Expr e) { - none() -} +predicate exprExits(Expr e) { none() } /** * DEPRECATED: customize `CustomOptions.alwaysCheckReturnValue` instead. @@ -169,9 +142,7 @@ predicate exprExits(Expr e) { * older `Options.qll` files. It should not be removed or modified by * end users. */ -predicate alwaysCheckReturnValue(Function f) { - none() -} +predicate alwaysCheckReturnValue(Function f) { none() } /** * DEPRECATED: customize `CustomOptions.okToIgnoreReturnValue` instead. @@ -180,6 +151,4 @@ predicate alwaysCheckReturnValue(Function f) { * older `Options.qll` files. It should not be removed or modified by * end users. */ -predicate okToIgnoreReturnValue(FunctionCall fc) { - none() -} +predicate okToIgnoreReturnValue(FunctionCall fc) { none() } diff --git a/cpp/ql/src/PointsTo/Debug.ql b/cpp/ql/src/PointsTo/Debug.ql index dce39ff83eb..c667af836ec 100644 --- a/cpp/ql/src/PointsTo/Debug.ql +++ b/cpp/ql/src/PointsTo/Debug.ql @@ -9,11 +9,13 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class FieldAccessPT extends PointsToExpr -{ override predicate interesting() { this instanceof FieldAccess } } +class FieldAccessPT extends PointsToExpr { + override predicate interesting() { this instanceof FieldAccess } +} from Function outer, FieldAccessPT fa -where outer.hasName("rtLnDeliverableMayContainDividends") - and fa.(FieldAccess).getTarget().hasName("pfFunction") - and fa.getEnclosingFunction() = outer +where + outer.hasName("rtLnDeliverableMayContainDividends") and + fa.(FieldAccess).getTarget().hasName("pfFunction") and + fa.getEnclosingFunction() = outer select fa, fa.pointsTo() diff --git a/cpp/ql/src/PointsTo/PreparedStagedPointsTo.ql b/cpp/ql/src/PointsTo/PreparedStagedPointsTo.ql index e0290e04734..14a15761053 100644 --- a/cpp/ql/src/PointsTo/PreparedStagedPointsTo.ql +++ b/cpp/ql/src/PointsTo/PreparedStagedPointsTo.ql @@ -6,8 +6,7 @@ * @deprecated This query is not suitable for production use and has been deprecated. */ - import semmle.code.cpp.pointsto.PointsTo - - select count(int set, Element location | setlocations(set, unresolveElement(location))), - count(int set, Element element | pointstosets(set, unresolveElement(element))) +import semmle.code.cpp.pointsto.PointsTo +select count(int set, Element location | setlocations(set, unresolveElement(location))), + count(int set, Element element | pointstosets(set, unresolveElement(element))) diff --git a/cpp/ql/src/PointsTo/Stats.ql b/cpp/ql/src/PointsTo/Stats.ql index a57a0f39832..605934f986e 100644 --- a/cpp/ql/src/PointsTo/Stats.ql +++ b/cpp/ql/src/PointsTo/Stats.ql @@ -9,14 +9,10 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -predicate inc(int set, int cnt) -{ - (setflow(set,_) or setflow(_, set)) and +predicate inc(int set, int cnt) { + (setflow(set, _) or setflow(_, set)) and cnt = count(int i | setflow(i, set) and i != set) } -select - count(int set | inc(set, _)) as total, - count(int set | inc(set, 0)) as nullary, - count(int set | inc(set, 1)) as unary, - total - nullary - unary as rest +select count(int set | inc(set, _)) as total, count(int set | inc(set, 0)) as nullary, + count(int set | inc(set, 1)) as unary, total - nullary - unary as rest diff --git a/cpp/ql/src/PointsTo/TaintedFormatStrings.ql b/cpp/ql/src/PointsTo/TaintedFormatStrings.ql index a681fc3e22f..1b671697573 100644 --- a/cpp/ql/src/PointsTo/TaintedFormatStrings.ql +++ b/cpp/ql/src/PointsTo/TaintedFormatStrings.ql @@ -9,11 +9,12 @@ import cpp import semmle.code.cpp.pointsto.PointsTo import semmle.code.cpp.pointsto.CallGraph -predicate inputArgument(string function, int arg) -{ - (function = "read" and arg = 1) or - (function = "fread" and arg = 0) or - (function = "fgets" and arg = 0) +predicate inputArgument(string function, int arg) { + function = "read" and arg = 1 + or + function = "fread" and arg = 0 + or + function = "fgets" and arg = 0 // ... add more } @@ -21,52 +22,81 @@ predicate inputBuffer(Expr e) { exists(FunctionCall fc, string fname, int i | fc.getTarget().getName() = fname and inputArgument(fname, i) and - e = fc.getArgument(i)) + e = fc.getArgument(i) + ) } -class InputBuffer extends PointsToExpr -{ +class InputBuffer extends PointsToExpr { InputBuffer() { inputBuffer(this) } + override predicate interesting() { inputBuffer(this) } } -predicate formatArgument(string function, int i) -{ - (function = "printf" and i = 0) or - (function = "fprintf" and i = 1) or - (function = "sprintf" and i = 1) or - (function = "snprintf" and i = 2) or - (function = "d_printf" and i = 0) or - (function = "talloc_asprintf" and i = 1) or - (function = "fstr_sprintf" and i = 1) or - (function = "talloc_asprintf_append" and i = 1) or - (function = "d_fprintf" and i = 1) or - (function = "asprintf" and i = 1) or - (function = "talloc_asprintf_append_buffer" and i = 1) or - (function = "fdprintf" and i = 1) or - (function = "d_vfprintf" and i = 1) or - (function = "smb_xvasprintf" and i = 1) or - (function = "asprintf_strupper_m" and i = 1) or - (function = "talloc_asprintf_strupper_m" and i = 1) or - (function = "sprintf_append" and i = 4) or - (function = "x_vfprintf" and i = 1) or - (function = "x_fprintf" and i = 1) or - (function = "vasprintf" and i = 1) or - (function = "ldb_asprintf_errstring" and i = 1) or - (function = "talloc_vasprintf" and i = 1) or - (function = "talloc_vasprintf" and i = 1) or - (function = "fprintf_file" and i = 1) or - (function = "vsnprintf" and i = 2) or - (function = "talloc_vasprintf_append" and i = 1) or - (function = "__talloc_vaslenprintf_append" and i = 2) or - (function = "talloc_vasprintf_append_buffer" and i = 1) or - (function = "fprintf_attr" and i = 2) or - (function = "vprintf" and i = 0) or - (function = "vsprintf" and i = 1) +predicate formatArgument(string function, int i) { + function = "printf" and i = 0 + or + function = "fprintf" and i = 1 + or + function = "sprintf" and i = 1 + or + function = "snprintf" and i = 2 + or + function = "d_printf" and i = 0 + or + function = "talloc_asprintf" and i = 1 + or + function = "fstr_sprintf" and i = 1 + or + function = "talloc_asprintf_append" and i = 1 + or + function = "d_fprintf" and i = 1 + or + function = "asprintf" and i = 1 + or + function = "talloc_asprintf_append_buffer" and i = 1 + or + function = "fdprintf" and i = 1 + or + function = "d_vfprintf" and i = 1 + or + function = "smb_xvasprintf" and i = 1 + or + function = "asprintf_strupper_m" and i = 1 + or + function = "talloc_asprintf_strupper_m" and i = 1 + or + function = "sprintf_append" and i = 4 + or + function = "x_vfprintf" and i = 1 + or + function = "x_fprintf" and i = 1 + or + function = "vasprintf" and i = 1 + or + function = "ldb_asprintf_errstring" and i = 1 + or + function = "talloc_vasprintf" and i = 1 + or + function = "talloc_vasprintf" and i = 1 + or + function = "fprintf_file" and i = 1 + or + function = "vsnprintf" and i = 2 + or + function = "talloc_vasprintf_append" and i = 1 + or + function = "__talloc_vaslenprintf_append" and i = 2 + or + function = "talloc_vasprintf_append_buffer" and i = 1 + or + function = "fprintf_attr" and i = 2 + or + function = "vprintf" and i = 0 + or + function = "vsprintf" and i = 1 } -predicate formatBuffer(Expr e) -{ +predicate formatBuffer(Expr e) { exists(FunctionCall fc, string fname, int i | fc.getTarget().getName() = fname and formatArgument(fname, i) and @@ -74,16 +104,17 @@ predicate formatBuffer(Expr e) ) } -class FormatBuffer extends PointsToExpr -{ +class FormatBuffer extends PointsToExpr { FormatBuffer() { formatBuffer(this) } + override predicate interesting() { formatBuffer(this) } } -predicate potentialViolation(InputBuffer source, FormatBuffer dest) -{ +predicate potentialViolation(InputBuffer source, FormatBuffer dest) { source.pointsTo() = dest.pointsTo() and - not exists(FunctionCall fc | fc = dest and fc.getTarget().hasName("lang_msg_rotate") and fc.getArgument(1) instanceof Literal) + not exists(FunctionCall fc | + fc = dest and fc.getTarget().hasName("lang_msg_rotate") and fc.getArgument(1) instanceof Literal + ) } from InputBuffer source, FormatBuffer dest diff --git a/cpp/ql/src/Power of 10/Rule 1/UseOfRecursion.ql b/cpp/ql/src/Power of 10/Rule 1/UseOfRecursion.ql index 8ac430a00a5..334703b424c 100644 --- a/cpp/ql/src/Power of 10/Rule 1/UseOfRecursion.ql +++ b/cpp/ql/src/Power of 10/Rule 1/UseOfRecursion.ql @@ -13,14 +13,14 @@ import cpp class RecursiveCall extends FunctionCall { - RecursiveCall() { - this.getTarget().calls*(this.getEnclosingFunction()) - } + RecursiveCall() { this.getTarget().calls*(this.getEnclosingFunction()) } } from RecursiveCall call, string msg -where if (call.getTarget() = call.getEnclosingFunction()) then - msg = "This call directly invokes its containing function $@." - else - msg = "The function " + call.getEnclosingFunction() + " is indirectly recursive via this call to $@." +where + if call.getTarget() = call.getEnclosingFunction() + then msg = "This call directly invokes its containing function $@." + else + msg = "The function " + call.getEnclosingFunction() + + " is indirectly recursive via this call to $@." select call, msg, call.getTarget(), call.getTarget().getName() diff --git a/cpp/ql/src/Power of 10/Rule 2/BoundedLoopIterations.ql b/cpp/ql/src/Power of 10/Rule 2/BoundedLoopIterations.ql index d662de5b60d..7ac45014988 100644 --- a/cpp/ql/src/Power of 10/Rule 2/BoundedLoopIterations.ql +++ b/cpp/ql/src/Power of 10/Rule 2/BoundedLoopIterations.ql @@ -32,7 +32,8 @@ predicate upperBoundCheck(Loop loop, VariableAccess checked) { rop.getGreaterOperand().(VariableAccess).getTarget().isConst() or validVarForBound(loop, rop.getGreaterOperand().(VariableAccess).getTarget()) ) and - not rop.getGreaterOperand() instanceof CharLiteral) + not rop.getGreaterOperand() instanceof CharLiteral + ) } predicate lowerBoundCheck(Loop loop, VariableAccess checked) { @@ -45,20 +46,23 @@ predicate lowerBoundCheck(Loop loop, VariableAccess checked) { rop.getLesserOperand().(VariableAccess).getTarget().isConst() or validVarForBound(loop, rop.getLesserOperand().(VariableAccess).getTarget()) ) and - not rop.getLesserOperand() instanceof CharLiteral) + not rop.getLesserOperand() instanceof CharLiteral + ) } VariableAccess getAnIncrement(Variable var) { result.getTarget() = var and ( result.getParent() instanceof IncrementOperation - or + or exists(AssignAddExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0) - or + or exists(AssignExpr a | a.getLValue() = result | - a.getRValue() = - any(AddExpr ae | ae.getAnOperand() = var.getAnAccess() and - ae.getAnOperand().getValue().toInt() > 0)) + a.getRValue() = any(AddExpr ae | + ae.getAnOperand() = var.getAnAccess() and + ae.getAnOperand().getValue().toInt() > 0 + ) + ) ) } @@ -66,55 +70,70 @@ VariableAccess getADecrement(Variable var) { result.getTarget() = var and ( result.getParent() instanceof DecrementOperation - or + or exists(AssignSubExpr a | a.getLValue() = result and a.getRValue().getValue().toInt() > 0) - or + or exists(AssignExpr a | a.getLValue() = result | - a.getRValue() = - any(SubExpr ae | ae.getLeftOperand() = var.getAnAccess() and - ae.getRightOperand().getValue().toInt() > 0)) + a.getRValue() = any(SubExpr ae | + ae.getLeftOperand() = var.getAnAccess() and + ae.getRightOperand().getValue().toInt() > 0 + ) + ) ) } -predicate inScope(Loop l, Stmt s) { - l.getAChild*() = s -} +predicate inScope(Loop l, Stmt s) { l.getAChild*() = s } predicate reachesNoInc(VariableAccess source, ControlFlowNode target) { - (upperBoundCheck(_, source) and source.getASuccessor() = target) or - exists(ControlFlowNode mid | reachesNoInc(source, mid) and not mid = getAnIncrement(source.getTarget()) | - target = mid.getASuccessor() and - inScope(source.getEnclosingStmt(), target.getEnclosingStmt())) + upperBoundCheck(_, source) and source.getASuccessor() = target + or + exists(ControlFlowNode mid | + reachesNoInc(source, mid) and not mid = getAnIncrement(source.getTarget()) + | + target = mid.getASuccessor() and + inScope(source.getEnclosingStmt(), target.getEnclosingStmt()) + ) } predicate reachesNoDec(VariableAccess source, ControlFlowNode target) { - (lowerBoundCheck(_, source) and source.getASuccessor() = target) or - exists(ControlFlowNode mid | reachesNoDec(source, mid) and not mid = getADecrement(source.getTarget()) | - target = mid.getASuccessor() and - inScope(source.getEnclosingStmt(), target.getEnclosingStmt())) + lowerBoundCheck(_, source) and source.getASuccessor() = target + or + exists(ControlFlowNode mid | + reachesNoDec(source, mid) and not mid = getADecrement(source.getTarget()) + | + target = mid.getASuccessor() and + inScope(source.getEnclosingStmt(), target.getEnclosingStmt()) + ) } predicate hasSafeBound(Loop l) { - exists(VariableAccess bound | upperBoundCheck(l, bound) | - not reachesNoInc(bound, bound) - ) or exists(VariableAccess bound | lowerBoundCheck(l, bound) | - not reachesNoDec(bound, bound) - ) or exists(l.getControllingExpr().getValue()) + exists(VariableAccess bound | upperBoundCheck(l, bound) | not reachesNoInc(bound, bound)) + or + exists(VariableAccess bound | lowerBoundCheck(l, bound) | not reachesNoDec(bound, bound)) + or + exists(l.getControllingExpr().getValue()) } from Loop loop, string msg -where not hasSafeBound(loop) and - ( - ( - not upperBoundCheck(loop, _) and - not lowerBoundCheck(loop, _) and - msg = "This loop does not have a fixed bound." - ) or exists(VariableAccess bound | upperBoundCheck(loop, bound) and - reachesNoInc(bound, bound) and - msg = "The loop counter " + bound.getTarget().getName() + " is not always incremented in the loop body." - ) or exists(VariableAccess bound | lowerBoundCheck(loop, bound) and - reachesNoDec(bound, bound) and - msg = "The loop counter " + bound.getTarget().getName() + " is not always decremented in the loop body." - ) +where + not hasSafeBound(loop) and + ( + not upperBoundCheck(loop, _) and + not lowerBoundCheck(loop, _) and + msg = "This loop does not have a fixed bound." + or + exists(VariableAccess bound | + upperBoundCheck(loop, bound) and + reachesNoInc(bound, bound) and + msg = "The loop counter " + bound.getTarget().getName() + + " is not always incremented in the loop body." ) + or + exists(VariableAccess bound | + lowerBoundCheck(loop, bound) and + reachesNoDec(bound, bound) and + msg = "The loop counter " + bound.getTarget().getName() + + " is not always decremented in the loop body." + ) + ) select loop, msg diff --git a/cpp/ql/src/Power of 10/Rule 3/DynamicAllocAfterInit.ql b/cpp/ql/src/Power of 10/Rule 3/DynamicAllocAfterInit.ql index a97eb3163ad..f44ae6e3a7b 100644 --- a/cpp/ql/src/Power of 10/Rule 3/DynamicAllocAfterInit.ql +++ b/cpp/ql/src/Power of 10/Rule 3/DynamicAllocAfterInit.ql @@ -22,12 +22,12 @@ class Initialization extends Function { class Allocation extends FunctionCall { Allocation() { - exists(string name | name = this.getTarget().getName() | - name = "malloc" or name = "calloc") + exists(string name | name = this.getTarget().getName() | name = "malloc" or name = "calloc") } } from Function f, Allocation a -where not f instanceof Initialization and - a.getEnclosingFunction() = f +where + not f instanceof Initialization and + a.getEnclosingFunction() = f select a, "Dynamic memory allocation is only allowed during initialization." diff --git a/cpp/ql/src/Power of 10/Rule 4/FunctionTooLong.ql b/cpp/ql/src/Power of 10/Rule 4/FunctionTooLong.ql index ca866b560c5..b09f9d882c6 100644 --- a/cpp/ql/src/Power of 10/Rule 4/FunctionTooLong.ql +++ b/cpp/ql/src/Power of 10/Rule 4/FunctionTooLong.ql @@ -23,14 +23,17 @@ class MacroFunctionCall extends MacroInvocation { } int logicalLength(FunctionDeclarationEntry f) { - result = count(Stmt s | s.getEnclosingFunction() = f.getFunction() and - s.getFile() = f.getFile() and - not s instanceof Block and - not s instanceof EmptyStmt and - not exists(ForStmt for | s = for.getInitialization()) and - not s.isAffectedByMacro()) + count(MacroFunctionCall mf | mf.getFunction() = f) + result = count(Stmt s | + s.getEnclosingFunction() = f.getFunction() and + s.getFile() = f.getFile() and + not s instanceof Block and + not s instanceof EmptyStmt and + not exists(ForStmt for | s = for.getInitialization()) and + not s.isAffectedByMacro() + ) + count(MacroFunctionCall mf | mf.getFunction() = f) } from FunctionDeclarationEntry f, int n where logicalLength(f) = n and n > 60 -select f.getFunction(), "Function " + f.getName() + " has too many logical lines (" + n + ", while 60 are allowed)." +select f.getFunction(), + "Function " + f.getName() + " has too many logical lines (" + n + ", while 60 are allowed)." diff --git a/cpp/ql/src/Power of 10/Rule 4/OneStmtPerLine.ql b/cpp/ql/src/Power of 10/Rule 4/OneStmtPerLine.ql index d597206c1e0..32ffbc241fb 100644 --- a/cpp/ql/src/Power of 10/Rule 4/OneStmtPerLine.ql +++ b/cpp/ql/src/Power of 10/Rule 4/OneStmtPerLine.ql @@ -18,7 +18,8 @@ class OneLineStmt extends Stmt { not exists(ForStmt for | this = for.getInitialization()) and ( // Either this statement is not touched by a macro at all... - not this.isAffectedByMacro() or + not this.isAffectedByMacro() + or // ... or it's the top-level statement generated by a macro invocation. exists(MacroInvocation mi | this = mi.getAGeneratedElement() | not this.getAChild+() = mi.getAGeneratedElement() @@ -31,11 +32,16 @@ class OneLineStmt extends Stmt { } } -int numStmt(File f, int line) { - result = strictcount(OneLineStmt o | o.onLine(f, line)) -} +int numStmt(File f, int line) { result = strictcount(OneLineStmt o | o.onLine(f, line)) } from File f, int line, OneLineStmt o, int cnt -where numStmt(f, line) = cnt and cnt > 1 and o.onLine(f, line) - and o.getLocation().getStartColumn() = min(OneLineStmt other, int toMin | (other.onLine(f, line)) and (toMin = other.getLocation().getStartColumn()) | toMin) +where + numStmt(f, line) = cnt and + cnt > 1 and + o.onLine(f, line) and + o.getLocation().getStartColumn() = min(OneLineStmt other, int toMin | + other.onLine(f, line) and toMin = other.getLocation().getStartColumn() + | + toMin + ) select o, "This line contains " + cnt + " statements; only one is allowed." diff --git a/cpp/ql/src/Power of 10/Rule 5/AssertionDensity.ql b/cpp/ql/src/Power of 10/Rule 5/AssertionDensity.ql index 3fb56776bd8..278f77d4c89 100644 --- a/cpp/ql/src/Power of 10/Rule 5/AssertionDensity.ql +++ b/cpp/ql/src/Power of 10/Rule 5/AssertionDensity.ql @@ -23,23 +23,29 @@ class MacroFunctionCall extends MacroInvocation { } int logicalLength(FunctionDeclarationEntry f) { - result = count(Stmt s | s.getEnclosingFunction() = f.getFunction() and - s.getFile() = f.getFile() and - not s instanceof Block and - not s instanceof EmptyStmt and - not exists(ForStmt for | s = for.getInitialization()) and - not s.isAffectedByMacro()) + count(MacroFunctionCall mf | mf.getFunction() = f) + result = count(Stmt s | + s.getEnclosingFunction() = f.getFunction() and + s.getFile() = f.getFile() and + not s instanceof Block and + not s instanceof EmptyStmt and + not exists(ForStmt for | s = for.getInitialization()) and + not s.isAffectedByMacro() + ) + count(MacroFunctionCall mf | mf.getFunction() = f) } int assertionCount(FunctionDeclarationEntry f) { - result = count(Assertion a | a.getAsserted().getEnclosingFunction() = f.getFunction() and a.getFile() = f.getFile()) + result = count(Assertion a | + a.getAsserted().getEnclosingFunction() = f.getFunction() and a.getFile() = f.getFile() + ) } from FunctionDeclarationEntry f, int numAsserts, int size, int minSize -where minSize = 20 and +where + minSize = 20 and numAsserts = assertionCount(f) and numAsserts < 2 and size = logicalLength(f) and size > minSize -select f.getFunction(), "Function " + f.getName() + " has " + size + " logical lines, but only " - + numAsserts + " assertion(s) -- minimum is 2 (for functions over " + minSize + " logical lines)." +select f.getFunction(), + "Function " + f.getName() + " has " + size + " logical lines, but only " + numAsserts + + " assertion(s) -- minimum is 2 (for functions over " + minSize + " logical lines)." diff --git a/cpp/ql/src/Power of 10/Rule 5/ConstantAssertion.ql b/cpp/ql/src/Power of 10/Rule 5/ConstantAssertion.ql index ece5a9b37c3..08d0d3ce1b0 100644 --- a/cpp/ql/src/Power of 10/Rule 5/ConstantAssertion.ql +++ b/cpp/ql/src/Power of 10/Rule 5/ConstantAssertion.ql @@ -12,9 +12,9 @@ import semmle.code.cpp.commons.Assertions from Assertion a, string value, string msg -where value = a.getAsserted().getValue() and - if value.toInt() = 0 then - msg = "This assertion is always false." - else - msg = "This assertion is always true." +where + value = a.getAsserted().getValue() and + if value.toInt() = 0 + then msg = "This assertion is always false." + else msg = "This assertion is always true." select a.getAsserted(), msg diff --git a/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql b/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql index 54c892c60e0..b72a00cc6e0 100644 --- a/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql +++ b/cpp/ql/src/Power of 10/Rule 6/GlobalCouldBeStatic.ql @@ -13,9 +13,11 @@ import cpp from GlobalVariable v -where forex(VariableAccess va | va.getTarget() = v | va.getFile() = v.getDefinitionLocation().getFile()) - and not v.hasSpecifier("static") - and strictcount(v.getAnAccess().getEnclosingFunction()) > 1 // If = 1, variable should be function-scope. - and not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere -select v, "The global variable " + v.getName() + " is not accessed outside of " + v.getFile().getBaseName() + - " and could be made static." +where + forex(VariableAccess va | va.getTarget() = v | va.getFile() = v.getDefinitionLocation().getFile()) and + not v.hasSpecifier("static") and + strictcount(v.getAnAccess().getEnclosingFunction()) > 1 and // If = 1, variable should be function-scope. + not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere +select v, + "The global variable " + v.getName() + " is not accessed outside of " + v.getFile().getBaseName() + + " and could be made static." diff --git a/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql b/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql index fe9a079f8c3..86529e116e2 100644 --- a/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql +++ b/cpp/ql/src/Power of 10/Rule 6/VariableScopeTooLarge.ql @@ -12,8 +12,11 @@ import cpp from GlobalVariable v, Function f -where v.getAnAccess().getEnclosingFunction() = f and - strictcount(v.getAnAccess().getEnclosingFunction()) = 1 and - forall(VariableAccess a | a = v.getAnAccess() | exists(a.getEnclosingFunction())) and - not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere -select v, "The variable " + v.getName() + " is only accessed in $@ and should be scoped accordingly.", f, f.getName() +where + v.getAnAccess().getEnclosingFunction() = f and + strictcount(v.getAnAccess().getEnclosingFunction()) = 1 and + forall(VariableAccess a | a = v.getAnAccess() | exists(a.getEnclosingFunction())) and + not v.getADeclarationEntry().getFile() instanceof HeaderFile // intended to be accessed elsewhere +select v, + "The variable " + v.getName() + " is only accessed in $@ and should be scoped accordingly.", f, + f.getName() diff --git a/cpp/ql/src/Power of 10/Rule 7/CheckArguments.ql b/cpp/ql/src/Power of 10/Rule 7/CheckArguments.ql index 4b18e98296c..f32631fe2ee 100644 --- a/cpp/ql/src/Power of 10/Rule 7/CheckArguments.ql +++ b/cpp/ql/src/Power of 10/Rule 7/CheckArguments.ql @@ -12,7 +12,7 @@ import cpp predicate flow(Parameter p, ControlFlowNode n) { - (exists(p.getAnAccess()) and n = p.getFunction().getBlock()) + exists(p.getAnAccess()) and n = p.getFunction().getBlock() or exists(ControlFlowNode mid | flow(p, mid) and not mid = p.getAnAccess() and n = mid.getASuccessor() diff --git a/cpp/ql/src/Power of 10/Rule 7/CheckReturnValues.ql b/cpp/ql/src/Power of 10/Rule 7/CheckReturnValues.ql index 3c4da6b51e7..5bca7123d52 100644 --- a/cpp/ql/src/Power of 10/Rule 7/CheckReturnValues.ql +++ b/cpp/ql/src/Power of 10/Rule 7/CheckReturnValues.ql @@ -11,7 +11,8 @@ import cpp -/** In its full generality, the rule applies to all functions that +/** + * In its full generality, the rule applies to all functions that * return non-void, including things like 'printf' and 'close', * which are routinely not checked because the behavior on success * is the same as the behavior on failure. The recommendation is @@ -27,13 +28,15 @@ predicate whitelist(Function f) { } from FunctionCall c, string msg -where not c.getTarget().getType() instanceof VoidType - and not whitelist(c.getTarget()) - and - ( - (c instanceof ExprInVoidContext and msg = "The return value of non-void function $@ is not checked.") - or - (definition(_, c.getParent()) and not definitionUsePair(_, c.getParent(), _) and - msg = "$@'s return value is stored but not checked.") - ) +where + not c.getTarget().getType() instanceof VoidType and + not whitelist(c.getTarget()) and + ( + c instanceof ExprInVoidContext and + msg = "The return value of non-void function $@ is not checked." + or + definition(_, c.getParent()) and + not definitionUsePair(_, c.getParent(), _) and + msg = "$@'s return value is stored but not checked." + ) select c, msg, c.getTarget() as f, f.getName() diff --git a/cpp/ql/src/Power of 10/Rule 8/AvoidConditionalCompilation.ql b/cpp/ql/src/Power of 10/Rule 8/AvoidConditionalCompilation.ql index 9b7882d677e..d49d51e0b2a 100644 --- a/cpp/ql/src/Power of 10/Rule 8/AvoidConditionalCompilation.ql +++ b/cpp/ql/src/Power of 10/Rule 8/AvoidConditionalCompilation.ql @@ -12,6 +12,7 @@ import cpp from PreprocessorDirective i -where (i instanceof PreprocessorIf or i instanceof PreprocessorIfdef or i instanceof PreprocessorIfndef) - and not i.getFile() instanceof HeaderFile +where + (i instanceof PreprocessorIf or i instanceof PreprocessorIfdef or i instanceof PreprocessorIfndef) and + not i.getFile() instanceof HeaderFile select i, "Use of conditional compilation must be kept to a minimum." diff --git a/cpp/ql/src/Power of 10/Rule 8/RestrictPreprocessor.ql b/cpp/ql/src/Power of 10/Rule 8/RestrictPreprocessor.ql index 436fdf10fca..9c1767c5569 100644 --- a/cpp/ql/src/Power of 10/Rule 8/RestrictPreprocessor.ql +++ b/cpp/ql/src/Power of 10/Rule 8/RestrictPreprocessor.ql @@ -12,12 +12,13 @@ import cpp from PreprocessorDirective p -where not p instanceof Include and - not p instanceof Macro and - not p instanceof PreprocessorIf and - not p instanceof PreprocessorElif and - not p instanceof PreprocessorElse and - not p instanceof PreprocessorIfdef and - not p instanceof PreprocessorIfndef and - not p instanceof PreprocessorEndif +where + not p instanceof Include and + not p instanceof Macro and + not p instanceof PreprocessorIf and + not p instanceof PreprocessorElif and + not p instanceof PreprocessorElse and + not p instanceof PreprocessorIfdef and + not p instanceof PreprocessorIfndef and + not p instanceof PreprocessorEndif select p, "This preprocessor directive is not allowed." diff --git a/cpp/ql/src/Power of 10/Rule 8/UndisciplinedMacro.ql b/cpp/ql/src/Power of 10/Rule 8/UndisciplinedMacro.ql index 4ebc022391f..6874c4a87fb 100644 --- a/cpp/ql/src/Power of 10/Rule 8/UndisciplinedMacro.ql +++ b/cpp/ql/src/Power of 10/Rule 8/UndisciplinedMacro.ql @@ -12,6 +12,10 @@ import cpp from Macro m, string msg -where (m.getHead().matches("%...%") and msg = "The macro " + m.getHead() + " is variadic, and hence not allowed.") or - (m.getBody().matches("%##%") and msg = "The macro " + m.getHead() + " uses token pasting and is not allowed.") +where + m.getHead().matches("%...%") and + msg = "The macro " + m.getHead() + " is variadic, and hence not allowed." + or + m.getBody().matches("%##%") and + msg = "The macro " + m.getHead() + " uses token pasting and is not allowed." select m, msg diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 972efb70312..096b1468bb9 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -30,38 +30,31 @@ class FileFunction extends FunctionWithWrappers { nme = "open" or nme = "_open" or nme = "_wopen" or - // create file function on windows nme.matches("CreateFile%") ) or - ( - // on any of the fstream classes, or filebuf - exists(string nme | this.getDeclaringType().getSimpleName() = nme | - nme = "basic_fstream" or - nme = "basic_ifstream" or - nme = "basic_ofstream" or - nme = "basic_filebuf" - ) - and - // we look for either the open method or the constructor - (this.getName() = "open" or this instanceof Constructor) - ) + // on any of the fstream classes, or filebuf + exists(string nme | this.getDeclaringType().getSimpleName() = nme | + nme = "basic_fstream" or + nme = "basic_ifstream" or + nme = "basic_ofstream" or + nme = "basic_filebuf" + ) and + // we look for either the open method or the constructor + (this.getName() = "open" or this instanceof Constructor) } // conveniently, all of these functions take the path as the first parameter! - override predicate interestingArg(int arg) { - arg = 0 - } + override predicate interestingArg(int arg) { arg = 0 } } -from FileFunction fileFunction, - Expr taintedArg, Expr taintSource, string taintCause, string callChain +from + FileFunction fileFunction, Expr taintedArg, Expr taintSource, string taintCause, string callChain where fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and tainted(taintSource, taintedArg) and isUserInput(taintSource, taintCause) -select - taintedArg, +select taintedArg, "This argument to a file access function is derived from $@ and then passed to " + callChain, taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql index 894212cd4cf..69d6ce9b98f 100644 --- a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql @@ -11,16 +11,17 @@ * external/cwe/cwe-078 * external/cwe/cwe-088 */ + import cpp import semmle.code.cpp.security.CommandExecution import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking from Expr taintedArg, Expr taintSource, string taintCause, string callChain -where shellCommand(taintedArg, callChain) - and tainted(taintSource, taintedArg) - and isUserInput(taintSource, taintCause) -select - taintedArg, - "This argument to an OS command is derived from $@ and then passed to " + callChain, - taintSource, "user input (" + taintCause + ")" +where + shellCommand(taintedArg, callChain) and + tainted(taintSource, taintedArg) and + isUserInput(taintSource, taintCause) +select taintedArg, + "This argument to an OS command is derived from $@ and then passed to " + callChain, taintSource, + "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql index f297171a9d1..4469517c369 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-079 */ + import cpp import semmle.code.cpp.commons.Environment import semmle.code.cpp.security.TaintTracking @@ -23,13 +24,11 @@ class PrintStdoutCall extends FunctionCall { /** A read of the QUERY_STRING environment variable */ class QueryString extends EnvironmentRead { - QueryString() { - getEnvironmentVariable() = "QUERY_STRING" - } + QueryString() { getEnvironmentVariable() = "QUERY_STRING" } } from QueryString query, PrintStdoutCall call, Element printedArg -where call.getAnArgument() = printedArg - and tainted(query, printedArg) -select printedArg, "Cross-site scripting vulnerability due to $@.", - query, "this query data" +where + call.getAnArgument() = printedArg and + tainted(query, printedArg) +select printedArg, "Cross-site scripting vulnerability due to $@.", query, "this query data" diff --git a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql index a2213ee084b..3f234dd0678 100644 --- a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -10,27 +10,23 @@ * @tags security * external/cwe/cwe-089 */ + import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking class SQLLikeFunction extends FunctionWithWrappers { - SQLLikeFunction() { - sqlArgument(this.getName(), _) - } + SQLLikeFunction() { sqlArgument(this.getName(), _) } - override predicate interestingArg(int arg) { - sqlArgument(this.getName(), arg) - } + override predicate interestingArg(int arg) { sqlArgument(this.getName(), arg) } } -from SQLLikeFunction runSql, - Expr taintedArg, Expr taintSource, string taintCause, string callChain -where runSql.outermostWrapperFunctionCall(taintedArg, callChain) - and tainted(taintSource, taintedArg) - and isUserInput(taintSource, taintCause) -select - taintedArg, +from SQLLikeFunction runSql, Expr taintedArg, Expr taintSource, string taintCause, string callChain +where + runSql.outermostWrapperFunctionCall(taintedArg, callChain) and + tainted(taintSource, taintedArg) and + isUserInput(taintSource, taintCause) +select taintedArg, "This argument to a SQL query function is derived from $@ and then passed to " + callChain, taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql index 408dedd943d..233fe34e6bf 100644 --- a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql +++ b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql @@ -15,12 +15,12 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking -from string processOperation, int processOperationArg, - FunctionCall call, Expr arg, Element source -where isProcessOperationArgument(processOperation, processOperationArg) - and call.getTarget().getName() = processOperation - and call.getArgument(processOperationArg) = arg - and tainted(source, arg) +from string processOperation, int processOperationArg, FunctionCall call, Expr arg, Element source +where + isProcessOperationArgument(processOperation, processOperationArg) and + call.getTarget().getName() = processOperation and + call.getArgument(processOperationArg) = arg and + tainted(source, arg) select arg, - "The value of this argument may come from $@ and is being passed to " + processOperation, - source, source.toString() + "The value of this argument may come from $@ and is being passed to " + processOperation, source, + source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql b/cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql index ec1d84b8d29..686b92c8888 100644 --- a/cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql +++ b/cpp/ql/src/Security/CWE/CWE-119/OverflowBuffer.ql @@ -12,42 +12,44 @@ * external/cwe/cwe-122 * external/cwe/cwe-126 */ + import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.BufferAccess bindingset[num, singular, plural] string plural(int num, string singular, string plural) { - if (num = 1) then ( - result = num + singular - ) else ( - result = num + plural - ) + if num = 1 then result = num + singular else result = num + plural } -from BufferAccess ba, string bufferDesc, int accessSize, int accessType, - Element bufferAlloc, int bufferSize, string message -where accessSize = ba.getSize() - and bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType), - bufferAlloc) - and (accessSize > bufferSize or (accessSize <= 0 and accessType = 3)) - and if accessType = 1 then ( - message = "This '" + ba.getName() + "' operation accesses " - + plural(accessSize, " byte", " bytes") - + " but the $@ is only " - + plural(bufferSize, " byte", " bytes") + "." - ) else if accessType = 2 then ( - message = "This '" + ba.getName() + "' operation may access " - + plural(accessSize, " byte", " bytes") - + " but the $@ is only " - + plural(bufferSize, " byte", " bytes") + "." - ) else ( - if accessSize > 0 then ( - message = "This array indexing operation accesses byte offset " - + (accessSize - 1) + " but the $@ is only " - + plural(bufferSize, " byte", " bytes") + "." - ) else ( - message = "This array indexing operation accesses a negative index " - + ((accessSize/ba.getActualType().getSize()) - 1) + " on the $@." - ) - ) +from + BufferAccess ba, string bufferDesc, int accessSize, int accessType, Element bufferAlloc, + int bufferSize, string message +where + accessSize = ba.getSize() and + bufferSize = getBufferSize(ba.getBuffer(bufferDesc, accessType), bufferAlloc) and + ( + accessSize > bufferSize + or + accessSize <= 0 and accessType = 3 + ) and + if accessType = 1 + then + message = "This '" + ba.getName() + "' operation accesses " + + plural(accessSize, " byte", " bytes") + " but the $@ is only " + + plural(bufferSize, " byte", " bytes") + "." + else + if accessType = 2 + then + message = "This '" + ba.getName() + "' operation may access " + + plural(accessSize, " byte", " bytes") + " but the $@ is only " + + plural(bufferSize, " byte", " bytes") + "." + else ( + if accessSize > 0 + then + message = "This array indexing operation accesses byte offset " + (accessSize - 1) + + " but the $@ is only " + plural(bufferSize, " byte", " bytes") + "." + else + message = "This array indexing operation accesses a negative index " + + ((accessSize / ba.getActualType().getSize()) - 1) + " on the $@." + ) select ba, message, bufferAlloc, bufferDesc diff --git a/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql index af618b107ed..77d514bc7b6 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/BadlyBoundedWrite.ql @@ -13,6 +13,7 @@ * external/cwe/cwe-787 * external/cwe/cwe-805 */ + import semmle.code.cpp.security.BufferWrite /* @@ -20,7 +21,10 @@ import semmle.code.cpp.security.BufferWrite */ from BufferWrite bw, int destSize -where bw.hasExplicitLimit() // has an explicit size limit - and destSize = getBufferSize(bw.getDest(), _) - and (bw.getExplicitLimit() > destSize) // but it's larger than the destination -select bw, "This '" + bw.getBWDesc() + "' operation is limited to " + bw.getExplicitLimit() + " bytes but the destination is only " + destSize + " bytes." +where + bw.hasExplicitLimit() and // has an explicit size limit + destSize = getBufferSize(bw.getDest(), _) and + bw.getExplicitLimit() > destSize // but it's larger than the destination +select bw, + "This '" + bw.getBWDesc() + "' operation is limited to " + bw.getExplicitLimit() + + " bytes but the destination is only " + destSize + " bytes." diff --git a/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql index 489fa5ac1a6..4ee20508e45 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/OverrunWrite.ql @@ -12,6 +12,7 @@ * external/cwe/cwe-787 * external/cwe/cwe-805 */ + import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.commons.Alloc @@ -20,12 +21,13 @@ import semmle.code.cpp.commons.Alloc */ from BufferWrite bw, Expr dest, int destSize -where not bw.hasExplicitLimit() // has no explicit size limit - and dest = bw.getDest() - and destSize = getBufferSize(dest, _) - and // we can deduce that too much data may be copied (even without - // long '%f' conversions) - bw.getMaxDataLimited() > destSize -select bw, "This '" + bw.getBWDesc() + "' operation requires " - + bw.getMaxData() + " bytes but the destination is only " - + destSize + " bytes." +where + not bw.hasExplicitLimit() and // has no explicit size limit + dest = bw.getDest() and + destSize = getBufferSize(dest, _) and + // we can deduce that too much data may be copied (even without + // long '%f' conversions) + bw.getMaxDataLimited() > destSize +select bw, + "This '" + bw.getBWDesc() + "' operation requires " + bw.getMaxData() + + " bytes but the destination is only " + destSize + " bytes." diff --git a/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql b/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql index 28cf3b5eaf1..79ba1e17df2 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/OverrunWriteFloat.ql @@ -13,6 +13,7 @@ * external/cwe/cwe-787 * external/cwe/cwe-805 */ + import semmle.code.cpp.security.BufferWrite /* @@ -20,8 +21,13 @@ import semmle.code.cpp.security.BufferWrite */ from BufferWrite bw, int destSize -where (not bw.hasExplicitLimit()) // has no explicit size limit - and destSize = getBufferSize(bw.getDest(), _) - and (bw.getMaxData() > destSize) // and we can deduce that too much data may be copied - and (bw.getMaxDataLimited() <= destSize) // but it would fit without long '%f' conversions -select bw, "This '" + bw.getBWDesc() + "' operation may require " + bw.getMaxData() + " bytes because of float conversions, but the target is only " + destSize + " bytes." +where + not bw.hasExplicitLimit() and + // has no explicit size limit + destSize = getBufferSize(bw.getDest(), _) and + bw.getMaxData() > destSize and + // and we can deduce that too much data may be copied + bw.getMaxDataLimited() <= destSize // but it would fit without long '%f' conversions +select bw, + "This '" + bw.getBWDesc() + "' operation may require " + bw.getMaxData() + + " bytes because of float conversions, but the target is only " + destSize + " bytes." diff --git a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql index c376e2b397d..ff136d2c06b 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql @@ -12,6 +12,7 @@ * external/cwe/cwe-787 * external/cwe/cwe-805 */ + import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking @@ -40,8 +41,8 @@ import semmle.code.cpp.security.TaintTracking */ predicate isUnboundedWrite(BufferWrite bw) { - not bw.hasExplicitLimit() // has no explicit size limit - and (not exists(bw.getMaxData())) // and we can't deduce an upper bound to the amount copied + not bw.hasExplicitLimit() and // has no explicit size limit + not exists(bw.getMaxData()) // and we can't deduce an upper bound to the amount copied } /* @@ -63,10 +64,10 @@ predicate isUnboundedWrite(BufferWrite bw) { * TaintTracking library. */ predicate tainted2(Expr expr, Expr inputSource, string inputCause) { - ( - taintedIncludingGlobalVars(inputSource, expr, _) and - inputCause = inputSource.toString() - ) or exists(Expr e | tainted2(e, inputSource, inputCause) | + taintedIncludingGlobalVars(inputSource, expr, _) and + inputCause = inputSource.toString() + or + exists(Expr e | tainted2(e, inputSource, inputCause) | // field accesses of a tainted struct are tainted e = expr.(FieldAccess).getQualifier() ) @@ -77,6 +78,8 @@ predicate tainted2(Expr expr, Expr inputSource, string inputCause) { */ from BufferWrite bw, Expr inputSource, string inputCause -where isUnboundedWrite(bw) - and tainted2(bw.getASource(), inputSource, inputCause) -select bw, "This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.", inputSource, inputCause +where + isUnboundedWrite(bw) and + tainted2(bw.getASource(), inputSource, inputCause) +select bw, "This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.", + inputSource, inputCause diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index cfd70334a31..473f0f72f12 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -20,9 +20,7 @@ import cpp * trailing `".0"` then it is removed. This means that, for example, * the values of `-1` and `-1.0` would be considered the same. */ -string normalisedExprValue(Expr e) { - result = e.getValue().regexpReplaceAll("\\.0$", "") -} +string normalisedExprValue(Expr e) { result = e.getValue().regexpReplaceAll("\\.0$", "") } /** * A variadic function which is not a formatting function. @@ -42,8 +40,7 @@ class VarargsFunction extends Function { result = normalisedExprValue(this.trailingArgumentIn(fc)) } - private - int trailingArgValueCount(string value) { + private int trailingArgValueCount(string value) { result = strictcount(FunctionCall fc | trailingArgValue(fc) = value) } @@ -54,19 +51,15 @@ class VarargsFunction extends Function { result = normalisedExprValue(fc.getArgument(index)) } - private - int totalCount() { + private int totalCount() { result = strictcount(FunctionCall fc | fc = this.getACallToThisFunction()) } string normalTerminator(int cnt) { - ( - result = "0" or result = "-1" - ) and ( - cnt = trailingArgValueCount(result) - ) and ( - 2 * cnt > totalCount() - ) and not exists(FunctionCall fc, int index | + (result = "0" or result = "-1") and + cnt = trailingArgValueCount(result) and + 2 * cnt > totalCount() and + not exists(FunctionCall fc, int index | // terminator value is used in a non-terminating position nonTrailingVarArgValue(fc, index) = result ) @@ -80,9 +73,11 @@ class VarargsFunction extends Function { } from VarargsFunction f, FunctionCall fc, string terminator, int cnt -where terminator = f.normalTerminator(cnt) - and fc = f.getACallToThisFunction() - and not normalisedExprValue(f.trailingArgumentIn(fc)) = terminator - and not f.isWhitelisted() -select fc, "Calls to $@ should use the value " + terminator - + " as a terminator (" + cnt + " calls do).", f, f.getQualifiedName() +where + terminator = f.normalTerminator(cnt) and + fc = f.getACallToThisFunction() and + not normalisedExprValue(f.trailingArgumentIn(fc)) = terminator and + not f.isWhitelisted() +select fc, + "Calls to $@ should use the value " + terminator + " as a terminator (" + cnt + " calls do).", f, + f.getQualifiedName() diff --git a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql index a50e164e8af..3d7379be507 100644 --- a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql +++ b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql @@ -9,17 +9,18 @@ * @tags security * external/cwe/cwe-129 */ + import cpp import semmle.code.cpp.controlflow.Guards private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import semmle.code.cpp.security.TaintTracking predicate hasUpperBound(VariableAccess offsetExpr) { - exists( - BasicBlock controlled, LocalScopeVariable offsetVar, SsaDefinition def - | controlled.contains(offsetExpr) and + exists(BasicBlock controlled, LocalScopeVariable offsetVar, SsaDefinition def | + controlled.contains(offsetExpr) and linearBoundControls(controlled, def, offsetVar) and - offsetExpr = def.getAUse(offsetVar)) + offsetExpr = def.getAUse(offsetVar) + ) } pragma[noinline] @@ -31,10 +32,10 @@ predicate linearBoundControls(BasicBlock controlled, SsaDefinition def, LocalSco } from Expr origin, ArrayExpr arrayExpr, VariableAccess offsetExpr -where tainted(origin, offsetExpr) - and offsetExpr = arrayExpr.getArrayOffset() - and not hasUpperBound(offsetExpr) -select - offsetExpr, +where + tainted(origin, offsetExpr) and + offsetExpr = arrayExpr.getArrayOffset() and + not hasUpperBound(offsetExpr) +select offsetExpr, "$@ flows to here and is used in an array indexing expression, potentially causing an invalid access.", origin, "User-provided value" diff --git a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql index d5ab739f348..575752f0b74 100644 --- a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +++ b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql @@ -13,24 +13,25 @@ * external/cwe/cwe-120 * external/cwe/cwe-122 */ + import cpp import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.models.implementations.Memcpy -class MallocCall extends FunctionCall -{ +class MallocCall extends FunctionCall { MallocCall() { - this.getTarget().hasGlobalName("malloc") or - this.getTarget().hasQualifiedName("std", "malloc") + this.getTarget().hasGlobalName("malloc") or + this.getTarget().hasQualifiedName("std", "malloc") } Expr getAllocatedSize() { - if this.getArgument(0) instanceof VariableAccess then + if this.getArgument(0) instanceof VariableAccess + then exists(LocalScopeVariable v, ControlFlowNode def | definitionUsePair(v, def, this.getArgument(0)) and - exprDefinition(v, def, result)) - else - result = this.getArgument(0) + exprDefinition(v, def, result) + ) + else result = this.getArgument(0) } } diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql index 4fa6efb2d91..02a0f42fa6b 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql @@ -17,12 +17,11 @@ import semmle.code.cpp.security.Security import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking -from PrintfLikeFunction printf, Expr arg, string printfFunction, - Expr userValue, string cause +from PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause where - printf.outermostWrapperFunctionCall(arg, printfFunction) - and tainted(userValue, arg) - and isUserInput(userValue, cause) + printf.outermostWrapperFunctionCall(arg, printfFunction) and + tainted(userValue, arg) and + isUserInput(userValue, cause) select arg, - "The value of this argument may come from $@ and is being used as a formatting argument to " + printfFunction, - userValue, cause + "The value of this argument may come from $@ and is being used as a formatting argument to " + + printfFunction, userValue, cause diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql index e4beeb8c24b..f3cb4fcf1bb 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql @@ -17,12 +17,14 @@ import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking -from PrintfLikeFunction printf, Expr arg, string printfFunction, - Expr userValue, string cause, string globalVar -where printf.outermostWrapperFunctionCall(arg, printfFunction) - and not tainted(_, arg) - and taintedIncludingGlobalVars(userValue, arg, globalVar) - and isUserInput(userValue, cause) +from + PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause, + string globalVar +where + printf.outermostWrapperFunctionCall(arg, printfFunction) and + not tainted(_, arg) and + taintedIncludingGlobalVars(userValue, arg, globalVar) and + isUserInput(userValue, cause) select arg, - "This value may flow through $@, originating from $@, and is a formatting argument to " + printfFunction + ".", - globalVarFromId(globalVar), globalVar, userValue, cause + "This value may flow through $@, originating from $@, and is a formatting argument to " + + printfFunction + ".", globalVarFromId(globalVar), globalVar, userValue, cause diff --git a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql index 0f93593cfd2..511c7a1d79f 100644 --- a/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-170/ImproperNullTerminationTainted.ql @@ -18,7 +18,8 @@ class TaintSource extends VariableAccess { TaintSource() { exists(SecurityOptions x, string cause | this.getTarget() instanceof SemanticStackVariable and - x.isUserInput(this, cause) | + x.isUserInput(this, cause) + | cause = "read" or cause = "fread" or cause = "recv" or @@ -71,13 +72,14 @@ class TaintSource extends VariableAccess { * either reach the sink or be reached from the source. (Ideally, * we should instead look for such accesses only on the path from * this source to `sink` found via `tainted(source, sink)`.) - * */ + */ predicate reaches(VariableAccess sink) { isSink(sink) and not exists(VariableAccess va | va != this and va != sink and - mayAddNullTerminator(_, va) | + mayAddNullTerminator(_, va) + | sourceReaches(va) or reachesSink(va, sink) @@ -87,7 +89,4 @@ class TaintSource extends VariableAccess { from TaintSource source, VariableAccess sink where source.reaches(sink) -select - sink, - "$@ flows to here and may not be null terminated.", - source, "User-provided value" +select sink, "$@ flows to here and may not be null terminated.", source, "User-provided value" diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql index 8b71e684651..7416af15865 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql @@ -10,22 +10,25 @@ * external/cwe/cwe-190 * external/cwe/cwe-191 */ -import cpp +import cpp import semmle.code.cpp.security.Overflow import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking from Expr origin, Operation op, Expr e, string effect -where isUserInput(origin, _) - and tainted(origin, e) - and op.getAnOperand() = e - and +where + isUserInput(origin, _) and + tainted(origin, e) and + op.getAnOperand() = e and + ( + missingGuardAgainstUnderflow(op, e) and effect = "underflow" + or + missingGuardAgainstOverflow(op, e) and effect = "overflow" + or + not e instanceof VariableAccess and effect = "overflow" + ) and ( - (missingGuardAgainstUnderflow(op, e) and effect = "underflow") or - (missingGuardAgainstOverflow(op, e) and effect = "overflow") or - (not e instanceof VariableAccess and effect = "overflow") - ) and ( op instanceof UnaryArithmeticOperation or op instanceof BinaryArithmeticOperation ) diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index b6526c8ea79..74eadb19adf 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -10,14 +10,15 @@ * external/cwe/cwe-190 * external/cwe/cwe-191 */ -import cpp +import cpp import semmle.code.cpp.security.Overflow import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking predicate isRandValue(Expr e) { - e.(FunctionCall).getTarget().getName() = "rand" or + e.(FunctionCall).getTarget().getName() = "rand" + or exists(MacroInvocation mi | e = mi.getExpr() and e.getAChild*().(FunctionCall).getTarget().getName() = "rand" @@ -26,8 +27,9 @@ predicate isRandValue(Expr e) { class SecurityOptionsArith extends SecurityOptions { override predicate isUserInput(Expr expr, string cause) { - isRandValue(expr) and cause = "rand" - and not expr.getParent*() instanceof DivExpr + isRandValue(expr) and + cause = "rand" and + not expr.getParent*() instanceof DivExpr } } @@ -42,18 +44,18 @@ predicate taintedVarAccess(Expr origin, VariableAccess va) { */ predicate guardedByAssignDiv(Expr origin) { isUserInput(origin, _) and - exists(AssignDivExpr div, VariableAccess va | - tainted(origin, va) and div.getLValue() = va) + exists(AssignDivExpr div, VariableAccess va | tainted(origin, va) and div.getLValue() = va) } from Expr origin, Operation op, VariableAccess va, string effect -where taintedVarAccess(origin, va) - and op.getAnOperand() = va - and +where + taintedVarAccess(origin, va) and + op.getAnOperand() = va and ( - (missingGuardAgainstUnderflow(op, va) and effect = "underflow") or - (missingGuardAgainstOverflow(op, va) and effect = "overflow") - ) - and not guardedByAssignDiv(origin) + missingGuardAgainstUnderflow(op, va) and effect = "underflow" + or + missingGuardAgainstOverflow(op, va) and effect = "overflow" + ) and + not guardedByAssignDiv(origin) select va, "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", origin, "Uncontrolled value" diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql index dd0ccee9154..668b07d72af 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticWithExtremeValues.ql @@ -12,8 +12,8 @@ * external/cwe/cwe-190 * external/cwe/cwe-191 */ -import cpp +import cpp import semmle.code.cpp.security.Overflow import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking @@ -45,8 +45,9 @@ predicate isMinValue(Expr mie) { class SecurityOptionsArith extends SecurityOptions { override predicate isUserInput(Expr expr, string cause) { - (isMaxValue(expr) and cause = "max value") or - (isMinValue(expr) and cause = "min value") + isMaxValue(expr) and cause = "max value" + or + isMinValue(expr) and cause = "min value" } } @@ -56,22 +57,21 @@ predicate taintedVarAccess(Expr origin, VariableAccess va, string cause) { } predicate causeEffectCorrespond(string cause, string effect) { - ( - cause = "max value" and - effect = "overflow" - ) or ( - cause = "min value" and - effect = "underflow" - ) + cause = "max value" and + effect = "overflow" + or + cause = "min value" and + effect = "underflow" } from Expr origin, Operation op, VariableAccess va, string cause, string effect -where taintedVarAccess(origin, va, cause) - and op.getAnOperand() = va - and +where + taintedVarAccess(origin, va, cause) and + op.getAnOperand() = va and ( - (missingGuardAgainstUnderflow(op, va) and effect = "underflow") or - (missingGuardAgainstOverflow(op, va) and effect = "overflow") + missingGuardAgainstUnderflow(op, va) and effect = "underflow" + or + missingGuardAgainstOverflow(op, va) and effect = "overflow" ) and causeEffectCorrespond(cause, effect) select va, "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", diff --git a/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql b/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql index 604f3915e98..c704506a4fa 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql @@ -11,7 +11,6 @@ * external/cwe/cwe-190 * external/cwe/cwe-197 * external/cwe/cwe-835 - * */ import cpp @@ -29,41 +28,40 @@ int getComparisonSize(Expr e) { else result = e.getType().getSize() } - predicate loopVariant(VariableAccess e, Loop loop) { - exists (SsaDefinition d - | d.getAUse(e.getTarget()) = e - | d.getAnUltimateDefiningValue(e.getTarget()) = loop.getCondition().getAChild*() - or d.getAnUltimateDefiningValue(e.getTarget()).getEnclosingStmt().getParent*() - = loop.getStmt() - or d.getAnUltimateDefiningValue(e.getTarget()) - = loop.(ForStmt).getUpdate().getAChild*()) + exists(SsaDefinition d | d.getAUse(e.getTarget()) = e | + d.getAnUltimateDefiningValue(e.getTarget()) = loop.getCondition().getAChild*() or + d.getAnUltimateDefiningValue(e.getTarget()).getEnclosingStmt().getParent*() = loop.getStmt() or + d.getAnUltimateDefiningValue(e.getTarget()) = loop.(ForStmt).getUpdate().getAChild*() + ) } Element friendlyLoc(Expr e) { - result = e.(Access).getTarget() or - result = e.(Call).getTarget() or + result = e.(Access).getTarget() + or + result = e.(Call).getTarget() + or not e instanceof Access and not e instanceof Call and result = e } from Loop l, RelationalOperation rel, Expr small, Expr large -where small = rel.getLesserOperand() - and large = rel.getGreaterOperand() - and rel = l.getCondition().getAChild*() - and upperBound(large).log2() > getComparisonSize(small) * 8 +where + small = rel.getLesserOperand() and + large = rel.getGreaterOperand() and + rel = l.getCondition().getAChild*() and + upperBound(large).log2() > getComparisonSize(small) * 8 and // Ignore cases where the smaller type is int or larger // These are still bugs, but you should need a very large string or array to // trigger them. We will want to disable this for some applications, but it's // very noisy on codebases that started as 32-bit - and small.getExplicitlyConverted().getType().getSize() < 4 + small.getExplicitlyConverted().getType().getSize() < 4 and // Ignore cases where integer promotion has occurred on /, -, or >> expressions. - and not getComparisonSize(large.(DivExpr).getLeftOperand() - .getExplicitlyConverted()) <= getComparisonSize(small) - and not getComparisonSize(large.(SubExpr).getLeftOperand() - .getExplicitlyConverted()) <= getComparisonSize(small) - and not getComparisonSize(large.(RShiftExpr).getLeftOperand() - .getExplicitlyConverted()) <= getComparisonSize(small) + not getComparisonSize(large.(DivExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and + not getComparisonSize(large.(SubExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and + not getComparisonSize(large.(RShiftExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and // ignore loop-invariant smaller variables - and loopVariant(small.getAChild*(), l) -select rel, "Comparison between $@ of type " + small.getType().getName() + " and $@ of wider type " + large.getType().getName() + ".", - friendlyLoc(small), small.toString(), friendlyLoc(large), large.toString() + loopVariant(small.getAChild*(), l) +select rel, + "Comparison between $@ of type " + small.getType().getName() + " and $@ of wider type " + + large.getType().getName() + ".", friendlyLoc(small), small.toString(), friendlyLoc(large), + large.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-190/IntegerOverflowTainted.ql b/cpp/ql/src/Security/CWE/CWE-190/IntegerOverflowTainted.ql index c219bbfe104..0adb600dbda 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/IntegerOverflowTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/IntegerOverflowTainted.ql @@ -11,26 +11,28 @@ * external/cwe/cwe-197 * external/cwe/cwe-681 */ + import cpp import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import semmle.code.cpp.security.TaintTracking /** Holds if `expr` might overflow. */ predicate outOfBoundsExpr(Expr expr, string kind) { - if convertedExprMightOverflowPositively(expr) then - kind = "overflow" - else if convertedExprMightOverflowNegatively(expr) then - kind = "overflow negatively" + if convertedExprMightOverflowPositively(expr) + then kind = "overflow" else - none() + if convertedExprMightOverflowNegatively(expr) + then kind = "overflow negatively" + else none() } from Expr use, Expr origin, string kind -where outOfBoundsExpr(use, kind) and tainted(origin, use) and origin != use -and not inSystemMacroExpansion(use) -// Avoid double-counting: don't include all the conversions of `use`. -and not (use instanceof Conversion) -select - use, - "$@ flows to here and is used in an expression which might " + kind + ".", - origin, "User-provided value" +where + outOfBoundsExpr(use, kind) and + tainted(origin, use) and + origin != use and + not inSystemMacroExpansion(use) and + // Avoid double-counting: don't include all the conversions of `use`. + not use instanceof Conversion +select use, "$@ flows to here and is used in an expression which might " + kind + ".", origin, + "User-provided value" diff --git a/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql index 810879e262f..e8c62a1d5d7 100644 --- a/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql +++ b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql @@ -13,58 +13,61 @@ * external/microsoft/C6217 * external/microsoft/C6230 */ + import cpp -predicate isHresultBooleanConverted( Expr e1, Cast e2 ) -{ - exists ( Type t1, Type t2 | +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") - )) + 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 | +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 not ctls instanceof SwitchStmt // not controlled by a boolean condition - and msg = "Direct usage of a type " + e1.getType().toString() + " as a conditional expression" - ) +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 + not ctls instanceof SwitchStmt and // not controlled by a boolean condition + 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" + 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) + 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 diff --git a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql index 5efd61c6f90..19bee24a16d 100644 --- a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql +++ b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql @@ -14,11 +14,9 @@ import semmle.code.cpp.security.TaintTracking predicate hardCodedAddressOrIP(StringLiteral txt) { - exists(string s - | s = txt.getValueText() - | // Hard-coded ip addresses, such as 127.0.0.1 + exists(string s | s = txt.getValueText() | + // Hard-coded ip addresses, such as 127.0.0.1 s.regexpMatch("\"[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+\"") or - // Hard-coded addresses such as www.mycompany.com s.matches("\"www.%\"") or s.matches("\"http:%\"") or @@ -84,15 +82,18 @@ predicate hardCodedAddressOrIP(StringLiteral txt) { s.matches("\"%.sg\"") or s.matches("\"%.io\"") or s.matches("\"%.edu\"") or - s.matches("\"%.gov\"")) + s.matches("\"%.gov\"") + ) } predicate useOfHardCodedAddressOrIP(Expr use) { - hardCodedAddressOrIP(use) or - exists(Expr def, Expr src, Variable v - | useOfHardCodedAddressOrIP(src) and + hardCodedAddressOrIP(use) + or + exists(Expr def, Expr src, Variable v | + useOfHardCodedAddressOrIP(src) and exprDefinition(v, def, src) and - definitionUsePair(v, def, use)) + definitionUsePair(v, def, use) + ) } /** @@ -103,22 +104,14 @@ predicate useOfHardCodedAddressOrIP(Expr use) { */ predicate hardCodedAddressInCondition(Expr source, Expr condition) { // One of the sub-expressions of the condition is tainted. - exists(Expr taintedExpr - | taintedExpr.getParent+() = condition - | tainted(source, taintedExpr)) and - + exists(Expr taintedExpr | taintedExpr.getParent+() = condition | tainted(source, taintedExpr)) and // One of the sub-expressions of the condition is a hard-coded // IP or web-address. - exists(Expr use - | use.getParent+() = condition - | useOfHardCodedAddressOrIP(use)) and - + exists(Expr use | use.getParent+() = condition | useOfHardCodedAddressOrIP(use)) and condition = any(IfStmt ifStmt).getCondition() } from Expr source, Expr condition where hardCodedAddressInCondition(source, condition) -select - condition, - "Untrusted input $@ might be vulnerable to a spoofing attack.", - source, source.toString() +select condition, "Untrusted input $@ might be vulnerable to a spoofing attack.", source, + source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index d8002212824..aa153779df1 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -15,13 +15,11 @@ import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.TaintTracking import semmle.code.cpp.security.SensitiveExprs -from BufferWrite w, - Expr taintedArg, Expr taintSource, string taintCause, - SensitiveExpr dest -where tainted(taintSource, taintedArg) - and isUserInput(taintSource, taintCause) - and w.getASource() = taintedArg - and dest = w.getDest() -select w, "This write into buffer '" + dest.toString() - + "' may contain unencrypted data from $@", - taintSource, "user input (" + taintCause + ")" +from BufferWrite w, Expr taintedArg, Expr taintSource, string taintCause, SensitiveExpr dest +where + tainted(taintSource, taintedArg) and + isUserInput(taintSource, taintCause) and + w.getASource() = taintedArg and + dest = w.getDest() +select w, "This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@", + taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql index 400088e2be0..8e447bafd90 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql @@ -15,8 +15,8 @@ import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.FileWrite from FileWrite w, SensitiveExpr source, Expr dest -where source = w.getASource() - and dest = w.getDest() -select w, "This write into file '" + dest.toString() - + "' may contain unencrypted data from $@", - source, "this source." +where + source = w.getASource() and + dest = w.getDest() +select w, "This write into file '" + dest.toString() + "' may contain unencrypted data from $@", + source, "this source." diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index c5f3ae71a57..e4f1e9c834a 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -21,13 +21,9 @@ class UserInputIsSensitiveExpr extends SecurityOptions { } class SqliteFunctionCall extends FunctionCall { - SqliteFunctionCall() { - this.getTarget().getName().matches("sqlite%") - } + SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") } - Expr getASource() { - result = this.getAnArgument() - } + Expr getASource() { result = this.getAnArgument() } } predicate sqlite_encryption_used() { @@ -37,9 +33,9 @@ predicate sqlite_encryption_used() { } from SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall -where tainted(taintSource, taintedArg) - and taintedArg = sqliteCall.getASource() - and not sqlite_encryption_used() -select sqliteCall, "This SQLite call may store $@ in a non-encrypted SQLite database", - taintSource, "sensitive information" - +where + tainted(taintSource, taintedArg) and + taintedArg = sqliteCall.getASource() and + not sqlite_encryption_used() +select sqliteCall, "This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, + "sensitive information" diff --git a/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql b/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql index 9d67bbd0c07..3f6ff63635e 100644 --- a/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +++ b/cpp/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-327 */ + import cpp import semmle.code.cpp.security.Encryption @@ -22,13 +23,12 @@ Function getAnInsecureFunction() { } class InsecureFunctionCall extends InsecureCryptoSpec, FunctionCall { - InsecureFunctionCall() { - this.getTarget() = getAnInsecureFunction() - } + InsecureFunctionCall() { this.getTarget() = getAnInsecureFunction() } override string description() { result = "function call" } override string toString() { result = FunctionCall.super.toString() } + override Location getLocation() { result = FunctionCall.super.getLocation() } } @@ -38,13 +38,12 @@ Macro getAnInsecureMacro() { } class InsecureMacroSpec extends InsecureCryptoSpec, MacroInvocation { - InsecureMacroSpec() { - this.getMacro() = getAnInsecureMacro() - } + InsecureMacroSpec() { this.getMacro() = getAnInsecureMacro() } override string description() { result = "macro invocation" } override string toString() { result = MacroInvocation.super.toString() } + override Location getLocation() { result = MacroInvocation.super.getLocation() } } diff --git a/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql b/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql index a8c4336aa6e..a7ffadc07be 100644 --- a/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql +++ b/cpp/ql/src/Security/CWE/CWE-327/OpenSslHeartbleed.ql @@ -17,8 +17,9 @@ import cpp * Holds if `v` and `w` are ever compared to each other. */ predicate comparedTo(Variable v, Variable w) { - v.getAnAssignedValue() = w.getAnAccess() or - exists (ComparisonOperation comp | + v.getAnAssignedValue() = w.getAnAccess() + or + exists(ComparisonOperation comp | comp = v.getAnAccess().getParent+() and comp = w.getAnAccess().getParent+() ) @@ -27,9 +28,10 @@ predicate comparedTo(Variable v, Variable w) { class DataVariable extends Variable { DataVariable() { exists(Struct ssl3_record_st | - ssl3_record_st.hasName("ssl3_record_st") and - this = ssl3_record_st.getAField() and - this.hasName("data")) + ssl3_record_st.hasName("ssl3_record_st") and + this = ssl3_record_st.getAField() and + this.hasName("data") + ) } } @@ -49,10 +51,13 @@ predicate varPointsInto(Variable tainted, DataVariable src) { } from FunctionCall fc, Struct ssl3_record_st, Field data, Field length -where fc.getTarget().getName().matches("%memcpy%") and - ssl3_record_st.hasName("ssl3_record_st") and - data = ssl3_record_st.getAField() and data.hasName("data") and - length = ssl3_record_st.getAField() and length.hasName("length") and - pointsInto(fc.getArgument(1), data) and - not comparedTo(fc.getArgument(2).(VariableAccess).getTarget(), length) +where + fc.getTarget().getName().matches("%memcpy%") and + ssl3_record_st.hasName("ssl3_record_st") and + data = ssl3_record_st.getAField() and + data.hasName("data") and + length = ssl3_record_st.getAField() and + length.hasName("length") and + pointsInto(fc.getArgument(1), data) and + not comparedTo(fc.getArgument(2).(VariableAccess).getTarget(), length) select fc, "This call to memcpy is insecure (Heartbleed vulnerability)." diff --git a/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql b/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql index f8764b7358a..67b2f5c7eef 100644 --- a/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql +++ b/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql @@ -10,6 +10,7 @@ * @tags security * external/cwe/cwe-367 */ + import cpp import semmle.code.cpp.controlflow.Guards @@ -22,32 +23,26 @@ import semmle.code.cpp.controlflow.Guards FunctionCall filenameOperation(Expr path) { exists(string name | name = result.getTarget().getName() | ( - ( - name = "remove" or - name = "unlink" or - name = "rmdir" or - name = "rename" or - name = "chmod" or - name = "chown" or - name = "fopen" or - name = "open" or - name = "freopen" or - name = "_open" or - name = "_wopen" or - name = "_wfopen" - ) - and - result.getArgument(0) = path - ) + name = "remove" or + name = "unlink" or + name = "rmdir" or + name = "rename" or + name = "chmod" or + name = "chown" or + name = "fopen" or + name = "open" or + name = "freopen" or + name = "_open" or + name = "_wopen" or + name = "_wfopen" + ) and + result.getArgument(0) = path or ( - ( - name = "fopen_s" or - name = "wfopen_s" - ) - and - result.getArgument(1) = path - ) + name = "fopen_s" or + name = "wfopen_s" + ) and + result.getArgument(1) = path ) } @@ -61,8 +56,7 @@ FunctionCall accessCheck(Expr path) { name = "_waccess" or name = "_access_s" or name = "_waccess_s" - ) - and + ) and path = result.getArgument(0) } @@ -76,10 +70,8 @@ FunctionCall stat(Expr path, Expr buf) { name = "fstat" or name.matches("\\_stat%") or name.matches("\\_wstat%") - ) - and - path = result.getArgument(0) - and + ) and + path = result.getArgument(0) and buf = result.getArgument(1) } @@ -91,38 +83,42 @@ predicate referenceTo(Expr source, Expr use) { source = use or exists(SsaDefinition def, LocalScopeVariable v | - def.getAnUltimateDefiningValue(v) = source and def.getAUse(v) = use) + def.getAnUltimateDefiningValue(v) = source and def.getAUse(v) = use + ) } from FunctionCall fc, Expr check, Expr checkUse, Expr opUse -where // checkUse looks like a check on a filename - ( - // either: - // an access check - check = accessCheck(checkUse) - or - // a stat - check = stat(checkUse, _) - or - // another filename operation (null pointers can indicate errors) - check = filenameOperation(checkUse) - or - // access to a member variable on the stat buf - // (morally, this should be a use-use pair, but it seems unlikely - // that this variable will get reused in practice) - exists(Variable buf | - exists(stat(checkUse, buf.getAnAccess())) | - check.(VariableAccess).getQualifier() = buf.getAnAccess()) - ) - and // checkUse and opUse refer to the same SSA variable - exists(SsaDefinition def, LocalScopeVariable v | - def.getAUse(v) = checkUse and def.getAUse(v) = opUse) - and // opUse looks like an operation on a filename - fc = filenameOperation(opUse) - and // the return value of check is used (possibly with one step of - // variable indirection) in a guard which controls fc - exists(GuardCondition guard | - referenceTo(check, guard.getAChild*()) | - guard.controls(fc.(ControlFlowNode).getBasicBlock(), _) - ) -select fc, "The $@ being operated upon was previously $@, but the underlying file may have been changed since then.", opUse, "filename", check, "checked" +where + // checkUse looks like a check on a filename + ( + // either: + // an access check + check = accessCheck(checkUse) + or + // a stat + check = stat(checkUse, _) + or + // another filename operation (null pointers can indicate errors) + check = filenameOperation(checkUse) + or + // access to a member variable on the stat buf + // (morally, this should be a use-use pair, but it seems unlikely + // that this variable will get reused in practice) + exists(Variable buf | exists(stat(checkUse, buf.getAnAccess())) | + check.(VariableAccess).getQualifier() = buf.getAnAccess() + ) + ) and + // checkUse and opUse refer to the same SSA variable + exists(SsaDefinition def, LocalScopeVariable v | + def.getAUse(v) = checkUse and def.getAUse(v) = opUse + ) and + // opUse looks like an operation on a filename + fc = filenameOperation(opUse) and + // the return value of check is used (possibly with one step of + // variable indirection) in a guard which controls fc + exists(GuardCondition guard | referenceTo(check, guard.getAChild*()) | + guard.controls(fc.(ControlFlowNode).getBasicBlock(), _) + ) +select fc, + "The $@ being operated upon was previously $@, but the underlying file may have been changed since then.", + opUse, "filename", check, "checked" diff --git a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql index c32ce5aae52..61576c254d4 100644 --- a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql @@ -10,55 +10,48 @@ * external/cwe/cwe-428 * external/microsoft/C6277 */ - + import cpp import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow2 predicate isCreateProcessFunction(FunctionCall call, int applicationNameIndex, int commandLineIndex) { - ( - call.getTarget().hasGlobalName("CreateProcessA") - and applicationNameIndex = 0 - and commandLineIndex = 1 - ) or ( - call.getTarget().hasGlobalName("CreateProcessW") - and applicationNameIndex = 0 - and commandLineIndex = 1 - ) or ( - call.getTarget().hasGlobalName("CreateProcessWithTokenW") - and applicationNameIndex = 2 - and commandLineIndex = 3 - ) or ( - call.getTarget().hasGlobalName("CreateProcessWithLogonW") - and applicationNameIndex = 4 - and commandLineIndex = 5 - ) or ( - call.getTarget().hasGlobalName("CreateProcessAsUserA") - and applicationNameIndex = 1 - and commandLineIndex = 2 - ) or ( - call.getTarget().hasGlobalName("CreateProcessAsUserW") - and applicationNameIndex = 1 - and commandLineIndex = 2 - ) + call.getTarget().hasGlobalName("CreateProcessA") and + applicationNameIndex = 0 and + commandLineIndex = 1 + or + call.getTarget().hasGlobalName("CreateProcessW") and + applicationNameIndex = 0 and + commandLineIndex = 1 + or + call.getTarget().hasGlobalName("CreateProcessWithTokenW") and + applicationNameIndex = 2 and + commandLineIndex = 3 + or + call.getTarget().hasGlobalName("CreateProcessWithLogonW") and + applicationNameIndex = 4 and + commandLineIndex = 5 + or + call.getTarget().hasGlobalName("CreateProcessAsUserA") and + applicationNameIndex = 1 and + commandLineIndex = 2 + or + call.getTarget().hasGlobalName("CreateProcessAsUserW") and + applicationNameIndex = 1 and + commandLineIndex = 2 } + /** * A function call to CreateProcess (either wide-char or single byte string versions) */ class CreateProcessFunctionCall extends FunctionCall { - CreateProcessFunctionCall() { - isCreateProcessFunction( this, _, _) - } - - int getApplicationNameArgumentId() { - isCreateProcessFunction( this, result, _) - } - - int getCommandLineArgumentId() { - isCreateProcessFunction( this, _, result) - } + CreateProcessFunctionCall() { isCreateProcessFunction(this, _, _) } + + int getApplicationNameArgumentId() { isCreateProcessFunction(this, result, _) } + + int getCommandLineArgumentId() { isCreateProcessFunction(this, _, result) } } - + /** * Dataflow that detects a call to CreateProcess with a NULL value for lpApplicationName argument */ @@ -67,15 +60,11 @@ class NullAppNameCreateProcessFunctionConfiguration extends DataFlow::Configurat this = "NullAppNameCreateProcessFunctionConfiguration" } - override predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof NullValue - } + override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } override predicate isSink(DataFlow::Node sink) { - exists( - CreateProcessFunctionCall call, Expr val | - val = sink.asExpr() | - val = call.getArgument(call.getApplicationNameArgumentId()) + exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() | + val = call.getArgument(call.getApplicationNameArgumentId()) ) } } @@ -89,42 +78,37 @@ class QuotedCommandInCreateProcessFunctionConfiguration extends DataFlow2::Confi } override predicate isSource(DataFlow2::Node source) { - exists( string s | - s = source.asExpr().getValue().toString() - and - not isQuotedOrNoSpaceApplicationNameOnCmd(s) - ) + exists(string s | + s = source.asExpr().getValue().toString() and + not isQuotedOrNoSpaceApplicationNameOnCmd(s) + ) } - + override predicate isSink(DataFlow2::Node sink) { - exists( - CreateProcessFunctionCall call, Expr val | - val = sink.asExpr() | - val = call.getArgument(call.getCommandLineArgumentId()) + exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() | + val = call.getArgument(call.getCommandLineArgumentId()) ) } } bindingset[s] -predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s){ - s.regexpMatch("\"([^\"])*\"(\\s|.)*") // The first element (path) is quoted - or - s.regexpMatch("[^\\s]+") // There are no spaces in the string +predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) { + s.regexpMatch("\"([^\"])*\"(\\s|.)*") // The first element (path) is quoted + or + s.regexpMatch("[^\\s]+") // There are no spaces in the string } from CreateProcessFunctionCall call, string msg1, string msg2 where - exists( Expr source, Expr appName, - NullAppNameCreateProcessFunctionConfiguration nullAppConfig | - appName = call.getArgument(call.getApplicationNameArgumentId()) - and nullAppConfig.hasFlow(DataFlow2::exprNode(source), DataFlow2::exprNode(appName)) - and msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")" - ) - and - exists( Expr source, Expr cmd, - QuotedCommandInCreateProcessFunctionConfiguration quotedConfig | - cmd = call.getArgument(call.getCommandLineArgumentId()) - and quotedConfig.hasFlow(DataFlow2::exprNode(source), DataFlow2::exprNode(cmd)) - and msg2 = " and with an unquoted lpCommandLine (" + cmd + ") introduces a security vulnerability if the path contains spaces." + exists(Expr source, Expr appName, NullAppNameCreateProcessFunctionConfiguration nullAppConfig | + appName = call.getArgument(call.getApplicationNameArgumentId()) and + nullAppConfig.hasFlow(DataFlow2::exprNode(source), DataFlow2::exprNode(appName)) and + msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")" + ) and + exists(Expr source, Expr cmd, QuotedCommandInCreateProcessFunctionConfiguration quotedConfig | + cmd = call.getArgument(call.getCommandLineArgumentId()) and + quotedConfig.hasFlow(DataFlow2::exprNode(source), DataFlow2::exprNode(cmd)) and + msg2 = " and with an unquoted lpCommandLine (" + cmd + + ") introduces a security vulnerability if the path contains spaces." ) select call, msg1 + " " + msg2 diff --git a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql index 2a60728c549..7cc00c05379 100644 --- a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql +++ b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScaling.ql @@ -9,44 +9,39 @@ * @tags security * external/cwe/cwe-468 */ + import IncorrectPointerScalingCommon -from Expr dest, Type destType, Type sourceType, Type sourceBase, - Type destBase, Location sourceLoc -where exists(pointerArithmeticParent(dest)) - and exprSourceType(dest, sourceType, sourceLoc) - and sourceBase = baseType(sourceType) - and destType = dest.getFullyConverted().getType() - and destBase = baseType(destType) - and destBase.getSize() != sourceBase.getSize() - and not dest.isInMacroExpansion() - +from Expr dest, Type destType, Type sourceType, Type sourceBase, Type destBase, Location sourceLoc +where + exists(pointerArithmeticParent(dest)) and + exprSourceType(dest, sourceType, sourceLoc) and + sourceBase = baseType(sourceType) and + destType = dest.getFullyConverted().getType() and + destBase = baseType(destType) and + destBase.getSize() != sourceBase.getSize() and + not dest.isInMacroExpansion() and // If the source type is a char* or void* then don't // produce a result, because it is likely to be a false // positive. - and not (sourceBase instanceof CharType) - and not (sourceBase instanceof VoidType) - + not sourceBase instanceof CharType and + not sourceBase instanceof VoidType and // Low-level pointer tricks often involve casting a struct pointer to a // char pointer, then accessing it at byte offsets. For example, this can // be necessary in order to resume an interrupted `write(2)`. - and not (destBase instanceof CharType) - + not destBase instanceof CharType and // Similarly, gcc and compilers emulating it will allow void pointer // arithmetic as if void were a 1-byte type - and not (destBase instanceof VoidType) - + not destBase instanceof VoidType and // Don't produce an alert if the root expression computes // an offset, rather than a pointer. For example: // ``` // (p + 1) - q // ``` - and forall(Expr parent | - parent = pointerArithmeticParent+(dest) | - parent.getFullyConverted().getUnspecifiedType() instanceof PointerType) -select - dest, + forall(Expr parent | parent = pointerArithmeticParent+(dest) | + parent.getFullyConverted().getUnspecifiedType() instanceof PointerType + ) +select dest, "This pointer might have type $@ (size " + sourceBase.getSize() + - "), but the pointer arithmetic here is done with type " + - destType + " (size " + destBase.getSize() + ").", - sourceLoc, sourceBase.toString() + "), but the pointer arithmetic here is done with type " + destType + " (size " + + destBase.getSize() + ").", sourceLoc, sourceBase.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingChar.ql b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingChar.ql index c0b6fbffeaa..f96598edd9e 100644 --- a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingChar.ql +++ b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingChar.ql @@ -9,51 +9,46 @@ * @tags security * external/cwe/cwe-468 */ + import IncorrectPointerScalingCommon -from Expr dest, Type destType, Type sourceType, Type sourceBase, - Type destBase, Location sourceLoc -where exists(pointerArithmeticParent(dest)) - and exprSourceType(dest, sourceType, sourceLoc) - and sourceBase = baseType(sourceType) - and destType = dest.getFullyConverted().getType() - and destBase = baseType(destType) - and destBase.getSize() != sourceBase.getSize() - and not dest.isInMacroExpansion() - +from Expr dest, Type destType, Type sourceType, Type sourceBase, Type destBase, Location sourceLoc +where + exists(pointerArithmeticParent(dest)) and + exprSourceType(dest, sourceType, sourceLoc) and + sourceBase = baseType(sourceType) and + destType = dest.getFullyConverted().getType() and + destBase = baseType(destType) and + destBase.getSize() != sourceBase.getSize() and + not dest.isInMacroExpansion() and // If the source type is a char* or void* then don't // produce a result, because it is likely to be a false // positive. - and not (sourceBase instanceof CharType) - and not (sourceBase instanceof VoidType) - - // Don't produce an alert if the dest type is `char *` but the - // expression contains a `sizeof`, which is probably correct. For - // example: - // ``` - // int x[3] = {1,2,3}; - // char* p = (char*)x; - // return *(int*)(p + (2 * sizeof(int))) - // ``` - and not ( - destBase instanceof CharType and - dest.getParent().(Expr).getAChild*() instanceof SizeofOperator - ) - + not sourceBase instanceof CharType and + not sourceBase instanceof VoidType and + // Don't produce an alert if the dest type is `char *` but the + // expression contains a `sizeof`, which is probably correct. For + // example: + // ``` + // int x[3] = {1,2,3}; + // char* p = (char*)x; + // return *(int*)(p + (2 * sizeof(int))) + // ``` + not ( + destBase instanceof CharType and + dest.getParent().(Expr).getAChild*() instanceof SizeofOperator + ) and // Don't produce an alert if the root expression computes // an offset, rather than a pointer. For example: // ``` // (p + 1) - q // ``` - and forall(Expr parent | - parent = pointerArithmeticParent+(dest) | - parent.getFullyConverted().getUnspecifiedType() instanceof PointerType) - + forall(Expr parent | parent = pointerArithmeticParent+(dest) | + parent.getFullyConverted().getUnspecifiedType() instanceof PointerType + ) and // Only produce alerts that are not produced by `IncorrectPointerScaling.ql`. - and (destBase instanceof CharType) -select - dest, + destBase instanceof CharType +select dest, "This pointer might have type $@ (size " + sourceBase.getSize() + - "), but the pointer arithmetic here is done with type " + - destType + " (size " + destBase.getSize() + ").", - sourceLoc, sourceBase.toString() + "), but the pointer arithmetic here is done with type " + destType + " (size " + + destBase.getSize() + ").", sourceLoc, sourceBase.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll index 8079a36a5d3..e2756de18fd 100644 --- a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll +++ b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingCommon.qll @@ -1,13 +1,13 @@ /** * Shared utilities for the CWE-468 queries. */ + import cpp /** * Gets the type parameter of `sizeof` expression `e`. */ -private -Type sizeofParam(Expr e) { +private Type sizeofParam(Expr e) { result = e.(SizeofExprOperator).getExprOperand().getFullyConverted().getType() or result = e.(SizeofTypeOperator).getTypeOperand() @@ -21,9 +21,8 @@ Type sizeofParam(Expr e) { * For example, if `e` is `4 * sizeof(T)` then `sizeofExpr` is * `sizeof(T)` and `sizeofParam` is `T`. */ -private -predicate multiplyWithSizeof(Expr e, Expr sizeofExpr, Type sizeofParam) { - (e = sizeofExpr and sizeofParam = sizeofParam(e).getUnspecifiedType()) +private predicate multiplyWithSizeof(Expr e, Expr sizeofExpr, Type sizeofParam) { + e = sizeofExpr and sizeofParam = sizeofParam(e).getUnspecifiedType() or multiplyWithSizeof(e.(MulExpr).getAnOperand(), sizeofExpr, sizeofParam) } @@ -32,19 +31,21 @@ predicate multiplyWithSizeof(Expr e, Expr sizeofExpr, Type sizeofParam) { * Holds if the pointer `e` is added to the `sizeof` expression * `sizeofExpr` (which may first be multiplied by another expression), * and `sizeofParam` is `sizeofExpr`'s type parameter. - + * * For example, if the program contains the expression * `p - (i * sizeof(T))` then `e` would be `p`, `sizeofExpr` would be * `sizeof(T)`, and `sizeofParam` would be `T`. */ predicate addWithSizeof(Expr e, Expr sizeofExpr, Type sizeofParam) { - exists (PointerAddExpr addExpr - | e = addExpr.getLeftOperand() and - multiplyWithSizeof(addExpr.getRightOperand(), sizeofExpr, sizeofParam)) + exists(PointerAddExpr addExpr | + e = addExpr.getLeftOperand() and + multiplyWithSizeof(addExpr.getRightOperand(), sizeofExpr, sizeofParam) + ) or - exists (PointerSubExpr subExpr - | e = subExpr.getLeftOperand() and - multiplyWithSizeof(subExpr.getRightOperand(), sizeofExpr, sizeofParam)) + exists(PointerSubExpr subExpr | + e = subExpr.getLeftOperand() and + multiplyWithSizeof(subExpr.getRightOperand(), sizeofExpr, sizeofParam) + ) } /** @@ -61,20 +62,25 @@ predicate isPointerType(Type t) { */ Type baseType(Type t) { ( - exists (PointerType dt - | dt = t.getUnspecifiedType() and - result = dt.getBaseType().getUnspecifiedType()) or - exists (ArrayType at - | at = t.getUnspecifiedType() and - (not at.getBaseType().getUnspecifiedType() instanceof ArrayType) and - result = at.getBaseType().getUnspecifiedType()) or - exists (ArrayType at, ArrayType at2 - | at = t.getUnspecifiedType() and + exists(PointerType dt | + dt = t.getUnspecifiedType() and + result = dt.getBaseType().getUnspecifiedType() + ) + or + exists(ArrayType at | + at = t.getUnspecifiedType() and + not at.getBaseType().getUnspecifiedType() instanceof ArrayType and + result = at.getBaseType().getUnspecifiedType() + ) + or + exists(ArrayType at, ArrayType at2 | + at = t.getUnspecifiedType() and at2 = at.getBaseType().getUnspecifiedType() and - result = baseType(at2)) - ) - // Make sure that the type has a size and that it isn't ambiguous. - and strictcount(result.getSize()) = 1 + result = baseType(at2) + ) + ) and + // Make sure that the type has a size and that it isn't ambiguous. + strictcount(result.getSize()) = 1 } /** @@ -94,51 +100,56 @@ Type baseType(Type t) { */ predicate exprSourceType(Expr use, Type sourceType, Location sourceLoc) { // Reaching definitions. - if exists (SsaDefinition def, LocalScopeVariable v | use = def.getAUse(v)) then - exists (SsaDefinition def, LocalScopeVariable v - | use = def.getAUse(v) - | defSourceType(def, v, sourceType, sourceLoc)) - - // Pointer arithmetic - else if use instanceof PointerAddExpr then - exprSourceType(use.(PointerAddExpr).getLeftOperand(), sourceType, sourceLoc) - else if use instanceof PointerSubExpr then - exprSourceType(use.(PointerSubExpr).getLeftOperand(), sourceType, sourceLoc) - else if use instanceof AddExpr then - exprSourceType(use.(AddExpr).getAnOperand(), sourceType, sourceLoc) - else if use instanceof SubExpr then - exprSourceType(use.(SubExpr).getAnOperand(), sourceType, sourceLoc) - else if use instanceof CrementOperation then - exprSourceType(use.(CrementOperation).getOperand(), sourceType, sourceLoc) - - // Conversions are not in the AST, so ignore them. - else if use instanceof Conversion then - none() - - // Source expressions + if exists(SsaDefinition def, LocalScopeVariable v | use = def.getAUse(v)) + then + exists(SsaDefinition def, LocalScopeVariable v | use = def.getAUse(v) | + defSourceType(def, v, sourceType, sourceLoc) + ) else - (sourceType = use.getUnspecifiedType() and - isPointerType(sourceType) and - sourceLoc = use.getLocation()) + // Pointer arithmetic + if use instanceof PointerAddExpr + then exprSourceType(use.(PointerAddExpr).getLeftOperand(), sourceType, sourceLoc) + else + if use instanceof PointerSubExpr + then exprSourceType(use.(PointerSubExpr).getLeftOperand(), sourceType, sourceLoc) + else + if use instanceof AddExpr + then exprSourceType(use.(AddExpr).getAnOperand(), sourceType, sourceLoc) + else + if use instanceof SubExpr + then exprSourceType(use.(SubExpr).getAnOperand(), sourceType, sourceLoc) + else + if use instanceof CrementOperation + then exprSourceType(use.(CrementOperation).getOperand(), sourceType, sourceLoc) + else + // Conversions are not in the AST, so ignore them. + if use instanceof Conversion + then none() + else ( + // Source expressions + sourceType = use.getUnspecifiedType() and + isPointerType(sourceType) and + sourceLoc = use.getLocation() + ) } /** * Holds if there is a pointer expression with type `sourceType` at * location `sourceLoc` which might define the value of `v` at `def`. */ -predicate defSourceType(SsaDefinition def, LocalScopeVariable v, - Type sourceType, Location sourceLoc) { +predicate defSourceType(SsaDefinition def, LocalScopeVariable v, Type sourceType, Location sourceLoc) { exprSourceType(def.getDefiningValue(v), sourceType, sourceLoc) or defSourceType(def.getAPhiInput(v), v, sourceType, sourceLoc) or - exists (Parameter p - | p = v and + exists(Parameter p | + p = v and def.definedByParameter(p) and sourceType = p.getUnspecifiedType() and strictcount(p.getType()) = 1 and isPointerType(sourceType) and - sourceLoc = p.getLocation()) + sourceLoc = p.getLocation() + ) } /** diff --git a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql index 12dcd0a9bd3..42bf03e8628 100644 --- a/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql +++ b/cpp/ql/src/Security/CWE/CWE-468/IncorrectPointerScalingVoid.ql @@ -9,22 +9,20 @@ * @tags security * external/cwe/cwe-468 */ + import IncorrectPointerScalingCommon -from Expr dest, Type destType, Type sourceType, Type sourceBase, - Type destBase, Location sourceLoc -where exists(pointerArithmeticParent(dest)) - and exprSourceType(dest, sourceType, sourceLoc) - and sourceBase = baseType(sourceType) - and destType = dest.getFullyConverted().getType() - and destBase = baseType(destType) - and destBase.getSize() != sourceBase.getSize() - and not dest.isInMacroExpansion() - +from Expr dest, Type destType, Type sourceType, Type sourceBase, Type destBase, Location sourceLoc +where + exists(pointerArithmeticParent(dest)) and + exprSourceType(dest, sourceType, sourceLoc) and + sourceBase = baseType(sourceType) and + destType = dest.getFullyConverted().getType() and + destBase = baseType(destType) and + destBase.getSize() != sourceBase.getSize() and + not dest.isInMacroExpansion() and // Only produce alerts that are not produced by `IncorrectPointerScaling.ql`. - and (destBase instanceof VoidType) -select - dest, + destBase instanceof VoidType +select dest, "This pointer might have type $@ (size " + sourceBase.getSize() + - "), but the pointer arithmetic here is done with type void", - sourceLoc, sourceBase.toString() + "), but the pointer arithmetic here is done with type void", sourceLoc, sourceBase.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql b/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql index 69711eb1309..692325ff373 100644 --- a/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql +++ b/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql @@ -10,14 +10,15 @@ * @tags security * external/cwe/cwe-468 */ + import cpp import IncorrectPointerScalingCommon private predicate isCharSzPtrExpr(Expr e) { - exists (PointerType pt - | pt = e.getFullyConverted().getUnspecifiedType() - | pt.getBaseType() instanceof CharType - or pt.getBaseType() instanceof VoidType) + exists(PointerType pt | pt = e.getFullyConverted().getUnspecifiedType() | + pt.getBaseType() instanceof CharType or + pt.getBaseType() instanceof VoidType + ) } from Expr sizeofExpr, Expr e @@ -26,8 +27,6 @@ where // the pointer expression to be char* or void*. Otherwise it // is probably a mistake. addWithSizeof(e, sizeofExpr, _) and not isCharSzPtrExpr(e) -select - sizeofExpr, - "Suspicious sizeof offset in a pointer arithmetic expression. " + - "The type of the pointer is " + - e.getFullyConverted().getType().toString() + "." +select sizeofExpr, + "Suspicious sizeof offset in a pointer arithmetic expression. " + "The type of the pointer is " + + e.getFullyConverted().getType().toString() + "." diff --git a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql index fc214b54f8e..fa74c85555d 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql @@ -31,20 +31,18 @@ abstract class SystemData extends Element { Expr getAnExprIndirect() { // direct SystemData result = getAnExpr() or - // flow via global or member variable (conservative approximation) result = getAnAffectedVar().getAnAccess() or - // flow via stack variable definitionUsePair(_, getAnExprIndirect(), result) or useUsePair(_, getAnExprIndirect(), result) or useUsePair(_, result, getAnExprIndirect()) or - // flow from assigned value to assignment expression result.(AssignExpr).getRValue() = getAnExprIndirect() } - /** Gets a global or member variable that may be affected by this system + /** + * Gets a global or member variable that may be affected by this system * data (conservative approximation). */ private Variable getAnAffectedVar() { @@ -60,137 +58,117 @@ abstract class SystemData extends Element { * Data originating from the environment. */ class EnvData extends SystemData { - EnvData() { - this instanceof EnvironmentRead - } + EnvData() { this instanceof EnvironmentRead } - override Expr getAnExpr() { - result = this - } + override Expr getAnExpr() { result = this } } /** * Data originating from a call to `mysql_get_client_info()`. */ class SQLClientInfo extends SystemData { - SQLClientInfo() { - this.(FunctionCall).getTarget().hasName("mysql_get_client_info") - } + SQLClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") } - override Expr getAnExpr() { - result = this - } + override Expr getAnExpr() { result = this } } private predicate sqlConnectInfo(FunctionCall source, VariableAccess use) { ( source.getTarget().hasName("mysql_connect") or source.getTarget().hasName("mysql_real_connect") - ) and ( - use = source.getAnArgument() - ) + ) and + use = source.getAnArgument() } /** * Data passed into an SQL connect function. */ class SQLConnectInfo extends SystemData { - SQLConnectInfo() { - sqlConnectInfo(this, _) - } + SQLConnectInfo() { sqlConnectInfo(this, _) } - override Expr getAnExpr() { - sqlConnectInfo(this, result) - } + override Expr getAnExpr() { sqlConnectInfo(this, result) } } private predicate posixSystemInfo(FunctionCall source, Element use) { + // long sysconf(int name) + // - various OS / system values and limits + source.getTarget().hasName("sysconf") and + use = source + or + // size_t confstr(int name, char *buf, size_t len) + // - various OS / system strings, such as the libc version + // int statvfs(const char *__path, struct statvfs *__buf) + // int fstatvfs(int __fd, struct statvfs *__buf) + // - various filesystem parameters + // int uname(struct utsname *buf) + // - OS name and version ( - // long sysconf(int name) - // - various OS / system values and limits - source.getTarget().hasName("sysconf") and - use = source - ) or ( - // size_t confstr(int name, char *buf, size_t len) - // - various OS / system strings, such as the libc version - // int statvfs(const char *__path, struct statvfs *__buf) - // int fstatvfs(int __fd, struct statvfs *__buf) - // - various filesystem parameters - // int uname(struct utsname *buf) - // - OS name and version - ( - source.getTarget().hasName("confstr") or - source.getTarget().hasName("statvfs") or - source.getTarget().hasName("fstatvfs") or - source.getTarget().hasName("uname") - ) and ( - use = source.getArgument(1) - ) - ) + source.getTarget().hasName("confstr") or + source.getTarget().hasName("statvfs") or + source.getTarget().hasName("fstatvfs") or + source.getTarget().hasName("uname") + ) and + use = source.getArgument(1) } /** * Data obtained from a POSIX system information call. */ class PosixSystemInfo extends SystemData { - PosixSystemInfo() { - posixSystemInfo(this, _) - } + PosixSystemInfo() { posixSystemInfo(this, _) } - override Expr getAnExpr() { - posixSystemInfo(this, result) - } + override Expr getAnExpr() { posixSystemInfo(this, result) } } private predicate posixPWInfo(FunctionCall source, Element use) { + // struct passwd *getpwnam(const char *name); + // struct passwd *getpwuid(uid_t uid); + // struct passwd *getpwent(void); + // struct group *getgrnam(const char *name); + // struct group *getgrgid(gid_t); + // struct group *getgrent(void); ( - // struct passwd *getpwnam(const char *name); - // struct passwd *getpwuid(uid_t uid); - // struct passwd *getpwent(void); - // struct group *getgrnam(const char *name); - // struct group *getgrgid(gid_t); - // struct group *getgrent(void); - ( - source.getTarget().hasName("getpwnam") or - source.getTarget().hasName("getpwuid") or - source.getTarget().hasName("getpwent") or - source.getTarget().hasName("getgrnam") or - source.getTarget().hasName("getgrgid") or - source.getTarget().hasName("getgrent") - ) and - use = source - ) or ( - // int getpwnam_r(const char *name, struct passwd *pwd, - // char *buf, size_t buflen, struct passwd **result); - // int getpwuid_r(uid_t uid, struct passwd *pwd, - // char *buf, size_t buflen, struct passwd **result); - // int getgrgid_r(gid_t gid, struct group *grp, - // char *buf, size_t buflen, struct group **result); - // int getgrnam_r(const char *name, struct group *grp, - // char *buf, size_t buflen, struct group **result); - ( - source.getTarget().hasName("getpwnam_r") or - source.getTarget().hasName("getpwuid_r") or - source.getTarget().hasName("getgrgid_r") or - source.getTarget().hasName("getgrnam_r") - ) and ( - use = source.getArgument(1) or - use = source.getArgument(2) or - use = source.getArgument(4) - ) - ) or ( - // int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, - // struct passwd **result); - // int getgrent_r(struct group *gbuf, char *buf, - // size_t buflen, struct group **gbufp); - ( - source.getTarget().hasName("getpwent_r") or - source.getTarget().hasName("getgrent_r") - ) and ( - use = source.getArgument(0) or - use = source.getArgument(1) or - use = source.getArgument(3) - ) + source.getTarget().hasName("getpwnam") or + source.getTarget().hasName("getpwuid") or + source.getTarget().hasName("getpwent") or + source.getTarget().hasName("getgrnam") or + source.getTarget().hasName("getgrgid") or + source.getTarget().hasName("getgrent") + ) and + use = source + or + // int getpwnam_r(const char *name, struct passwd *pwd, + // char *buf, size_t buflen, struct passwd **result); + // int getpwuid_r(uid_t uid, struct passwd *pwd, + // char *buf, size_t buflen, struct passwd **result); + // int getgrgid_r(gid_t gid, struct group *grp, + // char *buf, size_t buflen, struct group **result); + // int getgrnam_r(const char *name, struct group *grp, + // char *buf, size_t buflen, struct group **result); + ( + source.getTarget().hasName("getpwnam_r") or + source.getTarget().hasName("getpwuid_r") or + source.getTarget().hasName("getgrgid_r") or + source.getTarget().hasName("getgrnam_r") + ) and + ( + use = source.getArgument(1) or + use = source.getArgument(2) or + use = source.getArgument(4) + ) + or + // int getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, + // struct passwd **result); + // int getgrent_r(struct group *gbuf, char *buf, + // size_t buflen, struct group **gbufp); + ( + source.getTarget().hasName("getpwent_r") or + source.getTarget().hasName("getgrent_r") + ) and + ( + use = source.getArgument(0) or + use = source.getArgument(1) or + use = source.getArgument(3) ) } @@ -198,103 +176,89 @@ private predicate posixPWInfo(FunctionCall source, Element use) { * Data obtained from a POSIX user/password/group database information call. */ class PosixPWInfo extends SystemData { - PosixPWInfo() { - posixPWInfo(this, _) - } + PosixPWInfo() { posixPWInfo(this, _) } - override Expr getAnExpr() { - posixPWInfo(this, result) - } + override Expr getAnExpr() { posixPWInfo(this, result) } } private predicate windowsSystemInfo(FunctionCall source, Element use) { + // DWORD WINAPI GetVersion(void); + source.getTarget().hasGlobalName("GetVersion") and + use = source + or + // BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo); + // void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); + // void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); ( - // DWORD WINAPI GetVersion(void); - ( - source.getTarget().hasGlobalName("GetVersion") - ) and - use = source - ) or ( - // BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo); - // void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); - // void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); - ( - source.getTarget().hasName("GetVersionEx") or - source.getTarget().hasName("GetVersionExA") or - source.getTarget().hasName("GetVersionExW") or - source.getTarget().hasName("GetSystemInfo") or - source.getTarget().hasName("GetNativeSystemInfo") - ) and - use = source.getArgument(0) - ) + source.getTarget().hasName("GetVersionEx") or + source.getTarget().hasName("GetVersionExA") or + source.getTarget().hasName("GetVersionExW") or + source.getTarget().hasName("GetSystemInfo") or + source.getTarget().hasName("GetNativeSystemInfo") + ) and + use = source.getArgument(0) } /** * Data obtained from a Windows system information call. */ class WindowsSystemInfo extends SystemData { - WindowsSystemInfo() { - windowsSystemInfo(this, _) - } + WindowsSystemInfo() { windowsSystemInfo(this, _) } - override Expr getAnExpr() { - windowsSystemInfo(this, result) - } + override Expr getAnExpr() { windowsSystemInfo(this, result) } } private predicate windowsFolderPath(FunctionCall source, Element use) { + // BOOL SHGetSpecialFolderPath( + // HWND hwndOwner, + // _Out_ LPTSTR lpszPath, + // _In_ int csidl, + // _In_ BOOL fCreate + // ); ( - // BOOL SHGetSpecialFolderPath( - // HWND hwndOwner, - // _Out_ LPTSTR lpszPath, - // _In_ int csidl, - // _In_ BOOL fCreate - // ); - ( - source.getTarget().hasName("SHGetSpecialFolderPath") or - source.getTarget().hasName("SHGetSpecialFolderPathA") or - source.getTarget().hasName("SHGetSpecialFolderPathW") - ) and - use = source.getArgument(1) - ) or ( - // HRESULT SHGetKnownFolderPath( - // _In_ REFKNOWNFOLDERID rfid, - // _In_ DWORD dwFlags, - // _In_opt_ HANDLE hToken, - // _Out_ PWSTR *ppszPath - // ); - source.getTarget().hasName("SHGetKnownFolderPath") and - use = source.getArgument(3) - ) or ( - // HRESULT SHGetFolderPath( - // _In_ HWND hwndOwner, - // _In_ int nFolder, - // _In_ HANDLE hToken, - // _In_ DWORD dwFlags, - // _Out_ LPTSTR pszPath - // ); - ( - source.getTarget().hasName("SHGetFolderPath") or - source.getTarget().hasName("SHGetFolderPathA") or - source.getTarget().hasName("SHGetFolderPathW") - ) and - use = source.getArgument(4) - ) or ( - // HRESULT SHGetFolderPathAndSubDir( - // _In_ HWND hwnd, - // _In_ int csidl, - // _In_ HANDLE hToken, - // _In_ DWORD dwFlags, - // _In_ LPCTSTR pszSubDir, - // _Out_ LPTSTR pszPath - // ); - ( - source.getTarget().hasName("SHGetFolderPathAndSubDir") or - source.getTarget().hasName("SHGetFolderPathAndSubDirA") or - source.getTarget().hasName("SHGetFolderPathAndSubDirW") - ) and - use = source.getArgument(5) - ) + source.getTarget().hasName("SHGetSpecialFolderPath") or + source.getTarget().hasName("SHGetSpecialFolderPathA") or + source.getTarget().hasName("SHGetSpecialFolderPathW") + ) and + use = source.getArgument(1) + or + // HRESULT SHGetKnownFolderPath( + // _In_ REFKNOWNFOLDERID rfid, + // _In_ DWORD dwFlags, + // _In_opt_ HANDLE hToken, + // _Out_ PWSTR *ppszPath + // ); + source.getTarget().hasName("SHGetKnownFolderPath") and + use = source.getArgument(3) + or + // HRESULT SHGetFolderPath( + // _In_ HWND hwndOwner, + // _In_ int nFolder, + // _In_ HANDLE hToken, + // _In_ DWORD dwFlags, + // _Out_ LPTSTR pszPath + // ); + ( + source.getTarget().hasName("SHGetFolderPath") or + source.getTarget().hasName("SHGetFolderPathA") or + source.getTarget().hasName("SHGetFolderPathW") + ) and + use = source.getArgument(4) + or + // HRESULT SHGetFolderPathAndSubDir( + // _In_ HWND hwnd, + // _In_ int csidl, + // _In_ HANDLE hToken, + // _In_ DWORD dwFlags, + // _In_ LPCTSTR pszSubDir, + // _Out_ LPTSTR pszPath + // ); + ( + source.getTarget().hasName("SHGetFolderPathAndSubDir") or + source.getTarget().hasName("SHGetFolderPathAndSubDirA") or + source.getTarget().hasName("SHGetFolderPathAndSubDirW") + ) and + use = source.getArgument(5) } /** @@ -302,13 +266,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { * location of `System32`). */ class WindowsFolderPath extends SystemData { - WindowsFolderPath() { - windowsFolderPath(this, _) - } + WindowsFolderPath() { windowsFolderPath(this, _) } - override Expr getAnExpr() { - windowsFolderPath(this, result) - } + override Expr getAnExpr() { windowsFolderPath(this, result) } } private predicate logonUser(FunctionCall source, VariableAccess use) { @@ -316,102 +276,88 @@ private predicate logonUser(FunctionCall source, VariableAccess use) { source.getTarget().hasName("LogonUser") or source.getTarget().hasName("LogonUserW") or source.getTarget().hasName("LogonUserA") - ) and ( - use = source.getAnArgument() - ) + ) and + use = source.getAnArgument() } /** * Data passed into a `LogonUser` (Windows) function. */ class LogonUser extends SystemData { - LogonUser() { - logonUser(this, _) - } + LogonUser() { logonUser(this, _) } - override Expr getAnExpr() { - logonUser(this, result) - } + override Expr getAnExpr() { logonUser(this, result) } } private predicate regQuery(FunctionCall source, VariableAccess use) { + // LONG WINAPI RegQueryValue( + // _In_ HKEY hKey, + // _In_opt_ LPCTSTR lpSubKey, + // _Out_opt_ LPTSTR lpValue, + // _Inout_opt_ PLONG lpcbValue + // ); ( - // LONG WINAPI RegQueryValue( - // _In_ HKEY hKey, - // _In_opt_ LPCTSTR lpSubKey, - // _Out_opt_ LPTSTR lpValue, - // _Inout_opt_ PLONG lpcbValue - // ); - ( - source.getTarget().hasName("RegQueryValue") or - source.getTarget().hasName("RegQueryValueA") or - source.getTarget().hasName("RegQueryValueW") - ) and ( - use = source.getArgument(2) - ) - ) or ( - // LONG WINAPI RegQueryMultipleValues( - // _In_ HKEY hKey, - // _Out_ PVALENT val_list, - // _In_ DWORD num_vals, - // _Out_opt_ LPTSTR lpValueBuf, - // _Inout_opt_ LPDWORD ldwTotsize - // ); - ( - source.getTarget().hasName("RegQueryMultipleValues") or - source.getTarget().hasName("RegQueryMultipleValuesA") or - source.getTarget().hasName("RegQueryMultipleValuesW") - ) and ( - use = source.getArgument(3) - ) - ) or ( - // LONG WINAPI RegQueryValueEx( - // _In_ HKEY hKey, - // _In_opt_ LPCTSTR lpValueName, - // _Reserved_ LPDWORD lpReserved, - // _Out_opt_ LPDWORD lpType, - // _Out_opt_ LPBYTE lpData, - // _Inout_opt_ LPDWORD lpcbData - // ); - ( - source.getTarget().hasName("RegQueryValueEx") or - source.getTarget().hasName("RegQueryValueExA") or - source.getTarget().hasName("RegQueryValueExW") - ) and ( - use = source.getArgument(4) - ) - ) or ( - // LONG WINAPI RegGetValue( - // _In_ HKEY hkey, - // _In_opt_ LPCTSTR lpSubKey, - // _In_opt_ LPCTSTR lpValue, - // _In_opt_ DWORD dwFlags, - // _Out_opt_ LPDWORD pdwType, - // _Out_opt_ PVOID pvData, - // _Inout_opt_ LPDWORD pcbData - // ); - ( - source.getTarget().hasName("RegGetValue") or - source.getTarget().hasName("RegGetValueA") or - source.getTarget().hasName("RegGetValueW") - ) and ( - use = source.getArgument(5) - ) - ) + source.getTarget().hasName("RegQueryValue") or + source.getTarget().hasName("RegQueryValueA") or + source.getTarget().hasName("RegQueryValueW") + ) and + use = source.getArgument(2) + or + // LONG WINAPI RegQueryMultipleValues( + // _In_ HKEY hKey, + // _Out_ PVALENT val_list, + // _In_ DWORD num_vals, + // _Out_opt_ LPTSTR lpValueBuf, + // _Inout_opt_ LPDWORD ldwTotsize + // ); + ( + source.getTarget().hasName("RegQueryMultipleValues") or + source.getTarget().hasName("RegQueryMultipleValuesA") or + source.getTarget().hasName("RegQueryMultipleValuesW") + ) and + use = source.getArgument(3) + or + // LONG WINAPI RegQueryValueEx( + // _In_ HKEY hKey, + // _In_opt_ LPCTSTR lpValueName, + // _Reserved_ LPDWORD lpReserved, + // _Out_opt_ LPDWORD lpType, + // _Out_opt_ LPBYTE lpData, + // _Inout_opt_ LPDWORD lpcbData + // ); + ( + source.getTarget().hasName("RegQueryValueEx") or + source.getTarget().hasName("RegQueryValueExA") or + source.getTarget().hasName("RegQueryValueExW") + ) and + use = source.getArgument(4) + or + // LONG WINAPI RegGetValue( + // _In_ HKEY hkey, + // _In_opt_ LPCTSTR lpSubKey, + // _In_opt_ LPCTSTR lpValue, + // _In_opt_ DWORD dwFlags, + // _Out_opt_ LPDWORD pdwType, + // _Out_opt_ PVOID pvData, + // _Inout_opt_ LPDWORD pcbData + // ); + ( + source.getTarget().hasName("RegGetValue") or + source.getTarget().hasName("RegGetValueA") or + source.getTarget().hasName("RegGetValueW") + ) and + use = source.getArgument(5) } /** * Data read from the Windows registry. */ class RegQuery extends SystemData { - RegQuery() { - regQuery(this, _) - } + RegQuery() { regQuery(this, _) } - override Expr getAnExpr() { - regQuery(this, result) - } + override Expr getAnExpr() { regQuery(this, result) } } + /** * Somewhere data is output. */ @@ -426,21 +372,17 @@ abstract class DataOutput extends Element { * Data that is output via standard output or standard error. */ class StandardOutput extends DataOutput { - StandardOutput() { - this instanceof OutputWrite - } + StandardOutput() { this instanceof OutputWrite } - override Expr getASource() { - result = this.(OutputWrite).getASource() - } + override Expr getASource() { result = this.(OutputWrite).getASource() } } private predicate socketCallOrIndirect(FunctionCall call) { - ( - // direct socket call - // int socket(int domain, int type, int protocol); - call.getTarget().getName() = "socket" - ) or exists(ReturnStmt rtn | + // direct socket call + // int socket(int domain, int type, int protocol); + call.getTarget().getName() = "socket" + or + exists(ReturnStmt rtn | // indirect socket call call.getTarget() = rtn.getEnclosingFunction() and ( @@ -480,13 +422,9 @@ private predicate socketOutput(FunctionCall call, Expr data) { * Data that is output via a socket. */ class SocketOutput extends DataOutput { - SocketOutput() { - socketOutput(this, _) - } + SocketOutput() { socketOutput(this, _) } - override Expr getASource() { - socketOutput(this, result) - } + override Expr getASource() { socketOutput(this, result) } } from SystemData sd, DataOutput ow diff --git a/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql b/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql index 5cc80730f9f..84d7b48e265 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql @@ -9,6 +9,7 @@ * security * external/cwe/cwe-242 */ + import cpp from FunctionCall call, Function target diff --git a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql index 1e805b3822d..fc47d04c2c5 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/DangerousUseOfCin.ql @@ -10,6 +10,7 @@ * security * external/cwe/cwe-676 */ + import cpp /** @@ -88,19 +89,15 @@ class OperatorRShiftCall extends FunctionCall { */ Expr getSource() { - if (getTarget() instanceof MemberFunction) then ( - result = getQualifier() - ) else ( - result = getArgument(0) - ) + if getTarget() instanceof MemberFunction + then result = getQualifier() + else result = getArgument(0) } Expr getDest() { - if (getTarget() instanceof MemberFunction) then ( - result = getArgument(0) - ) else ( - result = getArgument(1) - ) + if getTarget() instanceof MemberFunction + then result = getArgument(0) + else result = getArgument(1) } } @@ -124,9 +121,7 @@ abstract class PotentiallyDangerousInput extends Expr { * Gets the width restriction that applies to the input stream * for this expression, if any. */ - Expr getWidth() { - result = getPreviousAccess().getWidthAfter() - } + Expr getWidth() { result = getPreviousAccess().getWidthAfter() } private Expr getWidthSetHere() { exists(FunctionCall widthCall | @@ -134,7 +129,9 @@ abstract class PotentiallyDangerousInput extends Expr { widthCall.getQualifier() = this and widthCall.getTarget().getName() = "width" and result = widthCall.getArgument(0) - ) or exists(FunctionCall setwCall, Function setw | + ) + or + exists(FunctionCall setwCall, Function setw | // >> std::setw setwCall = this.(OperatorRShiftCall).getDest() and setw = setwCall.getTarget() and @@ -147,11 +144,11 @@ abstract class PotentiallyDangerousInput extends Expr { private predicate isWidthConsumedHere() { // std::cin >> s, where s is a char*, char[] or std::string type // or wide character equivalent - exists(Type t | - t = this.(OperatorRShiftCall).getDest().getUnderlyingType() | - t instanceof AnyCharPointerType or - t instanceof AnyCharArrayType or - t instanceof AnyStdStringType) + exists(Type t | t = this.(OperatorRShiftCall).getDest().getUnderlyingType() | + t instanceof AnyCharPointerType or + t instanceof AnyCharArrayType or + t instanceof AnyStdStringType + ) } /** @@ -161,37 +158,31 @@ abstract class PotentiallyDangerousInput extends Expr { Expr getWidthAfter() { result = getWidthSetHere() or - ( - not exists(getWidthSetHere()) and - not isWidthConsumedHere() and - result = getWidth() - ) + not exists(getWidthSetHere()) and + not isWidthConsumedHere() and + result = getWidth() } } -predicate nextPotentiallyDangerousInput(ControlFlowNode cfn, PotentiallyDangerousInput next, Variable streamVariable) { - ( - // this node - next = cfn and - next.getStreamVariable() = streamVariable - ) or ( - // flow - not cfn.(PotentiallyDangerousInput).getStreamVariable() = streamVariable and - nextPotentiallyDangerousInput(cfn.getASuccessor(), next, streamVariable) - ) +predicate nextPotentiallyDangerousInput( + ControlFlowNode cfn, PotentiallyDangerousInput next, Variable streamVariable +) { + // this node + next = cfn and + next.getStreamVariable() = streamVariable + or + // flow + not cfn.(PotentiallyDangerousInput).getStreamVariable() = streamVariable and + nextPotentiallyDangerousInput(cfn.getASuccessor(), next, streamVariable) } /** * A direct access to `std::cin` or `std::wcin`. */ class CinAccess extends PotentiallyDangerousInput { - CinAccess() { - this.(VariableAccess).getTarget() instanceof CinVariable - } + CinAccess() { this.(VariableAccess).getTarget() instanceof CinVariable } - override Variable getStreamVariable() { - result = this.(VariableAccess).getTarget() - } + override Variable getStreamVariable() { result = this.(VariableAccess).getTarget() } override PotentiallyDangerousInput getPreviousAccess() { nextPotentiallyDangerousInput(result.getASuccessor(), this, result.getStreamVariable()) @@ -202,13 +193,9 @@ class CinAccess extends PotentiallyDangerousInput { * A direct access to a variable of type `std::ifstream` or `std::wifstream`. */ class IFStreamAccess extends PotentiallyDangerousInput { - IFStreamAccess() { - this.(VariableAccess).getTarget().getUnderlyingType() instanceof IFStream - } + IFStreamAccess() { this.(VariableAccess).getTarget().getUnderlyingType() instanceof IFStream } - override Variable getStreamVariable() { - result = this.(VariableAccess).getTarget() - } + override Variable getStreamVariable() { result = this.(VariableAccess).getTarget() } override PotentiallyDangerousInput getPreviousAccess() { nextPotentiallyDangerousInput(result.getASuccessor(), this, result.getStreamVariable()) @@ -219,9 +206,7 @@ class IFStreamAccess extends PotentiallyDangerousInput { * A chained call to `std::operator>>` on a potentially dangerous input. */ class ChainedInput extends PotentiallyDangerousInput { - ChainedInput() { - this.(OperatorRShiftCall).getSource() instanceof PotentiallyDangerousInput - } + ChainedInput() { this.(OperatorRShiftCall).getSource() instanceof PotentiallyDangerousInput } override Variable getStreamVariable() { result = this.(OperatorRShiftCall).getSource().(PotentiallyDangerousInput).getStreamVariable() @@ -238,21 +223,17 @@ where input = rshift.getSource() and dest = rshift.getDest() and ( - ( - // destination is char* or wchar_t* - dest.getUnderlyingType() instanceof AnyCharPointerType and - - // assume any width setting makes this safe - not exists(input.getWidthAfter()) - ) or exists(int arraySize | + // destination is char* or wchar_t* + dest.getUnderlyingType() instanceof AnyCharPointerType and + // assume any width setting makes this safe + not exists(input.getWidthAfter()) + or + exists(int arraySize | // destination is char[] or wchar_t* or a wide character equivalent. arraySize = dest.getUnderlyingType().(AnyCharArrayType).getArraySize() and - // assume any width setting makes this safe, unless we know // it to be larger than the array. - forall(Expr w | w = input.getWidthAfter() | - w.getValue().toInt() > arraySize - ) + forall(Expr w | w = input.getWidthAfter() | w.getValue().toInt() > arraySize) ) ) select rshift, "Use of 'cin' without specifying the length of the input may be dangerous." diff --git a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql index 63e6f125e3a..71601ec2181 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/PotentiallyDangerousFunction.ql @@ -9,6 +9,7 @@ * security * external/cwe/cwe-676 */ + import cpp predicate potentiallyDangerousFunction(Function f, string message) { @@ -23,7 +24,6 @@ predicate potentiallyDangerousFunction(Function f, string message) { ) } - from FunctionCall call, Function target, string message where call.getTarget() = target and diff --git a/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql b/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql index c415a966ee3..0d866ff1196 100644 --- a/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql +++ b/cpp/ql/src/Security/CWE/CWE-704/WcharCharConversion.ql @@ -1,7 +1,7 @@ /** * @name Cast from char* to wchar_t* - * @description Casting a byte string to a wide-character string is likely - * to yield a string that is incorrectly terminated or aligned. + * @description Casting a byte string to a wide-character string is likely + * to yield a string that is incorrectly terminated or aligned. * This can lead to undefined behavior, including buffer overruns. * @kind problem * @id cpp/incorrect-string-type-conversion @@ -11,19 +11,20 @@ * external/cwe/cwe-704 * external/microsoft/c/c6276 */ + import cpp class WideCharPointerType extends PointerType { - WideCharPointerType() { - this.getBaseType() instanceof WideCharType - } + WideCharPointerType() { this.getBaseType() instanceof WideCharType } } from Expr e1, Cast e2 -where +where e2 = e1.getConversion() and exists(WideCharPointerType w, CharPointerType c | w = e2.getUnspecifiedType().(PointerType) and c = e1.getUnspecifiedType().(PointerType) ) -select e1, "Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() + ". Use of invalid string can lead to undefined behavior." \ No newline at end of file +select e1, + "Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() + + ". Use of invalid string can lead to undefined behavior." diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql index 5d1480f59c5..ba4792e4c1a 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.ql @@ -14,8 +14,7 @@ import FilePermissions import semmle.code.cpp.commons.unix.Constants predicate worldWritableCreation(FileCreationExpr fc, int mode) { - mode = localUmask(fc).mask(fc.getMode()) - and + mode = localUmask(fc).mask(fc.getMode()) and sets(mode, s_iwoth()) } @@ -25,16 +24,18 @@ predicate setWorldWritable(FunctionCall fc, int mode) { name = "fchmod" or name = "_chmod" or name = "_wchmod" - ) - and - mode = fc.getArgument(1).getValue().toInt() - and + ) and + mode = fc.getArgument(1).getValue().toInt() and sets(mode, s_iwoth()) } from Expr fc, int mode, string message where - worldWritableCreation(fc, mode) and message = "A file may be created here with mode "+octalFileMode(mode)+", which would make it world-writable." + worldWritableCreation(fc, mode) and + message = "A file may be created here with mode " + octalFileMode(mode) + + ", which would make it world-writable." or - setWorldWritable(fc, mode) and message = "This sets a file's permissions to "+octalFileMode(mode)+", which would make it world-writable." + setWorldWritable(fc, mode) and + message = "This sets a file's permissions to " + octalFileMode(mode) + + ", which would make it world-writable." select fc, message diff --git a/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll b/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll index 3f89093fb04..e9e94624ae4 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll +++ b/cpp/ql/src/Security/CWE/CWE-732/FilePermissions.qll @@ -8,53 +8,42 @@ private string octalDigit(int n, int digit) { bindingset[n, digit] private string octalDigitOpt(int n, int digit) { - exists(string s | s = octalDigit(n, digit) | - if s = "0" then result = "" else result = s - ) + exists(string s | s = octalDigit(n, digit) | if s = "0" then result = "" else result = s) } bindingset[mode] string octalFileMode(int mode) { - if mode >= 0 and mode <= 4095 /* octal 07777 */ then - result = - "0" + - octalDigitOpt(mode, 3) + - octalDigit(mode, 2) + - octalDigit(mode, 1) + - octalDigit(mode, 0) - else - result = "[non-standard mode: decimal "+ mode +"]" + if mode >= 0 and mode <= 4095 + then + /* octal 07777 */ result = "0" + octalDigitOpt(mode, 3) + octalDigit(mode, 2) + + octalDigit(mode, 1) + octalDigit(mode, 0) + else result = "[non-standard mode: decimal " + mode + "]" } /** * Holds if the bitmask `mask` sets any of the bit fields in `fields`. */ bindingset[mask, fields] -predicate sets(int mask, int fields) { - mask.bitAnd(fields) != 0 -} +predicate sets(int mask, int fields) { mask.bitAnd(fields) != 0 } /** * Gets the value that `fc` sets the umask to, if `fc` is a call to * one of the `umask` family of functions. */ private int umask(FunctionCall fc) { - exists(string name | - name = fc.getTarget().getName() | - name = "umask" or - name = "_umask" or - name = "_umask_s") - and + exists(string name | name = fc.getTarget().getName() | + name = "umask" or + name = "_umask" or + name = "_umask_s" + ) and result = fc.getArgument(0).getValue().toInt() } class Umask extends int { Umask() { this = 0 or this = umask(_) } - bindingset[mode,this] - int mask(int mode) { - result = mode.bitAnd(this.bitNot()) - } + bindingset[mode, this] + int mask(int mode) { result = mode.bitAnd(this.bitNot()) } } Umask defaultUmask() { result = 0 } @@ -63,67 +52,67 @@ Umask defaultUmask() { result = 0 } * Gets the last umask set in `block`. */ private Umask lastUmask(BasicBlock block) { - exists(int i | result = umask(block.getNode(i)) - and not exists(int j | j > i | exists(umask(block.getNode(j))))) + exists(int i | + result = umask(block.getNode(i)) and + not exists(int j | j > i | exists(umask(block.getNode(j)))) + ) } private Umask umaskStrictlyReaches(BasicBlock block) { exists(BasicBlock pred | pred = block.getAPredecessor() | if exists(umask(pred.getNode(_))) - then - result = lastUmask(pred) - else - result = umaskStrictlyReaches(pred) + then result = lastUmask(pred) + else result = umaskStrictlyReaches(pred) ) } private Umask localDefinedUmask(FileCreationExpr e) { exists(BasicBlock b, int i | e = b.getNode(i) | - (not exists(umask(b.getNode(_))) and result = umaskStrictlyReaches(b)) + not exists(umask(b.getNode(_))) and result = umaskStrictlyReaches(b) or exists(Expr um, int j | um = b.getNode(j) and j <= i | - result = umask(um) - and - not exists(int k | k in [j+1 .. i] | exists(umask(b.getNode(k)))) + result = umask(um) and + not exists(int k | k in [j + 1 .. i] | exists(umask(b.getNode(k)))) ) ) } Umask localUmask(FileCreationExpr e) { - if exists(localDefinedUmask(e)) - then - result = localDefinedUmask(e) - else - result = defaultUmask() + if exists(localDefinedUmask(e)) then result = localDefinedUmask(e) else result = defaultUmask() } abstract class FileCreationExpr extends FunctionCall { abstract Expr getPath(); + abstract int getMode(); } class OpenCreationExpr extends FileCreationExpr { OpenCreationExpr() { - exists(string name | - name = this.getTarget().getName() | - name = "open" or - name = "_open" or - name = "_wopen") - and + exists(string name | name = this.getTarget().getName() | + name = "open" or + name = "_open" or + name = "_wopen" + ) and sets(this.getArgument(1).getValue().toInt(), o_creat()) } + override Expr getPath() { result = this.getArgument(0) } + override int getMode() { if exists(this.getArgument(2)) then result = this.getArgument(2).getValue().toInt() - else // assume anything is permitted - result = 0.bitNot() + else + // assume anything is permitted + result = 0.bitNot() } } class CreatCreationExpr extends FileCreationExpr { CreatCreationExpr() { this.getTarget().getName() = "creat" } + override Expr getPath() { result = this.getArgument(0) } + override int getMode() { result = this.getArgument(1).getValue().toInt() } } @@ -132,46 +121,54 @@ class OpenatCreationExpr extends FileCreationExpr { this.getTarget().getName() = "openat" and this.getNumberOfArguments() = 4 } + override Expr getPath() { result = this.getArgument(1) } + override int getMode() { result = this.getArgument(3).getValue().toInt() } } private int fopenMode() { - result = s_irusr().bitOr(s_irgrp()).bitOr(s_iroth()).bitOr(s_iwusr()).bitOr(s_iwgrp()).bitOr(s_iwoth()) + result = s_irusr() + .bitOr(s_irgrp()) + .bitOr(s_iroth()) + .bitOr(s_iwusr()) + .bitOr(s_iwgrp()) + .bitOr(s_iwoth()) } class FopenCreationExpr extends FileCreationExpr { FopenCreationExpr() { - exists(string name | - name = this.getTarget().getName() | - name = "fopen" or - name = "_wfopen" or - name = "fsopen" or - name = "_wfsopen") - and + exists(string name | name = this.getTarget().getName() | + name = "fopen" or + name = "_wfopen" or + name = "fsopen" or + name = "_wfsopen" + ) and exists(string mode | - (mode = "w" or mode = "a") - and - this.getArgument(1).getValue().matches(mode+"%")) + (mode = "w" or mode = "a") and + this.getArgument(1).getValue().matches(mode + "%") + ) } + override Expr getPath() { result = this.getArgument(0) } + override int getMode() { result = fopenMode() } } class FopensCreationExpr extends FileCreationExpr { FopensCreationExpr() { - exists(string name | - name = this.getTarget().getName() | - name = "fopen_s" or - name = "_wfopen_s") - and + exists(string name | name = this.getTarget().getName() | + name = "fopen_s" or + name = "_wfopen_s" + ) and exists(string mode | - (mode = "w" or mode = "a") - and - this.getArgument(2).getValue().matches(mode+"%") + (mode = "w" or mode = "a") and + this.getArgument(2).getValue().matches(mode + "%") ) } + override Expr getPath() { result = this.getArgument(1) } + override int getMode() { // fopen_s has restrictive permissions unless you have "u" in the mode if this.getArgument(2).getValue().charAt(_) = "u" diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql index af3b9744cf6..8538cc0c808 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql @@ -1,7 +1,7 @@ /** * @name Setting a DACL to NULL in a SECURITY_DESCRIPTOR * @description Setting a DACL to NULL in a SECURITY_DESCRIPTOR will result in an unprotected object. - * If the DACL that belongs to the security descriptor of an object is set to NULL, a null DACL is created. + * If the DACL that belongs to the security descriptor of an object is set to NULL, a null DACL is created. * A null DACL grants full access to any user who requests it; * normal security checking is not performed with respect to the object. * @id cpp/unsafe-dacl-security-descriptor @@ -12,6 +12,7 @@ * external/cwe/cwe-732 * external/microsoft/C6248 */ + import cpp import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow2 @@ -21,31 +22,24 @@ import semmle.code.cpp.dataflow.DataFlow2 */ class SetSecurityDescriptorDaclFunctionCall extends FunctionCall { SetSecurityDescriptorDaclFunctionCall() { - this.getTarget().hasGlobalName("SetSecurityDescriptorDacl") - and this.getArgument(1).getValue().toInt() != 0 + this.getTarget().hasGlobalName("SetSecurityDescriptorDacl") and + this.getArgument(1).getValue().toInt() != 0 } } - + /** * Dataflow that detects a call to SetSecurityDescriptorDacl with a NULL DACL as the pDacl argument */ class NullDaclConfig extends DataFlow::Configuration { - NullDaclConfig() { - this = "NullDaclConfig" - } + NullDaclConfig() { this = "NullDaclConfig" } override predicate isSource(DataFlow::Node source) { - exists( - NullValue nullExpr | - source.asExpr() = nullExpr - ) + exists(NullValue nullExpr | source.asExpr() = nullExpr) } - + override predicate isSink(DataFlow::Node sink) { - exists( - SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | - val = sink.asExpr() | - val = call.getArgument(2) + exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() | + val = call.getArgument(2) ) } } @@ -55,13 +49,12 @@ class NullDaclConfig extends DataFlow::Configuration { * argument that's _not_ likely to be NULL. */ class NonNullDaclConfig extends DataFlow2::Configuration { - NonNullDaclConfig() { - this = "NonNullDaclConfig" - } + NonNullDaclConfig() { this = "NonNullDaclConfig" } override predicate isSource(DataFlow::Node source) { - source.getType().getUnspecifiedType().(PointerType).getBaseType() = - any(Type t | t.getName() = "ACL").getUnspecifiedType() and + source.getType().getUnspecifiedType().(PointerType).getBaseType() = any(Type t | + t.getName() = "ACL" + ).getUnspecifiedType() and ( // If the value comes from a function whose body we can't see, assume // it's not null. @@ -74,33 +67,33 @@ class NonNullDaclConfig extends DataFlow2::Configuration { // flow library cannot currently follow flow from the body of a function to // an assignment by reference, so this rule applies whether we see the // body or not. - exists(Call call | - call.getAnArgument() = source.asDefiningArgument() - ) + exists(Call call | call.getAnArgument() = source.asDefiningArgument()) ) } override predicate isSink(DataFlow::Node sink) { - exists(SetSecurityDescriptorDaclFunctionCall call | - sink.asExpr() = call.getArgument(2) - ) + exists(SetSecurityDescriptorDaclFunctionCall call | sink.asExpr() = call.getArgument(2)) } } from SetSecurityDescriptorDaclFunctionCall call, string message -where exists - ( - NullValue nullExpr | - message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR will result in an unprotected object." | - call.getArgument(1).getValue().toInt() != 0 - and call.getArgument(2) = nullExpr - ) or exists - ( - Expr constassign, VariableAccess var, - NullDaclConfig nullDaclConfig, NonNullDaclConfig nonNullDaclConfig | - message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var + " that is set to NULL will result in an unprotected object." | - var = call.getArgument(2) - and nullDaclConfig.hasFlow(DataFlow::exprNode(constassign), DataFlow::exprNode(var)) - and not nonNullDaclConfig.hasFlow(_, DataFlow::exprNode(var)) +where + exists(NullValue nullExpr | + message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR will result in an unprotected object." + | + call.getArgument(1).getValue().toInt() != 0 and + call.getArgument(2) = nullExpr ) -select call, message \ No newline at end of file + or + exists( + Expr constassign, VariableAccess var, NullDaclConfig nullDaclConfig, + NonNullDaclConfig nonNullDaclConfig + | + message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var + + " that is set to NULL will result in an unprotected object." + | + var = call.getArgument(2) and + nullDaclConfig.hasFlow(DataFlow::exprNode(constassign), DataFlow::exprNode(var)) and + not nonNullDaclConfig.hasFlow(_, DataFlow::exprNode(var)) + ) +select call, message diff --git a/cpp/ql/src/Security/CWE/CWE-764/LockFlow.qll b/cpp/ql/src/Security/CWE/CWE-764/LockFlow.qll index a370b2a83f5..8d104b57fa2 100644 --- a/cpp/ql/src/Security/CWE/CWE-764/LockFlow.qll +++ b/cpp/ql/src/Security/CWE/CWE-764/LockFlow.qll @@ -2,6 +2,7 @@ * Provides classes and predicates for analyzing mutexes and the control * flow regions where they might be locked. */ + import cpp import semmle.code.cpp.commons.Synchronization @@ -12,31 +13,26 @@ import semmle.code.cpp.commons.Synchronization * like `if(lock(m) != 0)`. */ cached -predicate tryLockCondition(VariableAccess access, - ControlFlowNode cond, - ControlFlowNode failNode) { - exists (FunctionCall call - | lockCall(access, call) - | (cond = call and call.getAFalseSuccessor() = failNode) - +predicate tryLockCondition(VariableAccess access, ControlFlowNode cond, ControlFlowNode failNode) { + exists(FunctionCall call | lockCall(access, call) | + cond = call and call.getAFalseSuccessor() = failNode + or // Look for code like this: // // if (pthread_mutex_lock(mtx) != 0) return -1; // - or - (cond = call.getParent*() and - cond.isCondition() and - failNode = cond.getASuccessor() and - failNode instanceof BasicBlockWithReturn)) + cond = call.getParent*() and + cond.isCondition() and + failNode = cond.getASuccessor() and + failNode instanceof BasicBlockWithReturn + ) } /** * A basic block that ends with a return statement. */ class BasicBlockWithReturn extends BasicBlock { - BasicBlockWithReturn() { - this.contains(any(ReturnStmt r)) - } + BasicBlockWithReturn() { this.contains(any(ReturnStmt r)) } } /** @@ -44,21 +40,22 @@ class BasicBlockWithReturn extends BasicBlock { * function call `call`? */ private predicate lockedOrUnlockedInCall(Variable v, FunctionCall call) { - lockCall(v.getAnAccess(), call) or - unlockCall(v.getAnAccess(), call) or - + lockCall(v.getAnAccess(), call) + or + unlockCall(v.getAnAccess(), call) + or // Interprocedural analysis: look for mutexes which are locked or // unlocked in the body of the callee. - exists (Function fcn, Variable x - | fcn = call.getTarget() and + exists(Function fcn, Variable x | + fcn = call.getTarget() and lockedOrUnlockedInFunction(x, fcn) - | // If `x` is one of the function's parameters, then map it to the + | + // If `x` is one of the function's parameters, then map it to the // corresponding argument. if x = fcn.getAParameter() - then exists (int i | - x = fcn.getParameter(i) | - v.getAnAccess() = call.getArgument(i)) - else v = x) + then exists(int i | x = fcn.getParameter(i) | v.getAnAccess() = call.getArgument(i)) + else v = x + ) } /** @@ -67,9 +64,10 @@ private predicate lockedOrUnlockedInCall(Variable v, FunctionCall call) { * function). */ private predicate lockedOrUnlockedInFunction(Variable v, Function fcn) { - exists (FunctionCall call | - lockedOrUnlockedInCall(v, call) and - call.getEnclosingFunction() = fcn) + exists(FunctionCall call | + lockedOrUnlockedInCall(v, call) and + call.getEnclosingFunction() = fcn + ) } /** @@ -81,26 +79,26 @@ private predicate lockedOrUnlockedInFunction(Variable v, Function fcn) { predicate lockedOnExit(VariableAccess access, ControlFlowNode node) { lockCall(access, node) or - (lockedOnEntry(access, node) and - // Remove mutexes which are either unlocked by this statement or - // superseded by a another call to the lock method. - not lockedOrUnlockedInCall(access.getTarget(), node)) + lockedOnEntry(access, node) and + // Remove mutexes which are either unlocked by this statement or + // superseded by a another call to the lock method. + not lockedOrUnlockedInCall(access.getTarget(), node) or // Interprocedural analysis: if the node is a function call and a mutex // is still locked at the end of the function body, then it is also // locked after the function returns. Note that the Function object is // used to represent the exit node in the control flow graph. - exists (Function fcn, Variable x, VariableAccess xAccess | - fcn = node.(FunctionCall).getTarget() and - lockedOnEntry(xAccess, fcn) and - x = xAccess.getTarget() | - // If `x` is one of the function's parameters, then map it to the - // corresponding argument. - if x = fcn.getAParameter() - then exists (int i | - x = fcn.getParameter(i) | - access = node.(FunctionCall).getArgument(i)) - else access = xAccess) + exists(Function fcn, Variable x, VariableAccess xAccess | + fcn = node.(FunctionCall).getTarget() and + lockedOnEntry(xAccess, fcn) and + x = xAccess.getTarget() + | + // If `x` is one of the function's parameters, then map it to the + // corresponding argument. + if x = fcn.getAParameter() + then exists(int i | x = fcn.getParameter(i) | access = node.(FunctionCall).getArgument(i)) + else access = xAccess + ) } /** @@ -109,12 +107,13 @@ predicate lockedOnExit(VariableAccess access, ControlFlowNode node) { * after a predecessor of `node` has executed. */ predicate lockedOnEntry(VariableAccess access, ControlFlowNode node) { - exists (ControlFlowNode prev - | lockedOnExit(access, prev) and + exists(ControlFlowNode prev | + lockedOnExit(access, prev) and node = prev.getASuccessor() and // If we are on the false branch of a call to `try_lock` then the // mutex is not locked. - not tryLockCondition(access, prev, node)) + not tryLockCondition(access, prev, node) + ) } /** @@ -126,17 +125,17 @@ predicate lockedInCall(VariableAccess access, FunctionCall call) { or // Interprocedural analysis: look for mutexes which are locked in the // body of the callee. - exists (Function fcn, Variable x, VariableAccess xAccess - | fcn = call.getTarget() and + exists(Function fcn, Variable x, VariableAccess xAccess | + fcn = call.getTarget() and pathToLock(xAccess, fcn.getEntryPoint()) and x = xAccess.getTarget() - | // If `x` is one of the function's parameters, then map it to the + | + // If `x` is one of the function's parameters, then map it to the // corresponding argument. if x = fcn.getAParameter() - then exists (int i - | x = fcn.getParameter(i) - | access = call.getArgument(i)) - else access = xAccess) + then exists(int i | x = fcn.getParameter(i) | access = call.getArgument(i)) + else access = xAccess + ) } /** @@ -146,6 +145,6 @@ predicate lockedInCall(VariableAccess access, FunctionCall call) { predicate pathToLock(VariableAccess access, ControlFlowNode node) { lockedInCall(access, node) or - (pathToLock(access, node.getASuccessor()) and - not lockedOrUnlockedInCall(access.getTarget(), node)) + pathToLock(access, node.getASuccessor()) and + not lockedOrUnlockedInCall(access.getTarget(), node) } diff --git a/cpp/ql/src/Security/CWE/CWE-764/LockOrderCycle.ql b/cpp/ql/src/Security/CWE/CWE-764/LockOrderCycle.ql index 964eb1a7563..f53f84a4fb0 100644 --- a/cpp/ql/src/Security/CWE/CWE-764/LockOrderCycle.ql +++ b/cpp/ql/src/Security/CWE/CWE-764/LockOrderCycle.ql @@ -9,6 +9,7 @@ * external/cwe/cwe-764 * external/cwe/cwe-833 */ + import cpp import semmle.code.cpp.commons.Synchronization import LockFlow @@ -29,9 +30,10 @@ import LockFlow * source of deadlock. The dining philosophers are the classic example. */ Variable lockSuccessor(Variable v) { - exists (FunctionCall call - | lockedOnEntry(v.getAnAccess(), call) and - lockedInCall(result.getAnAccess(), call)) + exists(FunctionCall call | + lockedOnEntry(v.getAnAccess(), call) and + lockedInCall(result.getAnAccess(), call) + ) } from Variable v1, Variable v2 diff --git a/cpp/ql/src/Security/CWE/CWE-764/TwiceLocked.ql b/cpp/ql/src/Security/CWE/CWE-764/TwiceLocked.ql index aeff12bb0e3..0eb7e8451e5 100644 --- a/cpp/ql/src/Security/CWE/CWE-764/TwiceLocked.ql +++ b/cpp/ql/src/Security/CWE/CWE-764/TwiceLocked.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-764 * external/cwe/cwe-833 */ + import cpp import semmle.code.cpp.commons.Synchronization import LockFlow @@ -19,8 +20,8 @@ import LockFlow * be locked when we reach `call`. The access `a` might be in a function * which is called indirectly from `call`. */ -cached private predicate twiceLocked( - FunctionCall call, Variable v, VariableAccess a) { +cached +private predicate twiceLocked(FunctionCall call, Variable v, VariableAccess a) { lockedOnEntry(v.getAnAccess(), call) and lockedInCall(a, call) } @@ -34,7 +35,6 @@ from FunctionCall call, Variable v, VariableAccess access2 where twiceLocked(call, v, access2) and v = access2.getTarget() and - // If the second lock is a `try_lock` then it won't cause a deadlock. // We want to be extra sure that the second lock is not a `try_lock` // to make sure that we don't generate too many false positives, so @@ -46,7 +46,9 @@ where // 3. The call is a condition. Because the analysis is interprocedural, // `call` might be an indirect call to `lock`, so this heuristic // catches some cases which the second heuristic does not. - not (trylockCall(access2, _) or - tryLockCondition(access2, _, _) or - call.isCondition()) + not ( + trylockCall(access2, _) or + tryLockCondition(access2, _, _) or + call.isCondition() + ) select access2, "Mutex " + v + " might be locked already, which could cause a deadlock." diff --git a/cpp/ql/src/Security/CWE/CWE-764/UnreleasedLock.ql b/cpp/ql/src/Security/CWE/CWE-764/UnreleasedLock.ql index 27486e2f733..1c0ee4a500f 100644 --- a/cpp/ql/src/Security/CWE/CWE-764/UnreleasedLock.ql +++ b/cpp/ql/src/Security/CWE/CWE-764/UnreleasedLock.ql @@ -10,6 +10,7 @@ * external/cwe/cwe-764 * external/cwe/cwe-833 */ + import cpp import semmle.code.cpp.commons.Synchronization @@ -26,7 +27,7 @@ predicate unlockBlock(MutexType t, BasicBlock b, int unlocks) { * `lockblock`, and `failblock` is the successor if it fails. */ predicate failedLock(MutexType t, BasicBlock lockblock, BasicBlock failblock) { - exists (ControlFlowNode lock | + exists(ControlFlowNode lock | lock = lockblock.getEnd() and lock = t.getLockAccess() and lock.getAFalseSuccessor() = failblock @@ -39,11 +40,13 @@ predicate failedLock(MutexType t, BasicBlock lockblock, BasicBlock failblock) { * `-2`. */ predicate lockUnlockBlock(MutexType t, BasicBlock b, int netlocks) { - lockBlock(t, b, netlocks) and not unlockBlock(t, b, _) or - exists (int unlocks | + lockBlock(t, b, netlocks) and not unlockBlock(t, b, _) + or + exists(int unlocks | not lockBlock(t, b, _) and unlockBlock(t, b, unlocks) and netlocks = -unlocks - ) or - exists (int locks, int unlocks | + ) + or + exists(int locks, int unlocks | lockBlock(t, b, locks) and unlockBlock(t, b, unlocks) and netlocks = locks - unlocks ) } @@ -56,24 +59,26 @@ predicate lockUnlockBlock(MutexType t, BasicBlock b, int netlocks) { predicate blockIsLocked(MutexType t, BasicBlock src, BasicBlock b, int locks) { lockUnlockBlock(t, b, locks) and src = b and locks > 0 or - exists (BasicBlock pred, int predlocks, int curlocks, int failedlock | - pred = b.getAPredecessor() | + exists(BasicBlock pred, int predlocks, int curlocks, int failedlock | pred = b.getAPredecessor() | blockIsLocked(t, src, pred, predlocks) and - ( if failedLock(t, pred, b) then failedlock = 1 else failedlock = 0 ) and // count a failed lock as an unlock so the net is zero - ( not lockUnlockBlock(t, b, _) and curlocks = 0 or + (if failedLock(t, pred, b) then failedlock = 1 else failedlock = 0) and // count a failed lock as an unlock so the net is zero + ( + not lockUnlockBlock(t, b, _) and curlocks = 0 + or lockUnlockBlock(t, b, curlocks) ) and - locks = predlocks + curlocks -failedlock and locks > 0 and + locks = predlocks + curlocks - failedlock and + locks > 0 and locks < 10 // arbitrary bound to fail gracefully in case of locking in a loop ) } from Function c, MutexType t, BasicBlock src, BasicBlock exit, FunctionCall lock -where // restrict results to those methods that actually attempt to unlock - t.getUnlockAccess().getEnclosingFunction() = c - and blockIsLocked(t, src, exit, _) - and exit.getEnd() = c - and lock = src.getANode() - and lock = t.getLockAccess() -select - lock, "This lock might not be unlocked or might be locked more times than it is unlocked." +where + // restrict results to those methods that actually attempt to unlock + t.getUnlockAccess().getEnclosingFunction() = c and + blockIsLocked(t, src, exit, _) and + exit.getEnd() = c and + lock = src.getANode() and + lock = t.getLockAccess() +select lock, "This lock might not be unlocked or might be locked more times than it is unlocked." diff --git a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql index 68a9c7d5a53..b940da029ec 100644 --- a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql +++ b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql @@ -13,24 +13,21 @@ import semmle.code.cpp.security.TaintTracking - /** * Holds if there is an 'if' statement whose condition `condition` * is influenced by tainted data `source`, and the body contains * `raise` which escalates privilege. */ predicate cwe807violation(Expr source, Expr condition, Expr raise) { - tainted(source, condition) - and raisesPrivilege(raise) - and exists (IfStmt ifstmt | - ifstmt.getCondition() = condition - and raise.getEnclosingStmt().getParentStmt*() = ifstmt) + tainted(source, condition) and + raisesPrivilege(raise) and + exists(IfStmt ifstmt | + ifstmt.getCondition() = condition and + raise.getEnclosingStmt().getParentStmt*() = ifstmt + ) } from Expr source, Expr condition, Expr raise where cwe807violation(source, condition, raise) -select - condition, - "Reliance on untrusted input $@ to raise privilege at $@", - source, source.toString(), - raise, raise.toString() +select condition, "Reliance on untrusted input $@ to raise privilege at $@", source, + source.toString(), raise, raise.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-835/InfiniteLoopWithUnsatisfiableExitCondition.ql b/cpp/ql/src/Security/CWE/CWE-835/InfiniteLoopWithUnsatisfiableExitCondition.ql index df13779f8c1..e088b9a666d 100644 --- a/cpp/ql/src/Security/CWE/CWE-835/InfiniteLoopWithUnsatisfiableExitCondition.ql +++ b/cpp/ql/src/Security/CWE/CWE-835/InfiniteLoopWithUnsatisfiableExitCondition.ql @@ -9,6 +9,7 @@ * @tags security * external/cwe/cwe-835 */ + import cpp import semmle.code.cpp.controlflow.BasicBlocks private import semmle.code.cpp.rangeanalysis.PointlessComparison @@ -18,13 +19,10 @@ import semmle.code.cpp.controlflow.internal.ConstantExprs * Holds if there is a control flow edge from `src` to `dst`, but * it can never be taken due to `cmp` always having value `value`. */ -predicate impossibleEdge( - ComparisonOperation cmp, boolean value, BasicBlock src, BasicBlock dst) { +predicate impossibleEdge(ComparisonOperation cmp, boolean value, BasicBlock src, BasicBlock dst) { cmp = src.getEnd() and reachablePointlessComparison(cmp, _, _, value, _) and - if value = true - then dst = src.getAFalseSuccessor() - else dst = src.getATrueSuccessor() + if value = true then dst = src.getAFalseSuccessor() else dst = src.getATrueSuccessor() } BasicBlock enhancedSucc(BasicBlock bb) { @@ -45,20 +43,18 @@ BasicBlock enhancedSucc(BasicBlock bb) { * Since this loop is obviously infinite, we assume that it was written * intentionally. */ -predicate impossibleEdgeCausesNonTermination( - ComparisonOperation cmp, boolean value) { - exists (BasicBlock src - | impossibleEdge(cmp, value, src, _) and +predicate impossibleEdgeCausesNonTermination(ComparisonOperation cmp, boolean value) { + exists(BasicBlock src | + impossibleEdge(cmp, value, src, _) and src.getASuccessor+() instanceof ExitBasicBlock and - not (enhancedSucc+(src) instanceof ExitBasicBlock) and + not enhancedSucc+(src) instanceof ExitBasicBlock and // Make sure that the source is reachable to reduce // false positives. - exists (EntryBasicBlock entry | src = enhancedSucc+(entry))) + exists(EntryBasicBlock entry | src = enhancedSucc+(entry)) + ) } from ComparisonOperation cmp, boolean value where impossibleEdgeCausesNonTermination(cmp, value) -select - cmp, - "Function exit is unreachable because this condition is always " + - value.toString() + "." +select cmp, + "Function exit is unreachable because this condition is always " + value.toString() + "." diff --git a/cpp/ql/src/cpp.qll b/cpp/ql/src/cpp.qll index 1af894bacfd..78fde101a42 100644 --- a/cpp/ql/src/cpp.qll +++ b/cpp/ql/src/cpp.qll @@ -16,7 +16,6 @@ import semmle.code.cpp.File import semmle.code.cpp.Linkage import semmle.code.cpp.Location - import semmle.code.cpp.Compilation import semmle.code.cpp.Element import semmle.code.cpp.Namespace @@ -36,9 +35,7 @@ import semmle.code.cpp.Function import semmle.code.cpp.Parameter import semmle.code.cpp.Variable import semmle.code.cpp.Initializer - import semmle.code.cpp.FriendDecl - import semmle.code.cpp.exprs.Expr import semmle.code.cpp.exprs.ArithmeticOperation import semmle.code.cpp.exprs.BitwiseOperation @@ -51,15 +48,12 @@ import semmle.code.cpp.exprs.Call import semmle.code.cpp.exprs.Lambda import semmle.code.cpp.exprs.Literal import semmle.code.cpp.exprs.BuiltInOperations - import semmle.code.cpp.stmts.Stmt import semmle.code.cpp.stmts.Block - import semmle.code.cpp.metrics.MetricNamespace import semmle.code.cpp.metrics.MetricClass import semmle.code.cpp.metrics.MetricFile import semmle.code.cpp.metrics.MetricFunction - import semmle.code.cpp.commons.CommonType import semmle.code.cpp.commons.Printf import semmle.code.cpp.commons.VoidContext @@ -67,22 +61,13 @@ import semmle.code.cpp.commons.NULL import semmle.code.cpp.commons.PolymorphicClass import semmle.code.cpp.commons.Alloc import semmle.code.cpp.commons.StructLikeClass - import semmle.code.cpp.controlflow.ControlFlowGraph - import semmle.code.cpp.XML - import semmle.code.cpp.Diagnostics - import semmle.code.cpp.Comments import semmle.code.cpp.Preprocessor - import semmle.code.cpp.Iteration - import semmle.code.cpp.NameQualifiers - import semmle.code.cpp.ObjectiveC import semmle.code.cpp.exprs.ObjectiveC - import DefaultOptions - diff --git a/cpp/ql/src/definitions.qll b/cpp/ql/src/definitions.qll index d4840350dd8..4af638e07b9 100644 --- a/cpp/ql/src/definitions.qll +++ b/cpp/ql/src/definitions.qll @@ -26,10 +26,9 @@ class Top extends Element { * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). */ pragma[noopt] - final - predicate hasLocationInfo(string filepath, - int startline, int startcolumn, - int endline, int endcolumn) { + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { interestingElement(this) and not this instanceof MacroAccess and not this instanceof Include and @@ -85,7 +84,7 @@ predicate interestingElement(Element e) { /** * Holds if `f`, `line`, `column` indicate the start character - * of `cc`. + * of `cc`. */ private predicate constructorCallStartLoc(ConstructorCall cc, File f, int line, int column) { exists(Location l | @@ -115,7 +114,8 @@ private predicate typeMentionStartLoc(TypeMention tm, Type t, File f, int line, /** * Holds if `cc` and `tm` begin at the same character. */ -private cached predicate constructorCallTypeMention(ConstructorCall cc, TypeMention tm) { +cached +private predicate constructorCallTypeMention(ConstructorCall cc, TypeMention tm) { exists(File f, int line, int column | constructorCallStartLoc(cc, f, line, column) and typeMentionStartLoc(tm, _, f, line, column) @@ -134,72 +134,68 @@ private cached predicate constructorCallTypeMention(ConstructorCall cc, TypeMent */ Top definitionOf(Top e, string kind) { ( - ( - // call -> function called - kind = "M" and - result = e.(Call).getTarget() and - not e.(Expr).isCompilerGenerated() and - not e instanceof ConstructorCall // handled elsewhere - ) or ( - // access -> function, variable or enum constant accessed - kind = "V" and - result = e.(Access).getTarget() and - not e.(Expr).isCompilerGenerated() - ) or ( - // macro access -> macro accessed - kind = "X" and - result = e.(MacroAccess).getMacro() - ) or ( - // type mention -> type - kind = "T" and - e.(TypeMention).getMentionedType() = result and - not constructorCallTypeMention(_, e) and // handled elsewhere - // Multiple type mentions can be generated when a typedef is used, and - // in such cases we want to exclude all but the originating typedef. - not exists(Type secondary | - exists(TypeMention tm, File f, int startline, int startcol | - typeMentionStartLoc(e, result, f, startline, startcol) and - typeMentionStartLoc(tm, secondary, f, startline, startcol) and - ( - result = secondary.(TypedefType).getBaseType() or - result = secondary.(TypedefType).getBaseType().(SpecifiedType).getBaseType() - ) + // call -> function called + kind = "M" and + result = e.(Call).getTarget() and + not e.(Expr).isCompilerGenerated() and + not e instanceof ConstructorCall // handled elsewhere + or + // access -> function, variable or enum constant accessed + kind = "V" and + result = e.(Access).getTarget() and + not e.(Expr).isCompilerGenerated() + or + // macro access -> macro accessed + kind = "X" and + result = e.(MacroAccess).getMacro() + or + // type mention -> type + kind = "T" and + e.(TypeMention).getMentionedType() = result and + not constructorCallTypeMention(_, e) and // handled elsewhere + // Multiple type mentions can be generated when a typedef is used, and + // in such cases we want to exclude all but the originating typedef. + not exists(Type secondary | + exists(TypeMention tm, File f, int startline, int startcol | + typeMentionStartLoc(e, result, f, startline, startcol) and + typeMentionStartLoc(tm, secondary, f, startline, startcol) and + ( + result = secondary.(TypedefType).getBaseType() or + result = secondary.(TypedefType).getBaseType().(SpecifiedType).getBaseType() ) ) - ) or ( - // constructor call -> function called - // - but only if there is a corresponding type mention, since - // we don't want links for implicit conversions. - // - using the location of the type mention, since it's - // tighter that the location of the function call. - kind = "M" and - exists(ConstructorCall cc | - constructorCallTypeMention(cc, e) and - result = cc.getTarget() - ) - ) or ( - // include -> included file - kind = "I" and - result = e.(Include).getIncludedFile() and - - // exclude `#include` directives containing macros - not exists(MacroInvocation mi, Location l1, Location l2 | - l1 = e.(Include).getLocation() and - l2 = mi.getLocation() and - l1.getContainer() = l2.getContainer() and - l1.getStartLine() = l2.getStartLine() - // (an #include directive must be always on it's own line) - ) ) - ) and ( + or + // constructor call -> function called + // - but only if there is a corresponding type mention, since + // we don't want links for implicit conversions. + // - using the location of the type mention, since it's + // tighter that the location of the function call. + kind = "M" and + exists(ConstructorCall cc | + constructorCallTypeMention(cc, e) and + result = cc.getTarget() + ) + or + // include -> included file + kind = "I" and + result = e.(Include).getIncludedFile() and + // exclude `#include` directives containing macros + not exists(MacroInvocation mi, Location l1, Location l2 | + l1 = e.(Include).getLocation() and + l2 = mi.getLocation() and + l1.getContainer() = l2.getContainer() and + l1.getStartLine() = l2.getStartLine() + // (an #include directive must be always on it's own line) + ) + ) and + ( // exclude things inside macro invocations, as they will overlap // with the macro invocation. not e.(Element).isInMacroExpansion() and - // exclude nested macro invocations, as they will overlap with // the top macro invocation. not exists(e.(MacroAccess).getParentInvocation()) and - // exclude results from template instantiations, as: // (1) these dependencies will often be caused by a choice of // template parameter, which is non-local to this part of code; and @@ -208,13 +204,12 @@ Top definitionOf(Top e, string kind) { // It's possible we could allow a subset of these dependencies // in future, if we're careful to ensure the above don't apply. not e.isFromTemplateInstantiation(_) - ) and ( - // Some entities have many locations. This can arise for an external - // function that is frequently declared but not defined, or perhaps - // for a struct type that is declared in many places. Rather than - // letting the result set explode, we just exclude results that are - // "too ambiguous" -- we could also arbitrarily pick one location - // later on. - strictcount(result.getLocation()) < 10 - ) + ) and + // Some entities have many locations. This can arise for an external + // function that is frequently declared but not defined, or perhaps + // for a struct type that is declared in many places. Rather than + // letting the result set explode, we just exclude results that are + // "too ambiguous" -- we could also arbitrarily pick one location + // later on. + strictcount(result.getLocation()) < 10 } diff --git a/cpp/ql/src/external/CodeDuplication.qll b/cpp/ql/src/external/CodeDuplication.qll index 7d5e0148bb7..c11bcb96b49 100644 --- a/cpp/ql/src/external/CodeDuplication.qll +++ b/cpp/ql/src/external/CodeDuplication.qll @@ -1,22 +1,15 @@ import cpp -private -string relativePath(File file) { - result = file.getRelativePath().replaceAll("\\", "/") -} +private string relativePath(File file) { result = file.getRelativePath().replaceAll("\\", "/") } -private cached -predicate tokenLocation(string path, int sl, int sc, int ec, int el, Copy copy, int index) { +cached +private predicate tokenLocation(string path, int sl, int sc, int ec, int el, Copy copy, int index) { path = copy.sourceFile().getAbsolutePath() and tokens(copy, index, sl, sc, ec, el) } -class Copy extends @duplication_or_similarity -{ - private - int lastToken() { - result = max(int i | tokens(this, i, _, _, _, _) | i) - } +class Copy extends @duplication_or_similarity { + private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) } int tokenStartingAt(Location loc) { exists(string filepath, int startline, int startcol | @@ -32,102 +25,91 @@ class Copy extends @duplication_or_similarity ) } - int sourceStartLine() { - tokens(this, 0, result, _, _, _) - } + int sourceStartLine() { tokens(this, 0, result, _, _, _) } - int sourceStartColumn() { - tokens(this, 0, _, result, _, _) - } + int sourceStartColumn() { tokens(this, 0, _, result, _, _) } - int sourceEndLine() { - tokens(this, lastToken(), _, _, result, _) - } + int sourceEndLine() { tokens(this, lastToken(), _, _, result, _) } - int sourceEndColumn() { - tokens(this, lastToken(), _, _, _, result) - } + int sourceEndColumn() { tokens(this, lastToken(), _, _, _, result) } - int sourceLines() { - result = this.sourceEndLine() + 1 - this.sourceStartLine() - } + int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() } - int getEquivalenceClass() { - duplicateCode(this, _, result) or similarCode(this, _, result) - } + int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) } File sourceFile() { - exists(string name | - duplicateCode(this, name, _) or similarCode(this, name, _) | - name.replaceAll("\\", "/") = relativePath(result)) + exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) | + name.replaceAll("\\", "/") = relativePath(result) + ) } - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { - sourceFile().getAbsolutePath() = filepath and - startline = sourceStartLine() and - startcolumn = sourceStartColumn() and - endline = sourceEndLine() and - endcolumn = sourceEndColumn() + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + sourceFile().getAbsolutePath() = filepath and + startline = sourceStartLine() and + startcolumn = sourceStartColumn() and + endline = sourceEndLine() and + endcolumn = sourceEndColumn() } string toString() { none() } } -class DuplicateBlock extends Copy, @duplication -{ - override string toString() { - result = "Duplicate code: " + sourceLines() + " duplicated lines." - } +class DuplicateBlock extends Copy, @duplication { + override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." } } -class SimilarBlock extends Copy, @similarity -{ +class SimilarBlock extends Copy, @similarity { override string toString() { result = "Similar code: " + sourceLines() + " almost duplicated lines." } } - - FunctionDeclarationEntry sourceMethod() { result.isDefinition() and - exists(result.getLocation()) and numlines(unresolveElement(result.getFunction()),_,_,_) + exists(result.getLocation()) and + numlines(unresolveElement(result.getFunction()), _, _, _) } int numberOfSourceMethods(Class c) { result = count(FunctionDeclarationEntry m | - m = sourceMethod() and - m.getFunction().getDeclaringType() = c) + m = sourceMethod() and + m.getFunction().getDeclaringType() = c + ) } -private -predicate blockCoversStatement(int equivClass, int first, int last, Stmt stmt) { +private predicate blockCoversStatement(int equivClass, int first, int last, Stmt stmt) { exists(DuplicateBlock b, Location loc | stmt.getLocation() = loc and first = b.tokenStartingAt(loc) and last = b.tokenEndingAt(loc) and - b.getEquivalenceClass() = equivClass) + b.getEquivalenceClass() = equivClass + ) } -private -Stmt statementInMethod(FunctionDeclarationEntry m) { +private Stmt statementInMethod(FunctionDeclarationEntry m) { result.getParent+() = m.getBlock() and not result.getLocation() instanceof UnknownStmtLocation and not result instanceof Block } -private -predicate duplicateStatement(FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, Stmt s1, Stmt s2) { +private predicate duplicateStatement( + FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, Stmt s1, Stmt s2 +) { exists(int equivClass, int first, int last | s1 = statementInMethod(m1) and s2 = statementInMethod(m2) and blockCoversStatement(equivClass, first, last, s1) and blockCoversStatement(equivClass, first, last, s2) and - s1 != s2 and m1 != m2 + s1 != s2 and + m1 != m2 ) } -predicate duplicateStatements(FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, int duplicate, int total) { +predicate duplicateStatements( + FunctionDeclarationEntry m1, FunctionDeclarationEntry m2, int duplicate, int total +) { duplicate = strictcount(Stmt s | duplicateStatement(m1, m2, s, _)) and total = strictcount(statementInMethod(m1)) } @@ -140,42 +122,43 @@ predicate duplicateMethod(FunctionDeclarationEntry m, FunctionDeclarationEntry o } predicate similarLines(File f, int line) { - exists(SimilarBlock b | - b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()] - ) + exists(SimilarBlock b | b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()]) } -private -predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) -{ - lines = strictsum(SimilarBlock b, int toSum | (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and (toSum = b.sourceLines()) | toSum) +private predicate similarLinesPerEquivalenceClass(int equivClass, int lines, File f) { + lines = strictsum(SimilarBlock b, int toSum | + (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and + toSum = b.sourceLines() + | + toSum + ) } private predicate similarLinesCoveredFiles(File f, File otherFile) { exists(int numLines | numLines = f.getMetrics().getNumberOfLines() | - exists(int coveredApprox | - coveredApprox = strictsum(int num | - exists(int equivClass | - similarLinesPerEquivalenceClass(equivClass, num, f) and - similarLinesPerEquivalenceClass(equivClass, num, otherFile) and - f != otherFile - ) - ) and - ((coveredApprox * 100) / numLines > 75) - ) + exists(int coveredApprox | + coveredApprox = strictsum(int num | + exists(int equivClass | + similarLinesPerEquivalenceClass(equivClass, num, f) and + similarLinesPerEquivalenceClass(equivClass, num, otherFile) and + f != otherFile + ) + ) and + (coveredApprox * 100) / numLines > 75 + ) ) } predicate similarLinesCovered(File f, int coveredLines, File otherFile) { exists(int numLines | numLines = f.getMetrics().getNumberOfLines() | - similarLinesCoveredFiles(f, otherFile) and - exists(int notCovered | - notCovered = count(int j | - j in [1 .. numLines] and - not similarLines(f, j) - ) and - coveredLines = numLines - notCovered - ) + similarLinesCoveredFiles(f, otherFile) and + exists(int notCovered | + notCovered = count(int j | + j in [1 .. numLines] and + not similarLines(f, j) + ) and + coveredLines = numLines - notCovered + ) ) } @@ -185,31 +168,34 @@ predicate duplicateLines(File f, int line) { ) } -private -predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) -{ - lines = strictsum(DuplicateBlock b, int toSum | (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and (toSum = b.sourceLines()) | toSum) +private predicate duplicateLinesPerEquivalenceClass(int equivClass, int lines, File f) { + lines = strictsum(DuplicateBlock b, int toSum | + (b.sourceFile() = f and b.getEquivalenceClass() = equivClass) and + toSum = b.sourceLines() + | + toSum + ) } predicate duplicateLinesCovered(File f, int coveredLines, File otherFile) { exists(int numLines | numLines = f.getMetrics().getNumberOfLines() | - exists(int coveredApprox | - coveredApprox = strictsum(int num | - exists(int equivClass | - duplicateLinesPerEquivalenceClass(equivClass, num, f) and - duplicateLinesPerEquivalenceClass(equivClass, num, otherFile) and - f != otherFile - ) + exists(int coveredApprox | + coveredApprox = strictsum(int num | + exists(int equivClass | + duplicateLinesPerEquivalenceClass(equivClass, num, f) and + duplicateLinesPerEquivalenceClass(equivClass, num, otherFile) and + f != otherFile + ) + ) and + (coveredApprox * 100) / numLines > 75 ) and - ((coveredApprox * 100) / numLines > 75) - ) and - exists(int notCovered | - notCovered = count(int j | - j in [1 .. numLines] and - not duplicateLines(f, j) - ) and - coveredLines = numLines - notCovered - ) + exists(int notCovered | + notCovered = count(int j | + j in [1 .. numLines] and + not duplicateLines(f, j) + ) and + coveredLines = numLines - notCovered + ) ) } @@ -234,46 +220,48 @@ predicate duplicateFiles(File f, File other, int percent) { predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int total) { numDup = strictcount(FunctionDeclarationEntry m1 | - exists(FunctionDeclarationEntry m2 | - duplicateMethod(m1, m2) and - m1 = sourceMethod() and - exists(Function f | f = m1.getFunction() and f.getDeclaringType() = c) and - exists(Function f | f = m2.getFunction() and f.getDeclaringType() = other) and - c != other - ) - ) and + exists(FunctionDeclarationEntry m2 | + duplicateMethod(m1, m2) and + m1 = sourceMethod() and + exists(Function f | f = m1.getFunction() and f.getDeclaringType() = c) and + exists(Function f | f = m2.getFunction() and f.getDeclaringType() = other) and + c != other + ) + ) and total = numberOfSourceMethods(c) and - ((numDup * 100) / total > 80) + (numDup * 100) / total > 80 } predicate mostlyDuplicateClass(Class c, Class other, string message) { exists(int numDup, int total | - mostlyDuplicateClassBase(c,other,numDup,total) and + mostlyDuplicateClassBase(c, other, numDup, total) and ( - (total != numDup - and exists(string s1, string s2, string s3, string name | s1 = " out of " and s2 = " methods in " and s3 = " are duplicated in $@." and name = c.getName() | - message = numDup + s1 + total + s2 + name + s3 - ) - ) - or - (total = numDup - and exists(string s1, string s2, string name | s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName() | - message = s1 + name + s2 + total != numDup and + exists(string s1, string s2, string s3, string name | + s1 = " out of " and + s2 = " methods in " and + s3 = " are duplicated in $@." and + name = c.getName() + | + message = numDup + s1 + total + s2 + name + s3 ) + or + total = numDup and + exists(string s1, string s2, string name | + s1 = "All methods in " and s2 = " are identical in $@." and name = c.getName() + | + message = s1 + name + s2 ) ) - ) + ) } predicate fileLevelDuplication(File f, File other) { similarFiles(f, other, _) or duplicateFiles(f, other, _) } -predicate classLevelDuplication(Class c, Class other) { - mostlyDuplicateClass(c, other, _) -} +predicate classLevelDuplication(Class c, Class other) { mostlyDuplicateClass(c, other, _) } predicate whitelistedLineForDuplication(File f, int line) { - exists(Include i | i.getFile() = f and i.getLocation().getStartLine() = line) + exists(Include i | i.getFile() = f and i.getLocation().getStartLine() = line) } - diff --git a/cpp/ql/src/external/DefectFilter.qll b/cpp/ql/src/external/DefectFilter.qll index 54182636a0c..4c40995f67d 100644 --- a/cpp/ql/src/external/DefectFilter.qll +++ b/cpp/ql/src/external/DefectFilter.qll @@ -1,27 +1,33 @@ import cpp -external predicate defectResults(int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, string message); +external predicate defectResults( + int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, + string message +); class DefectResult extends int { - DefectResult() { defectResults(this, _, _, _, _, _, _, _) } string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) } - - File getFile() { exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path) } - - int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } - - int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) } - - int getEndLine() { defectResults(this, _, _, _, _, result, _, _) } - - int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) } - - string getMessage() { defectResults(this, _, _, _, _, _, _, result) } - - string getURL() { - result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() + + File getFile() { + exists(string path | + defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path + ) } + int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } + + int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) } + + int getEndLine() { defectResults(this, _, _, _, _, result, _, _) } + + int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) } + + string getMessage() { defectResults(this, _, _, _, _, _, _, result) } + + string getURL() { + result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + + ":" + getEndLine() + ":" + getEndColumn() + } } diff --git a/cpp/ql/src/external/DuplicateBlock.ql b/cpp/ql/src/external/DuplicateBlock.ql index 38f0803f1cb..90070ed6a7d 100644 --- a/cpp/ql/src/external/DuplicateBlock.ql +++ b/cpp/ql/src/external/DuplicateBlock.ql @@ -10,15 +10,17 @@ * duplicate-code * non-attributable */ + import CodeDuplication from DuplicateBlock d, DuplicateBlock other, int lines, File otherFile, int otherLine -where lines = d.sourceLines() and - lines > 10 and - other.getEquivalenceClass() = d.getEquivalenceClass() and - other != d and - otherFile = other.sourceFile() and - otherLine = other.sourceStartLine() -select - d, - "Duplicate code: " + lines + " lines are duplicated at " + otherFile.getBaseName() + ":" + otherLine +where + lines = d.sourceLines() and + lines > 10 and + other.getEquivalenceClass() = d.getEquivalenceClass() and + other != d and + otherFile = other.sourceFile() and + otherLine = other.sourceStartLine() +select d, + "Duplicate code: " + lines + " lines are duplicated at " + otherFile.getBaseName() + ":" + + otherLine diff --git a/cpp/ql/src/external/DuplicateFunction.ql b/cpp/ql/src/external/DuplicateFunction.ql index ceaac8d3cf6..ca749315bbf 100644 --- a/cpp/ql/src/external/DuplicateFunction.ql +++ b/cpp/ql/src/external/DuplicateFunction.ql @@ -10,6 +10,7 @@ * duplicate-code * non-attributable */ + import cpp import CodeDuplication @@ -25,12 +26,13 @@ predicate relevant(FunctionDeclarationEntry m) { } from FunctionDeclarationEntry m, FunctionDeclarationEntry other -where duplicateMethod(m, other) - and relevant(m) - and not m.getFunction().isConstructedFrom(_) - and not other.getFunction().isConstructedFrom(_) - and not fileLevelDuplication(m.getFile(), other.getFile()) - and not classLevelDuplication(m.getFunction().getDeclaringType(), other.getFunction().getDeclaringType()) -select m, "Function " + m.getName() + " is duplicated at $@.", - other, - other.getFile().getBaseName() + ":" + other.getLocation().getStartLine().toString() +where + duplicateMethod(m, other) and + relevant(m) and + not m.getFunction().isConstructedFrom(_) and + not other.getFunction().isConstructedFrom(_) and + not fileLevelDuplication(m.getFile(), other.getFile()) and + not classLevelDuplication(m.getFunction().getDeclaringType(), + other.getFunction().getDeclaringType()) +select m, "Function " + m.getName() + " is duplicated at $@.", other, + other.getFile().getBaseName() + ":" + other.getLocation().getStartLine().toString() diff --git a/cpp/ql/src/external/ExternalArtifact.qll b/cpp/ql/src/external/ExternalArtifact.qll index be673094898..94fa0d7e31a 100644 --- a/cpp/ql/src/external/ExternalArtifact.qll +++ b/cpp/ql/src/external/ExternalArtifact.qll @@ -1,7 +1,6 @@ import cpp class ExternalData extends @externalDataElement { - string getDataPath() { externalData(this, result, _, _) } string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } @@ -16,29 +15,25 @@ class ExternalData extends @externalDataElement { date getFieldAsDate(int index) { result = getField(index).toDate() } - string toString() { - result = getQueryPath() + ": " + buildTupleString(0) - } - - private string buildTupleString(int start) { - (start = getNumFields() - 1 and result = getField(start)) - or - (start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start+1)) - } + string toString() { result = getQueryPath() + ": " + buildTupleString(0) } + private string buildTupleString(int start) { + start = getNumFields() - 1 and result = getField(start) + or + start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1) + } } /** * External data with a location, and a message, as produced by tools that used to produce QLDs. */ class DefectExternalData extends ExternalData { - DefectExternalData() { + DefectExternalData() { this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and this.getNumFields() = 2 } - + string getURL() { result = getField(0) } string getMessage() { result = getField(1) } } - diff --git a/cpp/ql/src/external/MetricFilter.qll b/cpp/ql/src/external/MetricFilter.qll index 68cd2eba962..df13e3722ef 100644 --- a/cpp/ql/src/external/MetricFilter.qll +++ b/cpp/ql/src/external/MetricFilter.qll @@ -1,37 +1,43 @@ import cpp -external predicate metricResults(int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, float value); +external predicate metricResults( + int id, string queryPath, string file, int startline, int startcol, int endline, int endcol, + float value +); class MetricResult extends int { - MetricResult() { metricResults(this, _, _, _, _, _, _, _) } string getQueryPath() { metricResults(this, result, _, _, _, _, _, _) } - - File getFile() { exists(string path | metricResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path) } - + + File getFile() { + exists(string path | + metricResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path + ) + } + int getStartLine() { metricResults(this, _, _, result, _, _, _, _) } - + int getStartColumn() { metricResults(this, _, _, _, result, _, _, _) } - + int getEndLine() { metricResults(this, _, _, _, _, result, _, _) } int getEndColumn() { metricResults(this, _, _, _, _, _, result, _) } - + predicate hasMatchingLocation() { exists(this.getMatchingLocation()) } - - Location getMatchingLocation() { + + Location getMatchingLocation() { result.getFile() = this.getFile() and result.getStartLine() = this.getStartLine() and result.getEndLine() = this.getEndLine() and result.getStartColumn() = this.getStartColumn() and result.getEndColumn() = this.getEndColumn() } - - float getValue() { metricResults(this, _, _, _, _, _, _, result) } - - string getURL() { - result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() - } + float getValue() { metricResults(this, _, _, _, _, _, _, result) } + + string getURL() { + result = "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + + ":" + getEndLine() + ":" + getEndColumn() + } } diff --git a/cpp/ql/src/external/MostlyDuplicateClass.ql b/cpp/ql/src/external/MostlyDuplicateClass.ql index a1420f3e605..a7d6cc605a6 100644 --- a/cpp/ql/src/external/MostlyDuplicateClass.ql +++ b/cpp/ql/src/external/MostlyDuplicateClass.ql @@ -10,12 +10,14 @@ * duplicate-code * non-attributable */ + import cpp import CodeDuplication from Class c, Class other, string message -where mostlyDuplicateClass(c, other, message) - and not c.isConstructedFrom(_) - and not other.isConstructedFrom(_) - and not fileLevelDuplication(c.getFile(), _) +where + mostlyDuplicateClass(c, other, message) and + not c.isConstructedFrom(_) and + not other.isConstructedFrom(_) and + not fileLevelDuplication(c.getFile(), _) select c, message, other, other.getQualifiedName() diff --git a/cpp/ql/src/external/MostlyDuplicateFile.ql b/cpp/ql/src/external/MostlyDuplicateFile.ql index 55016a88e91..13ad0707ce8 100644 --- a/cpp/ql/src/external/MostlyDuplicateFile.ql +++ b/cpp/ql/src/external/MostlyDuplicateFile.ql @@ -10,9 +10,11 @@ * duplicate-code * non-attributable */ + import cpp import CodeDuplication from File f, File other, int percent where duplicateFiles(f, other, percent) -select f, percent + "% of the lines in " + f.getBaseName() + " are copies of lines in $@.", other, other.getBaseName() +select f, percent + "% of the lines in " + f.getBaseName() + " are copies of lines in $@.", other, + other.getBaseName() diff --git a/cpp/ql/src/external/MostlyDuplicateFunction.ql b/cpp/ql/src/external/MostlyDuplicateFunction.ql index f991b0692ed..1ec592a6568 100644 --- a/cpp/ql/src/external/MostlyDuplicateFunction.ql +++ b/cpp/ql/src/external/MostlyDuplicateFunction.ql @@ -9,6 +9,7 @@ * duplicate-code * non-attributable */ + import cpp import CodeDuplication @@ -22,6 +23,8 @@ where not m.getFunction().isConstructedFrom(_) and not other.getFunction().isConstructedFrom(_) and not duplicateMethod(m, other) and - not classLevelDuplication(m.getFunction().getDeclaringType(), other.getFunction().getDeclaringType()) and + not classLevelDuplication(m.getFunction().getDeclaringType(), + other.getFunction().getDeclaringType()) and not fileLevelDuplication(m.getFile(), other.getFile()) -select m, percent + "% of the statements in " + m.getName() + " are duplicated in $@.", other, other.getFunction().getQualifiedName() +select m, percent + "% of the statements in " + m.getName() + " are duplicated in $@.", other, + other.getFunction().getQualifiedName() diff --git a/cpp/ql/src/external/MostlySimilarFile.ql b/cpp/ql/src/external/MostlySimilarFile.ql index 64338c71d5d..27830a5c951 100644 --- a/cpp/ql/src/external/MostlySimilarFile.ql +++ b/cpp/ql/src/external/MostlySimilarFile.ql @@ -10,9 +10,11 @@ * duplicate-code * non-attributable */ + import cpp import CodeDuplication from File f, File other, int percent where similarFiles(f, other, percent) -select f, percent + "% of the lines in " + f.getBaseName() + " are similar to lines in $@.", other, other.getBaseName() +select f, percent + "% of the lines in " + f.getBaseName() + " are similar to lines in $@.", other, + other.getBaseName() diff --git a/cpp/ql/src/external/VCS.qll b/cpp/ql/src/external/VCS.qll index 51594b598fb..ce36ace56d9 100644 --- a/cpp/ql/src/external/VCS.qll +++ b/cpp/ql/src/external/VCS.qll @@ -1,7 +1,6 @@ import cpp class Commit extends @svnentry { - Commit() { svnaffectedfiles(this, _, _) and exists(date svnDate, date snapshotDate | @@ -34,9 +33,9 @@ class Commit extends @svnentry { File getAnAffectedFile(string action) { // Workaround for incorrect keys in SVN data exists(File svnFile | svnFile.getAbsolutePath() = result.getAbsolutePath() | - svnaffectedfiles(this,unresolveElement(svnFile),action) - ) - and exists(result.getMetrics().getNumberOfLinesOfCode()) + svnaffectedfiles(this, unresolveElement(svnFile), action) + ) and + exists(result.getMetrics().getNumberOfLinesOfCode()) } File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) } @@ -44,40 +43,32 @@ class Commit extends @svnentry { private predicate churnForFile(File f, int added, int deleted) { // Workaround for incorrect keys in SVN data exists(File svnFile | svnFile.getAbsolutePath() = f.getAbsolutePath() | - svnchurn(this,unresolveElement(svnFile),added,deleted) - ) - and exists(f.getMetrics().getNumberOfLinesOfCode()) + svnchurn(this, unresolveElement(svnFile), added, deleted) + ) and + exists(f.getMetrics().getNumberOfLinesOfCode()) } int getRecentChurnForFile(File f) { - exists (int added, int deleted | churnForFile(f, added, deleted) and result = added + deleted) + exists(int added, int deleted | churnForFile(f, added, deleted) and result = added + deleted) } - int getRecentAdditionsForFile(File f) { - churnForFile(f, result, _) - } + int getRecentAdditionsForFile(File f) { churnForFile(f, result, _) } - int getRecentDeletionsForFile(File f) { - churnForFile(f, _, result) - } + int getRecentDeletionsForFile(File f) { churnForFile(f, _, result) } predicate isRecent() { recentCommit(this) } int daysToNow() { - exists(date now | snapshotDate(now) | - result = getDate().daysTo(now) and result >= 0 - ) + exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0) } - } class Author extends string { - Author() { exists(Commit e | this = e.getAuthor()) } + Author() { exists(Commit e | this = e.getAuthor()) } - Commit getACommit() { result.getAuthor() = this } - - File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } + Commit getACommit() { result.getAuthor() = this } + File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } } predicate recentCommit(Commit e) { @@ -85,20 +76,17 @@ predicate recentCommit(Commit e) { snapshotDate(snapshotDate) and e.getDate() = commitDate and days = commitDate.daysTo(snapshotDate) and - days >= 0 and days <= 60 + days >= 0 and + days <= 60 ) } date firstChange(File f) { - result = min(Commit e, date toMin | (f = e.getAnAffectedFile()) and (toMin = e.getDate()) | toMin) + result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin) } predicate firstCommit(Commit e) { - not exists(File f | f = e.getAnAffectedFile() | - firstChange(f) < e.getDate() - ) + not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate()) } -predicate artificialChange(Commit e) { - firstCommit(e) or e.getChangeSize() >= 50000 -} +predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 } diff --git a/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql b/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql index 1a2849f5178..05faf374a8d 100644 --- a/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql +++ b/cpp/ql/src/external/examples/filters/BumpMetricBy10.ql @@ -5,9 +5,9 @@ * example the value is increased by 10. * @tags filter */ + import cpp import external.MetricFilter from MetricResult res -select res, - res.getValue() + 10 +select res, res.getValue() + 10 diff --git a/cpp/ql/src/external/examples/filters/EditDefectMessage.ql b/cpp/ql/src/external/examples/filters/EditDefectMessage.ql index 98d65977e5a..366a76f6bad 100644 --- a/cpp/ql/src/external/examples/filters/EditDefectMessage.ql +++ b/cpp/ql/src/external/examples/filters/EditDefectMessage.ql @@ -6,9 +6,9 @@ * prepended to the message. * @tags filter */ + import cpp import external.DefectFilter from DefectResult res -select res, - "Filtered query result: " + res.getMessage() +select res, "Filtered query result: " + res.getMessage() diff --git a/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql b/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql index 44dc78c1643..44ef72735fc 100644 --- a/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql +++ b/cpp/ql/src/external/examples/filters/ExcludeGeneratedCode.ql @@ -6,14 +6,12 @@ * contains 'generated' anywhere in its path. * @tags filter */ + import cpp import external.DefectFilter -predicate generatedFile(File f) { - f.getAbsolutePath().matches("%generated%") -} +predicate generatedFile(File f) { f.getAbsolutePath().matches("%generated%") } from DefectResult res where not generatedFile(res.getFile()) -select res, - res.getMessage() +select res, res.getMessage() diff --git a/cpp/ql/src/external/tests/DefectFilter.ql b/cpp/ql/src/external/tests/DefectFilter.ql index 7788961eccb..88da84e1a52 100644 --- a/cpp/ql/src/external/tests/DefectFilter.ql +++ b/cpp/ql/src/external/tests/DefectFilter.ql @@ -3,6 +3,7 @@ * @description Only include results in large files (200) lines of code, and change the message. * @tags filter */ + import cpp import external.DefectFilter diff --git a/cpp/ql/src/external/tests/DefectFromExternalData.ql b/cpp/ql/src/external/tests/DefectFromExternalData.ql index cea9b23fba6..276977e35b5 100644 --- a/cpp/ql/src/external/tests/DefectFromExternalData.ql +++ b/cpp/ql/src/external/tests/DefectFromExternalData.ql @@ -7,10 +7,12 @@ */ import cpp - import external.ExternalArtifact from ExternalData d, File u -where d.getQueryPath() = "external-data.ql" - and u.getShortName() = d.getField(0) -select u, d.getField(5) + ", " + d.getFieldAsDate(1) + ", " +d.getField(2) + ", " + d.getFieldAsFloat(3) + ", " + d.getFieldAsInt(4) + ": " + d.getNumFields() +where + d.getQueryPath() = "external-data.ql" and + u.getShortName() = d.getField(0) +select u, + d.getField(5) + ", " + d.getFieldAsDate(1) + ", " + d.getField(2) + ", " + d.getFieldAsFloat(3) + + ", " + d.getFieldAsInt(4) + ": " + d.getNumFields() diff --git a/cpp/ql/src/external/tests/DefectFromSVN.ql b/cpp/ql/src/external/tests/DefectFromSVN.ql index 84e6ea902e5..64dd69148eb 100644 --- a/cpp/ql/src/external/tests/DefectFromSVN.ql +++ b/cpp/ql/src/external/tests/DefectFromSVN.ql @@ -8,21 +8,13 @@ */ import cpp - import external.ExternalArtifact import external.VCS -predicate numCommits(File f, int i) { - i = count(Commit e | e.getAnAffectedFile() = f) -} +predicate numCommits(File f, int i) { i = count(Commit e | e.getAnAffectedFile() = f) } -predicate maxCommits(int i) { - i = max(File f, int j | numCommits(f, j) | j) -} +predicate maxCommits(int i) { i = max(File f, int j | numCommits(f, j) | j) } from File f, int i -where numCommits(f,i) and maxCommits(i) +where numCommits(f, i) and maxCommits(i) select f, "This file has " + i + " commits." - - - diff --git a/cpp/ql/src/external/tests/MetricFilter.ql b/cpp/ql/src/external/tests/MetricFilter.ql index 4730b19696d..ba2868254ef 100644 --- a/cpp/ql/src/external/tests/MetricFilter.ql +++ b/cpp/ql/src/external/tests/MetricFilter.ql @@ -3,6 +3,7 @@ * @description Only include results in large files (200) lines of code. * @tags filter */ + import cpp import external.MetricFilter diff --git a/cpp/ql/src/external/tests/MetricFromSVN.ql b/cpp/ql/src/external/tests/MetricFromSVN.ql index 90cf91ff87b..e81eec18ea5 100644 --- a/cpp/ql/src/external/tests/MetricFromSVN.ql +++ b/cpp/ql/src/external/tests/MetricFromSVN.ql @@ -8,12 +8,9 @@ */ import cpp - import external.VCS -predicate numCommits(File f, int i) { - i = count(Commit e | e.getAnAffectedFile() = f) -} +predicate numCommits(File f, int i) { i = count(Commit e | e.getAnAffectedFile() = f) } from File f, int i where numCommits(f, i) diff --git a/cpp/ql/src/filters/ClassifyFiles.ql b/cpp/ql/src/filters/ClassifyFiles.ql index 8f486e63fa7..f51a7d03178 100644 --- a/cpp/ql/src/filters/ClassifyFiles.ql +++ b/cpp/ql/src/filters/ClassifyFiles.ql @@ -11,13 +11,11 @@ import semmle.code.cpp.AutogeneratedFile import semmle.code.cpp.TestFile predicate classify(File f, string tag) { - ( - f instanceof AutogeneratedFile and - tag = "generated" - ) or ( - f instanceof TestFile and - tag = "test" - ) + f instanceof AutogeneratedFile and + tag = "generated" + or + f instanceof TestFile and + tag = "test" } from File f, string tag diff --git a/cpp/ql/src/filters/FilterAutogenerated.ql b/cpp/ql/src/filters/FilterAutogenerated.ql index f6b418d8d60..43956b48d05 100644 --- a/cpp/ql/src/filters/FilterAutogenerated.ql +++ b/cpp/ql/src/filters/FilterAutogenerated.ql @@ -6,12 +6,11 @@ * @id cpp/autogenerated-filter * @tags filter */ - + import cpp import semmle.code.cpp.AutogeneratedFile import external.DefectFilter from DefectResult res where not res.getFile() instanceof AutogeneratedFile -select res, - res.getMessage() +select res, res.getMessage() diff --git a/cpp/ql/src/filters/FilterAutogeneratedForMetric.ql b/cpp/ql/src/filters/FilterAutogeneratedForMetric.ql index 7661123cce4..6cc6833f7f8 100644 --- a/cpp/ql/src/filters/FilterAutogeneratedForMetric.ql +++ b/cpp/ql/src/filters/FilterAutogeneratedForMetric.ql @@ -10,8 +10,7 @@ import cpp import semmle.code.cpp.AutogeneratedFile import external.MetricFilter - + from MetricResult res where not res.getFile() instanceof AutogeneratedFile -select res, - res.getValue() +select res, res.getValue() diff --git a/cpp/ql/src/filters/FromSource.ql b/cpp/ql/src/filters/FromSource.ql index cc1d1563860..459ca94d3c6 100644 --- a/cpp/ql/src/filters/FromSource.ql +++ b/cpp/ql/src/filters/FromSource.ql @@ -13,5 +13,4 @@ import external.DefectFilter from DefectResult res where res.getFile().fromSource() -select res, - res.getMessage() +select res, res.getMessage() diff --git a/cpp/ql/src/filters/Macros.ql b/cpp/ql/src/filters/Macros.ql index c880cfa3370..b5e9e7ca5bf 100644 --- a/cpp/ql/src/filters/Macros.ql +++ b/cpp/ql/src/filters/Macros.ql @@ -7,11 +7,12 @@ * @id cpp/macros-filter * @tags filter */ + import cpp import external.DefectFilter predicate macroLocation(File f, int startLine, int endLine) { - exists(MacroInvocation mi, Location l | + exists(MacroInvocation mi, Location l | l = mi.getLocation() and l.getFile() = f and l.getStartLine() = startLine and @@ -32,5 +33,4 @@ predicate macroCovering(DefectResult r) { from DefectResult res where not macroCovering(res) -select res, - res.getMessage() +select res, res.getMessage() diff --git a/cpp/ql/src/filters/RecentDefects.ql b/cpp/ql/src/filters/RecentDefects.ql index 108b7565c3e..4b742849fda 100644 --- a/cpp/ql/src/filters/RecentDefects.ql +++ b/cpp/ql/src/filters/RecentDefects.ql @@ -10,15 +10,14 @@ * external-data * @deprecated */ + import cpp import external.DefectFilter import external.VCS -private pragma[noopt] -predicate recent(File file) { - exists(Commit e | file = e.getAnAffectedFile() | - e.isRecent() and not artificialChange(e) - ) +pragma[noopt] +private predicate recent(File file) { + exists(Commit e | file = e.getAnAffectedFile() | e.isRecent() and not artificialChange(e)) } from DefectResult res diff --git a/cpp/ql/src/filters/RecentDefectsForMetric.ql b/cpp/ql/src/filters/RecentDefectsForMetric.ql index f651e61dbf6..ee057fe71ca 100644 --- a/cpp/ql/src/filters/RecentDefectsForMetric.ql +++ b/cpp/ql/src/filters/RecentDefectsForMetric.ql @@ -10,15 +10,14 @@ * external-data * @deprecated */ + import cpp import external.MetricFilter import external.VCS -private pragma[noopt] -predicate recent(File file) { - exists(Commit e | file = e.getAnAffectedFile() | - e.isRecent() and not artificialChange(e) - ) +pragma[noopt] +private predicate recent(File file) { + exists(Commit e | file = e.getAnAffectedFile() | e.isRecent() and not artificialChange(e)) } from MetricResult res diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql index e4f6524ae5f..1ae7425a4d0 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 1.ql @@ -7,9 +7,13 @@ * @tags maintainability * external/jsf */ + import cpp from Function f, int n -where n = f.getMetrics().getNumberOfLinesOfCode() - and n > 200 -select f, "AV Rule 1: any one function (or method) will contain no more than 200 logical source lines of code. Function '" + f.toString() + "' contains " + n.toString() + " lines of code." +where + n = f.getMetrics().getNumberOfLinesOfCode() and + n > 200 +select f, + "AV Rule 1: any one function (or method) will contain no more than 200 logical source lines of code. Function '" + + f.toString() + "' contains " + n.toString() + " lines of code." diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql index 2ce690fe285..0420b9c3984 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql @@ -9,6 +9,7 @@ * testability * external/jsf */ + import cpp // We look for code that converts between function pointers and non-function, non-void @@ -16,14 +17,16 @@ import cpp // self-modification, nor will it spot the use of OS mechanisms to write into process // memory (such as WriteProcessMemory under Windows). predicate maybeSMCConversion(Type t1, Type t2) { - t1 instanceof FunctionPointerType and - t2 instanceof PointerType and - not t2 instanceof FunctionPointerType and - not t2 instanceof VoidPointerType - or maybeSMCConversion(t2, t1) + t1 instanceof FunctionPointerType and + t2 instanceof PointerType and + not t2 instanceof FunctionPointerType and + not t2 instanceof VoidPointerType + or + maybeSMCConversion(t2, t1) } from Expr e -where e.fromSource() and - maybeSMCConversion(e.getUnderlyingType(), e.getActualType()) -select e, "AV Rule 2: There shall not be any self-modifying code." \ No newline at end of file +where + e.fromSource() and + maybeSMCConversion(e.getUnderlyingType(), e.getActualType()) +select e, "AV Rule 2: There shall not be any self-modifying code." diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql index f079b89360c..a1b374eaba7 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 3.ql @@ -7,9 +7,11 @@ * @tags maintainability * external/jsf */ + import cpp from Function f, int c -where c = f.getMetrics().getCyclomaticComplexity() and - c > 20 +where + c = f.getMetrics().getCyclomaticComplexity() and + c > 20 select f, "AV Rule 3: All functions shall have a cyclomatic complexity number of 20 or less." diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql index ac46a454101..838af649255 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 11.ql @@ -8,9 +8,10 @@ * readability * external/jsf */ + import cpp import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.04 Environment/AV Rule 11.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql index b3460c5bc5f..c632de42748 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 12.ql @@ -14,4 +14,4 @@ import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.04 Environment/AV Rule 12.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql index 6d03cd712aa..7c997ba4c17 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 13.ql @@ -8,9 +8,11 @@ * portability * external/jsf */ + import cpp from Literal l -where l.getType() instanceof Wchar_t or - l.getType().(ArrayType).getBaseType().getUnspecifiedType() instanceof Wchar_t -select l, "AV Rule 13: Multi-byte characters and wide string literals will not be used." \ No newline at end of file +where + l.getType() instanceof Wchar_t or + l.getType().(ArrayType).getBaseType().getUnspecifiedType() instanceof Wchar_t +select l, "AV Rule 13: Multi-byte characters and wide string literals will not be used." diff --git a/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql b/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql index 792383baf77..119588b5ebd 100644 --- a/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql +++ b/cpp/ql/src/jsf/4.04 Environment/AV Rule 14.ql @@ -8,9 +8,11 @@ * readability * external/jsf */ + import cpp from Literal l -where l.fromSource() and - l.getValueText().regexpMatch(".*[ul][uUlL]*\\s*") -select l, "AV Rule 14: Literal suffixes shall use uppercase rather than lowercase letters." \ No newline at end of file +where + l.fromSource() and + l.getValueText().regexpMatch(".*[ul][uUlL]*\\s*") +select l, "AV Rule 14: Literal suffixes shall use uppercase rather than lowercase letters." diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql index 520cb67a622..07f78f0b027 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 17.ql @@ -7,10 +7,15 @@ * @tags maintainability * external/jsf */ + import cpp from Locatable errno, Locatable use -where ( errno.(Macro).getHead() = "errno" and use = errno.(Macro).getAnInvocation() - or errno.(Variable).hasName("errno") and use = errno.(Variable).getAnAccess()) and - errno.getFile().getAbsolutePath().matches("%errno.h") +where + ( + errno.(Macro).getHead() = "errno" and use = errno.(Macro).getAnInvocation() + or + errno.(Variable).hasName("errno") and use = errno.(Variable).getAnAccess() + ) and + errno.getFile().getAbsolutePath().matches("%errno.h") select use, "AV Rule 17: The error indicator errno shall not be used." diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql index a9eeb2e6639..09f3dfd6b17 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 18.ql @@ -7,9 +7,12 @@ * @tags maintainability * external/jsf */ + import cpp from Macro offsetof -where offsetof.getHead().matches("offsetof(%,%)") and - offsetof.getFile().getAbsolutePath().matches("%stddef.h") -select offsetof.getAnInvocation(), "AV Rule 18: The macro offsetof, in library , shall not be used." +where + offsetof.getHead().matches("offsetof(%,%)") and + offsetof.getFile().getAbsolutePath().matches("%stddef.h") +select offsetof.getAnInvocation(), + "AV Rule 18: The macro offsetof, in library , shall not be used." diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql index 414ba2e969f..f22ef860126 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 19.ql @@ -7,6 +7,7 @@ * @tags maintainability * external/jsf */ + import cpp from Include incl diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql index c543cb64663..3fcfee2f55d 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 20.ql @@ -9,6 +9,7 @@ * readability * external/jsf */ + import cpp class Setjmp extends Macro { @@ -27,6 +28,7 @@ class Longjmp extends Function { } from Setjmp setjmp, Longjmp longjmp, Locatable use -where use = setjmp.getAnInvocation() - or use = longjmp.getACallToThisFunction() +where + use = setjmp.getAnInvocation() or + use = longjmp.getACallToThisFunction() select use, "AV Rule 20: The setjmp macro and the longjmp function shall not be used." diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql index 8d3ed394737..3640ddcb4b6 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 21.ql @@ -8,6 +8,7 @@ * portability * external/jsf */ + import cpp from Include incl diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql index 8a1cb164e93..e13f767f581 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 22.ql @@ -8,6 +8,7 @@ * portability * external/jsf */ + import cpp from Include incl diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql index 1c0c84c7cdd..9bb63cb6b29 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 23.ql @@ -8,9 +8,12 @@ * portability * external/jsf */ + import cpp from Function f -where f.getName().regexpMatch("atof|atoi|atol") and - f.getFile().getAbsolutePath().matches("%stdlib.h") -select f.getACallToThisFunction(), "AV Rule 23: The library functions atof, atoi and atol from library shall not be used." +where + f.getName().regexpMatch("atof|atoi|atol") and + f.getFile().getAbsolutePath().matches("%stdlib.h") +select f.getACallToThisFunction(), + "AV Rule 23: The library functions atof, atoi and atol from library shall not be used." diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql index 42e456e3dd6..9e0fd1d5de8 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 24.ql @@ -8,9 +8,12 @@ * portability * external/jsf */ + import cpp from Function f -where f.getName().regexpMatch("abort|exit|getenv|system") and - f.getFile().getAbsolutePath().matches("%stdlib.h") -select f.getACallToThisFunction(), "The library functions abort, exit, getenv and system from library should not be used." +where + f.getName().regexpMatch("abort|exit|getenv|system") and + f.getFile().getAbsolutePath().matches("%stdlib.h") +select f.getACallToThisFunction(), + "The library functions abort, exit, getenv and system from library should not be used." diff --git a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql index 09df5fa8b56..5024a55f72b 100644 --- a/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql +++ b/cpp/ql/src/jsf/4.05 Libraries/AV Rule 25.ql @@ -8,6 +8,7 @@ * portability * external/jsf */ + import cpp from Include incl diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql index 9561f452cd3..aa2058d5ad4 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 26.ql @@ -7,11 +7,14 @@ * @tags maintainability * external/jsf */ + import cpp from PreprocessorDirective directive -where not directive instanceof PreprocessorIfndef and - not directive instanceof PreprocessorEndif and - not directive instanceof Macro and - not directive instanceof Include -select directive, "AV Rule 26: only the #ifndef, #endif, #define and #include directives shall be used." \ No newline at end of file +where + not directive instanceof PreprocessorIfndef and + not directive instanceof PreprocessorEndif and + not directive instanceof Macro and + not directive instanceof Include +select directive, + "AV Rule 26: only the #ifndef, #endif, #define and #include directives shall be used." diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql index 1aed7ddab59..08522170df6 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 27.ql @@ -8,8 +8,10 @@ * portability * external/jsf */ + import cpp import semmle.code.cpp.headers.MultipleInclusion from BadIncludeGuard bad -select bad.blame(), "AV Rule 27: techniques other than #ifndef/#define/#endif will not be used to prevent multiple inclusions of header files." \ No newline at end of file +select bad.blame(), + "AV Rule 27: techniques other than #ifndef/#define/#endif will not be used to prevent multiple inclusions of header files." diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql index 9d22ab3c340..da79656d800 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 28.ql @@ -7,10 +7,13 @@ * @tags maintainability * external/jsf */ + import cpp import semmle.code.cpp.headers.MultipleInclusion from PreprocessorDirective directive -where (directive instanceof PreprocessorIfndef or directive instanceof PreprocessorEndif) and - not exists(CorrectIncludeGuard cig | directive = cig.getIfndef() or directive = cig.getEndif()) -select directive, "AV Rule 28: the #ifndef and #endif directives will only be used as defined in AV Rule 27." +where + (directive instanceof PreprocessorIfndef or directive instanceof PreprocessorEndif) and + not exists(CorrectIncludeGuard cig | directive = cig.getIfndef() or directive = cig.getEndif()) +select directive, + "AV Rule 28: the #ifndef and #endif directives will only be used as defined in AV Rule 27." diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql index f3dc2a2e87f..c7187b2ba00 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 29.ql @@ -7,8 +7,9 @@ * @tags maintainability * external/jsf */ + import cpp from Macro m where m.getHead().matches("%(%") // Macro functions are simply macros with brackets in the head -select m, "The #define pre-processor directive shall not be used to create inline macros" \ No newline at end of file +select m, "The #define pre-processor directive shall not be used to create inline macros" diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql index ceedac6112f..86175efea49 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 30.ql @@ -7,20 +7,22 @@ * @tags maintainability * external/jsf */ + import cpp /** A macro defining a simple constant. */ class ConstantDefMacro extends Macro { ConstantDefMacro() { // Exclude functions - not (this.getHead().matches("%(%")) and - exists(string body | body = this.getBody() and - // Empty defines are allowed (rule 31 restricts their use though) - body != "" and - // No special characters in the body - not (body.matches("%(%")) and - not (body.matches("%{%")) - ) + not this.getHead().matches("%(%") and + exists(string body | + body = this.getBody() and + // Empty defines are allowed (rule 31 restricts their use though) + body != "" and + // No special characters in the body + not body.matches("%(%") and + not body.matches("%{%") + ) } } @@ -30,6 +32,7 @@ predicate commonMacro(string name) { } from ConstantDefMacro m -where not commonMacro(m.getHead()) - and m.fromSource() -select m, "The #define pre-processor directive shall not be used to define constant values." \ No newline at end of file +where + not commonMacro(m.getHead()) and + m.fromSource() +select m, "The #define pre-processor directive shall not be used to define constant values." diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql index 9c8f389cf3f..c6332829e38 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 31.ql @@ -7,9 +7,11 @@ * @tags maintainability * external/jsf */ + import cpp import semmle.code.cpp.headers.MultipleInclusion from Macro macro where not exists(CorrectIncludeGuard cig | macro = cig.getDefine()) -select macro, "AV Rule 31: The #define directive will only be used as part of the technique to prevent multiple inclusions of the same header file." \ No newline at end of file +select macro, + "AV Rule 31: The #define directive will only be used as part of the technique to prevent multiple inclusions of the same header file." diff --git a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql index 59fef7909e0..d78bc0ee2a7 100644 --- a/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql +++ b/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql @@ -10,16 +10,19 @@ * readability * external/jsf */ + import cpp import semmle.code.cpp.AutogeneratedFile from Include i, File f, string extension -where f = i.getIncludedFile() and extension = f.getExtension().toLowerCase() - and extension != "inl" - and extension != "tcc" - and extension != "tpp" - and extension != "txx" - and extension != "xpm" - and not (f instanceof AutogeneratedFile) - and not (f instanceof HeaderFile) +where + f = i.getIncludedFile() and + extension = f.getExtension().toLowerCase() and + extension != "inl" and + extension != "tcc" and + extension != "tpp" and + extension != "txx" and + extension != "xpm" and + not f instanceof AutogeneratedFile and + not f instanceof HeaderFile select i, "The #include pre-processor directive should only be used to include header files." diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql index 2b416c4ce21..b17bbd0f173 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 33.ql @@ -8,8 +8,9 @@ * portability * external/jsf */ + import cpp from Include i where i.getIncludeText().matches("<%") -select i, "AV Rule 33: the #include notation shall be used." \ No newline at end of file +select i, "AV Rule 33: the #include notation shall be used." diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql index 92f6b77822e..2d69fe498cc 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.ql @@ -12,6 +12,7 @@ * modularity * external/jsf */ + import cpp import semmle.code.cpp.headers.MultipleInclusion @@ -29,37 +30,26 @@ newtype TMaybePreprocessorDirective = abstract class MaybePreprocessorDirective extends TMaybePreprocessorDirective { abstract string toString(); + abstract Location getLocation(); } class NoPreprocessorDirective extends TNoPreprocessorDirective, MaybePreprocessorDirective { - override string toString() { - result = "" - } - - override Location getLocation() { - result instanceof UnknownDefaultLocation - } + override string toString() { result = "" } + + override Location getLocation() { result instanceof UnknownDefaultLocation } } class SomePreprocessorDirective extends TSomePreprocessorDirective, MaybePreprocessorDirective { PreprocessorDirective pd; - SomePreprocessorDirective() { - this = TSomePreprocessorDirective(pd) - } + SomePreprocessorDirective() { this = TSomePreprocessorDirective(pd) } - override string toString() { - result = pd.toString() - } - - override Location getLocation() { - result = pd.getLocation() - } - - PreprocessorDirective getPreprocessorDirective() { - result = pd - } + override string toString() { result = pd.toString() } + + override Location getLocation() { result = pd.getLocation() } + + PreprocessorDirective getPreprocessorDirective() { result = pd } } /** @@ -67,20 +57,30 @@ class SomePreprocessorDirective extends TSomePreprocessorDirective, MaybePreproc * The second and third parameters are option typed, and are only present * when there are additional links in the detail string. */ -string extraDetail(HeaderFile hf, SomePreprocessorDirective detail1, SomePreprocessorDirective detail2) { - exists(string s, PreprocessorEndif endif, PreprocessorDirective ifndef | startsWithIfndef(hf, ifndef, s) and endif.getIf() = ifndef | +string extraDetail( + HeaderFile hf, SomePreprocessorDirective detail1, SomePreprocessorDirective detail2 +) { + exists(string s, PreprocessorEndif endif, PreprocessorDirective ifndef | + startsWithIfndef(hf, ifndef, s) and endif.getIf() = ifndef + | detail1.getPreprocessorDirective() = endif and detail2.getPreprocessorDirective() = ifndef and - if not endsWithEndif(hf, endif) then - result = " ($@ matching $@ occurs before the end of the file)." - else if exists(Macro m | m.getFile() = hf and m.getHead() = s) then - result = " (#define " + s + " needs to appear immediately after #ifndef " + s + ")." - else if strictcount(possibleGuard(hf, _)) = 1 then - result = " (" + possibleGuard(hf, _) + " should appear in the #ifndef rather than " + s + ")." - else if strictcount(possibleGuard(hf, "")) = 1 then - result = " (" + possibleGuard(hf, "") + " should appear in the #ifndef rather than " + s + ")." + if not endsWithEndif(hf, endif) + then result = " ($@ matching $@ occurs before the end of the file)." else - result = " (the macro " + s + " is checked for, but is not defined)." + if exists(Macro m | m.getFile() = hf and m.getHead() = s) + then result = " (#define " + s + " needs to appear immediately after #ifndef " + s + ")." + else + if strictcount(possibleGuard(hf, _)) = 1 + then + result = " (" + possibleGuard(hf, _) + " should appear in the #ifndef rather than " + s + + ")." + else + if strictcount(possibleGuard(hf, "")) = 1 + then + result = " (" + possibleGuard(hf, "") + " should appear in the #ifndef rather than " + s + + ")." + else result = " (the macro " + s + " is checked for, but is not defined)." ) } @@ -130,9 +130,7 @@ predicate hasXMacro(HeaderFile hf) { // used in `hf`. exists(string macroName | usesMacro(hf, macroName) and - forex(File f | f.getAnIncludedFile() = hf | - defUndef(f, macroName) - ) + forex(File f | f.getAnIncludedFile() = hf | defUndef(f, macroName)) ) or // Every header that includes `hf` defines a macro that's used in `hf`, and @@ -140,27 +138,33 @@ predicate hasXMacro(HeaderFile hf) { exists(string macroName | usesMacro(hf, macroName) and undefinesMacro(hf, macroName) and - forex(File f | f.getAnIncludedFile() = hf | - definesMacro(f, macroName) - ) + forex(File f | f.getAnIncludedFile() = hf | definesMacro(f, macroName)) ) } -from HeaderFile hf, string detail, MaybePreprocessorDirective detail1, MaybePreprocessorDirective detail2 -where not hf instanceof IncludeGuardedHeader - and (if exists(extraDetail(hf, _, _)) +from + HeaderFile hf, string detail, MaybePreprocessorDirective detail1, + MaybePreprocessorDirective detail2 +where + not hf instanceof IncludeGuardedHeader and + ( + if exists(extraDetail(hf, _, _)) then detail = extraDetail(hf, detail1, detail2) - else (detail = "." and + else ( + detail = "." and detail1 instanceof NoPreprocessorDirective and - detail2 instanceof NoPreprocessorDirective)) + detail2 instanceof NoPreprocessorDirective + ) + ) and // Exclude files which contain no declaration entries or top level // declarations (e.g. just preprocessor directives; or non-top level // code). - and not hf.noTopLevelCode() + not hf.noTopLevelCode() and // Exclude files which look like they contain 'x-macros' - and not hasXMacro(hf) + not hasXMacro(hf) and // Exclude files which are always #imported. - and not forex(Include i | i.getIncludedFile() = hf | i instanceof Import) + not forex(Include i | i.getIncludedFile() = hf | i instanceof Import) and // Exclude files which are only included once. - and not strictcount(Include i | i.getIncludedFile() = hf) = 1 -select hf, "This header file should contain a header guard to prevent multiple inclusion" + detail, detail1, detail1.toString(), detail2, detail2.toString() + not strictcount(Include i | i.getIncludedFile() = hf) = 1 +select hf, "This header file should contain a header guard to prevent multiple inclusion" + detail, + detail1, detail1.toString(), detail2, detail2.toString() diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql index 0bf35a35f17..43862bede19 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 39.ql @@ -7,14 +7,18 @@ * @tags maintainability * external/jsf */ + import cpp predicate forbidden(Declaration d) { d instanceof Variable and not d.(Variable).isConst() - or (d instanceof Function and not d.hasSpecifier("inline")) + or + d instanceof Function and not d.hasSpecifier("inline") } from Declaration d -where d.getDefinitionLocation().getFile() instanceof HeaderFile - and forbidden(d) -select d.getDefinitionLocation(), "AV Rule 38: header files will not contain non-const variable definitions or function definitions." \ No newline at end of file +where + d.getDefinitionLocation().getFile() instanceof HeaderFile and + forbidden(d) +select d.getDefinitionLocation(), + "AV Rule 38: header files will not contain non-const variable definitions or function definitions." diff --git a/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql b/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql index 9ca933383df..61456131f07 100644 --- a/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql +++ b/cpp/ql/src/jsf/4.08 Implementation Files/AV Rule 40.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -40,10 +41,14 @@ predicate definedInImplementationFile(Declaration d) { } from Declaration d, string message -where relevant(d) and - ((hasTwoDefinitions(d) and message = " should not have several definitions.") - or definedInImplementationFile(d) and message = " should be defined in a header file.") - // Don't count member functions - the only way they can match this rule is by - // being in a class definition that already matches, so it would be redundant - and not d instanceof MemberFunction -select d.getDefinitionLocation(), "AV Rule 40: " + d.getName() + message \ No newline at end of file +where + relevant(d) and + ( + hasTwoDefinitions(d) and message = " should not have several definitions." + or + definedInImplementationFile(d) and message = " should be defined in a header file." + ) and + // Don't count member functions - the only way they can match this rule is by + // being in a class definition that already matches, so it would be redundant + not d instanceof MemberFunction +select d.getDefinitionLocation(), "AV Rule 40: " + d.getName() + message diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql index 7167bb59cd5..ab37b49f696 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 41.ql @@ -14,4 +14,4 @@ import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.09 Style/AV Rule 41.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql index e7058321347..bfb58237faa 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 42.ql @@ -8,12 +8,13 @@ * readability * external/jsf */ + import cpp predicate exprInStmtContext(Expr e, Location l, File f) { - e.getParent() instanceof ExprStmt - and l = e.getLocation() - and f = l.getFile() + e.getParent() instanceof ExprStmt and + l = e.getLocation() and + f = l.getFile() } predicate overlappingExprs(Expr e1, Expr e2) { @@ -21,11 +22,11 @@ predicate overlappingExprs(Expr e1, Expr e2) { exprInStmtContext(e1, l1, f) and exprInStmtContext(e2, l2, f) and e1 != e2 and - (l1.getEndLine() >= l2.getStartLine()) and - (l1.getStartLine() <= l2.getEndLine()) + l1.getEndLine() >= l2.getStartLine() and + l1.getStartLine() <= l2.getEndLine() ) } from Expr e where overlappingExprs(e, _) and not e.isInMacroExpansion() -select e, "AV Rule 42: Each expression-statement will be on a separate line." \ No newline at end of file +select e, "AV Rule 42: Each expression-statement will be on a separate line." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql index ef9d5fbd748..05838f8e0e4 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 43.ql @@ -14,4 +14,4 @@ import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.09 Style/AV Rule 43.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql index 540434cb718..f4cd3d60a09 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 44.ql @@ -14,4 +14,4 @@ import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.09 Style/AV Rule 44.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql index 1ed332b8477..659adf6c05d 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 45.ql @@ -8,6 +8,7 @@ * readability * external/jsf */ + import cpp /* @@ -16,10 +17,12 @@ import cpp */ from Declaration d, string name, string lowerCase, string upperCase, int pos -where name = d.getName() and - d.fromSource() and - lowerCase = name.charAt(pos) and - upperCase = name.charAt(pos+1) and - lowerCase.regexpMatch("[a-z]") and - upperCase.regexpMatch("[A-Z]") -select d, "AV Rule 45: All words in an identifier will be separated by the underscore character. Camel-case is not allowed." \ No newline at end of file +where + name = d.getName() and + d.fromSource() and + lowerCase = name.charAt(pos) and + upperCase = name.charAt(pos + 1) and + lowerCase.regexpMatch("[a-z]") and + upperCase.regexpMatch("[A-Z]") +select d, + "AV Rule 45: All words in an identifier will be separated by the underscore character. Camel-case is not allowed." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql index 80324b61ef1..4188f695abb 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 46.ql @@ -8,6 +8,7 @@ * readability * external/jsf */ + import cpp /* @@ -25,8 +26,8 @@ predicate longNameSignificance(Element e, string significance) { } predicate elementName(Element e, string name) { - name = e.(Declaration).getName() or name = e.(Namespace).getName() - } + name = e.(Declaration).getName() or name = e.(Namespace).getName() +} predicate clash(Element e1, Element e2) { exists(string significance, string n1, string n2 | @@ -39,6 +40,7 @@ predicate clash(Element e1, Element e2) { } from Element e1, Element e2, string name -where clash(e1, e2) - and elementName(e2, name) -select e1, "AV Rule 46: relies on more than 64 characters to separate from " + name \ No newline at end of file +where + clash(e1, e2) and + elementName(e2, name) +select e1, "AV Rule 46: relies on more than 64 characters to separate from " + name diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql index fb36adf66a9..f30a1cc0ead 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 47.ql @@ -7,9 +7,11 @@ * @tags maintainability * external/jsf */ + import cpp from Declaration d -where d.fromSource() and - d.getName().matches("\\_%") -select d, "Identifiers will not begin with the underscore character." \ No newline at end of file +where + d.fromSource() and + d.getName().matches("\\_%") +select d, "Identifiers will not begin with the underscore character." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql index e712c394b37..afb7d74e62a 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 48.ql @@ -8,6 +8,7 @@ * readability * external/jsf */ + import cpp /* @@ -29,63 +30,67 @@ predicate canonicalName1(Declaration d, string canonical) { } predicate canonicalName2(Declaration d, string canonical) { - canonical = d.getName() - .replaceAll("_", "") - .replaceAll("0", "O") - .replaceAll("D", "O") - .replaceAll("1", "I") - .replaceAll("l", "I") - .replaceAll("S", "5") - .replaceAll("Z", "2") - .replaceAll("n", "h") + canonical = d + .getName() + .replaceAll("_", "") + .replaceAll("0", "O") + .replaceAll("D", "O") + .replaceAll("1", "I") + .replaceAll("l", "I") + .replaceAll("S", "5") + .replaceAll("Z", "2") + .replaceAll("n", "h") } predicate same(Declaration d1, Declaration d2) { - exists (string common | canonicalName1(d1, common) and canonicalName1(d2, common)) + exists(string common | canonicalName1(d1, common) and canonicalName1(d2, common)) or - exists (string common | canonicalName2(d1, common) and canonicalName2(d2, common)) + exists(string common | canonicalName2(d1, common) and canonicalName2(d2, common)) } /** Is the declaration local to that function? */ predicate local(Declaration d, Function f) { d.(Parameter).getFunction() = f - or exists(DeclStmt ds | d = ds.getADeclaration().(LocalVariable) and ds.getEnclosingFunction() = f) + or + exists(DeclStmt ds | d = ds.getADeclaration().(LocalVariable) and ds.getEnclosingFunction() = f) } -/** Is the declaration local to that struct? Reduce false warning by taking into - * account struct lookup rules - since a struct members can never be referred to - * other than in a qualified way it doesn't really count.*/ -predicate structLocal(Declaration d, Struct s) { - d = s.getAMemberVariable() -} +/** + * Is the declaration local to that struct? Reduce false warning by taking into + * account struct lookup rules - since a struct members can never be referred to + * other than in a qualified way it doesn't really count. + */ +predicate structLocal(Declaration d, Struct s) { d = s.getAMemberVariable() } predicate compatibleScopes(Declaration d1, Declaration d2) { - // Either they're both local to the same struct, or - exists (Struct s | structLocal(d1,s) and structLocal(d2,s)) - or - ( - // Neither of them is a struct member and ... - not(structLocal(d1,_)) and not(structLocal(d2,_)) and - same(d1, d2) and - ( - // d2 is global and d1 is either, or - not local(d2, _) or - // both are local to the same function - exists (Function f | local(d1,f) and local(d2,f)) - ) - ) + // Either they're both local to the same struct, or + exists(Struct s | structLocal(d1, s) and structLocal(d2, s)) + or + // Neither of them is a struct member and ... + not structLocal(d1, _) and + not structLocal(d2, _) and + same(d1, d2) and + ( + // d2 is global and d1 is either, or + not local(d2, _) + or + // both are local to the same function + exists(Function f | local(d1, f) and local(d2, f)) + ) } from Declaration d1, Declaration d2 -where d1.fromSource() and d2.fromSource() and - // Test that the names are confusing according to the above criteria - same(d1, d2) and - d1.getName() != d2.getName() and - ( - // either they are both type names, or - (d1 instanceof UserType and d2 instanceof UserType) - or - // they are both variable names in close enough scopes for the confusion to matter - (d1 instanceof Variable and d2 instanceof Variable and compatibleScopes(d1, d2)) - ) -select d1, "AV Rule 48: this identifier is too close to another identifier (" + d2.getName() + ")" \ No newline at end of file +where + d1.fromSource() and + d2.fromSource() and + // Test that the names are confusing according to the above criteria + same(d1, d2) and + d1.getName() != d2.getName() and + ( + // either they are both type names, or + d1 instanceof UserType and d2 instanceof UserType + or + // they are both variable names in close enough scopes for the confusion to matter + d1 instanceof Variable and d2 instanceof Variable and compatibleScopes(d1, d2) + ) +select d1, "AV Rule 48: this identifier is too close to another identifier (" + d2.getName() + ")" diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql index 56e07e207fe..ceeb1e10a25 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 49.ql @@ -8,6 +8,7 @@ * readability * external/jsf */ + import cpp import Naming @@ -16,9 +17,12 @@ import Naming */ from Declaration d, Name n, Word w -where d.fromSource() and - n = d.getName() and - w = n.getAWord() and - w.isDefiniteAcronym() and - not w.isUppercase() -select d, "AV Rule 49: acronyms in identifiers will be uppercase. Incorrect case for acronym " + w.toString() + "." \ No newline at end of file +where + d.fromSource() and + n = d.getName() and + w = n.getAWord() and + w.isDefiniteAcronym() and + not w.isUppercase() +select d, + "AV Rule 49: acronyms in identifiers will be uppercase. Incorrect case for acronym " + + w.toString() + "." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql index ca45954eeb6..ec55976ec35 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 50.ql @@ -8,23 +8,32 @@ * readability * external/jsf */ + import cpp import Naming predicate relevant(Element elem, Element blame, string kind, string name) { - exists(Class c | elem = c and blame = c and kind = "class or struct" and name = c.getName()) or // includes struct - exists(Namespace n | elem = n and blame = n.getADeclarationEntry() and kind = "namespace" and name = n.getName()) or - exists(Enum e | elem = e and blame = e and kind = "enumeration" and name = e.getName()) or + exists(Class c | elem = c and blame = c and kind = "class or struct" and name = c.getName()) // includes struct + or + exists(Namespace n | + elem = n and blame = n.getADeclarationEntry() and kind = "namespace" and name = n.getName() + ) + or + exists(Enum e | elem = e and blame = e and kind = "enumeration" and name = e.getName()) + or exists(TypedefType t | elem = t and blame = t and kind = "typedef" and name = t.getName()) } from Element d, Element blame, Word w, int pos, string kind, string name -where relevant(d, blame, kind, name) and - w = name.(Name).getWord(pos) and - not (w.couldBeUppercaseAcronym() and w != name) and - ( - (pos = 0 and not w.isCapitalized()) - or - (pos > 0 and not w.isLowercase()) - ) -select blame, "AV Rule 50: The first word of a " + kind + " will begin with an uppercase letter, and all other letters will be lowercase." \ No newline at end of file +where + relevant(d, blame, kind, name) and + w = name.(Name).getWord(pos) and + not (w.couldBeUppercaseAcronym() and w != name) and + ( + pos = 0 and not w.isCapitalized() + or + pos > 0 and not w.isLowercase() + ) +select blame, + "AV Rule 50: The first word of a " + kind + + " will begin with an uppercase letter, and all other letters will be lowercase." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql index e6fe9828e88..e60cfe7f42d 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 51.ql @@ -8,17 +8,20 @@ * readability * external/jsf */ + import cpp import Naming predicate relevant(Declaration d, string kind) { - (d instanceof Function and kind = "function") or - (d instanceof Variable and kind = "variable") + d instanceof Function and kind = "function" + or + d instanceof Variable and kind = "variable" } from Declaration d, Word w, string kind -where relevant(d, kind) and - w = d.getName().(Name).getAWord() and - not (w.couldBeUppercaseAcronym() and w != d.getName()) and - not w.isLowercase() -select d, "AV Rule 51: All letters contained in " + kind + " names will be lowercase." \ No newline at end of file +where + relevant(d, kind) and + w = d.getName().(Name).getAWord() and + not (w.couldBeUppercaseAcronym() and w != d.getName()) and + not w.isLowercase() +select d, "AV Rule 51: All letters contained in " + kind + " names will be lowercase." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql index 3c1d3631843..bf72ba47648 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 52.ql @@ -8,17 +8,20 @@ * readability * external/jsf */ + import cpp import Naming predicate relevant(Declaration d, string kind) { - (d instanceof EnumConstant and kind = "enumerator") or - (d.(Variable).isConst() and kind = "constant") + d instanceof EnumConstant and kind = "enumerator" + or + d.(Variable).isConst() and kind = "constant" } from Declaration d, Word w, string kind -where relevant(d, kind) and - w = d.getName().(Name).getAWord() and - not (w.couldBeUppercaseAcronym() and w != d.getName()) and - not w.isLowercase() +where + relevant(d, kind) and + w = d.getName().(Name).getAWord() and + not (w.couldBeUppercaseAcronym() and w != d.getName()) and + not w.isLowercase() select d, "AV Rule 52: identifiers for " + kind + " values shall be lowercase." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql index d70e7ff48bc..608374b241c 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.1.ql @@ -8,14 +8,18 @@ * portability * external/jsf */ + import cpp from Include i, string name -where name = i.getIncludeText() - and (name.matches("%'%") or - name.matches("%\\\\%") or - name.matches("%/*%") or - name.matches("%//%") or - name.matches("%\"%\"%\"%") or - name.matches("%<%\"%>%")) +where + name = i.getIncludeText() and + ( + name.matches("%'%") or + name.matches("%\\\\%") or + name.matches("%/*%") or + name.matches("%//%") or + name.matches("%\"%\"%\"%") or + name.matches("%<%\"%>%") + ) select i, "AV Rule 53.1: Invalid character sequence in header file name '" + name + "'" diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql index 2da4907f726..db8ad52e1f3 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 53.ql @@ -8,6 +8,7 @@ * readability * external/jsf */ + import cpp /* @@ -16,6 +17,7 @@ import cpp */ from File f -where (f.getExtension().toLowerCase() = "h" or f.getExtension().toLowerCase() = "hpp") - and f.getExtension() != "h" -select f, "AV Rule 53: Header files will always have a file name extension of .h." \ No newline at end of file +where + (f.getExtension().toLowerCase() = "h" or f.getExtension().toLowerCase() = "hpp") and + f.getExtension() != "h" +select f, "AV Rule 53: Header files will always have a file name extension of .h." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql index d7f10a88e57..158c6a23a4f 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 54.ql @@ -8,8 +8,9 @@ * readability * external/jsf */ + import cpp from CppFile f where f.getExtension() != "cpp" -select f, "AV Rule 53: Implementation files will always have a file name extension of .cpp." \ No newline at end of file +select f, "AV Rule 53: Implementation files will always have a file name extension of .cpp." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql index fe629ce5a4c..8d0f3065113 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 57.ql @@ -8,13 +8,20 @@ * readability * external/jsf */ + import cpp from Class c, Declaration m1, Declaration m2, int pos1, int pos2 -where m1 = c.getCanonicalMember(pos1) and - m2 = c.getCanonicalMember(pos2) and - pos1 < pos2 and - ( (m1.hasSpecifier("private") and m2.hasSpecifier("protected")) - or (m1.hasSpecifier("private") and m2.hasSpecifier("public")) - or (m1.hasSpecifier("protected") and m2.hasSpecifier("public"))) -select c, "AV Rule 57: The public, protected, and private sections of a class will be declared in that order." +where + m1 = c.getCanonicalMember(pos1) and + m2 = c.getCanonicalMember(pos2) and + pos1 < pos2 and + ( + m1.hasSpecifier("private") and m2.hasSpecifier("protected") + or + m1.hasSpecifier("private") and m2.hasSpecifier("public") + or + m1.hasSpecifier("protected") and m2.hasSpecifier("public") + ) +select c, + "AV Rule 57: The public, protected, and private sections of a class will be declared in that order." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql index 80b6ec08004..d393cf1e0ab 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 58.ql @@ -8,10 +8,13 @@ * readability * external/jsf */ + import cpp class ParamLoc extends Parameter { - int getValidLine() { result = this.getLocation().getStartLine() and result = this.getLocation().getEndLine() } + int getValidLine() { + result = this.getLocation().getStartLine() and result = this.getLocation().getEndLine() + } } predicate valid(Function f) { @@ -19,16 +22,19 @@ predicate valid(Function f) { f.getParameter(0).(ParamLoc).getValidLine() = f.getLocation().getStartLine() and // Check that each subsequent parameter is on its own line not exists(ParamLoc p1, ParamLoc p2 | - p1 = f.getAParameter() and p2 = f.getAParameter() and - p1 != p2 and - p1.getValidLine() = p2.getValidLine() + p1 = f.getAParameter() and + p2 = f.getAParameter() and + p1 != p2 and + p1.getValidLine() = p2.getValidLine() ) and // Check that there are no parameters on two lines - forall (ParamLoc p | p = f.getAParameter() | exists(p.getValidLine())) + forall(ParamLoc p | p = f.getAParameter() | exists(p.getValidLine())) } from Function f -where f.getNumberOfParameters() > 2 - and f.hasDefinition() - and not valid(f) -select f, "AV Rule 58: functions with more than two parameters will conform to style rules for declaring parameters" \ No newline at end of file +where + f.getNumberOfParameters() > 2 and + f.hasDefinition() and + not valid(f) +select f, + "AV Rule 58: functions with more than two parameters will conform to style rules for declaring parameters" diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql index 6baf82e3b32..2a5681093c7 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 59.ql @@ -8,15 +8,22 @@ * readability * external/jsf */ + import cpp from Stmt parent, Stmt child -where not child instanceof Block - and - (child = parent.(IfStmt).getThen() or - child = parent.(WhileStmt).getStmt() or - child = parent.(DoStmt).getStmt() or - child = parent.(ForStmt).getStmt() or - (child = parent.(IfStmt).getElse() and not child instanceof IfStmt) - ) -select child.findRootCause(), "The statements forming the body of an if, else if, else, while, do...while or for statement shall always be enclosed in braces, even if the braces form an empty block." \ No newline at end of file +where + not child instanceof Block and + ( + child = parent.(IfStmt).getThen() + or + child = parent.(WhileStmt).getStmt() + or + child = parent.(DoStmt).getStmt() + or + child = parent.(ForStmt).getStmt() + or + child = parent.(IfStmt).getElse() and not child instanceof IfStmt + ) +select child.findRootCause(), + "The statements forming the body of an if, else if, else, while, do...while or for statement shall always be enclosed in braces, even if the braces form an empty block." diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql index c1b2729aec2..3294b49b21a 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 60.ql @@ -14,4 +14,4 @@ import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.09 Style/AV Rule 60.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql index feee51df3de..3d81061f1fe 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 61.ql @@ -14,4 +14,4 @@ import external.ExternalArtifact from DefectExternalData d where d.getQueryPath() = "jsf/4.09 Style/AV Rule 61.ql" -select d, d.getMessage() \ No newline at end of file +select d, d.getMessage() diff --git a/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql b/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql index dcba779ee5f..06a0d65ee79 100644 --- a/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql +++ b/cpp/ql/src/jsf/4.09 Style/AV Rule 63.ql @@ -8,41 +8,43 @@ * readability * external/jsf */ + import cpp -predicate hasLocation(Expr e) { - e.getLocation().getStartLine() != 0 -} +predicate hasLocation(Expr e) { e.getLocation().getStartLine() != 0 } predicate outermostConvWithLocation(Expr e, Expr res) { - if(exists(Expr p | e.getConversion+() = p and hasLocation(p))) then - outermostConvWithLocation(e.getConversion(), res) - else - res = e + if exists(Expr p | e.getConversion+() = p and hasLocation(p)) + then outermostConvWithLocation(e.getConversion(), res) + else res = e } predicate diffEndBegin(Expr lhs, Expr rhs, int length) { exists(Location l, Location r | - l = lhs.getLocation() and r = rhs.getLocation() - and length = r.getStartColumn() - l.getEndColumn() - and l.getEndLine() = r.getStartLine() - ) -} -predicate diffEndEnd(Expr lhs, Expr rhs, int length) { - exists(Location l, Location r | - l = lhs.getLocation() and r = rhs.getLocation() - and length = r.getEndColumn() - l.getEndColumn() - and l.getEndLine() = r.getEndLine() - ) -} -predicate diffBeginBegin(Expr lhs, Expr rhs, int length) { - exists(Location l, Location r | - l = lhs.getLocation() and r = rhs.getLocation() - and length = r.getStartColumn() - l.getStartColumn() - and l.getStartLine() = r.getStartLine() + l = lhs.getLocation() and + r = rhs.getLocation() and + length = r.getStartColumn() - l.getEndColumn() and + l.getEndLine() = r.getStartLine() ) } +predicate diffEndEnd(Expr lhs, Expr rhs, int length) { + exists(Location l, Location r | + l = lhs.getLocation() and + r = rhs.getLocation() and + length = r.getEndColumn() - l.getEndColumn() and + l.getEndLine() = r.getEndLine() + ) +} + +predicate diffBeginBegin(Expr lhs, Expr rhs, int length) { + exists(Location l, Location r | + l = lhs.getLocation() and + r = rhs.getLocation() and + length = r.getStartColumn() - l.getStartColumn() and + l.getStartLine() = r.getStartLine() + ) +} /* * Unary postfix operations: PostfixDecrExpr, PostfixIncrExpr @@ -52,39 +54,79 @@ predicate diffBeginBegin(Expr lhs, Expr rhs, int length) { from Expr err where - not err.isInMacroExpansion() and hasLocation(err) - and + not err.isInMacroExpansion() and + hasLocation(err) and ( - exists(Call c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e) - and e.getType() instanceof PointerType and not diffEndBegin(e, c, 3)) - or - exists(Call c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e) - and not e.getType() instanceof PointerType and not diffEndBegin(e, c, 2)) - or - exists(VariableAccess c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e) - and e.getType() instanceof PointerType and not diffEndBegin(e, c, 3)) - or - exists(VariableAccess c, Expr e | c = err and outermostConvWithLocation(c.getQualifier(), e) - and not e.getType() instanceof PointerType and not diffEndBegin(e, c, 2)) - or - exists(UnaryOperation c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e) - and (c instanceof ComplementExpr or c instanceof NotExpr or c instanceof UnaryMinusExpr - or c instanceof UnaryPlusExpr or c instanceof AddressOfExpr) - and not diffBeginBegin(c, e, 1)) - or - exists(PrefixIncrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e) - and not diffBeginBegin(c, e, 2)) - or - exists(PrefixDecrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e) - and not diffBeginBegin(c, e, 2)) - or - exists(PointerDereferenceExpr c, Expr e | c = err and outermostConvWithLocation(c.getChild(0), e) - and not diffBeginBegin(c, e, 1)) - or - exists(PostfixIncrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e) - and not diffEndEnd(e, c, 2)) - or - exists(PostfixDecrExpr c, Expr e | c = err and outermostConvWithLocation(c.getOperand(), e) - and not diffEndEnd(e, c, 2)) + exists(Call c, Expr e | + c = err and + outermostConvWithLocation(c.getQualifier(), e) and + e.getType() instanceof PointerType and + not diffEndBegin(e, c, 3) + ) + or + exists(Call c, Expr e | + c = err and + outermostConvWithLocation(c.getQualifier(), e) and + not e.getType() instanceof PointerType and + not diffEndBegin(e, c, 2) + ) + or + exists(VariableAccess c, Expr e | + c = err and + outermostConvWithLocation(c.getQualifier(), e) and + e.getType() instanceof PointerType and + not diffEndBegin(e, c, 3) + ) + or + exists(VariableAccess c, Expr e | + c = err and + outermostConvWithLocation(c.getQualifier(), e) and + not e.getType() instanceof PointerType and + not diffEndBegin(e, c, 2) + ) + or + exists(UnaryOperation c, Expr e | + c = err and + outermostConvWithLocation(c.getOperand(), e) and + ( + c instanceof ComplementExpr or + c instanceof NotExpr or + c instanceof UnaryMinusExpr or + c instanceof UnaryPlusExpr or + c instanceof AddressOfExpr + ) and + not diffBeginBegin(c, e, 1) + ) + or + exists(PrefixIncrExpr c, Expr e | + c = err and + outermostConvWithLocation(c.getOperand(), e) and + not diffBeginBegin(c, e, 2) + ) + or + exists(PrefixDecrExpr c, Expr e | + c = err and + outermostConvWithLocation(c.getOperand(), e) and + not diffBeginBegin(c, e, 2) + ) + or + exists(PointerDereferenceExpr c, Expr e | + c = err and + outermostConvWithLocation(c.getChild(0), e) and + not diffBeginBegin(c, e, 1) + ) + or + exists(PostfixIncrExpr c, Expr e | + c = err and + outermostConvWithLocation(c.getOperand(), e) and + not diffEndEnd(e, c, 2) + ) + or + exists(PostfixDecrExpr c, Expr e | + c = err and + outermostConvWithLocation(c.getOperand(), e) and + not diffEndEnd(e, c, 2) + ) ) - select err, "AV Rule 63: Spaces will not be used around '.' or '->', nor between unary operators and operands." +select err, + "AV Rule 63: Spaces will not be used around '.' or '->', nor between unary operators and operands." diff --git a/cpp/ql/src/jsf/4.09 Style/Naming.qll b/cpp/ql/src/jsf/4.09 Style/Naming.qll index 4fa28325969..264a6bac219 100644 --- a/cpp/ql/src/jsf/4.09 Style/Naming.qll +++ b/cpp/ql/src/jsf/4.09 Style/Naming.qll @@ -1,45 +1,44 @@ /* - Common functions for implementing naming conventions - - Naming rules are the following: - - [45] All words in an ident will be separated by '_' - [46] Idents will not rely on significance of more than 64 characters - [47] Idents will not begin with '_' - [48] Idents will not differ in certain confusing ways (listed) - [49] All acronyms in an ident will be uppercase - [50] Classes, namespaces, enums, structs, typedefs: - begin first word with uppercase, all other lowercase - [51] Functions and variables: - lowercase - [52] Constants and enum values: - lowercase - -The tricky rules are: 45, 49, 50, 51, 52. There are two reasons: - - - Reference to 'words'. We ignore this (beyond the scope). For 45, - detect camel-case and any other bad conventions. For 50 this just - means the first letter should be uppercase. - - Acronyms. [49] has a comment that it applies to *all* identifiers, - even if some other rule specified that they should be lowercase or - differently capitalized. - -The strategy is as follows: - - apart from 45, 'words' are just _-separated parts of the identifier - - apart from 49, always allow a 'word' to be entirely in uppercase (URL), - but make sure that the whole identifier is not in uppercase. - - 49: check common acronyms and allow extensibility to check that they are - uppercase. -*/ + * Common functions for implementing naming conventions + * + * Naming rules are the following: + * + * [45] All words in an ident will be separated by '_' + * [46] Idents will not rely on significance of more than 64 characters + * [47] Idents will not begin with '_' + * [48] Idents will not differ in certain confusing ways (listed) + * [49] All acronyms in an ident will be uppercase + * [50] Classes, namespaces, enums, structs, typedefs: + * begin first word with uppercase, all other lowercase + * [51] Functions and variables: + * lowercase + * [52] Constants and enum values: + * lowercase + * + * The tricky rules are: 45, 49, 50, 51, 52. There are two reasons: + * + * - Reference to 'words'. We ignore this (beyond the scope). For 45, + * detect camel-case and any other bad conventions. For 50 this just + * means the first letter should be uppercase. + * - Acronyms. [49] has a comment that it applies to *all* identifiers, + * even if some other rule specified that they should be lowercase or + * differently capitalized. + * + * The strategy is as follows: + * - apart from 45, 'words' are just _-separated parts of the identifier + * - apart from 49, always allow a 'word' to be entirely in uppercase (URL), + * but make sure that the whole identifier is not in uppercase. + * - 49: check common acronyms and allow extensibility to check that they are + * uppercase. + */ import cpp /** The name of an identifier, for the purpose of JSF naming conventions */ class Name extends string { - Name() { - exists(Declaration d | this = d.getName() ) - or exists(Namespace n | this = n.getName() ) + exists(Declaration d | this = d.getName()) or + exists(Namespace n | this = n.getName()) } /** @@ -52,20 +51,18 @@ class Name extends string { * just portions separated by underscores. */ Word getWord(int index) { result = this.splitAt("_", index) } - } /** A (nonempty) word in an identifier, for JSF naming conventions */ class Word extends string { - Word() { exists(Name n | this = n.splitAt("_") and this != "") } /** * Gets the 0-based position of this word in the identifier. */ - int getIndex() { exists (Name n | this = n.getWord(result)) } + int getIndex() { exists(Name n | this = n.getWord(result)) } - /** + /** * Holds if this word is capitalized (for example 'Word', not 'word' * or 'WORD'). */ @@ -98,10 +95,9 @@ class Word extends string { // Don't look at case exists(string s | s = this.toLowerCase() | // A few standard acronyms - s = "url" - or s = "http" - or s = "html" - + s = "url" or + s = "http" or + s = "html" // // // // CUSTOMIZATION: // // ANY ACRONYMS TO ENFORCE IN A PROJECT CAN BE ADDED HERE @@ -109,5 +105,4 @@ class Word extends string { // eg. 'or s = "myacronym"' ) } - -} \ No newline at end of file +} diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql index bfe52e65a65..e0a69c139ea 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 68.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -29,27 +30,24 @@ import cpp */ predicate definesDefaultConstructor(Class c) { - exists(Constructor constr | - constr.getDeclaringType() = c and constr.isDefault()) - or definesDefaultConstructor(c.getABaseClass()) + exists(Constructor constr | constr.getDeclaringType() = c and constr.isDefault()) + or + definesDefaultConstructor(c.getABaseClass()) } predicate definesCopyConstructor(Class c) { - exists(CopyConstructor constr | - constr.getDeclaringType() = c) - or definesCopyConstructor(c.getABaseClass()) + exists(CopyConstructor constr | constr.getDeclaringType() = c) or + definesCopyConstructor(c.getABaseClass()) } predicate definesCopyAssignmentOperator(Class c) { - exists(CopyAssignmentOperator op | - op.getDeclaringType() = c) - or definesCopyAssignmentOperator(c.getABaseClass()) + exists(CopyAssignmentOperator op | op.getDeclaringType() = c) or + definesCopyAssignmentOperator(c.getABaseClass()) } predicate definesDestructor(Class c) { - exists(Destructor op | - op.getDeclaringType() = c) - or definesDestructor(c.getABaseClass()) + exists(Destructor op | op.getDeclaringType() = c) or + definesDestructor(c.getABaseClass()) } class ProperClass extends Class { @@ -61,9 +59,23 @@ class ProperClass extends Class { * and (c) it will be generated (ie for default constructors, if there is any constructor at all then default * constructors will not be generated) */ + from ProperClass c, string msg -where (not definesDefaultConstructor(c) and not c.hasConstructor() and msg="AV Rule 68: class " + c.getName() + " does not need a default constructor and should explicitly disallow it.") or - (not definesCopyConstructor(c) and msg="AV Rule 68: class " + c.getName() + " does not need a copy constructor and should explicitly disallow it.") or - (not definesCopyAssignmentOperator(c) and msg="AV Rule 68: class " + c.getName() + " does not need a copy assignment operator and should explicitly disallow it.") or - (not definesDestructor(c) and msg="AV Rule 68: class " + c.getName() + " does not need a destructor and should explicitly disallow it.") -select c, msg \ No newline at end of file +where + not definesDefaultConstructor(c) and + not c.hasConstructor() and + msg = "AV Rule 68: class " + c.getName() + + " does not need a default constructor and should explicitly disallow it." + or + not definesCopyConstructor(c) and + msg = "AV Rule 68: class " + c.getName() + + " does not need a copy constructor and should explicitly disallow it." + or + not definesCopyAssignmentOperator(c) and + msg = "AV Rule 68: class " + c.getName() + + " does not need a copy assignment operator and should explicitly disallow it." + or + not definesDestructor(c) and + msg = "AV Rule 68: class " + c.getName() + + " does not need a destructor and should explicitly disallow it." +select c, msg diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql index 3f9b23311aa..80fb71103ce 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 69.ql @@ -8,16 +8,23 @@ * @tags maintainability * external/jsf */ + import cpp from MemberFunction mf -where mf.fromSource() and - mf.hasDefinition() and - not mf instanceof Constructor and - not exists(VariableAccess va | va.isLValue() and - va.getEnclosingFunction() = mf and - (va.getTarget() instanceof MemberVariable - or va.getTarget() instanceof GlobalVariable)) and - forall(Call c | c.getEnclosingFunction() = mf | c.isPure()) and - not mf.hasSpecifier("const") -select mf, "AV Rule 69: A member function that does not affect the state of an object will be declared const." \ No newline at end of file +where + mf.fromSource() and + mf.hasDefinition() and + not mf instanceof Constructor and + not exists(VariableAccess va | + va.isLValue() and + va.getEnclosingFunction() = mf and + ( + va.getTarget() instanceof MemberVariable or + va.getTarget() instanceof GlobalVariable + ) + ) and + forall(Call c | c.getEnclosingFunction() = mf | c.isPure()) and + not mf.hasSpecifier("const") +select mf, + "AV Rule 69: A member function that does not affect the state of an object will be declared const." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql index 1e08577217d..e37b8cb6164 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 70.ql @@ -9,18 +9,23 @@ * @tags maintainability * external/jsf */ + import cpp // whether b is the same as a, or b is "const a&" predicate isTypeOrConstRef(Type a, Type b) { - a=b - or exists(ReferenceType r, SpecifiedType s | b=r and s=r.getBaseType() and s.hasSpecifier("const") and a=s.getUnspecifiedType()) + a = b + or + exists(ReferenceType r, SpecifiedType s | + b = r and s = r.getBaseType() and s.hasSpecifier("const") and a = s.getUnspecifiedType() + ) } // whether the first parameter of f may be subject to implicit conversions predicate implicitConvOnFirstParm(Function f) { exists(ImplicitConversionFunction conv | - isTypeOrConstRef(conv.getDestType(), f.getParameter(0).getUnderlyingType())) + isTypeOrConstRef(conv.getDestType(), f.getParameter(0).getUnderlyingType()) + ) } // whether f is declared as a friend by all its parameter types @@ -29,10 +34,14 @@ predicate multiFriend(Function f) { forall(Parameter p | p = f.getAParameter() | exists(FriendDecl fd | fd.getFriend() = f and - p.getType().refersTo(fd.getDeclaringClass()))) + p.getType().refersTo(fd.getDeclaringClass()) + ) + ) } from FriendDecl fd -where not implicitConvOnFirstParm(fd.getFriend()) and - not multiFriend(fd.getFriend()) -select fd, "AV Rule 70: Friend declarations will only be used if the friend is unable to be a member of the class for logical or efficiency reasons." \ No newline at end of file +where + not implicitConvOnFirstParm(fd.getFriend()) and + not multiFriend(fd.getFriend()) +select fd, + "AV Rule 70: Friend declarations will only be used if the friend is unable to be a member of the class for logical or efficiency reasons." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql index c6af8d7ec9d..f325251f6a8 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.1.ql @@ -10,6 +10,7 @@ * language-features * external/jsf */ + import cpp predicate thisCall(FunctionCall c) { @@ -30,44 +31,62 @@ predicate virtualThisCall(FunctionCall c, Function overridingFunction) { predicate nonVirtualMember(MemberFunction mf, Class c) { mf = c.getAMemberFunction() and - not (mf instanceof Constructor) and not (mf instanceof Destructor) and + not mf instanceof Constructor and + not mf instanceof Destructor and not mf.isVirtual() } predicate callFromNonVirtual(MemberFunction source, Class c, MemberFunction targ) { - exists (FunctionCall fc | fc.getEnclosingFunction() = source and fc.getTarget() = targ and thisCall(fc)) and + exists(FunctionCall fc | + fc.getEnclosingFunction() = source and fc.getTarget() = targ and thisCall(fc) + ) and targ = c.getAMemberFunction() and nonVirtualMember(source, c) } pragma[noopt] predicate indirectlyCallsVirtualFunction(MemberFunction caller, Function target, Class c) { - exists (FunctionCall fc | - virtualThisCall(fc,_) and + exists(FunctionCall fc | + virtualThisCall(fc, _) and fc.getEnclosingFunction() = caller and fc.getTarget() = target and nonVirtualMember(caller, c) - ) or - exists (MemberFunction mid | + ) + or + exists(MemberFunction mid | indirectlyCallsVirtualFunction(mid, target, c) and callFromNonVirtual(caller, c, mid) ) } from FunctionCall call, string explanation, Function virtFunction, Function overridingFunction -where (call.getEnclosingFunction() instanceof Constructor or call.getEnclosingFunction() instanceof Destructor) and - ( - (virtualThisCall(call, overridingFunction) and explanation = "Call to virtual function $@ which is overridden in $@. If you intend to statically call this virtual function, it should be qualified with " + virtFunction.getDeclaringType().toString() + "::.") - and virtFunction = call.getTarget() - and overridingFunction.getDeclaringType().getABaseClass+() = call.getEnclosingFunction().getDeclaringType() - or - exists(VirtualFunction target | thisCall(call) and indirectlyCallsVirtualFunction(call.getTarget(), target, _) | - explanation = "Call to function " + call.getTarget().getName() + " that calls virtual function $@ (overridden in $@)." - and virtFunction = target - and overridingFunction = target.getAnOverridingFunction() - and overridingFunction.getDeclaringType().getABaseClass+() = call.getEnclosingFunction().getDeclaringType() - ) - ) -select call, explanation, - virtFunction, virtFunction.getName(), - overridingFunction, overridingFunction.getDeclaringType().getName() +where + ( + call.getEnclosingFunction() instanceof Constructor or + call.getEnclosingFunction() instanceof Destructor + ) and + ( + ( + virtualThisCall(call, overridingFunction) and + explanation = "Call to virtual function $@ which is overridden in $@. If you intend to statically call this virtual function, it should be qualified with " + + virtFunction.getDeclaringType().toString() + "::." + ) and + virtFunction = call.getTarget() and + overridingFunction.getDeclaringType().getABaseClass+() = call + .getEnclosingFunction() + .getDeclaringType() + or + exists(VirtualFunction target | + thisCall(call) and indirectlyCallsVirtualFunction(call.getTarget(), target, _) + | + explanation = "Call to function " + call.getTarget().getName() + + " that calls virtual function $@ (overridden in $@)." and + virtFunction = target and + overridingFunction = target.getAnOverridingFunction() and + overridingFunction.getDeclaringType().getABaseClass+() = call + .getEnclosingFunction() + .getDeclaringType() + ) + ) +select call, explanation, virtFunction, virtFunction.getName(), overridingFunction, + overridingFunction.getDeclaringType().getName() diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql index 6c17af2541a..6533592932d 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 71.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -32,13 +33,16 @@ predicate memberDirectlyNeedsVariable(MemberFunction mf, Class c, MemberVariable (mf.isPublic() or mf.isProtected()) and c = mf.getDeclaringType() and c = mv.getDeclaringType() and - exists(VariableAccess va | va = mv.getAnAccess() and - not exists(Assignment a | va = a.getLValue()) and - va.getEnclosingFunction() = mf) + exists(VariableAccess va | + va = mv.getAnAccess() and + not exists(Assignment a | va = a.getLValue()) and + va.getEnclosingFunction() = mf + ) } predicate memberNeedsVariable(MemberFunction mf, Class c, MemberVariable mv) { - memberDirectlyNeedsVariable(mf, c, mv) or + memberDirectlyNeedsVariable(mf, c, mv) + or exists(MemberFunction mf2 | memberNeedsVariable(mf2, c, mv) and mf.getDeclaringType() = c and @@ -59,7 +63,8 @@ predicate memberDirectlyInitialisesVariable(MemberFunction mf, Class c, MemberVa } predicate memberInitialisesVariable(MemberFunction mf, Class c, MemberVariable mv) { - memberDirectlyInitialisesVariable(mf, c, mv) or + memberDirectlyInitialisesVariable(mf, c, mv) + or exists(MemberFunction mf2 | memberDirectlyInitialisesVariable(_, c, mv) and // (optimizer hint) memberInitialisesVariable(mf2, c, mv) and @@ -80,14 +85,14 @@ predicate preInitialises(Constructor c, MemberVariable mv) { predicate exprInitialises(Constructor c, ControlFlowNode cf, MemberVariable mv) { cf.getControlFlowScope() = c and ( - cf.(Assignment).getLValue() = mv.getAnAccess() - or memberInitialisesVariable(cf.(FunctionCall).getTarget(), c.getDeclaringType(), mv) + cf.(Assignment).getLValue() = mv.getAnAccess() or + memberInitialisesVariable(cf.(FunctionCall).getTarget(), c.getDeclaringType(), mv) ) } predicate initialises(Constructor c, MemberVariable mv) { - exprInitialises(c, _, mv) - or preInitialises(c, mv) + exprInitialises(c, _, mv) or + preInitialises(c, mv) } predicate doesNotInitialise(Constructor c, MemberVariable mv) { @@ -102,14 +107,14 @@ predicate doesNotInitialise(Constructor c, MemberVariable mv) { */ predicate reachableWithoutInitialising(Constructor c, ControlFlowNode cf, MemberVariable mv) { - not (preInitialises(c, mv)) - and + not preInitialises(c, mv) and ( - cf = c.getBlock() or + cf = c.getBlock() + or exists(ControlFlowNode mid | - reachableWithoutInitialising(c, mid, mv) and - cf = mid.getASuccessor() and - not exprInitialises(c, cf, mv) + reachableWithoutInitialising(c, mid, mv) and + cf = mid.getASuccessor() and + not exprInitialises(c, cf, mv) ) ) } @@ -124,6 +129,10 @@ predicate badCall(Constructor c, FunctionCall call, MemberVariable mv) { */ from Element e, MemberVariable mv, string message -where (doesNotInitialise(e, mv) and message = "Constructor does not initialize member variable " + mv.getName() + ".") or - (badCall(_, e, mv) and message = "Constructor calls function using " + mv.getName() + " before it is initialized.") -select e, "AV Rule 71: " + message \ No newline at end of file +where + doesNotInitialise(e, mv) and + message = "Constructor does not initialize member variable " + mv.getName() + "." + or + badCall(_, e, mv) and + message = "Constructor calls function using " + mv.getName() + " before it is initialized." +select e, "AV Rule 71: " + message diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql index db98e854921..7bbfc2a0a5e 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 73.ql @@ -8,31 +8,43 @@ * @tags maintainability * external/jsf */ + import cpp -/* bug finding approach: look for no-argument constructors that set a certain field x, +/* + * bug finding approach: look for no-argument constructors that set a certain field x, * such that every member function reading x also contains a comparison involving x as * part of an if statement; the host class should not be used in an array type or as * part of an array new, it should not be used in a template instantiation, and it should - * not be a virtual base class */ + * not be a virtual base class + */ from Constructor c, MemberVariable f -where c.fromSource() and - c.isDefault() and - not c.isCompilerGenerated() and - f = c.getAWrittenVariable() and - forall(MemberFunction m, VariableAccess va | - va = f.getAnAccess() and - m = va.getEnclosingFunction() and - not m instanceof Constructor and - not va.getEnclosingStmt() instanceof IfStmt | - exists(VariableAccess va2 | va2 = f.getAnAccess() and m = va2.getEnclosingFunction() | - va != va2 and - va2.getEnclosingStmt() instanceof IfStmt)) and - not (exists(ArrayType at | at.getBaseType+() = c.getDeclaringType()) - or - exists(NewArrayExpr nae | nae.getType().(ArrayType).getBaseType+() = c.getDeclaringType()) - or - exists(ClassDerivation cd | cd.hasSpecifier("virtual") and cd.getBaseClass() = c.getDeclaringType())) -select c, "This default constructor possibly doesn't put the object in a usable state, indicated by the member variable $@.", +where + c.fromSource() and + c.isDefault() and + not c.isCompilerGenerated() and + f = c.getAWrittenVariable() and + forall(MemberFunction m, VariableAccess va | + va = f.getAnAccess() and + m = va.getEnclosingFunction() and + not m instanceof Constructor and + not va.getEnclosingStmt() instanceof IfStmt + | + exists(VariableAccess va2 | va2 = f.getAnAccess() and m = va2.getEnclosingFunction() | + va != va2 and + va2.getEnclosingStmt() instanceof IfStmt + ) + ) and + not ( + exists(ArrayType at | at.getBaseType+() = c.getDeclaringType()) + or + exists(NewArrayExpr nae | nae.getType().(ArrayType).getBaseType+() = c.getDeclaringType()) + or + exists(ClassDerivation cd | + cd.hasSpecifier("virtual") and cd.getBaseClass() = c.getDeclaringType() + ) + ) +select c, + "This default constructor possibly doesn't put the object in a usable state, indicated by the member variable $@.", f, f.toString() diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql index d0ec52033c1..2a969016909 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 74.ql @@ -9,13 +9,16 @@ * @tags correctness * external/jsf */ + import cpp // find assignment to non-static member variable in constructor, where that variable is // not also initialised through the member initialisation list from Assignment ass, Field mv, Constructor ctor -where ass.getEnclosingFunction() = ctor and - mv.getDeclaringType() = ctor.getDeclaringType() and - ass.getLValue().(Access).getTarget() = mv and - not exists(ConstructorFieldInit cfi | cfi = ctor.getAnInitializer() | cfi.getTarget() = mv) -select ass, "AV Rule 74: Nonstatic members will be initialized through the member initialization list, not through assignment." \ No newline at end of file +where + ass.getEnclosingFunction() = ctor and + mv.getDeclaringType() = ctor.getDeclaringType() and + ass.getLValue().(Access).getTarget() = mv and + not exists(ConstructorFieldInit cfi | cfi = ctor.getAnInitializer() | cfi.getTarget() = mv) +select ass, + "AV Rule 74: Nonstatic members will be initialized through the member initialization list, not through assignment." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql index c16f09dbb93..eb3af502d26 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 75.ql @@ -8,8 +8,10 @@ * readability * external/jsf */ + import cpp from Diagnostic d where d.hasTag("out_of_order_ctor_init") -select d, "AV Rule 75: Members of the initialization list shall be listed in the order in which they are declared in the class." +select d, + "AV Rule 75: Members of the initialization list shall be listed in the order in which they are declared in the class." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql index b065b75aed3..d9be1b9901e 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 76.ql @@ -7,35 +7,41 @@ * @tags maintainability * external/jsf */ + import cpp predicate hasPointerMember(Class c) { // Note: any function pointers are fine - exists (MemberVariable v, Type t | + exists(MemberVariable v, Type t | v.getDeclaringType() = c and t = v.getType().getUnderlyingType() and (t instanceof PointerType or t instanceof PointerToMemberType) and - not (t instanceof FunctionPointerType) and + not t instanceof FunctionPointerType and not t.(PointerToMemberType).getBaseType() instanceof RoutineType ) } class TrivialStmt extends Stmt { - TrivialStmt() { - this instanceof EmptyStmt - or this instanceof ReturnStmt and not this.(ReturnStmt).hasExpr() - } + TrivialStmt() { + this instanceof EmptyStmt + or + this instanceof ReturnStmt and not this.(ReturnStmt).hasExpr() + } } // What is a nontrivial destructor? JSF is unclear about that. We'll just // take any nonempty destructor as nontrivial. Exclude the generated 'return' stmt predicate hasNontrivialDestructor(Class c) { - exists (Stmt s | s = c.getDestructor().getBlock().getAStmt() | not s instanceof TrivialStmt) + exists(Stmt s | s = c.getDestructor().getBlock().getAStmt() | not s instanceof TrivialStmt) } from Class c -where (hasPointerMember(c) or hasNontrivialDestructor(c)) and - not (c.getAMemberFunction() instanceof CopyConstructor and - c.getAMemberFunction() instanceof CopyAssignmentOperator) and - not (c instanceof Struct) -select c, "AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors." +where + (hasPointerMember(c) or hasNontrivialDestructor(c)) and + not ( + c.getAMemberFunction() instanceof CopyConstructor and + c.getAMemberFunction() instanceof CopyAssignmentOperator + ) and + not c instanceof Struct +select c, + "AV Rule 76: A copy constructor and an assignment operator shall be declared for classes that contain pointers to data items or nontrivial destructors." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql index 458616eea8c..a3212dedb18 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 77.1.ql @@ -10,9 +10,13 @@ * language-features * external/jsf */ + import cpp from CopyConstructor f -where f.getNumberOfParameters() > 1 - and not f.mayNotBeCopyConstructorInInstantiation() -select f, f.getName() + " is signature-compatible with a copy constructor when its default arguments are taken into account." +where + f.getNumberOfParameters() > 1 and + not f.mayNotBeCopyConstructorInInstantiation() +select f, + f.getName() + + " is signature-compatible with a copy constructor when its default arguments are taken into account." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql index e20f1f81147..727155dc9dd 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 78.ql @@ -9,6 +9,7 @@ * language-features * external/jsf */ + import cpp /* @@ -17,10 +18,13 @@ import cpp */ from Class c -where exists(VirtualFunction f | f.getDeclaringType() = c) - and exists(Destructor d | d.getDeclaringType() = c and - not d.isVirtual() and - not d.isDeleted() and - not d.isCompilerGenerated()) - and exists(ClassDerivation d | d.getBaseClass() = c) +where + exists(VirtualFunction f | f.getDeclaringType() = c) and + exists(Destructor d | + d.getDeclaringType() = c and + not d.isVirtual() and + not d.isDeleted() and + not d.isCompilerGenerated() + ) and + exists(ClassDerivation d | d.getBaseClass() = c) select c, "Base classes with a virtual function must define a virtual destructor." 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 99c8ab4bfe7..4b1f45185d1 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,6 +10,7 @@ * external/cwe/cwe-404 * external/jsf */ + import cpp import Critical.NewDelete @@ -21,22 +22,20 @@ predicate acquireExpr(Expr acquire, string kind) { exists(FunctionCall fc, Function f, string name | fc = acquire and f = fc.getTarget() and - f.hasGlobalName(name) and + f.hasGlobalName(name) and ( - ( - name = "fopen" and - kind = "file" - ) or ( - name = "open" and - kind = "file descriptor" - ) or ( - name = "socket" and - kind = "file descriptor" - ) + name = "fopen" and + kind = "file" + or + name = "open" and + kind = "file descriptor" + or + name = "socket" and + kind = "file descriptor" ) - ) or ( - allocExpr(acquire, kind) ) + or + allocExpr(acquire, kind) } /** @@ -47,31 +46,29 @@ predicate releaseExpr(Expr release, Expr resource, string kind) { exists(FunctionCall fc, Function f, string name | fc = release and f = fc.getTarget() and - f.hasGlobalName(name) and + f.hasGlobalName(name) and ( - ( - name = "fclose" and - resource = fc.getArgument(0) and - kind = "file" - ) or ( - name = "close" and - resource = fc.getArgument(0) and - kind = "file descriptor" - ) + 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 | + ) + 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[]" - ) + kind = "malloc" and + releaseKind = "free" + or + kind = "new" and + releaseKind = "delete" + or + kind = "new[]" and + releaseKind = "delete[]" ) ) } @@ -90,10 +87,10 @@ Expr exprOrDereference(Expr e) { * or via one or more function call(s). */ private predicate exprReleases(Expr e, Expr released, string kind) { - ( - // `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 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 ( @@ -102,7 +99,9 @@ private predicate exprReleases(Expr e, Expr released, string kind) { ) and e.(FunctionCall).getArgument(arg) = released and exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), kind) - ) or exists(Function f, ThisExpr innerThis | + ) + or + exists(Function f, ThisExpr innerThis | // `e` is a call to a method that releases `this`, and `released` // is the object that is called ( @@ -116,7 +115,6 @@ private predicate exprReleases(Expr e, Expr released, string kind) { } class Resource extends MemberVariable { - Resource() { not isStatic() } // Check that an expr is somewhere in this class - does not have to be a constructor @@ -125,19 +123,18 @@ class Resource extends MemberVariable { } private predicate calledFromDestructor(Function f) { - (f instanceof Destructor and f.getDeclaringType() = this.getDeclaringType()) + f instanceof Destructor and f.getDeclaringType() = this.getDeclaringType() or exists(Function mid, FunctionCall fc | calledFromDestructor(mid) and fc.getEnclosingFunction() = mid and fc.getTarget() = f and - f.getDeclaringType() = this.getDeclaringType()) + f.getDeclaringType() = this.getDeclaringType() + ) } predicate inDestructor(Expr e) { - exists(Function f | f = e.getEnclosingFunction() | - calledFromDestructor(f) - ) + exists(Function f | f = e.getEnclosingFunction() | calledFromDestructor(f)) } predicate acquisitionWithRequiredKind(Assignment acquireAssign, string kind) { @@ -149,41 +146,38 @@ class Resource extends MemberVariable { acquireExpr(acquireAssign.getRValue(), kind) } - Expr getAReleaseExpr(string kind) { - exprReleases(result, this.getAnAccess(), kind) - } + Expr getAReleaseExpr(string kind) { exprReleases(result, this.getAnAccess(), kind) } } predicate unreleasedResource(Resource r, Expr acquire, File f, int acquireLine) { - // Note: there could be several release functions, because there could be - // several functions called 'fclose' for example. We want to check that - // *none* of these functions are called to release the resource - r.acquisitionWithRequiredKind(acquire, _) and - not exists(Expr releaseExpr, string kind | - r.acquisitionWithRequiredKind(acquire, kind) and - releaseExpr = r.getAReleaseExpr(kind) and - r.inDestructor(releaseExpr) - ) - and f = acquire.getFile() - and acquireLine = acquire.getLocation().getStartLine() - - and not exists(ExprCall exprCall | - // expression call (function pointer or lambda) with `r` as an - // argument, which could release it. - exprCall.getAnArgument() = r.getAnAccess() and - r.inDestructor(exprCall) - ) - - // check that any destructor for this class has a block; if it doesn't, - // we must be missing information. - and forall(Class c, Destructor d | - r.getDeclaringType().isConstructedFrom*(c) and - d = c.getAMember() and - not d.isCompilerGenerated() and - not d.isDefaulted() and - not d.isDeleted() | - exists(d.getBlock()) - ) + // Note: there could be several release functions, because there could be + // several functions called 'fclose' for example. We want to check that + // *none* of these functions are called to release the resource + r.acquisitionWithRequiredKind(acquire, _) and + not exists(Expr releaseExpr, string kind | + r.acquisitionWithRequiredKind(acquire, kind) and + releaseExpr = r.getAReleaseExpr(kind) and + r.inDestructor(releaseExpr) + ) and + f = acquire.getFile() and + acquireLine = acquire.getLocation().getStartLine() and + not exists(ExprCall exprCall | + // expression call (function pointer or lambda) with `r` as an + // argument, which could release it. + exprCall.getAnArgument() = r.getAnAccess() and + r.inDestructor(exprCall) + ) and + // check that any destructor for this class has a block; if it doesn't, + // we must be missing information. + forall(Class c, Destructor d | + r.getDeclaringType().isConstructedFrom*(c) and + d = c.getAMember() and + not d.isCompilerGenerated() and + not d.isDefaulted() and + not d.isDeleted() + | + exists(d.getBlock()) + ) } predicate freedInSameMethod(Resource r, Expr acquire) { @@ -210,14 +204,18 @@ predicate leakedInSameMethod(Resource r, Expr acquire) { // near to where it's acquired, and might be stored elsewhere. fc.getAnArgument().getAChild*() = r.getAnAccess() and fc.getEnclosingFunction() = f - ) or exists(Variable v, Expr e | + ) + or + exists(Variable v, Expr e | // `r` (or something computed from it) is stored in another variable // near to where it's acquired, and might be released through that // variable. v.getAnAssignedValue() = e and e.getAChild*() = r.getAnAccess() and e.getEnclosingFunction() = f - ) or exists(FunctionCall fc | + ) + or + exists(FunctionCall fc | // `this` (i.e. the class where `r` is acquired) is passed into `r` via a // method, or the constructor. `r` may use this to register itself with // `this` in some way, ensuring it is later deleted. @@ -228,7 +226,9 @@ predicate leakedInSameMethod(Resource r, Expr acquire) { fc = acquire.getAChild*() // e.g. `r = new MyClass(this)` ) ) - ) or exists(FunctionAccess fa, string kind | + ) + or + exists(FunctionAccess fa, string kind | // the address of a function that releases `r` is taken (and likely // used to release `r` at some point). r.acquisitionWithRequiredKind(acquire, kind) and @@ -237,10 +237,10 @@ predicate leakedInSameMethod(Resource r, Expr acquire) { ) } -pragma[noopt] predicate badRelease(Resource r, Expr acquire, Function functionCallingRelease, int line) { +pragma[noopt] +predicate badRelease(Resource r, Expr acquire, Function functionCallingRelease, int line) { unreleasedResource(r, acquire, _, _) and - exists(Expr releaseExpr, string kind, - Location releaseExprLocation, Function acquireFunction | + exists(Expr releaseExpr, string kind, Location releaseExprLocation, Function acquireFunction | r.acquisitionWithRequiredKind(acquire, kind) and releaseExpr = r.getAReleaseExpr(kind) and releaseExpr.getEnclosingFunction() = functionCallingRelease and @@ -253,7 +253,9 @@ pragma[noopt] predicate badRelease(Resource r, Expr acquire, Function functionCa } Class qtObject() { result.getABaseClass*().hasGlobalName("QObject") } + PointerType qtObjectReference() { result.getBaseType() = qtObject() } + Constructor qtParentConstructor() { exists(Parameter p | p.getName() = "parent" and @@ -263,8 +265,7 @@ Constructor qtParentConstructor() { ) } -predicate automaticallyReleased(Assignment acquire) -{ +predicate automaticallyReleased(Assignment acquire) { // sub-types of the Qt type QObject are released by their parent (if they have one) exists(NewExpr alloc | alloc.getAllocatedType() = qtObject() and @@ -274,22 +275,24 @@ predicate automaticallyReleased(Assignment acquire) } from Resource r, Expr acquire, File f, string message -where unreleasedResource(r, acquire, f, _) and - not freedInSameMethod(r, acquire) and - not leakedInSameMethod(r, acquire) and - ( - exists(Function releaseFunction, int releaseLine | badRelease(r, acquire, releaseFunction, releaseLine) and - message = - "Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() + - " but not released in the destructor. It is released from " + releaseFunction.getName() + " on line " + releaseLine + +where + unreleasedResource(r, acquire, f, _) and + not freedInSameMethod(r, acquire) and + not leakedInSameMethod(r, acquire) and + ( + exists(Function releaseFunction, int releaseLine | + badRelease(r, acquire, releaseFunction, releaseLine) and + message = "Resource " + r.getName() + " is acquired by class " + + r.getDeclaringType().getName() + + " but not released in the destructor. It is released from " + releaseFunction.getName() + + " on line " + releaseLine + ", so this function may need to be called from the destructor." - ) - or - ( - not badRelease(r, _, _, _) and - message = "Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() + " but not released anywhere in this class." - ) - ) and - not automaticallyReleased(acquire) and - not r.getDeclaringType() instanceof TemplateClass // template classes may contain insufficient information for this analysis; results from instantiations will usually suffice. + ) + or + not badRelease(r, _, _, _) and + message = "Resource " + r.getName() + " is acquired by class " + r.getDeclaringType().getName() + + " but not released anywhere in this class." + ) and + not automaticallyReleased(acquire) and + not r.getDeclaringType() instanceof TemplateClass // template classes may contain insufficient information for this analysis; results from instantiations will usually suffice. select acquire, message diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql index d0f90e7c770..5a8df7fc625 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 81.ql @@ -8,6 +8,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -18,18 +19,21 @@ import cpp * Hopefully correct implementations also pass, but 'cunning' implementations may not. */ -/** A copy assignment operator taking its parameter by reference. - * For our purposes, copy assignment operators taking parameters by - * value are likely fine, since the copy already happened - */ +/** + * A copy assignment operator taking its parameter by reference. + * For our purposes, copy assignment operators taking parameters by + * value are likely fine, since the copy already happened + */ class ReferenceCopyAssignmentOperator extends MemberFunction { ReferenceCopyAssignmentOperator() { this.getName() = "operator=" and this.getNumberOfParameters() = 1 and - exists (ReferenceType rt | + exists(ReferenceType rt | rt = this.getParameter(0).getType() and - (rt.getBaseType() = this.getDeclaringType() or - rt.getBaseType().(SpecifiedType).getBaseType() = this.getDeclaringType()) + ( + rt.getBaseType() = this.getDeclaringType() or + rt.getBaseType().(SpecifiedType).getBaseType() = this.getDeclaringType() + ) ) } @@ -45,10 +49,11 @@ class ReferenceCopyAssignmentOperator extends MemberFunction { ) } - /** A call to a function called swap. Note: could be a member, - * std::swap or a function overloading std::swap (not in std::) - * so keep it simple - */ + /** + * A call to a function called swap. Note: could be a member, + * std::swap or a function overloading std::swap (not in std::) + * so keep it simple + */ FunctionCall getASwapCall() { result.getEnclosingFunction() = this and result.getTarget().getName() = "swap" @@ -57,25 +62,28 @@ class ReferenceCopyAssignmentOperator extends MemberFunction { /** A call to delete on a member variable */ DeleteExpr getADeleteExpr() { result.getEnclosingFunction() = this and - result.getExpr().(VariableAccess).getTarget().(MemberVariable).getDeclaringType() = this.getDeclaringType() + result.getExpr().(VariableAccess).getTarget().(MemberVariable).getDeclaringType() = this + .getDeclaringType() } - } -/** Test whether a class has a resource that needs management. Value class types are - * okay because they get their semantics from their assignment operator. Primitive - * types are fine (no management needed). Constant and reference values are okay too - * (they can't be changed anyway). All that remains are pointer types. - */ +/** + * Test whether a class has a resource that needs management. Value class types are + * okay because they get their semantics from their assignment operator. Primitive + * types are fine (no management needed). Constant and reference values are okay too + * (they can't be changed anyway). All that remains are pointer types. + */ predicate hasResource(Class c) { - exists (MemberVariable mv | + exists(MemberVariable mv | mv.getDeclaringType() = c and - mv.getType() instanceof PointerType) + mv.getType() instanceof PointerType + ) } from ReferenceCopyAssignmentOperator op -where hasResource(op.getDeclaringType()) - and not exists(op.getASelfEqualityTest()) - and not exists(op.getASwapCall()) - and exists(op.getADeleteExpr()) +where + hasResource(op.getDeclaringType()) and + not exists(op.getASelfEqualityTest()) and + not exists(op.getASwapCall()) and + exists(op.getADeleteExpr()) select op, "AV Rule 81: The assignment operator shall handle self-assignment correctly." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql index c76226ae30a..84200a8b5e9 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql @@ -10,6 +10,7 @@ * language-features * external/jsf */ + import cpp /* @@ -18,35 +19,31 @@ import cpp predicate callOnThis(FunctionCall fc) { // `this->f(...)` - fc.getQualifier() instanceof ThisExpr or - + fc.getQualifier() instanceof ThisExpr + or // `(*this).f(...)` fc.getQualifier().(PointerDereferenceExpr).getChild(0) instanceof ThisExpr } predicate pointerThis(Expr e) { - e instanceof ThisExpr or - + e instanceof ThisExpr + or // `f(...)` // (includes `this = ...`, where `=` is overloaded so a `FunctionCall`) - exists(FunctionCall fc | fc = e and callOnThis(fc) | - returnsPointerThis(fc.getTarget()) - ) or - - // `this = ...` (where `=` is not overloaded, so an `AssignExpr`) + exists(FunctionCall fc | fc = e and callOnThis(fc) | returnsPointerThis(fc.getTarget())) + or + // `this = ...` (where `=` is not overloaded, so an `AssignExpr`) pointerThis(e.(AssignExpr).getLValue()) } predicate dereferenceThis(Expr e) { - pointerThis(e.(PointerDereferenceExpr).getChild(0)) or - + pointerThis(e.(PointerDereferenceExpr).getChild(0)) + or // `f(...)` // (includes `*this = ...`, where `=` is overloaded so a `FunctionCall`) - exists(FunctionCall fc | fc = e and callOnThis(fc) | - returnsDereferenceThis(fc.getTarget()) - ) or - - // `*this = ...` (where `=` is not overloaded, so an `AssignExpr`) + exists(FunctionCall fc | fc = e and callOnThis(fc) | returnsDereferenceThis(fc.getTarget())) + or + // `*this = ...` (where `=` is not overloaded, so an `AssignExpr`) dereferenceThis(e.(AssignExpr).getLValue()) } @@ -74,25 +71,28 @@ predicate returnsDereferenceThis(Function f) { } predicate assignOperatorWithWrongType(Operator op, string msg) { - op.hasName("operator=") - and exists(op.getBlock()) - and exists(Class c | - c = op.getDeclaringType() - and op.getUnspecifiedType() = c - and msg = "Assignment operator in class " + c.getName() + " should have return type " + c.getName() + "&. Otherwise a copy is created at each call." + op.hasName("operator=") and + exists(op.getBlock()) and + exists(Class c | + c = op.getDeclaringType() and + op.getUnspecifiedType() = c and + msg = "Assignment operator in class " + c.getName() + " should have return type " + c.getName() + + "&. Otherwise a copy is created at each call." ) } predicate assignOperatorWithWrongResult(Operator op, string msg) { - op.hasName("operator=") - and not returnsDereferenceThis(op) - and exists(op.getBlock()) - and not op.getType() instanceof VoidType - and not assignOperatorWithWrongType(op, _) - and msg = "Assignment operator in class " + op.getDeclaringType().getName() + " does not return a reference to *this." + op.hasName("operator=") and + not returnsDereferenceThis(op) and + exists(op.getBlock()) and + not op.getType() instanceof VoidType and + not assignOperatorWithWrongType(op, _) and + msg = "Assignment operator in class " + op.getDeclaringType().getName() + + " does not return a reference to *this." } from Operator op, string msg -where assignOperatorWithWrongType(op, msg) - or assignOperatorWithWrongResult(op, msg) +where + assignOperatorWithWrongType(op, msg) or + assignOperatorWithWrongResult(op, msg) select op, msg diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql index 2caaa78fb9b..dcfaf06f49b 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 85.ql @@ -8,13 +8,17 @@ * reliability * external/jsf */ + import cpp predicate oppositeOperators(string op1, string op2) { - op1="operator<" and op2="operator>=" - or op1="operator<=" and op2="operator>" - or op1="operator==" and op2="operator!=" - or oppositeOperators(op2, op1) + op1 = "operator<" and op2 = "operator>=" + or + op1 = "operator<=" and op2 = "operator>" + or + op1 = "operator==" and op2 = "operator!=" + or + oppositeOperators(op2, op1) } /** @@ -31,12 +35,18 @@ predicate implementedAsNegationOf(Operator op1, Operator op2) { n = r.getExpr() and o = n.getOperand() and ( - o instanceof LTExpr and op2.hasName("operator<") or - o instanceof LEExpr and op2.hasName("operator<=") or - o instanceof GTExpr and op2.hasName("operator>") or - o instanceof GEExpr and op2.hasName("operator>=") or - o instanceof EQExpr and op2.hasName("operator==") or - o instanceof NEExpr and op2.hasName("operator!=") or + o instanceof LTExpr and op2.hasName("operator<") + or + o instanceof LEExpr and op2.hasName("operator<=") + or + o instanceof GTExpr and op2.hasName("operator>") + or + o instanceof GEExpr and op2.hasName("operator>=") + or + o instanceof EQExpr and op2.hasName("operator==") + or + o instanceof NEExpr and op2.hasName("operator!=") + or o.(FunctionCall).getTarget() = op2 ) ) @@ -49,25 +59,32 @@ predicate classIsCheckableFor(Class c, string op) { // Member functions of templates are not necessarily instantiated, so // if the function we want to check exists, then make sure that its // body also exists - ((c instanceof TemplateClass) - implies - forall(Function f | f = c.getAMember() and f.hasName(op) - | exists(f.getEntryPoint()))) + ( + c instanceof TemplateClass + implies + forall(Function f | f = c.getAMember() and f.hasName(op) | exists(f.getEntryPoint())) + ) } from Class c, string op, string opp, Operator rator -where c.fromSource() and - oppositeOperators(op, opp) and - classIsCheckableFor(c, op) and - classIsCheckableFor(c, opp) and - rator = c.getAMember() and - rator.hasName(op) and - forex(Operator aRator | - aRator = c.getAMember() and aRator.hasName(op) | - not exists(Operator oprator | - oprator = c.getAMember() and - oprator.hasName(opp) and - ( implementedAsNegationOf(aRator, oprator) - or implementedAsNegationOf(oprator, aRator)))) -select c, "When two operators are opposites, both should be defined and one should be defined in terms of the other. Operator " + op + - " is declared on line " + rator.getLocation().getStartLine().toString() + ", but it is not defined in terms of its opposite operator " + opp + "." +where + c.fromSource() and + oppositeOperators(op, opp) and + classIsCheckableFor(c, op) and + classIsCheckableFor(c, opp) and + rator = c.getAMember() and + rator.hasName(op) and + forex(Operator aRator | aRator = c.getAMember() and aRator.hasName(op) | + not exists(Operator oprator | + oprator = c.getAMember() and + oprator.hasName(opp) and + ( + implementedAsNegationOf(aRator, oprator) or + implementedAsNegationOf(oprator, aRator) + ) + ) + ) +select c, + "When two operators are opposites, both should be defined and one should be defined in terms of the other. Operator " + + op + " is declared on line " + rator.getLocation().getStartLine().toString() + + ", but it is not defined in terms of its opposite operator " + opp + "." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql index 90efc3cba0f..7822ac6e32f 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.1.ql @@ -7,12 +7,15 @@ * @tags maintainability * external/jsf */ + import cpp -predicate derivesVirtual(Class c, Class base) -{ - exists(ClassDerivation d | d.getDerivedClass() = c and d.getBaseClass() = base - and d.hasSpecifier("virtual")) +predicate derivesVirtual(Class c, Class base) { + exists(ClassDerivation d | + d.getDerivedClass() = c and + d.getBaseClass() = base and + d.hasSpecifier("virtual") + ) } predicate derivesVirtualStar(Class c, Class base) { @@ -20,7 +23,8 @@ predicate derivesVirtualStar(Class c, Class base) { } from Class c, Class base -where c.getABaseClass+() = base - and derivesVirtualStar(c, base) - and not derivesVirtual(c, base) +where + c.getABaseClass+() = base and + derivesVirtualStar(c, base) and + not derivesVirtual(c, base) select c, "AV Rule 88.1: The virtual base " + base.getName() + " shall be explicitly declared." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql index 655b79aa7f4..a8d87cbc3fc 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 88.ql @@ -9,6 +9,7 @@ * readability * external/jsf */ + import cpp /** @@ -24,35 +25,62 @@ import cpp */ class InterfaceClass extends Class { InterfaceClass() { - exists(MemberFunction m | m.getDeclaringType() = this and not compgenerated(unresolveElement(m))) - and - forall(MemberFunction m | m.getDeclaringType() = this and not compgenerated(unresolveElement(m)) | m instanceof PureVirtualFunction) - and - count(MemberVariable v | v.getDeclaringType() = this) < 3 + exists(MemberFunction m | + m.getDeclaringType() = this and not compgenerated(unresolveElement(m)) + ) and + forall(MemberFunction m | + m.getDeclaringType() = this and not compgenerated(unresolveElement(m)) + | + m instanceof PureVirtualFunction + ) and + count(MemberVariable v | v.getDeclaringType() = this) < 3 } } class InterfaceImplementor extends Class { InterfaceImplementor() { - exists(ClassDerivation d | d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass) + exists(ClassDerivation d | + d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass + ) } + int getNumInterfaces() { - result = count(ClassDerivation d | d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass) + result = count(ClassDerivation d | + d.getDerivedClass() = this and d.getBaseClass() instanceof InterfaceClass + ) } + int getNumProtectedImplementations() { - result = count(ClassDerivation d | d.hasSpecifier("protected") and d.getDerivedClass() = this and not d.getBaseClass() instanceof InterfaceClass) + result = count(ClassDerivation d | + d.hasSpecifier("protected") and + d.getDerivedClass() = this and + not d.getBaseClass() instanceof InterfaceClass + ) } + int getNumPrivateImplementations() { - result = count(ClassDerivation d | d.hasSpecifier("private") and d.getDerivedClass() = this and not d.getBaseClass() instanceof InterfaceClass) + result = count(ClassDerivation d | + d.hasSpecifier("private") and + d.getDerivedClass() = this and + not d.getBaseClass() instanceof InterfaceClass + ) } + int getNumPublicImplementations() { - result = count(ClassDerivation d | d.hasSpecifier("public") and d.getDerivedClass() = this and not d.getBaseClass() instanceof InterfaceClass) + result = count(ClassDerivation d | + d.hasSpecifier("public") and + d.getDerivedClass() = this and + not d.getBaseClass() instanceof InterfaceClass + ) } } from InterfaceImplementor d -where d.getNumPublicImplementations() > 0 - or d.getNumProtectedImplementations() > 1 -select d, "Multiple inheritance should not be used with " + d.getNumInterfaces().toString() - + " interfaces, " + d.getNumPrivateImplementations().toString() + " private implementations, " + d.getNumProtectedImplementations().toString() + " protected implementations, and " - + d.getNumPublicImplementations().toString() + " public implementations." +where + d.getNumPublicImplementations() > 0 or + d.getNumProtectedImplementations() > 1 +select d, + "Multiple inheritance should not be used with " + d.getNumInterfaces().toString() + + " interfaces, " + d.getNumPrivateImplementations().toString() + " private implementations, " + + d.getNumProtectedImplementations().toString() + " protected implementations, and " + + d.getNumPublicImplementations().toString() + " public implementations." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql index 53d6b95b011..d5d5100b3af 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 89.ql @@ -9,22 +9,33 @@ * readability * external/jsf */ + import cpp predicate derivesVirtual(Class c, Class base) { - exists(ClassDerivation d | d.getDerivedClass() = c and d.getBaseClass() = base - and d.hasSpecifier("virtual")) - or derivesVirtual(c.getABaseClass(), base) + exists(ClassDerivation d | + d.getDerivedClass() = c and + d.getBaseClass() = base and + d.hasSpecifier("virtual") + ) + or + derivesVirtual(c.getABaseClass(), base) } predicate derivesNonVirtual(Class c, Class base) { - exists(ClassDerivation d | d.getDerivedClass() = c and d.getBaseClass() = base - and not d.hasSpecifier("virtual")) - or derivesNonVirtual(c.getABaseClass(), base) + exists(ClassDerivation d | + d.getDerivedClass() = c and + d.getBaseClass() = base and + not d.hasSpecifier("virtual") + ) + or + derivesNonVirtual(c.getABaseClass(), base) } from Class c, Class base -where c.getABaseClass+() = base - and derivesVirtual(c, base) - and derivesNonVirtual(c, base) -select c, "AV Rule 89: The base class " + base.getName() + " is derived both virtual and non-virtual." +where + c.getABaseClass+() = base and + derivesVirtual(c, base) and + derivesNonVirtual(c, base) +select c, + "AV Rule 89: The base class " + base.getName() + " is derived both virtual and non-virtual." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql index 68b6c7fd506..5af7892afc4 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 94.ql @@ -7,13 +7,17 @@ * @tags maintainability * external/jsf */ + import cpp from MemberFunction f1, MemberFunction f2 -where f1 != f2 - and not (f1 instanceof VirtualFunction) - and not (f2 instanceof VirtualFunction) - and f1.getDeclaringType().getABaseClass+() = f2.getDeclaringType() - and f1.getName() = f2.getName() - and forall(Parameter p1, Parameter p2, int i | f1.getParameter(i) = p1 and f2.getParameter(i) = p2 | p1.getType() = p2.getType() ) +where + f1 != f2 and + not f1 instanceof VirtualFunction and + not f2 instanceof VirtualFunction and + f1.getDeclaringType().getABaseClass+() = f2.getDeclaringType() and + f1.getName() = f2.getName() and + forall(Parameter p1, Parameter p2, int i | f1.getParameter(i) = p1 and f2.getParameter(i) = p2 | + p1.getType() = p2.getType() + ) select f1, "AV Rule 94: An inherited nonvirtual function shall not be redefined in a derived class." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql index 405c90c1991..2e8a67587f8 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 96.ql @@ -7,28 +7,29 @@ * @tags correctness * external/jsf */ + import cpp predicate compatible(Type t1, Type t2) { - t1 = t2 - or compatible(t1.(DerivedType).getBaseType().getUnspecifiedType(), t2.(DerivedType).getBaseType().getUnspecifiedType()) + t1 = t2 or + compatible(t1.(DerivedType).getBaseType().getUnspecifiedType(), + t2.(DerivedType).getBaseType().getUnspecifiedType()) } + predicate baseElement(ArrayType t, Type e) { t.getBaseType() instanceof ArrayType and baseElement(t.getBaseType(), e) - or not t.getBaseType() instanceof ArrayType and e = t.getBaseType() + or + not t.getBaseType() instanceof ArrayType and e = t.getBaseType() } from Expr e, Class cl -where e.getType() instanceof ArrayType - and exists( - FunctionCall c, int i, Function f | - c.getArgument(i) = e - and - c.getTarget() = f - and - exists(Parameter p | f.getParameter(i) = p) // varargs - and - baseElement(e.getType(), cl) // only interested in arrays with classes - and - not compatible(f.getParameter(i).getUnspecifiedType(), e.getUnspecifiedType())) - select e, "AV Rule 96: Arrays shall not be teated polymorphically" +where + e.getType() instanceof ArrayType and + exists(FunctionCall c, int i, Function f | + c.getArgument(i) = e and + c.getTarget() = f and + exists(Parameter p | f.getParameter(i) = p) and // varargs + baseElement(e.getType(), cl) and // only interested in arrays with classes + not compatible(f.getParameter(i).getUnspecifiedType(), e.getUnspecifiedType()) + ) +select e, "AV Rule 96: Arrays shall not be teated polymorphically" diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql index 02d0f169245..090eb0baa67 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.1.ql @@ -8,9 +8,13 @@ * portability * external/jsf */ + import cpp from EqualityOperation e, PointerToMemberType t, Class c -where e.getAnOperand().getType() = t - and t.getClass() = c and exists(VirtualFunction f | c.getAMemberFunction() = f) -select e, "AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function." +where + e.getAnOperand().getType() = t and + t.getClass() = c and + exists(VirtualFunction f | c.getAMemberFunction() = f) +select e, + "AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function." diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql index 781e3c922d3..501101f706c 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql @@ -10,16 +10,21 @@ * language-features * external/jsf */ + import cpp predicate containsArray(Type t) { t instanceof ArrayType - or containsArray(t.(PointerType).getBaseType()) - or containsArray(t.(SpecifiedType).getBaseType()) - or (containsArray(t.getUnderlyingType()) and not exists(TypedefType allowed | allowed = t | + or + containsArray(t.(PointerType).getBaseType()) + or + containsArray(t.(SpecifiedType).getBaseType()) + or + containsArray(t.getUnderlyingType()) and + not exists(TypedefType allowed | allowed = t | allowed.hasGlobalName("jmp_buf") or allowed.hasGlobalName("va_list") - )) + ) } predicate functionAPIViolation(MemberFunction f) { @@ -28,6 +33,7 @@ predicate functionAPIViolation(MemberFunction f) { } from MemberFunction m -where functionAPIViolation(m) - and not m.getDeclaringType() instanceof Struct +where + functionAPIViolation(m) and + not m.getDeclaringType() instanceof Struct select m, "Raw arrays should not be used in interfaces. A container class should be used instead." diff --git a/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql b/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql index 4d4713026f1..22ab9221d1e 100644 --- a/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql +++ b/cpp/ql/src/jsf/4.11 Namespaces/AV Rule 99.ql @@ -8,15 +8,21 @@ * readability * external/jsf */ + import cpp // Pick a representative file for a namespace - more than a bit dodgy, but otherwise // the results don't show up anywhere which is less than helpful predicate namespaceRepresentative(Namespace ns, File rep) { - rep.getAbsolutePath() = min(File f | exists(Declaration d | d = ns.getADeclaration() | d.getFile() = f) | f.getAbsolutePath()) + rep.getAbsolutePath() = min(File f | + exists(Declaration d | d = ns.getADeclaration() | d.getFile() = f) + | + f.getAbsolutePath() + ) } from Namespace ns, File rep -where exists(ns.getParentNamespace().getParentNamespace().getParentNamespace()) - and namespaceRepresentative(ns, rep) +where + exists(ns.getParentNamespace().getParentNamespace().getParentNamespace()) and + namespaceRepresentative(ns, rep) select rep, "AV Rule 99: namespace " + ns.toString() + " is nested more than two levels deep" diff --git a/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql b/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql index a88a8f165e9..bc1ebf8c1d9 100644 --- a/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql +++ b/cpp/ql/src/jsf/4.12 Templates/AV Rule 104.ql @@ -7,23 +7,26 @@ * @tags correctness * external/jsf */ + import cpp -/** A compiler warning that a template specialization occurs after - * what would have been its use. In C++ a template specialization - * only applies after it is defined; if it would have applied had - * it been defined earlier this warning is triggered. - * - * The warning is also triggered if the specialization would have - * made a use ambiguous had it occurred earlier. */ +/** + * A compiler warning that a template specialization occurs after + * what would have been its use. In C++ a template specialization + * only applies after it is defined; if it would have applied had + * it been defined earlier this warning is triggered. + * + * The warning is also triggered if the specialization would have + * made a use ambiguous had it occurred earlier. + */ class WarningLateTemplateSpecialization extends CompilerWarning { - WarningLateTemplateSpecialization() { this.getTag() = "partial_spec_after_instantiation" or this.getTag() = "partial_spec_after_instantiation_ambiguous" } - } from WarningLateTemplateSpecialization warning -select warning, "AV Rule 104: A template specialization shall be declared before its use; " + warning.getMessage() + "." \ No newline at end of file +select warning, + "AV Rule 104: A template specialization shall be declared before its use; " + warning.getMessage() + + "." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql index 3a0aab0b591..872ccf23828 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 107.ql @@ -9,10 +9,12 @@ * readability * external/jsf */ + import cpp from DeclStmt ds -where ds.getADeclaration() instanceof Function - and not ds.isInMacroExpansion() - and not exists(MacroInvocation mi | mi.getLocation() = ds.getADeclarationEntry().getLocation()) +where + ds.getADeclaration() instanceof Function and + not ds.isInMacroExpansion() and + not exists(MacroInvocation mi | mi.getLocation() = ds.getADeclarationEntry().getLocation()) select ds, "Functions should be declared at file scope, not inside blocks." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql index b463e51afa7..1f21255a9a2 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 108.ql @@ -7,8 +7,9 @@ * @tags correctness * external/jsf */ + import cpp from Function f where f.fromSource() and f.hasSpecifier("varargs") -select f, "AV Rule 108: Functions with variable number of arguments shall not be used." \ No newline at end of file +select f, "AV Rule 108: Functions with variable number of arguments shall not be used." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql index 9afa55ee4ca..a52faec234e 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 110.ql @@ -8,9 +8,11 @@ * readability * external/jsf */ + import cpp from Function f -where f.getNumberOfParameters() > 7 - and f.fromSource() -select f, "AV Rule 110: Functions with more than 7 arguments will not be used." \ No newline at end of file +where + f.getNumberOfParameters() > 7 and + f.fromSource() +select f, "AV Rule 110: Functions with more than 7 arguments will not be used." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql index 6e6d8004a1c..8c62c5763aa 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 111.ql @@ -8,20 +8,22 @@ * reliability * external/jsf */ + import semmle.code.cpp.pointsto.PointsTo -class ReturnPointsToExpr extends PointsToExpr -{ +class ReturnPointsToExpr extends PointsToExpr { override predicate interesting() { - exists(ReturnStmt ret | ret.getExpr() = this) - and pointerValue(this) + exists(ReturnStmt ret | ret.getExpr() = this) and + pointerValue(this) } ReturnStmt getReturnStmt() { result.getExpr() = this } } from ReturnPointsToExpr ret, LocalVariable dest -where ret.pointsTo() = dest - and ret.getReturnStmt().getParentStmt().getEnclosingFunction() = dest.getFunction() - and not(dest.isStatic()) -select ret.getReturnStmt(), "AV Rule 111: A function shall not return a pointer or reference to a non-static local object." +where + ret.pointsTo() = dest and + ret.getReturnStmt().getParentStmt().getEnclosingFunction() = dest.getFunction() and + not dest.isStatic() +select ret.getReturnStmt(), + "AV Rule 111: A function shall not return a pointer or reference to a non-static local object." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql index ca934aa84e1..d007c139fd8 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 113.ql @@ -7,10 +7,12 @@ * @tags maintainability * external/jsf */ + import cpp from Function f, Stmt s1, Stmt s2 -where s1 = f.getAPredecessor().getEnclosingStmt() and - s2 = f.getAPredecessor().getEnclosingStmt() and - s1 != s2 -select f, "AV Rule 113: Functions will have a single exit point." \ No newline at end of file +where + s1 = f.getAPredecessor().getEnclosingStmt() and + s2 = f.getAPredecessor().getEnclosingStmt() and + s1 != s2 +select f, "AV Rule 113: Functions will have a single exit point." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql index 0cd1063f99a..f893868b5d6 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql @@ -10,13 +10,16 @@ * language-features * external/jsf */ + import cpp -/* This is slightly subtle: The extractor adds a dummy 'return;' statement for control paths +/* + * This is slightly subtle: The extractor adds a dummy 'return;' statement for control paths * that fall off the end of a function. So we can simply look for non-void functions containing * a non-value carrying return. If the predecessor is a return statement it means that * the return did not return a value. (If that return was not added by the extractor but by the - * programmer, we can flag it anyway, since this is arguably a bug.) */ + * programmer, we can flag it anyway, since this is arguably a bug.) + */ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) { f.fromSource() and @@ -31,10 +34,12 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) { ) } -/** If a function has a value-carrying return statement, but the extractor hit a snag +/** + * If a function has a value-carrying return statement, but the extractor hit a snag * whilst parsing the value, then the control flow graph will not include the value. * As such, to avoid embarrassing false positives, we exclude any function which - * wasn't perfectly extracted. */ + * wasn't perfectly extracted. + */ predicate functionImperfectlyExtracted(Function f) { exists(CompilerError e | f.getBlock().getLocation().subsumes(e.getLocation())) or @@ -49,5 +54,6 @@ where reachable(blame) and not functionImperfectlyExtracted(f) and (blame = stmt or blame.(Expr).getEnclosingStmt() = stmt) and - msg = "Function " + f.getName() + " should return a value of type " + f.getType().getName() + " but does not return a value here" + msg = "Function " + f.getName() + " should return a value of type " + f.getType().getName() + + " but does not return a value here" select stmt, msg diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql index 2cec08f027b..5ab9886deed 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 115.ql @@ -8,6 +8,7 @@ * @tags correctness * external/jsf */ + import cpp // a return statement that looks like it returns an error code @@ -19,9 +20,12 @@ class ErrorReturn extends ReturnStmt { ErrorReturn() { exists(Expr e | e = super.getExpr() and - (e instanceof Literal - or e.(VariableAccess).getTarget().isConst()) and - not (e.getValue() = "0" and e.getActualType() instanceof IntegralType)) + ( + e instanceof Literal or + e.(VariableAccess).getTarget().isConst() + ) and + not (e.getValue() = "0" and e.getActualType() instanceof IntegralType) + ) } } @@ -31,11 +35,13 @@ class FunctionReturningErrorCode extends Function { exists(ErrorReturn er, ReturnStmt nr | er.getEnclosingFunction() = this and nr.getEnclosingFunction() = this and - not nr instanceof ErrorReturn) + not nr instanceof ErrorReturn + ) } } from FunctionReturningErrorCode frec, Call c -where c = frec.getACallToThisFunction() and - c instanceof ExprInVoidContext -select c, "AV Rule 115: If a function returns error information, it will be tested." \ No newline at end of file +where + c = frec.getACallToThisFunction() and + c instanceof ExprInVoidContext +select c, "AV Rule 115: If a function returns error information, it will be tested." diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql index 3e365d28ddf..d788502424c 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 119.ql @@ -7,9 +7,11 @@ * @tags resources * external/jsf */ + import cpp from Function f -where f.fromSource() and - f.calls+(f) -select f, "Functions shall not call theselves, either directly or indirectly" \ No newline at end of file +where + f.fromSource() and + f.calls+(f) +select f, "Functions shall not call theselves, either directly or indirectly" diff --git a/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql b/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql index bc0a6a4be1d..d6f2e1089ee 100644 --- a/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql +++ b/cpp/ql/src/jsf/4.14 Comments/AV Rule 126.ql @@ -8,9 +8,11 @@ * documentation * external/jsf */ + import cpp from Comment c -where c.fromSource() and - not c.getContents().regexpMatch("\\s*//.*") -select c, "AV Rule 126: Only valid C++ style comments shall be used." \ No newline at end of file +where + c.fromSource() and + not c.getContents().regexpMatch("\\s*//.*") +select c, "AV Rule 126: Only valid C++ style comments shall be used." diff --git a/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql b/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql index 94026501130..5f814740399 100644 --- a/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql +++ b/cpp/ql/src/jsf/4.14 Comments/AV Rule 133.ql @@ -8,12 +8,17 @@ * documentation * external/jsf */ + import cpp class FirstComment extends Comment { - FirstComment() { - not exists(Locatable l | l != this and shouldNotBeBefore(l) and l.getFile() = this.getFile() and l.getLocation().getEndLine() <= this.getLocation().getStartLine()) + not exists(Locatable l | + l != this and + shouldNotBeBefore(l) and + l.getFile() = this.getFile() and + l.getLocation().getEndLine() <= this.getLocation().getStartLine() + ) } /* @@ -22,17 +27,16 @@ class FirstComment extends Comment { * Simple checks only - if there is a comment at the beginning of the file, that * is pretty much enough */ - predicate isValid() { - // At least 3 lines long: make sure it's a proper comment - this.getLocation().getEndLine() >= this.getLocation().getStartLine() + 2 - and - exists (string contents | contents = this.getContents() | - // Make sure the name of the file is included - contents.matches("%" + this.getFile().getShortName() + "%") - // Other checks could go here; for instance containing a standard copyright notice - ) - } + predicate isValid() { + // At least 3 lines long: make sure it's a proper comment + this.getLocation().getEndLine() >= this.getLocation().getStartLine() + 2 and + exists(string contents | contents = this.getContents() | + // Make sure the name of the file is included + contents.matches("%" + this.getFile().getShortName() + "%") + // Other checks could go here; for instance containing a standard copyright notice + ) + } } /** Elements that should not appear before the 'first' comment */ @@ -43,19 +47,17 @@ predicate shouldNotBeBefore(Locatable l) { } from File f, Element blame, string message -where f.fromSource() and - ( - ( - not exists(FirstComment comment | comment.getFile() = f) - and blame = f - and message = "" - ) - - or - - ( - exists(FirstComment comment | comment.getFile() = f and not comment.isValid() and blame = comment ) - and message = "The introductory comment does not match the required style rules." - ) - ) -select blame, "AV Rule 133: every source file will be documented with an introductory comment. " + message \ No newline at end of file +where + f.fromSource() and + ( + not exists(FirstComment comment | comment.getFile() = f) and + blame = f and + message = "" + or + exists(FirstComment comment | + comment.getFile() = f and not comment.isValid() and blame = comment + ) and + message = "The introductory comment does not match the required style rules." + ) +select blame, + "AV Rule 133: every source file will be documented with an introductory comment. " + message diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql index b7561398468..0b3572af97e 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 135.ql @@ -7,16 +7,14 @@ * @tags maintainability * external/jsf */ + import cpp import Best_Practices.Hiding.Shadowing // Shadowing globals by locals or parameters. Only in the same file; // otherwise the rule is violated too often - class LocalVariableOrParameter extends Variable { - LocalVariableOrParameter() { - this instanceof LocalVariable or this instanceof Parameter - } + LocalVariableOrParameter() { this instanceof LocalVariable or this instanceof Parameter } predicate shadowsGlobal(GlobalVariable gv) { this.getName() = gv.getName() and this.getFile() = gv.getFile() @@ -24,17 +22,17 @@ class LocalVariableOrParameter extends Variable { } // Shadowing parameters by locals - predicate localShadowsParameter(LocalVariable lv, Parameter p) { p.getName() = lv.getName() and p.getFunction() = lv.getFunction() } from Variable v, Variable shadowed -where not v.getParentScope().(Block).isInMacroExpansion() and - ( - v.(LocalVariableOrParameter).shadowsGlobal((GlobalVariable)shadowed) - or localShadowsParameter(v, shadowed) - or shadowing(v, shadowed) - ) +where + not v.getParentScope().(Block).isInMacroExpansion() and + ( + v.(LocalVariableOrParameter).shadowsGlobal(shadowed.(GlobalVariable)) or + localShadowsParameter(v, shadowed) or + shadowing(v, shadowed) + ) select v, "Identifiers in an inner scope should not hide identifiers in an outer scope" diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql index 98c1122e4c0..91cd94ab22a 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 138.ql @@ -7,6 +7,7 @@ * @tags maintainability * external/jsf */ + import cpp /* @@ -29,18 +30,21 @@ import cpp */ predicate externalLinkage(Variable v) { - v.getADeclarationEntry().hasSpecifier("extern") - or v instanceof GlobalVariable and - not v.isConst() and - not v.isStatic() + v.getADeclarationEntry().hasSpecifier("extern") + or + v instanceof GlobalVariable and + not v.isConst() and + not v.isStatic() } predicate internalLinkage(GlobalVariable v) { - v.isStatic() - or v.isConst() and - not v.hasSpecifier("extern") + v.isStatic() + or + v.isConst() and + not v.hasSpecifier("extern") } from Variable v where externalLinkage(v) and internalLinkage(v) -select v, "AV Rule 138: Identifiers shall not simultaneously have both internal and external linkage in the same translation unit." \ No newline at end of file +select v, + "AV Rule 138: Identifiers shall not simultaneously have both internal and external linkage in the same translation unit." diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql index 83de729ba60..1f9bf5309fc 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 139.ql @@ -7,6 +7,7 @@ * @tags maintainability * external/jsf */ + import cpp predicate twoDeclarations(Declaration element, Location l1, Location l2) { @@ -18,25 +19,46 @@ predicate twoDeclarations(Declaration element, Location l1, Location l2) { } predicate twoDeclarationFilesWithDifferentNames(Declaration d, string f1, string f2) { - f1 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() | s) and - f2 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() and s != f1 | s) + f1 = min(string s, File f, Location l | + twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() + | + s + ) and + f2 = min(string s, File f, Location l | + twoDeclarations(d, l, _) and l.getFile() = f and s = f.getBaseName() and s != f1 + | + s + ) } predicate twoDeclarationFilesWithSameNames(Declaration d, string f1, string f2) { - f1 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() | s) and - f2 = min(string s, File f, Location l | twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() and s != f1 | s) + f1 = min(string s, File f, Location l | + twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() + | + s + ) and + f2 = min(string s, File f, Location l | + twoDeclarations(d, l, _) and l.getFile() = f and s = f.toString() and s != f1 + | + s + ) } - predicate twoDeclarationFilesMessage(Declaration d, string msg) { // If we can get two files with different names, all the better for the error message - if twoDeclarationFilesWithDifferentNames(d,_,_) then - exists(string f1, string f2 | twoDeclarationFilesWithDifferentNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2) + if twoDeclarationFilesWithDifferentNames(d, _, _) + then + exists(string f1, string f2 | + twoDeclarationFilesWithDifferentNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2 + ) else - exists(string f1, string f2 | twoDeclarationFilesWithSameNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2) + exists(string f1, string f2 | + twoDeclarationFilesWithSameNames(d, f1, f2) and msg = "Declared in " + f1 + " and " + f2 + ) } from Declaration d, string msg -where twoDeclarations(d, _, _) and - twoDeclarationFilesMessage(d, msg) +where + twoDeclarations(d, _, _) and + twoDeclarationFilesMessage(d, msg) select d, "AV Rule 139: external objects will not be declared in more than one file. " + msg diff --git a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql index 0088664dcd8..1631aeee34a 100644 --- a/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql +++ b/cpp/ql/src/jsf/4.15 Declarations and Definitions/AV Rule 140.ql @@ -8,8 +8,10 @@ * portability * external/jsf */ + import cpp from Declaration d where d.hasSpecifier("register") -select d, "The register storage class specifier should not be used; compilers can be trusted to decide whether to store a variable in a register." \ No newline at end of file +select d, + "The register storage class specifier should not be used; compilers can be trusted to decide whether to store a variable in a register." diff --git a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql index 4b8cd81eb63..63158de7c9c 100644 --- a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql +++ b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 142.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp // whether s defines variable v (conservative) @@ -16,19 +17,22 @@ predicate defines(ControlFlowNode s, Variable lv) { // whether s uses variable v (conservative) predicate uses(ControlFlowNode s, Variable lv) { - exists(VariableAccess va | va = s and va.getTarget() = lv and va.isRValue() - and not va.getParent+() instanceof SizeofOperator) + exists(VariableAccess va | + va = s and + va.getTarget() = lv and + va.isRValue() and + not va.getParent+() instanceof SizeofOperator + ) } // whether there is a path from the declaration of lv to n such that lv is definitely not defined before n predicate noDefPath(LocalVariable lv, ControlFlowNode n) { - n.(DeclStmt).getADeclaration() = lv and not exists(lv.getInitializer()) - or exists(ControlFlowNode p | noDefPath(lv, p) and n = p.getASuccessor() and not defines(p, lv)) + n.(DeclStmt).getADeclaration() = lv and not exists(lv.getInitializer()) + or + exists(ControlFlowNode p | noDefPath(lv, p) and n = p.getASuccessor() and not defines(p, lv)) } -predicate isAggregateType(Type t) { - t instanceof Class or t instanceof ArrayType -} +predicate isAggregateType(Type t) { t instanceof Class or t instanceof ArrayType } // whether va is a use of a local variable that has not been previously defined predicate undefinedLocalUse(VariableAccess va) { @@ -38,7 +42,8 @@ predicate undefinedLocalUse(VariableAccess va) { not lv.getType().hasName("va_list") and va = lv.getAnAccess() and noDefPath(lv, va) and - uses(va, lv)) + uses(va, lv) + ) } // whether gv is a potentially uninitialised global variable @@ -48,9 +53,10 @@ predicate uninitialisedGlobal(GlobalVariable gv) { va = gv.getAnAccess() and va.isRValue() and not gv.hasInitializer() and - not gv.hasSpecifier("extern")) + not gv.hasSpecifier("extern") + ) } from Element elt where undefinedLocalUse(elt) or uninitialisedGlobal(elt) -select elt, "AV Rule 142: All variables shall be initialized before use." \ No newline at end of file +select elt, "AV Rule 142: All variables shall be initialized before use." diff --git a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql index 9bac57b913a..973cb016579 100644 --- a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql +++ b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 143.ql @@ -8,40 +8,50 @@ * @tags maintainability * external/jsf */ + import cpp // whether s defines variable v (conservative) -predicate defines(VariableAccess va, Variable lv) { - va.getTarget() = lv and va.isLValue() -} +predicate defines(VariableAccess va, Variable lv) { va.getTarget() = lv and va.isLValue() } // whether s uses variable v (conservative) predicate uses(ControlFlowNode s, Variable lv) { - exists(VariableAccess va | va = s and va.getTarget() = lv and va.isRValue() - and not va.getParent+() instanceof SizeofOperator) + exists(VariableAccess va | + va = s and + va.getTarget() = lv and + va.isRValue() and + not va.getParent+() instanceof SizeofOperator + ) } // whether there is a path from the declaration of lv to n such that lv is definitely not used or defined // before n predicate noDefUsePath(LocalVariable lv, ControlFlowNode n) { - n.(DeclStmt).getADeclaration() = lv - or exists(ControlFlowNode p | noDefUsePath(lv, p) and - n = p.getASuccessor() and - not defines(p, lv) and - not uses(p, lv)) + n.(DeclStmt).getADeclaration() = lv + or + exists(ControlFlowNode p | + noDefUsePath(lv, p) and + n = p.getASuccessor() and + not defines(p, lv) and + not uses(p, lv) + ) } predicate neighbouringStmts(Stmt s1, Stmt s2) { exists(Block b, int i | - i in [0..b.getNumStmt()-2] and + i in [0 .. b.getNumStmt() - 2] and s1 = b.getStmt(i) and - s2 = b.getStmt(i+1)) + s2 = b.getStmt(i + 1) + ) } from LocalVariable lv, VariableAccess def, DeclStmt d -where lv.fromSource() and - d.getADeclaration() = lv and - noDefUsePath(lv, def) and defines(def, lv) and - not neighbouringStmts(d, def.getEnclosingStmt()) and - not exists(ControlFlowNode use | noDefUsePath(lv, use) and uses(use, lv)) -select def, "AV Rule 143: Variables will not be introduced until they can be initialized with meaningful values." \ No newline at end of file +where + lv.fromSource() and + d.getADeclaration() = lv and + noDefUsePath(lv, def) and + defines(def, lv) and + not neighbouringStmts(d, def.getEnclosingStmt()) and + not exists(ControlFlowNode use | noDefUsePath(lv, use) and uses(use, lv)) +select def, + "AV Rule 143: Variables will not be introduced until they can be initialized with meaningful values." diff --git a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql index 0388e533650..dd5ee4bf963 100644 --- a/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql +++ b/cpp/ql/src/jsf/4.16 Initialization/AV Rule 145.ql @@ -10,15 +10,14 @@ * language-features * external/jsf */ + import cpp -predicate hasInitializer(EnumConstant c) { - c.getInitializer().fromSource() -} +predicate hasInitializer(EnumConstant c) { c.getInitializer().fromSource() } /** Does this have an initializer that is not just a ref to another constant in the same enum? */ predicate hasNonReferenceInitializer(EnumConstant c) { - exists (Initializer init | + exists(Initializer init | init = c.getInitializer() and init.fromSource() and not init.getExpr().(EnumConstantAccess).getTarget().getDeclaringEnum() = c.getDeclaringEnum() @@ -26,14 +25,13 @@ predicate hasNonReferenceInitializer(EnumConstant c) { } predicate hasReferenceInitializer(EnumConstant c) { - exists (Initializer init | + exists(Initializer init | init = c.getInitializer() and init.fromSource() and init.getExpr().(EnumConstantAccess).getTarget().getDeclaringEnum() = c.getDeclaringEnum() ) } - // There exists another constant whose value is implicit, but it's // not the last one: the last value is okay to use to get the highest // enum value automatically. It can be followed by aliases though. @@ -50,15 +48,16 @@ predicate enumThatHasConstantWithImplicitValue(Enum e) { } from Enum e, int i -where // e is at position i, and has an explicit value in the source - but - // not just a reference to another enum constant - hasNonReferenceInitializer(e.getEnumConstant(i)) and - // but e is not the first or the last constant of the enum - i != 0 and - exists(e.getEnumConstant(i+1)) and - // and there exists another constant whose value is implicit, but it's - // not the last one: the last value is okay to use to get the highest - // enum value automatically. It can be followed by aliases though. - enumThatHasConstantWithImplicitValue(e) - -select e, "In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized." +where + // e is at position i, and has an explicit value in the source - but + // not just a reference to another enum constant + hasNonReferenceInitializer(e.getEnumConstant(i)) and + // but e is not the first or the last constant of the enum + i != 0 and + exists(e.getEnumConstant(i + 1)) and + // and there exists another constant whose value is implicit, but it's + // not the last one: the last value is okay to use to get the highest + // enum value automatically. It can be followed by aliases though. + enumThatHasConstantWithImplicitValue(e) +select e, + "In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized." diff --git a/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql b/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql index a7e9c611764..e149f8c2b00 100644 --- a/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql +++ b/cpp/ql/src/jsf/4.17 Types/AV Rule 147.ql @@ -7,6 +7,7 @@ * @tags reliability * external/jsf */ + import cpp /* @@ -21,7 +22,6 @@ class GeneralPointerType extends DerivedType { } class InvalidFloatCastExpr extends Expr { - InvalidFloatCastExpr() { exists(Type src, Type dst | src = this.getUnspecifiedType() and @@ -33,19 +33,28 @@ class InvalidFloatCastExpr extends Expr { } class FloatUnion extends Union { - FloatUnion() { - exists (MemberVariable mv | this.getAMemberVariable() = mv and mv.getType().getUnderlyingType() instanceof FloatingPointType) - and exists (MemberVariable mv | this.getAMemberVariable() = mv and not mv.getType().getUnderlyingType() instanceof FloatingPointType) + exists(MemberVariable mv | + this.getAMemberVariable() = mv and + mv.getType().getUnderlyingType() instanceof FloatingPointType + ) and + exists(MemberVariable mv | + this.getAMemberVariable() = mv and + not mv.getType().getUnderlyingType() instanceof FloatingPointType + ) } - MemberVariable getAFloatMember() { result = this.getAMemberVariable() and result.getType().getUnderlyingType() instanceof FloatingPointType } - + MemberVariable getAFloatMember() { + result = this.getAMemberVariable() and + result.getType().getUnderlyingType() instanceof FloatingPointType + } } from Element e, string message where - (e instanceof InvalidFloatCastExpr and message = "Casting a float pointer to another pointer type exposes the bit representation of the float, leading to unportable code.") + e instanceof InvalidFloatCastExpr and + message = "Casting a float pointer to another pointer type exposes the bit representation of the float, leading to unportable code." or - (exists (FloatUnion fu | e = fu.getAFloatMember()) and message = "Defining a union with a float member exposes the bit representation of the float, leading to unportable code.") + exists(FloatUnion fu | e = fu.getAFloatMember()) and + message = "Defining a union with a float member exposes the bit representation of the float, leading to unportable code." select e, message diff --git a/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql b/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql index 3c047d68150..1629e8cc8bd 100644 --- a/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql +++ b/cpp/ql/src/jsf/4.17 Types/AV Rule 148.ql @@ -10,12 +10,16 @@ * language-features * external/jsf */ + import cpp // flag switch statements where every non-default case dispatches on an integer constant from SwitchStmt s -where forex(SwitchCase sc | sc = s.getASwitchCase() and not sc instanceof DefaultCase | - sc.getExpr().(VariableAccess).getTarget().isConst()) - // Allow switch on character types - and not (s.getExpr().getUnspecifiedType() instanceof CharType) -select s, "Enumeration types should be used instead of integers to select from a limited series of choices." +where + forex(SwitchCase sc | sc = s.getASwitchCase() and not sc instanceof DefaultCase | + sc.getExpr().(VariableAccess).getTarget().isConst() + ) and + // Allow switch on character types + not s.getExpr().getUnspecifiedType() instanceof CharType +select s, + "Enumeration types should be used instead of integers to select from a limited series of choices." diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql index 1485bb67573..1e91b7c2469 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 149.ql @@ -7,9 +7,11 @@ * @tags maintainability * external/jsf */ + import cpp from OctalLiteral l -where l.fromSource() and - l.getValue() != "0" -select l, "AV Rule 149: Octal constants (other than zero) shall not be used." \ No newline at end of file +where + l.fromSource() and + l.getValue() != "0" +select l, "AV Rule 149: Octal constants (other than zero) shall not be used." diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql index eaa41fc002f..48965c157ad 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 150.ql @@ -7,9 +7,11 @@ * @tags maintainability * external/jsf */ + import cpp from HexLiteral l -where l.fromSource() and - l.getValueText().regexpMatch(".*[a-z].*") -select l, "AV Rule 150: Hexadecimal constants will be represented using all uppercase letters." \ No newline at end of file +where + l.fromSource() and + l.getValueText().regexpMatch(".*[a-z].*") +select l, "AV Rule 150: Hexadecimal constants will be represented using all uppercase letters." diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql index 750faea8d3f..562ade924f2 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.1.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -28,4 +29,5 @@ class NonConstStringType extends DerivedType { from StringLiteral l where l.getFullyConverted().getType().getUnderlyingType() instanceof NonConstStringType -select l, "A string literal must not be used as a non-const value: modifying string literals leads to undefined behavior." +select l, + "A string literal must not be used as a non-const value: modifying string literals leads to undefined behavior." diff --git a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql index 5cd0052b455..7ecb8ff3bdf 100644 --- a/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql +++ b/cpp/ql/src/jsf/4.18 Constants/AV Rule 151.ql @@ -7,17 +7,22 @@ * @tags maintainability * external/jsf */ + import cpp from Literal l -where l.fromSource() and - l.getType() instanceof ArithmeticType and - not l.isInMacroExpansion() and - not l.getParent() instanceof ArrayExpr and - not exists(Variable v | v.getInitializer().getExpr() = l) and - not exists(Assignment a | a.getLValue() instanceof ArrayExpr and - a.getRValue() = l and - a.getControlFlowScope() instanceof Constructor) and - not l.getValue() = "0" and - not l.getValue() = "1" -select l, "AV Rule 151: Numeric values in code will not be used; symbolic values will be used instead." \ No newline at end of file +where + l.fromSource() and + l.getType() instanceof ArithmeticType and + not l.isInMacroExpansion() and + not l.getParent() instanceof ArrayExpr and + not exists(Variable v | v.getInitializer().getExpr() = l) and + not exists(Assignment a | + a.getLValue() instanceof ArrayExpr and + a.getRValue() = l and + a.getControlFlowScope() instanceof Constructor + ) and + not l.getValue() = "0" and + not l.getValue() = "1" +select l, + "AV Rule 151: Numeric values in code will not be used; symbolic values will be used instead." diff --git a/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql b/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql index c83d96102a5..54481a407a1 100644 --- a/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql +++ b/cpp/ql/src/jsf/4.19 Variables/AV Rule 152.ql @@ -8,27 +8,33 @@ * readability * external/jsf */ + import cpp predicate isNonSolitary(Declaration d) { exists(DeclStmt ds, Variable v | - ds.fromSource() and - d = ds.getADeclaration() and - d instanceof Variable and - v = ds.getADeclaration() and - v != d) + ds.fromSource() and + d = ds.getADeclaration() and + d instanceof Variable and + v = ds.getADeclaration() and + v != d + ) or - exists(GlobalVariable g | g.fromSource() and - g.getLocation().getStartLine() = d.(GlobalVariable).getLocation().getStartLine() and - g.getLocation().getFile() = d.getLocation().getFile() and - g != d) + exists(GlobalVariable g | + g.fromSource() and + g.getLocation().getStartLine() = d.(GlobalVariable).getLocation().getStartLine() and + g.getLocation().getFile() = d.getLocation().getFile() and + g != d + ) or - exists(Field f | f.fromSource() and - f.getLocation().getStartLine() = d.(Field).getLocation().getStartLine() and - f.getLocation().getFile() = d.getLocation().getFile() and - f != d) + exists(Field f | + f.fromSource() and + f.getLocation().getStartLine() = d.(Field).getLocation().getStartLine() and + f.getLocation().getFile() = d.getLocation().getFile() and + f != d + ) } from Declaration d where isNonSolitary(d) -select d, "AV Rule 152: Multiple variable declarations shall not be allowed on the same line." \ No newline at end of file +select d, "AV Rule 152: Multiple variable declarations shall not be allowed on the same line." diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql index 46d779a6e6c..be7fda83268 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 153.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -15,4 +16,4 @@ import cpp from Union u where u.fromSource() -select u, "AV Rule 153: Unions shall not be used." \ No newline at end of file +select u, "AV Rule 153: Unions shall not be used." diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql index d39ffb2c3be..cd08362ad35 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 154.ql @@ -13,13 +13,17 @@ * external/jsf * external/cwe/cwe-190 */ + import cpp from BitField bf -where not bf.getUnspecifiedType().(IntegralType).isUnsigned() - and not bf.getUnderlyingType() instanceof Enum - and not bf.getUnspecifiedType() instanceof BoolType - and not bf.getType().hasName("BOOL") // At least for C programs on Windows, BOOL is a common typedef for a type representing BoolType. - and not bf.getDeclaredNumBits() = bf.getType().getSize() * 8 // If this is true, then there cannot be unsigned sign extension or overflow. - and not bf.isAnonymous() -select bf, "Bit field " + bf.getName() + " of type " + bf.getUnderlyingType().getName() + " should have explicitly unsigned integral or enumeration type." +where + not bf.getUnspecifiedType().(IntegralType).isUnsigned() and + not bf.getUnderlyingType() instanceof Enum and + not bf.getUnspecifiedType() instanceof BoolType and + not bf.getType().hasName("BOOL") and // At least for C programs on Windows, BOOL is a common typedef for a type representing BoolType. + not bf.getDeclaredNumBits() = bf.getType().getSize() * 8 and // If this is true, then there cannot be unsigned sign extension or overflow. + not bf.isAnonymous() +select bf, + "Bit field " + bf.getName() + " of type " + bf.getUnderlyingType().getName() + + " should have explicitly unsigned integral or enumeration type." diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql index 784cc19d109..60f255b3702 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 155.ql @@ -8,9 +8,11 @@ * @tags correctness * external/jsf */ + import cpp from BitField bf -where not bf.getUnderlyingType() instanceof Enum and - not bf.getDeclaredNumBits() = 0 +where + not bf.getUnderlyingType() instanceof Enum and + not bf.getDeclaredNumBits() = 0 select bf, "AV Rule 155: Bit fields will not be used purely to save space." diff --git a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql index 961a5e0c80b..27ced03ed0b 100644 --- a/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql +++ b/cpp/ql/src/jsf/4.20 Unions and Bit Fields/AV Rule 156.ql @@ -9,6 +9,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -18,6 +19,9 @@ import cpp */ from Declaration m -where m.isMember() and m.getName().matches("(%") and - not m.(BitField).getDeclaredNumBits() = 0 -select m, "AV Rule 156: All the members of a structure (or class) shall be named and shall only be accessed via their names." \ No newline at end of file +where + m.isMember() and + m.getName().matches("(%") and + not m.(BitField).getDeclaredNumBits() = 0 +select m, + "AV Rule 156: All the members of a structure (or class) shall be named and shall only be accessed via their names." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql index 75e670dc50b..21216621c51 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 157.ql @@ -9,6 +9,7 @@ * readability * external/jsf */ + import cpp /* @@ -16,6 +17,8 @@ import cpp */ from BinaryLogicalOperation blo -where blo.fromSource() and - not blo.getRightOperand().isPure() -select blo, "AV Rule 157: The right hand operand of a && or || operator shall not contain side effects." +where + blo.fromSource() and + not blo.getRightOperand().isPure() +select blo, + "AV Rule 157: The right hand operand of a && or || operator shall not contain side effects." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql index 0c526f21c3a..805ee616be7 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 158.ql @@ -9,6 +9,7 @@ * readability * external/jsf */ + import cpp /* @@ -16,7 +17,9 @@ import cpp */ from BinaryLogicalOperation blo, BinaryOperation bo -where blo.fromSource() and - bo = blo.getAnOperand() and - not bo.isParenthesised() -select blo, "AV Rule 158: The operands of a logical && or || operator shall be parenthesized if the operands contain binary operators." \ No newline at end of file +where + blo.fromSource() and + bo = blo.getAnOperand() and + not bo.isParenthesised() +select blo, + "AV Rule 158: The operands of a logical && or || operator shall be parenthesized if the operands contain binary operators." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql index 2b2318b955a..99d60f7290d 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 159.ql @@ -16,8 +16,14 @@ import cpp from Function o, string message -where (o.getName() = "operator&&" and message = "AV Rule 159: the && operator shall not be overloaded as short-circuit semantics cannot be obtained.")or - (o.getName() = "operator||" and message = "AV Rule 159: the || operator shall not be overloaded as short-circuit semantics cannot be obtained.")or - (o.getName() = "operator&" and o.getNumberOfParameters() = 1 and - message = "AV Rule 159: the unary & operator shall not be overloaded because of undefined behavior.") -select o, message \ No newline at end of file +where + o.getName() = "operator&&" and + message = "AV Rule 159: the && operator shall not be overloaded as short-circuit semantics cannot be obtained." + or + o.getName() = "operator||" and + message = "AV Rule 159: the || operator shall not be overloaded as short-circuit semantics cannot be obtained." + or + o.getName() = "operator&" and + o.getNumberOfParameters() = 1 and + message = "AV Rule 159: the unary & operator shall not be overloaded because of undefined behavior." +select o, message diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql index f339291976c..068715dbf8f 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 160.ql @@ -8,27 +8,27 @@ * readability * external/jsf */ + import cpp predicate multipleAssignExpr(Expr e) { e instanceof AssignExpr - or exists(CommaExpr ce | ce = e | + or + exists(CommaExpr ce | ce = e | multipleAssignExpr(ce.getLeftOperand()) and multipleAssignExpr(ce.getRightOperand()) ) - } class MultipleAssignExpr extends Expr { MultipleAssignExpr() { multipleAssignExpr(this) } Assignment getAnAssignment() { result = this.getAChild*() } - } class ForStmtSideEffectExpr extends Expr { ForStmtSideEffectExpr() { - exists (ForStmt stmt | + exists(ForStmt stmt | this = stmt.getUpdate() or this = stmt.getInitialization().getAChild().(MultipleAssignExpr).getAnAssignment() ) @@ -36,7 +36,9 @@ class ForStmtSideEffectExpr extends Expr { } from AssignExpr ae -where ae.fromSource() and - not ae.getParent() instanceof ExprStmt and - not ae instanceof ForStmtSideEffectExpr -select ae, "AV Rule 160: An assignment expression shall be used only as the exprression in an expression statement." \ No newline at end of file +where + ae.fromSource() and + not ae.getParent() instanceof ExprStmt and + not ae instanceof ForStmtSideEffectExpr +select ae, + "AV Rule 160: An assignment expression shall be used only as the exprression in an expression statement." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql index 757eb78292e..635acb42c0a 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 162.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp predicate excluded(Expr e) { @@ -15,16 +16,19 @@ predicate excluded(Expr e) { } predicate isSignedOperand(Expr e) { - e.getExplicitlyConverted().getUnderlyingType().(IntegralType).isSigned() - and not excluded(e) + e.getExplicitlyConverted().getUnderlyingType().(IntegralType).isSigned() and + not excluded(e) } + predicate isUnsignedOperand(Expr e) { - e.getExplicitlyConverted().getUnderlyingType().(IntegralType).isUnsigned() - and not excluded(e) + e.getExplicitlyConverted().getUnderlyingType().(IntegralType).isUnsigned() and + not excluded(e) } from BinaryOperation op -where (op instanceof BinaryArithmeticOperation or op instanceof ComparisonOperation) - and isSignedOperand(op.getAnOperand()) - and isUnsignedOperand(op.getAnOperand()) -select op, "AV Rule 162: signed and unsigned values shall not be mixed in arithmetic or comparison operations" \ No newline at end of file +where + (op instanceof BinaryArithmeticOperation or op instanceof ComparisonOperation) and + isSignedOperand(op.getAnOperand()) and + isUnsignedOperand(op.getAnOperand()) +select op, + "AV Rule 162: signed and unsigned values shall not be mixed in arithmetic or comparison operations" diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql index 51f970c912e..1df5b96e4a5 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 163.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp predicate excluded(Expr e) { @@ -15,12 +16,13 @@ predicate excluded(Expr e) { } predicate isUnsignedOperand(Expr e) { - e.getUnderlyingType().(IntegralType).isUnsigned() - and not excluded(e) + e.getUnderlyingType().(IntegralType).isUnsigned() and + not excluded(e) } from BinaryOperation op -where op instanceof BinaryArithmeticOperation - and isUnsignedOperand(op.getChild(0)) - and isUnsignedOperand(op.getChild(1)) -select op, "AV Rule 163: unsigned arithmetic shall not be used" \ No newline at end of file +where + op instanceof BinaryArithmeticOperation and + isUnsignedOperand(op.getChild(0)) and + isUnsignedOperand(op.getChild(1)) +select op, "AV Rule 163: unsigned arithmetic shall not be used" diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql index fca52f6ae77..a1c4dab4412 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 164.ql @@ -8,6 +8,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -26,23 +27,26 @@ predicate constantValue(Expr e, int value) { e.getUnspecifiedType() instanceof IntegralType and ( // Either the expr has a constant value - value = e.getValue().toInt() or + value = e.getValue().toInt() + or // The expr is a variable access and all values of the variable are constant - exists(VariableAccess va | va = e and - forall(Expr init | possibleValue(va.getTarget(), init) | constantValue(init,_)) and - exists(Expr init | possibleValue(va.getTarget(), init) | constantValue(init,value)) + exists(VariableAccess va | + va = e and + forall(Expr init | possibleValue(va.getTarget(), init) | constantValue(init, _)) and + exists(Expr init | possibleValue(va.getTarget(), init) | constantValue(init, value)) ) ) } predicate violation(BinaryBitwiseOperation op, int lhsBytes, int value) { - (op instanceof LShiftExpr or op instanceof RShiftExpr) and - constantValue(op.getRightOperand(), value) and - lhsBytes = op.getLeftOperand().getExplicitlyConverted().getType().getSize() and - (value < 0 or value >= lhsBytes * 8) + (op instanceof LShiftExpr or op instanceof RShiftExpr) and + constantValue(op.getRightOperand(), value) and + lhsBytes = op.getLeftOperand().getExplicitlyConverted().getType().getSize() and + (value < 0 or value >= lhsBytes * 8) } - from BinaryBitwiseOperation op, int lhsBytes, int canonicalValue where canonicalValue = min(int v | violation(op, lhsBytes, v)) -select op, "AV Rule 164: The right-hand operand (here a value is " + canonicalValue.toString() + ") of this shift shall lie between 0 and " + (lhsBytes * 8 - 1).toString() + "." \ No newline at end of file +select op, + "AV Rule 164: The right-hand operand (here a value is " + canonicalValue.toString() + + ") of this shift shall lie between 0 and " + (lhsBytes * 8 - 1).toString() + "." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql index 5ac69b2aeca..655b1b420c4 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 165.ql @@ -9,6 +9,7 @@ * reliability * external/jsf */ + import cpp /* @@ -16,6 +17,7 @@ import cpp */ from UnaryMinusExpr ume -where ume.getOperand().getExplicitlyConverted().getUnderlyingType().(IntegralType).isUnsigned() - and not ume.getOperand() instanceof Literal +where + ume.getOperand().getExplicitlyConverted().getUnderlyingType().(IntegralType).isUnsigned() and + not ume.getOperand() instanceof Literal select ume, "The unary minus operator should not be applied to an unsigned expression." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql index 9eea44cf016..16e5115a4e2 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 166.ql @@ -9,8 +9,10 @@ * correctness * external/jsf */ + import cpp import jsf.lib.section_4_21_Operators.AV_Rule_166 from SizeofImpureExprOperator sz -select sz, "A sizeof operator should not be used on expressions that contain side effects as the effect is confusing." +select sz, + "A sizeof operator should not be used on expressions that contain side effects as the effect is confusing." diff --git a/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql b/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql index 8dde82bb06c..c2a59d5155c 100644 --- a/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql +++ b/cpp/ql/src/jsf/4.21 Operators/AV Rule 168.ql @@ -8,6 +8,7 @@ * readability * external/jsf */ + import cpp /* @@ -15,6 +16,7 @@ import cpp */ from CommaExpr ce -where ce.fromSource() - and not exists (MacroInvocation me | ce = me.getAnAffectedElement()) -select ce, "AV Rule 168: The comma operator shall not be used." \ No newline at end of file +where + ce.fromSource() and + not exists(MacroInvocation me | ce = me.getAnAffectedElement()) +select ce, "AV Rule 168: The comma operator shall not be used." diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql index 3dbc992773c..5950f4f797d 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 170.ql @@ -8,9 +8,11 @@ * readability * external/jsf */ + import cpp from PointerType t, Element e -where t.getPointerIndirectionLevel() > 2 and - t.getATypeNameUse() = e -select e, "AV Rule 170: More than two levels of pointer indirection shall not be used." \ No newline at end of file +where + t.getPointerIndirectionLevel() > 2 and + t.getATypeNameUse() = e +select e, "AV Rule 170: More than two levels of pointer indirection shall not be used." diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql index 2ff8d5464c5..b295db2d648 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 171.ql @@ -8,6 +8,7 @@ * @tags correctness * external/jsf */ + import cpp import semmle.code.cpp.pointsto.PointsTo @@ -17,20 +18,23 @@ class PointerInComparison extends PointsToExpr { pointerValue(this) } - ComparisonOperation getComparison() { - result.getAChild() = this - } + ComparisonOperation getComparison() { result.getAChild() = this } } predicate mayBeCompared(PointerInComparison p, PointerInComparison q) { p.getUnderlyingType() = q.getUnderlyingType() and p.pointsTo() = q.pointsTo() + or // TODO: should handle null pointers (p and q can only be compared if either both or none can be null) // for now, just allow comparisons with null - or p.getValue() = "0" or q.getValue() = "0" + p.getValue() = "0" + or + q.getValue() = "0" } from PointerInComparison p, PointerInComparison q -where p.getComparison() = q.getComparison() and - not mayBeCompared(p, q) -select p.getComparison(), "AV Rule 171: Relational operators shall not be applied to pointer types except in very specific circumstances." \ No newline at end of file +where + p.getComparison() = q.getComparison() and + not mayBeCompared(p, q) +select p.getComparison(), + "AV Rule 171: Relational operators shall not be applied to pointer types except in very specific circumstances." diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql index b42fb665623..49ed13f1b48 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 173.ql @@ -9,6 +9,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -23,11 +24,15 @@ import cpp */ from Assignment a, Variable global, Variable local -where a.fromSource() and - global.getAnAccess() = a.getLValue().(VariableAccess) and - local.getAnAccess() = a.getRValue().(AddressOfExpr).getOperand() and - local.hasSpecifier("auto") and - (not global instanceof LocalVariable - or global.getParentScope() = local.getParentScope().getParentScope+() - or global.hasSpecifier("static")) -select a, "AV Rule 173: The address of an object with automatic storage shall not be assigned to another object that may persist after the first object has ceased to exist" \ No newline at end of file +where + a.fromSource() and + global.getAnAccess() = a.getLValue().(VariableAccess) and + local.getAnAccess() = a.getRValue().(AddressOfExpr).getOperand() and + local.hasSpecifier("auto") and + ( + not global instanceof LocalVariable or + global.getParentScope() = local.getParentScope().getParentScope+() or + global.hasSpecifier("static") + ) +select a, + "AV Rule 173: The address of an object with automatic storage shall not be assigned to another object that may persist after the first object has ceased to exist" diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql index 3662d050c3d..b722fa1f8cf 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 175.ql @@ -7,9 +7,11 @@ * @tags correctness * external/jsf */ + import cpp from NULL null -where exists (Assignment a | null = a.getRValue()) - or exists (ComparisonOperation op | null = op.getAnOperand()) -select null, "A pointer shall not be compared to NULL or be assigned NULL; use plain 0 instead." \ No newline at end of file +where + exists(Assignment a | null = a.getRValue()) or + exists(ComparisonOperation op | null = op.getAnOperand()) +select null, "A pointer shall not be compared to NULL or be assigned NULL; use plain 0 instead." diff --git a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql index 1ddce11dc2b..99bd38b4a55 100644 --- a/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql +++ b/cpp/ql/src/jsf/4.22 Pointers and References/AV Rule 176.ql @@ -8,14 +8,15 @@ * readability * external/jsf */ + import cpp -predicate allowed(TypeDeclarationEntry tde, FunctionPointerType t) -{ +predicate allowed(TypeDeclarationEntry tde, FunctionPointerType t) { tde.getDeclaration().(TypedefType).getBaseType() = t } from FunctionPointerType t, Locatable l -where t.getATypeNameUse() = l and - not allowed(l, t) -select l, "AV Rule 176: A typedef will be used when declaring function pointers." \ No newline at end of file +where + t.getATypeNameUse() = l and + not allowed(l, t) +select l, "AV Rule 176: A typedef will be used when declaring function pointers." diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql index d8738ccc158..9ca476a4d7f 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 178.ql @@ -8,6 +8,7 @@ * @tags correctness * external/jsf */ + import cpp predicate subtype(Type sub, Type sup) { @@ -15,10 +16,13 @@ predicate subtype(Type sub, Type sup) { } from Expr e, Type declared, Type converted -where e.fromSource() and - declared = e.getUnderlyingType() and - converted = e.getActualType() and - (subtype(converted.(ReferenceType).getBaseType(), declared.(ReferenceType).getBaseType()) - or - subtype(converted.(PointerType).getBaseType(), declared.(PointerType).getBaseType())) -select e, "AV Rule 178: Down casting shall only be allowed through virtual functions." \ No newline at end of file +where + e.fromSource() and + declared = e.getUnderlyingType() and + converted = e.getActualType() and + ( + subtype(converted.(ReferenceType).getBaseType(), declared.(ReferenceType).getBaseType()) + or + subtype(converted.(PointerType).getBaseType(), declared.(PointerType).getBaseType()) + ) +select e, "AV Rule 178: Down casting shall only be allowed through virtual functions." diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql index ea16c751592..9746c7aca89 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 179.ql @@ -8,13 +8,16 @@ * @tags correctness * external/jsf */ + import cpp from Expr e, Class declared, Class converted, Class sub, Class sup -where e.fromSource() and - declared = e.getUnderlyingType().(PointerType).getBaseType().getUnderlyingType() and - converted = e.getActualType().(PointerType).getBaseType().getUnderlyingType() and - converted.getABaseClass*() = sub and - sub.hasVirtualBaseClass(sup) and - sup.getABaseClass*() = declared -select e, "AV Rule 179: A pointer to a virtual base class shall not be converted to a pointer to a derived class." \ No newline at end of file +where + e.fromSource() and + declared = e.getUnderlyingType().(PointerType).getBaseType().getUnderlyingType() and + converted = e.getActualType().(PointerType).getBaseType().getUnderlyingType() and + converted.getABaseClass*() = sub and + sub.hasVirtualBaseClass(sup) and + sup.getABaseClass*() = declared +select e, + "AV Rule 179: A pointer to a virtual base class shall not be converted to a pointer to a derived class." diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql index a190874796e..4932a48eb37 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 180.ql @@ -8,98 +8,100 @@ * @tags correctness * external/jsf */ + import cpp class IntConstantExpr extends Expr { - IntConstantExpr() { - this.getType() instanceof IntegralType - and exists (this.getValue()) + this.getType() instanceof IntegralType and + exists(this.getValue()) } - int getIntValue() { - result = this.getValue().toInt() - } + int getIntValue() { result = this.getValue().toInt() } - predicate isNegative() { - this.getIntValue() < 0 - } + predicate isNegative() { this.getIntValue() < 0 } - /** Find out how many (8, 16, 32, 64) bits are required. - FIXME Currently only works up to 32 bits */ + /** + * Find out how many (8, 16, 32, 64) bits are required. + * FIXME Currently only works up to 32 bits + */ int getRequiredSizeBits() { - exists (int value | + exists(int value | value = this.getIntValue() and ( - (value < -32768 and result = 32) or - (value >= -32768 and value < -128 and result = 16) or - (value >= -128 and value < 0 and result = 8) or - (value >= 0 and value < 128 and result = 7) or - (value >= 128 and value < 256 and result = 8) or - (value >= 256 and value < 32768 and result = 15) or - (value >= 32768 and value < 65536 and result = 16) or - (value >= 65536 and value <= 2147483647 and result = 31) or - (value > 2147483647 and result = 32) + value < -32768 and result = 32 + or + value >= -32768 and value < -128 and result = 16 + or + value >= -128 and value < 0 and result = 8 + or + value >= 0 and value < 128 and result = 7 + or + value >= 128 and value < 256 and result = 8 + or + value >= 256 and value < 32768 and result = 15 + or + value >= 32768 and value < 65536 and result = 16 + or + value >= 65536 and value <= 2147483647 and result = 31 + or + value > 2147483647 and result = 32 ) ) } - } class ImplicitConversion extends Expr { - ImplicitConversion() { - super.hasImplicitConversion() - } + ImplicitConversion() { super.hasImplicitConversion() } - Type getUnderlyingSourceType() { - result = this.getUnderlyingType() - } + Type getUnderlyingSourceType() { result = this.getUnderlyingType() } - Type getUnderlyingTargetType() { - result = this.getConversion().getUnderlyingType() - } + Type getUnderlyingTargetType() { result = this.getConversion().getUnderlyingType() } int getSourceSize() { - if this instanceof IntConstantExpr then - result = this.(IntConstantExpr).getRequiredSizeBits() - else - result = this.getUnderlyingSourceType().getSize() * 8 + if this instanceof IntConstantExpr + then result = this.(IntConstantExpr).getRequiredSizeBits() + else result = this.getUnderlyingSourceType().getSize() * 8 } - int getTargetSize() { - result = this.getUnderlyingTargetType().getSize() * 8 - } + int getTargetSize() { result = this.getUnderlyingTargetType().getSize() * 8 } predicate isSourceSignedInt() { - if this instanceof IntConstantExpr then - this.(IntConstantExpr).isNegative() - else - this.getUnderlyingSourceType().(IntegralType).isSigned() - } - predicate isTargetSignedInt() { - this.getUnderlyingTargetType().(IntegralType).isSigned() + if this instanceof IntConstantExpr + then this.(IntConstantExpr).isNegative() + else this.getUnderlyingSourceType().(IntegralType).isSigned() } + + predicate isTargetSignedInt() { this.getUnderlyingTargetType().(IntegralType).isSigned() } } class LossyImplicitConversion extends ImplicitConversion { LossyImplicitConversion() { - // conversion to smaller type - super.getTargetSize() < super.getSourceSize() - // signed to unsigned conversion - or super.isSourceSignedInt() and not super.isTargetSignedInt() - // unsigned to signed conversion without increasing size - or (not super.isSourceSignedInt() and super.isTargetSignedInt() - and super.getTargetSize() = super.getSourceSize()) - // floating-integral conversion - or super.getUnderlyingSourceType() instanceof FloatingPointType and - super.getUnderlyingTargetType() instanceof IntegralType - // integral-floating conversion - or super.getUnderlyingSourceType() instanceof IntegralType and - super.getUnderlyingTargetType() instanceof FloatingPointType + // conversion to smaller type + super.getTargetSize() < super.getSourceSize() + or + // signed to unsigned conversion + super.isSourceSignedInt() and not super.isTargetSignedInt() + or + // unsigned to signed conversion without increasing size + not super.isSourceSignedInt() and + super.isTargetSignedInt() and + super.getTargetSize() = super.getSourceSize() + or + // floating-integral conversion + super.getUnderlyingSourceType() instanceof FloatingPointType and + super.getUnderlyingTargetType() instanceof IntegralType + or + // integral-floating conversion + super.getUnderlyingSourceType() instanceof IntegralType and + super.getUnderlyingTargetType() instanceof FloatingPointType } } from LossyImplicitConversion lic -where // Conversions to bool are always fine - not lic.getUnderlyingTargetType() instanceof BoolType -select lic, "AV Rule 180: implicit conversion from " + lic.getUnderlyingSourceType().toString() + " to " + lic.getUnderlyingTargetType().toString() + " may lose information" \ No newline at end of file +where + // Conversions to bool are always fine + not lic.getUnderlyingTargetType() instanceof BoolType +select lic, + "AV Rule 180: implicit conversion from " + lic.getUnderlyingSourceType().toString() + " to " + + lic.getUnderlyingTargetType().toString() + " may lose information" diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql index bad480ef016..39b29f1210d 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 181.ql @@ -8,12 +8,14 @@ * readability * external/jsf */ + import cpp from Expr e, Conversion c -where e.fromSource() and - c = e.getConversion() and - not c instanceof ParenthesisExpr and - not c.isCompilerGenerated() and - c.getUnderlyingType() = e.getUnderlyingType() -select c.findRootCause(), "AV Rule 181: Redundant explicit casts will not be used." \ No newline at end of file +where + e.fromSource() and + c = e.getConversion() and + not c instanceof ParenthesisExpr and + not c.isCompilerGenerated() and + c.getUnderlyingType() = e.getUnderlyingType() +select c.findRootCause(), "AV Rule 181: Redundant explicit casts will not be used." diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql index 9a80f93e7c4..71916391b97 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 182.ql @@ -8,6 +8,7 @@ * portability * external/jsf */ + import cpp class NullPointer extends Expr { @@ -19,15 +20,18 @@ class NullPointer extends Expr { } from Expr e, Type t1, Type t2 -where t1 = e.getUnspecifiedType() and - t2 = e.getFullyConverted().getUnspecifiedType() and - t1 != t2 and - (t1 instanceof PointerType or t2 instanceof PointerType) and - not (t2 instanceof VoidPointerType and t1 instanceof PointerType) and - // Conversion to bool type is always fine - not (t2 instanceof BoolType) and - // Ignore assigning NULL to a pointer - not e instanceof NullPointer and - // Allow array -> pointer conversion - not t1.(ArrayType).getBaseType() = t2.(PointerType).getBaseType() -select e, "AV Rule 182: illegal cast from type " + t1.toString() + " to type " + t2.toString() + ". Casting to or from pointers shall not be used" \ No newline at end of file +where + t1 = e.getUnspecifiedType() and + t2 = e.getFullyConverted().getUnspecifiedType() and + t1 != t2 and + (t1 instanceof PointerType or t2 instanceof PointerType) and + not (t2 instanceof VoidPointerType and t1 instanceof PointerType) and + // Conversion to bool type is always fine + not t2 instanceof BoolType and + // Ignore assigning NULL to a pointer + not e instanceof NullPointer and + // Allow array -> pointer conversion + not t1.(ArrayType).getBaseType() = t2.(PointerType).getBaseType() +select e, + "AV Rule 182: illegal cast from type " + t1.toString() + " to type " + t2.toString() + + ". Casting to or from pointers shall not be used" diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql index 828d655cd3d..a29b93d990e 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 184.ql @@ -9,12 +9,11 @@ * @tags correctness * external/jsf */ + import cpp // extend to allow certain conversions -predicate necessaryFloatToIntConversion(Expr e) { - none() -} +predicate necessaryFloatToIntConversion(Expr e) { none() } predicate badConversion(Expr e) { e.fromSource() and @@ -24,10 +23,11 @@ predicate badConversion(Expr e) { } from Expr e -where badConversion(e) and - // Only include outermost matches; no need to be transitive - // (should report an expr if a distant parent is a violation - // but the exprs in between are fine). Exclude brackets - not badConversion(e.getParent()) and - not e instanceof ParenthesisExpr -select e, "AV Rule 184: Floating point numbers shall not be converted to integers." \ No newline at end of file +where + badConversion(e) and + // Only include outermost matches; no need to be transitive + // (should report an expr if a distant parent is a violation + // but the exprs in between are fine). Exclude brackets + not badConversion(e.getParent()) and + not e instanceof ParenthesisExpr +select e, "AV Rule 184: Floating point numbers shall not be converted to integers." diff --git a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql index ad7aef37eb9..f5fab8debd6 100644 --- a/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql +++ b/cpp/ql/src/jsf/4.23 Type Conversions/AV Rule 185.ql @@ -8,12 +8,15 @@ * @tags correctness * external/jsf */ + import cpp from Cast c -where c.fromSource() and - c.getFile() instanceof CppFile and // Ignore C-style casts in C files - not c instanceof ConstCast and - not c instanceof ReinterpretCast and - not c instanceof StaticCast -select c.findRootCause(), "AV Rule 184: C++ style casts shall be used instead of the traditional C-style casts." \ No newline at end of file +where + c.fromSource() and + c.getFile() instanceof CppFile and // Ignore C-style casts in C files + not c instanceof ConstCast and + not c instanceof ReinterpretCast and + not c instanceof StaticCast +select c.findRootCause(), + "AV Rule 184: C++ style casts shall be used instead of the traditional C-style casts." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql index 9f56a1ab564..ed713c4b109 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 186.ql @@ -8,12 +8,13 @@ * useless-code * external/jsf */ + import cpp // whether f is to be considered an API entry point, and hence reachable by default predicate isAPI(Function f) { - f.hasName("main") - or f.(MemberFunction).hasSpecifier("public") + f.hasName("main") or + f.(MemberFunction).hasSpecifier("public") } predicate unusedFunction(Function f) { @@ -23,10 +24,8 @@ predicate unusedFunction(Function f) { f.hasDefinition() } -predicate unreachableStmt(Stmt s) { - not s.getControlFlowScope().getBlock().getASuccessor*() = s -} +predicate unreachableStmt(Stmt s) { not s.getControlFlowScope().getBlock().getASuccessor*() = s } from ControlFlowNode n where unreachableStmt(n) or unusedFunction(n) -select n, "AV Rule 186: There shall be no unreachable code." \ No newline at end of file +select n, "AV Rule 186: There shall be no unreachable code." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql index f0435485ce7..7a8919faf89 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 187.ql @@ -7,19 +7,21 @@ * @tags correctness * external/jsf */ + import cpp from Stmt s -where s.fromSource() and - // Exclude empty statements - not s instanceof EmptyStmt and - // Exclude control statements - not s instanceof LabelStmt and - not s instanceof JumpStmt and - not s instanceof ReturnStmt and - not s instanceof ControlStructure and - // Exclude blocks; if a child of the block violates the rule that will still - // be picked up so there is no point in blaming the block as well - not s instanceof Block and - s.isPure() -select s, "AV Rule 187: All non-null statements shall potentially have a side-effect." \ No newline at end of file +where + s.fromSource() and + // Exclude empty statements + not s instanceof EmptyStmt and + // Exclude control statements + not s instanceof LabelStmt and + not s instanceof JumpStmt and + not s instanceof ReturnStmt and + not s instanceof ControlStructure and + // Exclude blocks; if a child of the block violates the rule that will still + // be picked up so there is no point in blaming the block as well + not s instanceof Block and + s.isPure() +select s, "AV Rule 187: All non-null statements shall potentially have a side-effect." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql index 1c13ac90ef4..1da92d26687 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 188.ql @@ -8,8 +8,9 @@ * readability * external/jsf */ + import cpp from LabelStmt l where not exists(GotoStmt g | g.breaksFromNestedLoops() and g.getTarget() = l) -select l, "AV Rule 188: Labels will not be used, except in switch statements." \ No newline at end of file +select l, "AV Rule 188: Labels will not be used, except in switch statements." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql index 79c68166ae3..ecb20f63a1e 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 189.ql @@ -8,9 +8,11 @@ * readability * external/jsf */ + import cpp from GotoStmt s -where s.fromSource() and - not s.breaksFromNestedLoops() -select s, "AV Rule 189: The goto statement shall not be used." \ No newline at end of file +where + s.fromSource() and + not s.breaksFromNestedLoops() +select s, "AV Rule 189: The goto statement shall not be used." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql index 19a60dbc8f5..e660083ccd6 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 190.ql @@ -7,8 +7,9 @@ * @tags maintainability * external/jsf */ + import cpp from ContinueStmt s where s.fromSource() -select s, "AV Rule 190: The continue statement shall not be used." \ No newline at end of file +select s, "AV Rule 190: The continue statement shall not be used." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql index 3e643f43840..579a615c27f 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 191.ql @@ -7,19 +7,23 @@ * @tags maintainability * external/jsf */ + import cpp -/* TODO: "The break statement may be used to break out of a single loop provided +/* + * TODO: "The break statement may be used to break out of a single loop provided * the alternative would obscure or otherwise significantly complicate the - * control logic." */ + * control logic." + */ // whether t is the last statement of s, possibly peeling off blocks predicate isTerminatingStmt(Stmt s, Stmt t) { - s=t or isTerminatingStmt(s.(Block).getLastStmt(), t) + s = t or isTerminatingStmt(s.(Block).getLastStmt(), t) } from BreakStmt s -where s.fromSource() and - // exclude break statements that terminate switch cases - not exists(SwitchCase sc | isTerminatingStmt(sc.getLastStmt(), s)) -select s, "AV Rule 191: The break statement shall not be used." \ No newline at end of file +where + s.fromSource() and + // exclude break statements that terminate switch cases + not exists(SwitchCase sc | isTerminatingStmt(sc.getLastStmt(), s)) +select s, "AV Rule 191: The break statement shall not be used." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql index b20f82241cc..b546b76cfd3 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 192.ql @@ -8,6 +8,7 @@ * @tags maintainability * external/jsf */ + import cpp // the extractor associates comments with the statement immediately following them @@ -15,14 +16,17 @@ import cpp // as this seems a likely place to put a comment explaining the absence of an else predicate isCommented(IfStmt i) { exists(Comment c | - c.getCommentedElement() = i - or i.getLocation().getEndLine() = c.getLocation().getStartLine()) + c.getCommentedElement() = i or + i.getLocation().getEndLine() = c.getLocation().getStartLine() + ) } from IfStmt i -where i.fromSource() and - // only applies if there are one or more else-ifs - exists(IfStmt i2 | i2.getElse() = i) and - not i.hasElse() and - not isCommented(i) -select i, "AV Rule 192: All if-else if chains will have an else clause or a comment explaining its absence." \ No newline at end of file +where + i.fromSource() and + // only applies if there are one or more else-ifs + exists(IfStmt i2 | i2.getElse() = i) and + not i.hasElse() and + not isCommented(i) +select i, + "AV Rule 192: All if-else if chains will have an else clause or a comment explaining its absence." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql index 32754f6d20b..1d2369668d7 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 193.ql @@ -9,9 +9,11 @@ * readability * external/jsf */ + import cpp -/* Interpretation: +/* + * Interpretation: * - return statements should be okay too; if not desired another rule should catch it * - the default case should be excluded, as long as it is at the end * We don't allow the last case to omit the break/return, because that seems to violate the @@ -19,13 +21,18 @@ import cpp */ predicate lastDefaultCase(SwitchCase sc) { - sc.isDefault() and not exists(SwitchCase sc2 | sc2.getSwitchStmt() = sc.getSwitchStmt() and sc2.getChildNum() > sc.getChildNum()) + sc.isDefault() and + not exists(SwitchCase sc2 | + sc2.getSwitchStmt() = sc.getSwitchStmt() and sc2.getChildNum() > sc.getChildNum() + ) } from SwitchCase sc -where sc.fromSource() and - exists(sc.getAStmt()) and - not lastDefaultCase(sc) and - not sc.terminatesInBreakStmt() and - not sc.terminatesInReturnStmt() -select sc, "AV Rule 193: Every non-empty case clause in a switch statement shall be terminated with a break statement." \ No newline at end of file +where + sc.fromSource() and + exists(sc.getAStmt()) and + not lastDefaultCase(sc) and + not sc.terminatesInBreakStmt() and + not sc.terminatesInReturnStmt() +select sc, + "AV Rule 193: Every non-empty case clause in a switch statement shall be terminated with a break statement." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql index 82713fa58ea..98605818dcd 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 194.ql @@ -7,14 +7,22 @@ * @tags correctness * external/jsf */ + import cpp from EnumSwitch es, EnumConstant ec -where // A switch without a default case ... - not es.hasDefaultCase() and - // ... that misses at least one value ... - ec = es.getAMissingCase() and - // ... and make sure we pick a single missed value; choose the first one - not exists (EnumConstant ec2, int i, int j | - ec2 = es.getAMissingCase() and ec2 = ec2.getDeclaringEnum().getEnumConstant(i) and ec = ec.getDeclaringEnum().getEnumConstant(j) and i < j) -select es, "AV Rule 195: all switch statements that do not intend to test for every enumeration value shall contain a final default clause. This statement is missing a case for " + ec.getName() \ No newline at end of file +where + // A switch without a default case ... + not es.hasDefaultCase() and + // ... that misses at least one value ... + ec = es.getAMissingCase() and + // ... and make sure we pick a single missed value; choose the first one + not exists(EnumConstant ec2, int i, int j | + ec2 = es.getAMissingCase() and + ec2 = ec2.getDeclaringEnum().getEnumConstant(i) and + ec = ec.getDeclaringEnum().getEnumConstant(j) and + i < j + ) +select es, + "AV Rule 195: all switch statements that do not intend to test for every enumeration value shall contain a final default clause. This statement is missing a case for " + + ec.getName() diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql index 318a5879a4d..015cf8f6ae7 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 195.ql @@ -8,9 +8,11 @@ * readability * external/jsf */ + import cpp from SwitchStmt s -where s.fromSource() and - s.getExpr().getUnderlyingType() instanceof BoolType -select s, "AV Rule 195: A switch expression will not represent a Boolean value." \ No newline at end of file +where + s.fromSource() and + s.getExpr().getUnderlyingType() instanceof BoolType +select s, "AV Rule 195: A switch expression will not represent a Boolean value." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql index 33eaacee040..8424fab68a6 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 196.ql @@ -9,10 +9,13 @@ * readability * external/jsf */ + import cpp from SwitchStmt s -where s.fromSource() and - count(SwitchCase sc | sc.getSwitchStmt() = s and not sc instanceof DefaultCase) < 2 and - not exists(s.getGeneratingMacro()) -select s, "This switch statement should either handle more cases, or be rewritten as an if statement." +where + s.fromSource() and + count(SwitchCase sc | sc.getSwitchStmt() = s and not sc instanceof DefaultCase) < 2 and + not exists(s.getGeneratingMacro()) +select s, + "This switch statement should either handle more cases, or be rewritten as an if statement." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql index 9230255a9a0..4f76b4c10ea 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 197.ql @@ -9,6 +9,7 @@ * reliability * external/jsf */ + import cpp from LoopCounter lc diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql index 5b1058b42d7..da151e1c8c7 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 198.ql @@ -9,14 +9,17 @@ * readability * external/jsf */ + import cpp predicate isValidLoopInitialization(Stmt s) { - s instanceof DeclStmt - or s.(ExprStmt).getExpr() instanceof AssignExpr + s instanceof DeclStmt or + s.(ExprStmt).getExpr() instanceof AssignExpr } from ForStmt for -where for.fromSource() and - not isValidLoopInitialization(for.getInitialization()) -select for, "AV Rule 198: The initialization statement in a for loop will only initialize a single loop parameter." \ No newline at end of file +where + for.fromSource() and + not isValidLoopInitialization(for.getInitialization()) +select for, + "AV Rule 198: The initialization statement in a for loop will only initialize a single loop parameter." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql index 2cb5e918c44..3efe68d54a0 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 199.ql @@ -9,15 +9,18 @@ * readability * external/jsf */ + import cpp predicate isValidLoopUpdate(Expr e) { - e instanceof CrementOperation - or e instanceof AssignExpr - or e instanceof FunctionCall // this is to account for overloaded operators + e instanceof CrementOperation or + e instanceof AssignExpr or + e instanceof FunctionCall // this is to account for overloaded operators } from ForStmt for -where for.fromSource() and - not isValidLoopUpdate(for.getUpdate()) -select for, "AV Rule 199: The increment expression in a for loop will only update a single for loop parameter." \ No newline at end of file +where + for.fromSource() and + not isValidLoopUpdate(for.getUpdate()) +select for, + "AV Rule 199: The increment expression in a for loop will only update a single for loop parameter." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql index 159074279ea..9fcf0c38dde 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 200.ql @@ -8,9 +8,11 @@ * @tags maintainability * external/jsf */ + import cpp from ForStmt f -where f.fromSource() and - (not exists(f.getInitialization()) or not exists(f.getUpdate())) -select f, "AV Rule 200: Every for loop will have non-null initialize and increment expressions." \ No newline at end of file +where + f.fromSource() and + (not exists(f.getInitialization()) or not exists(f.getUpdate())) +select f, "AV Rule 200: Every for loop will have non-null initialize and increment expressions." diff --git a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql index fa9510681d5..6af7e3c367a 100644 --- a/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql +++ b/cpp/ql/src/jsf/4.24 Control Flow Structures/AV Rule 201.ql @@ -9,6 +9,7 @@ * readability * external/jsf */ + import cpp import Likely_Bugs.NestedLoopSameVar @@ -22,23 +23,26 @@ predicate loopModification(ForStmt for, Variable loopVariable, VariableAccess ac pragma[noopt] predicate stmtInForBody(Stmt stmt, ForStmt forStmt) { - (forStmt.getStmt() = stmt or exists(StmtParent parent | parent = stmt.getParent() | stmtInForBody(parent, forStmt))) - and forStmt instanceof ForStmt + ( + forStmt.getStmt() = stmt + or + exists(StmtParent parent | parent = stmt.getParent() | stmtInForBody(parent, forStmt)) + ) and + forStmt instanceof ForStmt } from ForStmt for, Variable loopVariable, VariableAccess acc where loopModification(for, loopVariable, acc) and - // field accesses must have the same object ( - loopVariable instanceof Field implies + loopVariable instanceof Field + implies exists(Variable obj | simpleFieldAccess(obj, loopVariable, acc) and simpleFieldAccess(obj, loopVariable, for.getCondition().getAChild*()) ) ) and - // don't duplicate results from NestedLoopSameVar.ql not exists(ForStmt inner | nestedForViolation(inner, loopVariable, for) and @@ -47,6 +51,4 @@ where acc.getParent*() = inner.getInitialization() ) ) -select - acc, "Loop counters should not be modified in the body of the $@.", - for.getStmt(), "loop" +select acc, "Loop counters should not be modified in the body of the $@.", for.getStmt(), "loop" diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql index 4b3b8330f70..005e7b8b0c0 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 202.ql @@ -7,6 +7,7 @@ * @tags correctness * external/jsf */ + import cpp /* @@ -14,6 +15,8 @@ import cpp */ from EqualityOperation e -where e.fromSource() and - e.getAnOperand().getType() instanceof FloatingPointType -select e, "AV Rule 202: Floating point variables shall not be tested for exact equality or inequality." \ No newline at end of file +where + e.fromSource() and + e.getAnOperand().getType() instanceof FloatingPointType +select e, + "AV Rule 202: Floating point variables shall not be tested for exact equality or inequality." diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql index 132084c0488..45d0431ebc8 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.1.ql @@ -7,27 +7,35 @@ * @tags correctness * external/jsf */ + import cpp class SideEffectVariableExpr extends VariableAccess { SideEffectVariableExpr() { - exists(CrementOperation o | o.getOperand() = this) - or exists(AssignExpr e | e.getLValue() = this) + exists(CrementOperation o | o.getOperand() = this) or + exists(AssignExpr e | e.getLValue() = this) } } predicate characteristicSequencePointExpr(Expr e, Expr c) { - if exists(Expr p | p = e.getParent() and not p instanceof BinaryLogicalOperation - and not p instanceof CommaExpr and not p instanceof ConditionalExpr) then - characteristicSequencePointExpr(e.getParent(), c) - else - e = c + if + exists(Expr p | + p = e.getParent() and + not p instanceof BinaryLogicalOperation and + not p instanceof CommaExpr and + not p instanceof ConditionalExpr + ) + then characteristicSequencePointExpr(e.getParent(), c) + else e = c } from SideEffectVariableExpr e, Expr c, Variable v, VariableAccess va -where e.getTarget() = v and va.getTarget() = v and - characteristicSequencePointExpr(e, c) - and characteristicSequencePointExpr(va, c) - and va != e - and not e.getParent().(AssignExpr).getLValue() = e -select c, "AV Rule 204.1: The value of an expression shall be the same under any order of evaluation that the standard permits" +where + e.getTarget() = v and + va.getTarget() = v and + characteristicSequencePointExpr(e, c) and + characteristicSequencePointExpr(va, c) and + va != e and + not e.getParent().(AssignExpr).getLValue() = e +select c, + "AV Rule 204.1: The value of an expression shall be the same under any order of evaluation that the standard permits" diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql index 676e4789244..50c4f431dba 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 204.ql @@ -11,6 +11,7 @@ * readability * external/jsf */ + import cpp // whether the main operation of e is pure (not considering its operands) @@ -24,42 +25,44 @@ predicate isPureOperation(Expr e) { // pure operators such that e is the only non-constant subexpression // e.g., in x = g(y) + 1, if e is g(y), then f is g(y) + 1 predicate stripOffConstants(Expr e, Expr f) { - (not isPureOperation(e.getParent()) and f=e) - - or exists(Operation p | - p = e.getParent() and - isPureOperation(p) and - (if forall(Expr g | g = p.getAChild() and e != g | g.isConstant()) then - stripOffConstants(p, f) - else f=e)) + not isPureOperation(e.getParent()) and f = e + or + exists(Operation p | + p = e.getParent() and + isPureOperation(p) and + ( + if forall(Expr g | g = p.getAChild() and e != g | g.isConstant()) + then stripOffConstants(p, f) + else f = e + ) + ) } // whether e occurs by itself as a statement predicate occursByItself(Expr e) { - exists(ExprStmt s | e = s.getExpr()) - or exists(ForStmt s | s.getUpdate() = e) + exists(ExprStmt s | e = s.getExpr()) or + exists(ForStmt s | s.getUpdate() = e) } // whether e is the source of an assignment or an initializer predicate isOnRightOfAssignment(Expr e) { - exists(Assignment a | a.getRValue() = e) - or exists(Initializer i | i.getExpr() = e) + exists(Assignment a | a.getRValue() = e) or + exists(Initializer i | i.getExpr() = e) } // whether e is a loop condition, an if condition, or a switch expression -predicate isControllingExpr(Expr e) { - exists(ControlStructure c | c.getControllingExpr() = e) -} +predicate isControllingExpr(Expr e) { exists(ControlStructure c | c.getControllingExpr() = e) } // whether e is the only impure argument expression of a function call predicate isSoleNonConstFunArg(Expr e) { - exists(FunctionCall fc | fc.getAnArgument() = e and forall(Expr g | g = fc.getAnArgument() and g!=e | g.isPure())) + exists(FunctionCall fc | + fc.getAnArgument() = e and + forall(Expr g | g = fc.getAnArgument() and g != e | g.isPure()) + ) } // whether e occurs as part of a chain of qualifiers -predicate isPartOfChain(Expr e) { - qualifies(e, _) or qualifies(_, e) -} +predicate isPartOfChain(Expr e) { qualifies(e, _) or qualifies(_, e) } // whether q qualifies e predicate qualifies(Expr q, Expr e) { @@ -68,23 +71,26 @@ predicate qualifies(Expr q, Expr e) { predicate impureExprInDisallowedContext(Expr e) { exists(Expr f | - e.fromSource() and - not e.isPure() and - stripOffConstants(e, f) and - not occursByItself(f) and - not isOnRightOfAssignment(f) and - not isControllingExpr(f) and - not isSoleNonConstFunArg(f) and - not isPartOfChain(f)) + e.fromSource() and + not e.isPure() and + stripOffConstants(e, f) and + not occursByItself(f) and + not isOnRightOfAssignment(f) and + not isControllingExpr(f) and + not isSoleNonConstFunArg(f) and + not isPartOfChain(f) + ) } from Expr e -where impureExprInDisallowedContext(e) and - not e.isCompilerGenerated() and - // A few cases that are always ok - not e instanceof Conversion and - not exists(@ctorinit ci | e = mkElement(ci)) and - not exists(@dtordestruct dd | e = mkElement(dd)) and - // Avoid flagging nested expressions - not impureExprInDisallowedContext(e.getParent+()) -select e.findRootCause(), "AV Rule 204: A single operation with side-effects shall only be used in certain contexts." +where + impureExprInDisallowedContext(e) and + not e.isCompilerGenerated() and + // A few cases that are always ok + not e instanceof Conversion and + not exists(@ctorinit ci | e = mkElement(ci)) and + not exists(@dtordestruct dd | e = mkElement(dd)) and + // Avoid flagging nested expressions + not impureExprInDisallowedContext(e.getParent+()) +select e.findRootCause(), + "AV Rule 204: A single operation with side-effects shall only be used in certain contexts." diff --git a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql index e468e38a980..26567638dea 100644 --- a/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql +++ b/cpp/ql/src/jsf/4.25 Expressions/AV Rule 205.ql @@ -7,6 +7,7 @@ * @tags efficiency * external/jsf */ + import cpp // whether it is acceptable for s to be declared volatile @@ -16,6 +17,8 @@ predicate acceptableVolatile(Variable v) { } from Variable v -where v.getType().hasSpecifier("volatile") and - not acceptableVolatile(v) -select v, "AV Rule 205: The volatile keyword shall not be used unless directly interfacing with hardware." \ No newline at end of file +where + v.getType().hasSpecifier("volatile") and + not acceptableVolatile(v) +select v, + "AV Rule 205: The volatile keyword shall not be used unless directly interfacing with hardware." diff --git a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql index da5c599615a..7de2e4bc0cc 100644 --- a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql +++ b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 206.ql @@ -8,6 +8,7 @@ * @tags resources * external/jsf */ + import cpp predicate occursAfterInitialization(Expr e) { @@ -17,4 +18,4 @@ predicate occursAfterInitialization(Expr e) { from Expr e where isMemoryManagementExpr(e) and occursAfterInitialization(e) -select e, "AV Rule 206: Memory management shall not occur after initialization." \ No newline at end of file +select e, "AV Rule 206: Memory management shall not occur after initialization." diff --git a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql index c9d4015cb40..04d5c599680 100644 --- a/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql +++ b/cpp/ql/src/jsf/4.26 Memory Allocation/AV Rule 207.ql @@ -8,24 +8,26 @@ * modularity * external/jsf */ + import cpp predicate unencapsulated(Type t) { - exists(Type base | base = t.getUnderlyingType() and + exists(Type base | + base = t.getUnderlyingType() and ( - base instanceof ArithmeticType or - base instanceof Enum or - base instanceof StructLikeClass or - unencapsulated(base.(PointerType).getBaseType()) or - unencapsulated(base.(SpecifiedType).getBaseType()) or - unencapsulated(base.(ReferenceType).getBaseType()) + base instanceof ArithmeticType or + base instanceof Enum or + base instanceof StructLikeClass or + unencapsulated(base.(PointerType).getBaseType()) or + unencapsulated(base.(SpecifiedType).getBaseType()) or + unencapsulated(base.(ReferenceType).getBaseType()) ) ) } - from GlobalVariable gv -where unencapsulated(gv.getType()) - // Allow immutable global constants - and not gv.getType().isDeeplyConst() -select gv, "AV Rule 207: Unencapsulated global data will be avoided." \ No newline at end of file +where + unencapsulated(gv.getType()) and + // Allow immutable global constants + not gv.getType().isDeeplyConst() +select gv, "AV Rule 207: Unencapsulated global data will be avoided." diff --git a/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql b/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql index 26c2d25b784..5e97444e214 100644 --- a/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql +++ b/cpp/ql/src/jsf/4.27 Fault Handling/AV Rule 208.ql @@ -7,8 +7,9 @@ * @tags language-features * external/jsf */ + import cpp from Element e where e instanceof TryStmt or e instanceof ThrowExpr -select e, "AV Rule 208: C++ exceptions shall not be used." \ No newline at end of file +select e, "AV Rule 208: C++ exceptions shall not be used." diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql index 964eec6bbe4..b881c5ed601 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 209.ql @@ -10,11 +10,18 @@ * portability * external/jsf */ + import cpp from Element u, ArithmeticType at -where (at.hasName("int") or at.hasName("short") or at.hasName("long") - or at.hasName("float") or at.hasName("double")) and - u = at.getATypeNameUse() and - not at instanceof WideCharType +where + ( + at.hasName("int") or + at.hasName("short") or + at.hasName("long") or + at.hasName("float") or + at.hasName("double") + ) and + u = at.getATypeNameUse() and + not at instanceof WideCharType select u, "AV Rule 209: The basic types of int, short, long, float and double shall not be used." diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql index 113c039baec..c12edf0c02a 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 210.ql @@ -10,9 +10,11 @@ * portability * external/jsf */ + import cpp -/* The standard lists three things that are disallowed in particular: +/* + * The standard lists three things that are disallowed in particular: * - relying on big vs. little endian representation * - relying on base class subobject ordering in derived classes * - relying on nonstatic data member ordering across access specifiers @@ -20,7 +22,8 @@ import cpp * We currently only check for violations of the first one, in a similar way * to AV Rule 147: No casts from pointers to/arrays of integrals to pointers to * integrals of a different size, no unions that both contain an integral and - * an array of smaller integrals. */ + * an array of smaller integrals. + */ class PointerOrArrayType extends DerivedType { PointerOrArrayType() { this instanceof PointerType or this instanceof ArrayType } @@ -29,35 +32,39 @@ class PointerOrArrayType extends DerivedType { // cast from pointer to integral type to pointer to a different integral type class ExposingIntegralCastExpr extends Expr { ExposingIntegralCastExpr() { - exists(PointerOrArrayType src, PointerOrArrayType dst, IntegralType srcbase, IntegralType dstbase | + exists( + PointerOrArrayType src, PointerOrArrayType dst, IntegralType srcbase, IntegralType dstbase + | src = this.getUnderlyingType() and srcbase = src.getBaseType().getUnderlyingType() and dst = this.getActualType() and dstbase = dst.getBaseType().getUnderlyingType() and - srcbase != dstbase) + srcbase != dstbase + ) } } class ExposingIntegralUnion extends Union { ExposingIntegralUnion() { - exists (MemberVariable mv1, MemberVariable mv2, IntegralType mv1tp, IntegralType mv2tp | + exists(MemberVariable mv1, MemberVariable mv2, IntegralType mv1tp, IntegralType mv2tp | mv1 = this.getAMemberVariable() and mv2 = this.getAMemberVariable() and mv1tp = mv1.getUnderlyingType().(IntegralType) and - (mv2tp = mv2.getUnderlyingType().(IntegralType) - or - mv2tp = mv2.getUnderlyingType().(ArrayType).getBaseType().getUnderlyingType().(IntegralType)) and - mv1tp.getSize() > mv2tp.getSize()) + ( + mv2tp = mv2.getUnderlyingType().(IntegralType) + or + mv2tp = mv2.getUnderlyingType().(ArrayType).getBaseType().getUnderlyingType().(IntegralType) + ) and + mv1tp.getSize() > mv2tp.getSize() + ) } } from Element e, string message where - ( - e instanceof ExposingIntegralCastExpr and - message = "AV Rule 210: This cast makes assumptions concerning data representation in memory." - ) or ( - e instanceof ExposingIntegralUnion and - message = "AV Rule 210: This union may make assumptions concerning data representation in memory." - ) + e instanceof ExposingIntegralCastExpr and + message = "AV Rule 210: This cast makes assumptions concerning data representation in memory." + or + e instanceof ExposingIntegralUnion and + message = "AV Rule 210: This union may make assumptions concerning data representation in memory." select e, message diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql index 83f427418da..79bf17ec946 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 212.ql @@ -9,6 +9,7 @@ * portability * external/jsf */ + import cpp /* @@ -16,12 +17,12 @@ import cpp */ predicate isNonNegative(Expr e) { - e.getUnderlyingType().(IntegralType).isUnsigned() - or e.getValue().toInt() >= 0 + e.getUnderlyingType().(IntegralType).isUnsigned() or + e.getValue().toInt() >= 0 } predicate sameExpr(Expr e, Expr f) { - e.(VariableAccess).getTarget() = f.(VariableAccess).getTarget() + e.(VariableAccess).getTarget() = f.(VariableAccess).getTarget() // adding the following disjunct OOMs on non-trivial databases //or e.getValue() = f.getValue() } @@ -33,10 +34,14 @@ class UnreliableOverflowTest extends LTExpr { a = l.getLeftOperand() and b = l.getRightOperand() and r = super.getRightOperand() and - ( sameExpr(a, r) and isNonNegative(b) - or sameExpr(b, r) and isNonNegative(a))) + ( + sameExpr(a, r) and isNonNegative(b) + or + sameExpr(b, r) and isNonNegative(a) + ) + ) } } from UnreliableOverflowTest t -select t, "AV Rule 212: Underflow or overflow functioning shall not be depended on." \ No newline at end of file +select t, "AV Rule 212: Underflow or overflow functioning shall not be depended on." diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql index af03ca801c8..fbfe211cb19 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 213.ql @@ -9,6 +9,7 @@ * readability * external/jsf */ + import cpp /* @@ -21,17 +22,19 @@ import cpp * RATIONALE: x==y+z is common and unambiguous */ -predicate arithmeticPrecedence(int p) { p = 12 or p = 13 } +predicate arithmeticPrecedence(int p) { p = 12 or p = 13 } + predicate comparisonPrecedence(int p) { p = 9 or p = 10 } from Expr e1, Expr e2, int p1, int p2 -where e1.getAChild() = e2 and - p1 = e1.getPrecedence() and - p2 = e2.getPrecedence() and - p1 < p2 and - not e2.isParenthesised() and - p1 <= 11 and - p2 <= 13 and // allow > arithmetic operators - not (arithmeticPrecedence(p2) and comparisonPrecedence(p1)) and // arith-compare deviation - not e2 = e1.(Assignment).getRValue() // assignment deviation -select e1, "AV Rule 213: Limited dependence shall be placed on operator precedence rules." \ No newline at end of file +where + e1.getAChild() = e2 and + p1 = e1.getPrecedence() and + p2 = e2.getPrecedence() and + p1 < p2 and + not e2.isParenthesised() and + p1 <= 11 and + p2 <= 13 and // allow > arithmetic operators + not (arithmeticPrecedence(p2) and comparisonPrecedence(p1)) and // arith-compare deviation + not e2 = e1.(Assignment).getRValue() // assignment deviation +select e1, "AV Rule 213: Limited dependence shall be placed on operator precedence rules." diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql index fb267186095..07655e3890f 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 214.ql @@ -8,12 +8,15 @@ * @tags correctness * external/jsf */ + import cpp // whether e is part of an initializer of a global variable in file f predicate inGlobalInitializer(Expr e, File f) { - exists(GlobalVariable gv | gv.getInitializer().getExpr() = e.getParent*() and - f = gv.getFile()) + exists(GlobalVariable gv | + gv.getInitializer().getExpr() = e.getParent*() and + f = gv.getFile() + ) } // whether c is called from within a global initializer in f @@ -24,7 +27,8 @@ predicate calledFromGlobalInitializer(Function fn, File f) { predicate evaluatedBeforeMain(Expr e, File f) { inGlobalInitializer(e, f) - or exists(Function fn | calledFromGlobalInitializer(fn, f) and fn = e.getControlFlowScope()) + or + exists(Function fn | calledFromGlobalInitializer(fn, f) and fn = e.getControlFlowScope()) } // whether f1 and f2 belong to the same translation unit @@ -33,9 +37,11 @@ predicate sameTranslationUnit(File f1, File f2) { } from VariableAccess v, File f1, File f2 -where v.fromSource() and - v.isRValue() and - evaluatedBeforeMain(v, f1) and - v.getTarget().getFile() = f2 and - not sameTranslationUnit(f1, f2) -select v, "AV Rule 214: It shall not be assumed that objects in separated translation units are initialized in a special order." \ No newline at end of file +where + v.fromSource() and + v.isRValue() and + evaluatedBeforeMain(v, f1) and + v.getTarget().getFile() = f2 and + not sameTranslationUnit(f1, f2) +select v, + "AV Rule 214: It shall not be assumed that objects in separated translation units are initialized in a special order." diff --git a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql index 642feb697a7..92b75c13650 100644 --- a/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql +++ b/cpp/ql/src/jsf/4.28 Portable Code/AV Rule 215.ql @@ -8,8 +8,9 @@ * language-features * external/jsf */ + import cpp from PointerArithmeticOperation pao where pao.fromSource() -select pao, "AV Rule 215: Pointer arithmetic will not be used." \ No newline at end of file +select pao, "AV Rule 215: Pointer arithmetic will not be used." diff --git a/cpp/ql/src/jsf/lib/section_4_21_Operators/AV_Rule_166.qll b/cpp/ql/src/jsf/lib/section_4_21_Operators/AV_Rule_166.qll index 6e7176fb86d..0e316e86892 100644 --- a/cpp/ql/src/jsf/lib/section_4_21_Operators/AV_Rule_166.qll +++ b/cpp/ql/src/jsf/lib/section_4_21_Operators/AV_Rule_166.qll @@ -1,19 +1,20 @@ import cpp class IgnoreAllVolatileSpecifiersEverywhere extends Specifier { - override string getName() { result = super.getName() and result != "volatile" } + override string getName() { result = super.getName() and result != "volatile" } } class SizeofImpureExprOperator extends SizeofExprOperator { - SizeofImpureExprOperator () { - exists (Expr e | - e = this.getExprOperand() - and not e.isPure() - and not e.isAffectedByMacro() - and not e.(OverloadedPointerDereferenceExpr).getExpr().isPure() - and not exists(OverloadedArrayExpr op | op = e | - op.getArrayBase().isPure() - and op.getArrayOffset().isPure())) - } + SizeofImpureExprOperator() { + exists(Expr e | + e = this.getExprOperand() and + not e.isPure() and + not e.isAffectedByMacro() and + not e.(OverloadedPointerDereferenceExpr).getExpr().isPure() and + not exists(OverloadedArrayExpr op | op = e | + op.getArrayBase().isPure() and + op.getArrayOffset().isPure() + ) + ) + } } - diff --git a/cpp/ql/src/semmle/code/cpp/ASTSanity.ql b/cpp/ql/src/semmle/code/cpp/ASTSanity.ql index 3eef95621c4..aeb05379f8c 100644 --- a/cpp/ql/src/semmle/code/cpp/ASTSanity.ql +++ b/cpp/ql/src/semmle/code/cpp/ASTSanity.ql @@ -1,6 +1,6 @@ /** * @name AST Sanity Check - * @description Performs sanity checks on the Abstract Syntax Tree. This query should have no results. + * @description Performs sanity checks on the Abstract Syntax Tree. This query should have no results. * @kind table * @id cpp/ast-sanity-check */ diff --git a/cpp/ql/src/semmle/code/cpp/AutogeneratedFile.qll b/cpp/ql/src/semmle/code/cpp/AutogeneratedFile.qll index b766d4f854f..d70da222de2 100644 --- a/cpp/ql/src/semmle/code/cpp/AutogeneratedFile.qll +++ b/cpp/ql/src/semmle/code/cpp/AutogeneratedFile.qll @@ -6,45 +6,37 @@ import semmle.code.cpp.Preprocessor * Holds if comment `c` indicates that it might be in an auto-generated file, for * example because it contains the text "auto-generated by". */ -private bindingset[comment] predicate autogeneratedComment(string comment) { +bindingset[comment] +private predicate autogeneratedComment(string comment) { // ?s = include newlines in anything (`.`) // ?i = ignore case exists(string cond | cond = // generated by (not mid-sentence) - "(^ generated by[^a-z])|" + - "(! generated by[^a-z])|" + - - // generated file - "(generated file)|" + - - // file [is/was/has been] generated - "(file( is| was| has been)? generated)|" + - - // changes made in this file will be lost - "(changes made in this file will be lost)|" + - - // do not edit/modify (not mid-sentence) - "(^ do(n't|nt| not) (hand-?)?(edit|modify))|" + - "(! do(n't|nt| not) (hand-?)?(edit|modify))|" + - - // do not edit/modify + generated - "(do(n't|nt| not) (hand-?)?(edit|modify).*generated)|" + - "(generated.*do(n't|nt| not) (hand-?)?(edit|modify))" and - - comment.regexpMatch("(?si).*(" + - // replace `generated` with a regexp that also catches things like - // `auto-generated`. - cond.replaceAll("generated", "(auto[\\w-]*[\\s/\\*\\r\\n]*)?generated") - - // replace `!` with a regexp for end-of-sentence / separator characters. - .replaceAll("!", "[\\.\\?\\!\\-\\;\\,]") - - // replace ` ` with a regexp for one or more whitespace characters - // (including newlines and `/*`). - .replaceAll(" ", "[\\s/\\*\\r\\n]+") + - ").*" - ) + "(^ generated by[^a-z])|" + "(! generated by[^a-z])|" + + // generated file + "(generated file)|" + + // file [is/was/has been] generated + "(file( is| was| has been)? generated)|" + + // changes made in this file will be lost + "(changes made in this file will be lost)|" + + // do not edit/modify (not mid-sentence) + "(^ do(n't|nt| not) (hand-?)?(edit|modify))|" + + "(! do(n't|nt| not) (hand-?)?(edit|modify))|" + + // do not edit/modify + generated + "(do(n't|nt| not) (hand-?)?(edit|modify).*generated)|" + + "(generated.*do(n't|nt| not) (hand-?)?(edit|modify))" and + comment + .regexpMatch("(?si).*(" + + // replace `generated` with a regexp that also catches things like + // `auto-generated`. + cond + .replaceAll("generated", "(auto[\\w-]*[\\s/\\*\\r\\n]*)?generated") + // replace `!` with a regexp for end-of-sentence / separator characters. + .replaceAll("!", "[\\.\\?\\!\\-\\;\\,]") + // replace ` ` with a regexp for one or more whitespace characters + // (including newlines and `/*`). + .replaceAll(" ", "[\\s/\\*\\r\\n]+") + ").*") ) } @@ -54,12 +46,13 @@ private bindingset[comment] predicate autogeneratedComment(string comment) { * Such pragmas usually indicate that the file was automatically generated. */ predicate hasPragmaDifferentFile(File f) { - exists (PreprocessorLine pl, string s | + exists(PreprocessorLine pl, string s | pl.getFile() = f and - pl.getHead().splitAt(" ", 1) = s and /* Zero index is line number, one index is file reference */ - not ("\"" + f.getAbsolutePath() + "\"" = s) and - not ("\"" + f.getRelativePath() + "\"" = s) and - not ("\"" + f.getBaseName() + "\"" = s) + pl.getHead().splitAt(" ", 1) = s and + /* Zero index is line number, one index is file reference */ + not "\"" + f.getAbsolutePath() + "\"" = s and + not "\"" + f.getRelativePath() + "\"" = s and + not "\"" + f.getBaseName() + "\"" = s ) } @@ -69,12 +62,12 @@ predicate hasPragmaDifferentFile(File f) { */ private int fileFirstComment(File f) { result = min(int line | - exists(Comment c | - c.getFile() = f and - c.getLocation().getStartLine() = line and - line < 5 - ) - ).minimum(5) + exists(Comment c | + c.getFile() = f and + c.getLocation().getStartLine() = line and + line < 5 + ) + ).minimum(5) } /** @@ -85,23 +78,29 @@ private int fileHeaderLimit(File f) { exists(int fc | fc = fileFirstComment(f) and result = min(int line | - exists(DeclarationEntry de, Location l | - l = de.getLocation() and - l.getFile() = f and - line = l.getStartLine() - 1 and - line > fc - ) or exists(PreprocessorDirective pd, Location l | - l = pd.getLocation() and - l.getFile() = f and - line = l.getStartLine() - 1 and - line > fc - ) or exists(NamespaceDeclarationEntry nde, Location l | - l = nde.getLocation() and - l.getFile() = f and - line = l.getStartLine() - 1 and - line > fc - ) or line = f.getMetrics().getNumberOfLines() - ) + exists(DeclarationEntry de, Location l | + l = de.getLocation() and + l.getFile() = f and + line = l.getStartLine() - 1 and + line > fc + ) + or + exists(PreprocessorDirective pd, Location l | + l = pd.getLocation() and + l.getFile() = f and + line = l.getStartLine() - 1 and + line > fc + ) + or + exists(NamespaceDeclarationEntry nde, Location l | + l = nde.getLocation() and + l.getFile() = f and + line = l.getStartLine() - 1 and + line > fc + ) + or + line = f.getMetrics().getNumberOfLines() + ) ) } @@ -115,14 +114,14 @@ private int fileHeaderLimit(File f) { * 2. There is a `#line` directive referring to a different file. */ class AutogeneratedFile extends File { - cached AutogeneratedFile() { - autogeneratedComment( - strictconcat(Comment c | + cached + AutogeneratedFile() { + autogeneratedComment(strictconcat(Comment c | c.getFile() = this and - c.getLocation().getStartLine() <= fileHeaderLimit(this) | + c.getLocation().getStartLine() <= fileHeaderLimit(this) + | c.getContents() order by c.getLocation().getStartLine() - ) - ) or + )) or hasPragmaDifferentFile(this) } } diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 5c14acdea34..5ac4f52392e 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -15,7 +15,7 @@ private import semmle.code.cpp.internal.ResolveClass * public: * MyClass(); * }; - * + * * struct MyStruct { * int x, y, z; * }; @@ -27,9 +27,7 @@ private import semmle.code.cpp.internal.ResolveClass * ``` */ class Class extends UserType { - Class() { - isClass(underlyingElement(this)) - } + Class() { isClass(underlyingElement(this)) } override string getCanonicalQLClass() { result = "Class" } @@ -53,9 +51,7 @@ class Class extends UserType { * If you also want instantiations of the template, then use * `getAMemberFunction()` instead. */ - MemberFunction getACanonicalMemberFunction() { - result = this.getACanonicalMember() - } + MemberFunction getACanonicalMemberFunction() { result = this.getACanonicalMember() } /** * Gets a member variable declared in this class, struct or union. @@ -94,7 +90,9 @@ class Class extends UserType { * If you also want template instantiations of results, see * `getAMember(int)`. */ - Declaration getCanonicalMember(int index) { member(underlyingElement(this),index,unresolveElement(result)) } + Declaration getCanonicalMember(int index) { + member(underlyingElement(this), index, unresolveElement(result)) + } /** * Gets the (zero-based) `index`th canonical member declared in this @@ -113,7 +111,9 @@ class Class extends UserType { * DEPRECATED: Use `getCanonicalMember(int)` or `getAMember(int)` instead. * Gets the `index`th member of this class. */ - deprecated Declaration getMember(int index) { member(underlyingElement(this),index,unresolveElement(result)) } + deprecated Declaration getMember(int index) { + member(underlyingElement(this), index, unresolveElement(result)) + } /** * DEPRECATED: As this includes a somewhat arbitrary number of @@ -131,9 +131,7 @@ class Class extends UserType { * instantiation of that template. For just the template, use * `getAPrivateCanonicalMember()`. */ - Declaration getAPrivateMember() { - result = this.getAMember() and result.hasSpecifier("private") - } + Declaration getAPrivateMember() { result = this.getAMember() and result.hasSpecifier("private") } /** * Gets a private canonical member declared in this class, struct or union. @@ -169,9 +167,7 @@ class Class extends UserType { * instantiation of that template. For just the template, use * `getAPublicCanonicalMember()`. */ - Declaration getAPublicMember() { - result = this.getAMember() and result.hasSpecifier("public") - } + Declaration getAPublicMember() { result = this.getAMember() and result.hasSpecifier("public") } /** * Gets a public canonical member declared in this class, struct or union. @@ -183,9 +179,7 @@ class Class extends UserType { } /** Gets a static member declared in this class, struct or union. */ - Declaration getAStaticMember() { - result = this.getAMember() and result.isStatic() - } + Declaration getAStaticMember() { result = this.getAMember() and result.isStatic() } /** Gets a field of this class, struct or union. */ Field getAField() { result = this.getAMemberVariable() } @@ -233,16 +227,13 @@ class Class extends UserType { * Like accessOfBaseMember but returns multiple results if there are multiple * paths to `base` through the inheritance graph. */ - private AccessSpecifier accessOfBaseMemberMulti(Class base, - AccessSpecifier fieldInBase) - { - (this = base and result = fieldInBase) + private AccessSpecifier accessOfBaseMemberMulti(Class base, AccessSpecifier fieldInBase) { + this = base and result = fieldInBase or exists(ClassDerivation cd | cd.getBaseClass() = base | - result = this.accessOfBaseMemberMulti( - cd.getDerivedClass(), - fieldInBase.accessInDirectDerived(cd.getASpecifier().(AccessSpecifier)) - ) + result = this + .accessOfBaseMemberMulti(cd.getDerivedClass(), + fieldInBase.accessInDirectDerived(cd.getASpecifier().(AccessSpecifier))) ) } @@ -256,9 +247,7 @@ class Class extends UserType { // If there are multiple paths through the inheritance graph, we take the // most permissive one (C++14 11.6/1). This implementation relies on the // alphabetical order of "private", "protected", "public". - result.hasName( - max(this.accessOfBaseMemberMulti(base, fieldInBase).getName()) - ) + result.hasName(max(this.accessOfBaseMemberMulti(base, fieldInBase).getName())) } /** @@ -268,27 +257,21 @@ class Class extends UserType { * includes the case of `base` = `this`. */ AccessSpecifier accessOfBaseMember(Declaration member) { - result = this.accessOfBaseMember( - member.getDeclaringType(), - member.getASpecifier().(AccessSpecifier) - ) + result = this + .accessOfBaseMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier)) } /** * DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that * `= default` members are no longer included. */ - deprecated predicate hasGeneratedCopyConstructor() { - hasImplicitCopyConstructor() - } + deprecated predicate hasGeneratedCopyConstructor() { hasImplicitCopyConstructor() } /** * DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to * reflect that `= default` members are no longer included. */ - deprecated predicate hasGeneratedCopyAssignmentOperator() { - hasImplicitCopyConstructor() - } + deprecated predicate hasGeneratedCopyAssignmentOperator() { hasImplicitCopyConstructor() } /** * Holds if this class, struct or union has an implicitly-declared copy @@ -330,17 +313,17 @@ class Class extends UserType { // - T has non-static data members that cannot be copied (have deleted, // inaccessible, or ambiguous copy constructors); exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() | - // Note: Overload resolution is not implemented -- all copy - // constructors are considered equal. - this.cannotAccessCopyConstructorOnAny(t.(Class)) + // Note: Overload resolution is not implemented -- all copy + // constructors are considered equal. + this.cannotAccessCopyConstructorOnAny(t.(Class)) ) or // - T has direct or virtual base class that cannot be copied (has deleted, // inaccessible, or ambiguous copy constructors); exists(Class c | c = this.getADirectOrVirtualBase() | - // Note: Overload resolution is not implemented -- all copy - // constructors are considered equal. - this.cannotAccessCopyConstructorOnThis(c) + // Note: Overload resolution is not implemented -- all copy + // constructors are considered equal. + this.cannotAccessCopyConstructorOnThis(c) ) or // - T has direct or virtual base class with a deleted or inaccessible @@ -350,20 +333,18 @@ class Class extends UserType { ) or // - T has a user-defined move constructor or move assignment operator; - exists(MoveConstructor mc | mc = this.getAMemberFunction() | - not mc.isCompilerGenerated()) + exists(MoveConstructor mc | mc = this.getAMemberFunction() | not mc.isCompilerGenerated()) or exists(MoveAssignmentOperator ma | ma = this.getAMemberFunction() | - not ma.isCompilerGenerated()) + not ma.isCompilerGenerated() + ) or // - T is a union and has a variant member with non-trivial copy // constructor (since C++11) none() // Not implemented or // - T has a data member of rvalue reference type. - exists (Type t | t = this.getAFieldSubobjectType() | - t instanceof RValueReferenceType - ) + exists(Type t | t = this.getAFieldSubobjectType() | t instanceof RValueReferenceType) } /** @@ -374,49 +355,46 @@ class Class extends UserType { */ predicate implicitCopyAssignmentOperatorDeleted() { // - T has a user-declared move constructor; - exists(MoveConstructor mc | mc = this.getAMemberFunction() | - not mc.isCompilerGenerated()) + exists(MoveConstructor mc | mc = this.getAMemberFunction() | not mc.isCompilerGenerated()) or // - T has a user-declared move assignment operator. exists(MoveAssignmentOperator ma | ma = this.getAMemberFunction() | - not ma.isCompilerGenerated()) + not ma.isCompilerGenerated() + ) or - // - T has a non-static data member of non-class type (or array thereof) // that is const; exists(Type t | t = this.getAFieldSubobjectType() | - // The rule for this case refers only to non-class types only, but our - // implementation extends it to cover class types too. Class types are - // supposed to be covered by the rule below on data members that - // cannot be copy-assigned. Copy-assigning a const class-typed member - // would call an overload of type - // `const C& operator=(const C&) const;`. Such an overload is unlikely - // to exist because it contradicts the intention of "const": it allows - // assigning to a const object. But since we have not implemented the - // ability to distinguish between overloads, we cannot distinguish that - // overload from the ordinary `C& operator=(const C&);`. Instead, we - // require class types to be non-const in this clause. - /* not t instanceof Class and */ t.isConst() + // The rule for this case refers only to non-class types only, but our + // implementation extends it to cover class types too. Class types are + // supposed to be covered by the rule below on data members that + // cannot be copy-assigned. Copy-assigning a const class-typed member + // would call an overload of type + // `const C& operator=(const C&) const;`. Such an overload is unlikely + // to exist because it contradicts the intention of "const": it allows + // assigning to a const object. But since we have not implemented the + // ability to distinguish between overloads, we cannot distinguish that + // overload from the ordinary `C& operator=(const C&);`. Instead, we + // require class types to be non-const in this clause. + /* not t instanceof Class and */ t.isConst() ) or // - T has a non-static data member of a reference type; - exists (Type t | t = this.getAFieldSubobjectType() | - t instanceof ReferenceType - ) + exists(Type t | t = this.getAFieldSubobjectType() | t instanceof ReferenceType) or // - T has a non-static data member or a direct or virtual base class that // cannot be copy-assigned (overload resolution for the copy assignment // fails, or selects a deleted or inaccessible function); exists(Type t | t = this.getAFieldSubobjectType().getUnspecifiedType() | - // Note: Overload resolution is not implemented -- all copy assignment - // operators are considered equal. - this.cannotAccessCopyAssignmentOperatorOnAny(t.(Class)) + // Note: Overload resolution is not implemented -- all copy assignment + // operators are considered equal. + this.cannotAccessCopyAssignmentOperatorOnAny(t.(Class)) ) or exists(Class c | c = this.getADirectOrVirtualBase() | - // Note: Overload resolution is not implemented -- all copy assignment - // operators are considered equal. - this.cannotAccessCopyAssignmentOperatorOnThis(c) + // Note: Overload resolution is not implemented -- all copy assignment + // operators are considered equal. + this.cannotAccessCopyAssignmentOperatorOnThis(c) ) // - T is a union-like class, and has a variant member whose corresponding // assignment operator is non-trivial. @@ -459,9 +437,7 @@ class Class extends UserType { Class getADerivedClass() { result.getABaseClass() = this } /** Holds if this class/struct derives directly from that. */ - predicate derivesFrom(Class that) { - this.getABaseClass() = that - } + predicate derivesFrom(Class that) { this.getABaseClass() = that } override predicate refersToDirectly(Type t) { t = this.getATemplateArgument() or @@ -480,9 +456,9 @@ class Class extends UserType { ClassDerivation getADerivation() { exists(ClassDerivation d | d.getDerivedClass() = this and d = result) } + ClassDerivation getDerivation(int index) { - exists(ClassDerivation d - | d.getDerivedClass() = this and d.getIndex() = index and d = result) + exists(ClassDerivation d | d.getDerivedClass() = this and d.getIndex() = index and d = result) } /** @@ -493,13 +469,13 @@ class Class extends UserType { * it hold for further base class subobjects of virtual base classes. */ private int getANonVirtualBaseClassByteOffset(Class baseClass) { - baseClass = this and result = 0 or // `baseClass` is the most-derived type + baseClass = this and result = 0 // `baseClass` is the most-derived type + or exists(ClassDerivation cd | // Add the offset of the direct base class and the offset of `baseClass` // within that direct base class. cd = getADerivation() and - result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + - cd.getByteOffset() + result = cd.getBaseClass().getANonVirtualBaseClassByteOffset(baseClass) + cd.getByteOffset() ) } @@ -513,14 +489,13 @@ class Class extends UserType { */ int getABaseClassByteOffset(Class baseClass) { // Handle the non-virtual case. - result = getANonVirtualBaseClassByteOffset(baseClass) or - exists(Class virtualBaseClass, int virtualBaseOffset, - int offsetFromVirtualBase | + result = getANonVirtualBaseClassByteOffset(baseClass) + or + exists(Class virtualBaseClass, int virtualBaseOffset, int offsetFromVirtualBase | // Look for the base class as a non-virtual base of a direct or indirect // virtual base, adding the two offsets. getVirtualBaseClassByteOffset(virtualBaseClass) = virtualBaseOffset and - offsetFromVirtualBase = - virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and + offsetFromVirtualBase = virtualBaseClass.getANonVirtualBaseClassByteOffset(baseClass) and result = virtualBaseOffset + offsetFromVirtualBase ) } @@ -535,11 +510,11 @@ class Class extends UserType { * ``` */ predicate hasVirtualBaseClass(Class base) { - exists(ClassDerivation cd | - this.getADerivation() = cd and - cd.getBaseClass() = base and - cd.hasSpecifier("virtual") - ) + exists(ClassDerivation cd | + this.getADerivation() = cd and + cd.getBaseClass() = base and + cd.hasSpecifier("virtual") + ) } /** @@ -564,11 +539,11 @@ class Class extends UserType { * ``` */ predicate hasPrivateBaseClass(Class base) { - exists(ClassDerivation cd | - this.getADerivation() = cd and - cd.getBaseClass() = base and - cd.hasSpecifier("private") - ) + exists(ClassDerivation cd | + this.getADerivation() = cd and + cd.getBaseClass() = base and + cd.hasSpecifier("private") + ) } /** @@ -581,11 +556,11 @@ class Class extends UserType { * ``` */ predicate hasPublicBaseClass(Class base) { - exists(ClassDerivation cd | - this.getADerivation() = cd and - cd.getBaseClass() = base and - cd.hasSpecifier("public") - ) + exists(ClassDerivation cd | + this.getADerivation() = cd and + cd.getBaseClass() = base and + cd.hasSpecifier("public") + ) } /** @@ -598,11 +573,11 @@ class Class extends UserType { * ``` */ predicate hasProtectedBaseClass(Class base) { - exists(ClassDerivation cd | - this.getADerivation() = cd and - cd.getBaseClass() = base and - cd.hasSpecifier("protected") - ) + exists(ClassDerivation cd | + this.getADerivation() = cd and + cd.getBaseClass() = base and + cd.hasSpecifier("protected") + ) } /** Gets the metric class associated with this class, struct or union. */ @@ -619,7 +594,7 @@ class Class extends UserType { * Gets the alignment of this type in bytes (on the machine where facts were * extracted). */ - override int getAlignment() { usertypesize(underlyingElement(this),_,result) } + override int getAlignment() { usertypesize(underlyingElement(this), _, result) } /** * Holds if this class, struct or union is constructed from another class as @@ -636,7 +611,7 @@ class Class extends UserType { * `i`th template parameter. */ override Type getTemplateArgument(int i) { - class_template_argument(underlyingElement(this),i,unresolveElement(result)) + class_template_argument(underlyingElement(this), i, unresolveElement(result)) } /** @@ -652,14 +627,10 @@ class Class extends UserType { } /** Holds if this class, struct or union was declared 'final'. */ - predicate isFinal() { - usertype_final(underlyingElement(this)) - } + predicate isFinal() { usertype_final(underlyingElement(this)) } /** Gets a link target which references this class, struct or union. */ - LinkTarget getALinkTarget() { - this = result.getAClass() - } + LinkTarget getALinkTarget() { this = result.getAClass() } /** * Gets the UUID that associated with this class, struct or union via the @@ -669,9 +640,7 @@ class Class extends UserType { * value is normalized to the standard "registry format", without braces, and * using lowercase letters (e.g. "01234567-89ab-cdef-0123-456789abcdef"). */ - string getUuid() { - usertype_uuid(underlyingElement(this), result) - } + string getUuid() { usertype_uuid(underlyingElement(this), result) } private Type getAFieldSubobjectType() { result = stripArrayTypes(this.getAField().getUnderlyingType()) @@ -684,9 +653,7 @@ class Class extends UserType { // `result` is an indirect virtual base of `this`. The case where `result` // is a direct virtual base of `this` is included in the above clause, and // therefore we can use "+"-closure instead of "*"-closure here. - result.(VirtualBaseClass) - .getAVirtuallyDerivedClass() - .getADerivedClass+() = this + result.(VirtualBaseClass).getAVirtuallyDerivedClass().getADerivedClass+() = this } /** @@ -700,12 +667,9 @@ class Class extends UserType { // The destructor in our db, if any, is accessible. If there is no // destructor in our db, it usually means that there is a default // public one. - exists(Destructor d | d = c.getAMemberFunction() | - not this.canAccessMember(d, objectClass)) - + exists(Destructor d | d = c.getAMemberFunction() | not this.canAccessMember(d, objectClass)) // The extractor doesn't seem to support the case of a deleted destructor, // so we ignore that. It is very much a corner case. - // To implement this properly, there should be a predicate about whether // the implicit destructor is deleted, similar to // `implicitCopyConstructorDeleted`. See @@ -734,14 +698,13 @@ class Class extends UserType { // then this.cannotAccess(cc) // else this.implicitCopyConstructorDeleted() exists(CopyConstructor cc | cc = c.getAMemberFunction() | - not this.canAccessMember(cc, objectClass)) - or - ( - not exists(CopyConstructor cc | cc = c.getAMemberFunction() and not cc.isDeleted()) and - c.implicitCopyConstructorDeleted() // mutual recursion here - // no access check in this case since the implicit member is always - // public. + not this.canAccessMember(cc, objectClass) ) + or + not exists(CopyConstructor cc | cc = c.getAMemberFunction() and not cc.isDeleted()) and + c.implicitCopyConstructorDeleted() // mutual recursion here + // no access check in this case since the implicit member is always + // public. } private predicate cannotAccessCopyAssignmentOperatorOnThis(Class c) { @@ -765,14 +728,13 @@ class Class extends UserType { // then this.cannotAccess(ca) // else this.implicitCopyAssignmentOperatorDeleted() exists(CopyAssignmentOperator ca | ca = c.getAMemberFunction() | - not this.canAccessMember(ca, objectClass)) - or - ( - not exists(CopyAssignmentOperator ca | ca = c.getAMemberFunction() and not ca.isDeleted()) and - c.implicitCopyAssignmentOperatorDeleted() // mutual recursion here - // no access check in this case since the implicit member is always - // public. + not this.canAccessMember(ca, objectClass) ) + or + not exists(CopyAssignmentOperator ca | ca = c.getAMemberFunction() and not ca.isDeleted()) and + c.implicitCopyAssignmentOperatorDeleted() // mutual recursion here + // no access check in this case since the implicit member is always + // public. } } @@ -799,10 +761,8 @@ class ClassDerivation extends Locatable, @derivation { * }; * ``` */ - Class getBaseClass() { - result = getBaseType().getUnderlyingType() - } - + Class getBaseClass() { result = getBaseType().getUnderlyingType() } + override string getCanonicalQLClass() { result = "ClassDerivation" } /** @@ -818,9 +778,7 @@ class ClassDerivation extends Locatable, @derivation { * }; * ``` */ - Type getBaseType() { - derivations(underlyingElement(this),_,_,unresolveElement(result),_) - } + Type getBaseType() { derivations(underlyingElement(this), _, _, unresolveElement(result), _) } /** * Gets the class/struct that is doing the deriving. For example, the derived @@ -834,7 +792,7 @@ class ClassDerivation extends Locatable, @derivation { * ``` */ Class getDerivedClass() { - derivations(underlyingElement(this),unresolveElement(result),_,_,_) + derivations(underlyingElement(this), unresolveElement(result), _, _, _) } /** @@ -847,29 +805,19 @@ class ClassDerivation extends Locatable, @derivation { * }; * ``` */ - int getIndex() { - derivations(underlyingElement(this),_,result,_,_) - } + int getIndex() { derivations(underlyingElement(this), _, result, _, _) } /** Gets a specifier (for example `public`) applied to the derivation. */ - Specifier getASpecifier() { - derspecifiers(underlyingElement(this),unresolveElement(result)) - } + Specifier getASpecifier() { derspecifiers(underlyingElement(this), unresolveElement(result)) } /** Holds if the derivation has specifier `s`. */ - predicate hasSpecifier(string s) { - this.getASpecifier().hasName(s) - } + predicate hasSpecifier(string s) { this.getASpecifier().hasName(s) } /** Holds if the derivation is for a virtual base class. */ - predicate isVirtual() { - hasSpecifier("virtual") - } + predicate isVirtual() { hasSpecifier("virtual") } /** Gets the location of the derivation. */ - override Location getLocation() { - derivations(underlyingElement(this),_,_,_,result) - } + override Location getLocation() { derivations(underlyingElement(this), _, _, _, result) } /** * Gets the byte offset of the base class subobject relative to the start of @@ -879,13 +827,9 @@ class ClassDerivation extends Locatable, @derivation { * See `Class.getVirtualBaseClassByteOffset` for offsets of virtual base * classes. */ - int getByteOffset() { - direct_base_offsets(underlyingElement(this), result) - } + int getByteOffset() { direct_base_offsets(underlyingElement(this), result) } - override string toString() { - result = "derivation" - } + override string toString() { result = "derivation" } } /** @@ -898,16 +842,13 @@ class ClassDerivation extends Locatable, @derivation { * ``` */ class LocalClass extends Class { - LocalClass() { - isLocal() + LocalClass() { isLocal() } + + override string getCanonicalQLClass() { + not this instanceof LocalStruct and result = "LocalClass" } - override string getCanonicalQLClass() - { not this instanceof LocalStruct and result = "LocalClass" } - - override Function getEnclosingAccessHolder() { - result = this.getEnclosingFunction() - } + override Function getEnclosingAccessHolder() { result = this.getEnclosingFunction() } } /** @@ -924,12 +865,11 @@ class LocalClass extends Class { * ``` */ class NestedClass extends Class { - NestedClass() { - this.isMember() - } + NestedClass() { this.isMember() } - override string getCanonicalQLClass() - { not this instanceof NestedStruct and result = "NestedClass" } + override string getCanonicalQLClass() { + not this instanceof NestedStruct and result = "NestedClass" + } /** Holds if this member is private. */ predicate isPrivate() { this.hasSpecifier("private") } @@ -939,7 +879,6 @@ class NestedClass extends Class { /** Holds if this member is public. */ predicate isPublic() { this.hasSpecifier("public") } - } /** @@ -947,9 +886,7 @@ class NestedClass extends Class { * pure virtual function. */ class AbstractClass extends Class { - AbstractClass() { - exists(PureVirtualFunction f| this.getAMemberFunction() = f) - } + AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) } override string getCanonicalQLClass() { result = "AbstractClass" } } @@ -969,7 +906,8 @@ class AbstractClass extends Class { * `FullClassTemplateSpecialization`. */ class TemplateClass extends Class { - TemplateClass() { usertypes(underlyingElement(this),_,6) } + TemplateClass() { usertypes(underlyingElement(this), _, 6) } + Class getAnInstantiation() { result.isConstructedFrom(this) and exists(result.getATemplateArgument()) @@ -986,7 +924,7 @@ class TemplateClass extends Class { * class MyTemplateClass { * ... * }; - * + * * MyTemplateClass instance; * ``` * For the `MyTemplateClass` template itself, see `TemplateClass`. @@ -994,9 +932,7 @@ class TemplateClass extends Class { class ClassTemplateInstantiation extends Class { TemplateClass tc; - ClassTemplateInstantiation() { - tc.getAnInstantiation() = this - } + ClassTemplateInstantiation() { tc.getAnInstantiation() = this } override string getCanonicalQLClass() { result = "ClassTemplateInstantiation" } @@ -1010,13 +946,11 @@ class ClassTemplateInstantiation extends Class { * class MyTemplateClass { * ... * }; - * + * * MyTemplateClass instance; * ``` */ - TemplateClass getTemplate() { - result = tc - } + TemplateClass getTemplate() { result = tc } } /** @@ -1032,15 +966,14 @@ abstract class ClassTemplateSpecialization extends Class { TemplateClass getPrimaryTemplate() { // Ignoring template arguments, the primary template has the same name // as each of its specializations. - result.getSimpleName() = getSimpleName() - + result.getSimpleName() = getSimpleName() and // It is in the same namespace as its specializations. - and result.getNamespace() = getNamespace() - + result.getNamespace() = getNamespace() and // It is distinguished by the fact that each of its template arguments // is a distinct template parameter. - and count(TemplateParameter tp | tp = result.getATemplateArgument()) = - count(int i | exists(result.getTemplateArgument(i))) + count(TemplateParameter tp | tp = result.getATemplateArgument()) = count(int i | + exists(result.getTemplateArgument(i)) + ) } override string getCanonicalQLClass() { result = "ClassTemplateSpecialization" } @@ -1064,14 +997,12 @@ abstract class ClassTemplateSpecialization extends Class { class FullClassTemplateSpecialization extends ClassTemplateSpecialization { FullClassTemplateSpecialization() { // This class has template arguments, but none of them involves a template parameter. - exists(getATemplateArgument()) - and not exists(Type ta | ta = getATemplateArgument() and ta.involvesTemplateParameter()) - + exists(getATemplateArgument()) and + not exists(Type ta | ta = getATemplateArgument() and ta.involvesTemplateParameter()) and // This class does not have any instantiations. - and not exists(this.(TemplateClass).getAnInstantiation()) - + not exists(this.(TemplateClass).getAnInstantiation()) and // This class is not an instantiation of a class template. - and not this instanceof ClassTemplateInstantiation + not this instanceof ClassTemplateInstantiation } override string getCanonicalQLClass() { result = "FullClassTemplateSpecialization" } @@ -1107,9 +1038,11 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization { * template class Y {}; // class template * template class Y {}; // partial class template specialization */ - exists(Type ta | ta = getATemplateArgument() and ta.involvesTemplateParameter()) - and count(TemplateParameter tp | tp = getATemplateArgument()) != - count(int i | exists(getTemplateArgument(i))) + + exists(Type ta | ta = getATemplateArgument() and ta.involvesTemplateParameter()) and + count(TemplateParameter tp | tp = getATemplateArgument()) != count(int i | + exists(getTemplateArgument(i)) + ) } override string getCanonicalQLClass() { result = "PartialClassTemplateSpecialization" } @@ -1125,12 +1058,16 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization { * virtual void myMethod2() = 0; * }; * ``` - * + * * DEPRECATED: This class is considered to be too specific for general usage. */ deprecated class Interface extends Class { Interface() { - forex(Declaration m | m.getDeclaringType() = this.getABaseClass*() and not compgenerated(unresolveElement(m)) | m instanceof PureVirtualFunction) + forex(Declaration m | + m.getDeclaringType() = this.getABaseClass*() and not compgenerated(unresolveElement(m)) + | + m instanceof PureVirtualFunction + ) } override string getCanonicalQLClass() { result = "Interface" } @@ -1146,9 +1083,7 @@ deprecated class Interface extends Class { * ``` */ class VirtualClassDerivation extends ClassDerivation { - VirtualClassDerivation() { - hasSpecifier("virtual") - } + VirtualClassDerivation() { hasSpecifier("virtual") } override string getCanonicalQLClass() { result = "VirtualClassDerivation" } } @@ -1168,21 +1103,15 @@ class VirtualClassDerivation extends ClassDerivation { * ``` */ class VirtualBaseClass extends Class { - VirtualBaseClass() { - exists(VirtualClassDerivation cd | cd.getBaseClass() = this) - } + VirtualBaseClass() { exists(VirtualClassDerivation cd | cd.getBaseClass() = this) } override string getCanonicalQLClass() { result = "VirtualBaseClass" } /** A virtual class derivation of which this class/struct is the base. */ - VirtualClassDerivation getAVirtualDerivation() { - result.getBaseClass() = this - } + VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this } /** A class/struct that is derived from this one using virtual inheritance. */ - Class getAVirtuallyDerivedClass() { - result = getAVirtualDerivation().getDerivedClass() - } + Class getAVirtuallyDerivedClass() { result = getAVirtualDerivation().getDerivedClass() } } /** @@ -1196,25 +1125,22 @@ class VirtualBaseClass extends Class { * ``` */ class ProxyClass extends UserType { - ProxyClass() { - usertypes(underlyingElement(this),_,9) - } + ProxyClass() { usertypes(underlyingElement(this), _, 9) } override string getCanonicalQLClass() { result = "ProxyClass" } - + /** Gets the location of the proxy class. */ - override Location getLocation() { - result = getTemplateParameter().getDefinitionLocation() - } + override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() } /** Gets the template parameter for which this is the proxy class. */ TemplateParameter getTemplateParameter() { - is_proxy_class_for(underlyingElement(this),unresolveElement(result)) + is_proxy_class_for(underlyingElement(this), unresolveElement(result)) } } // Unpacks "array of ... of array of t" into t. private Type stripArrayTypes(Type t) { - not t instanceof ArrayType and result = t or + not t instanceof ArrayType and result = t + or result = stripArrayTypes(t.(ArrayType).getBaseType()) } diff --git a/cpp/ql/src/semmle/code/cpp/Comments.qll b/cpp/ql/src/semmle/code/cpp/Comments.qll index 10757bc5254..e517f8e7b0e 100644 --- a/cpp/ql/src/semmle/code/cpp/Comments.qll +++ b/cpp/ql/src/semmle/code/cpp/Comments.qll @@ -10,18 +10,21 @@ import semmle.code.cpp.Element */ class Comment extends Locatable, @comment { override string toString() { result = this.getContents() } - override Location getLocation() { comments(underlyingElement(this),_,result) } - string getContents() { comments(underlyingElement(this),result,_) } - Element getCommentedElement() { commentbinding(underlyingElement(this),unresolveElement(result)) } + + override Location getLocation() { comments(underlyingElement(this), _, result) } + + string getContents() { comments(underlyingElement(this), result, _) } + + Element getCommentedElement() { + commentbinding(underlyingElement(this), unresolveElement(result)) + } } /** * A C style comment (one which starts with `/*`). */ class CStyleComment extends Comment { - CStyleComment() { - this.getContents().matches("/*%") - } + CStyleComment() { this.getContents().matches("/*%") } } /** @@ -31,7 +34,5 @@ class CStyleComment extends Comment { * ``` */ class CppStyleComment extends Comment { - CppStyleComment() { - this.getContents().prefix(2) = "//" - } + CppStyleComment() { this.getContents().prefix(2) = "//" } } diff --git a/cpp/ql/src/semmle/code/cpp/Compilation.qll b/cpp/ql/src/semmle/code/cpp/Compilation.qll index a38e3fb10db..02d962844c8 100644 --- a/cpp/ql/src/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/src/semmle/code/cpp/Compilation.qll @@ -6,7 +6,9 @@ import semmle.code.cpp.File * These integers are not stable across trap imports, but stable across * runs with the same database. */ + private predicate id(@compilation x, @compilation y) { x = y } + private predicate idOf(@compilation x, int y) = equivalenceRelation(id/2)(x, y) /** @@ -29,48 +31,40 @@ private predicate idOf(@compilation x, int y) = equivalenceRelation(id/2)(x, y) class Compilation extends @compilation { /** Gets a textual representation of this element. */ string toString() { - exists(int i - | idOf(this, i) and - result = "") + exists(int i | + idOf(this, i) and + result = "" + ) } /** Gets a file compiled during this invocation. */ File getAFileCompiled() { result = getFileCompiled(_) } - File getFileCompiled(int i) { - compilation_compiling_files(this, i, unresolveElement(result)) - } + + File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) } /** * Gets the amount of CPU time spent processing file number `i` in the C++ * front-end. */ - float getFrontendCpuSeconds(int i) { - compilation_time(this, i, 1, result) - } + float getFrontendCpuSeconds(int i) { compilation_time(this, i, 1, result) } /** * Gets the amount of elapsed time while processing file number `i` in the * C++ front-end. */ - float getFrontendElapsedSeconds(int i) { - compilation_time(this, i, 2, result) - } + float getFrontendElapsedSeconds(int i) { compilation_time(this, i, 2, result) } /** * Gets the amount of CPU time spent processing file number `i` in the * extractor. */ - float getExtractorCpuSeconds(int i) { - compilation_time(this, i, 3, result) - } + float getExtractorCpuSeconds(int i) { compilation_time(this, i, 3, result) } /** * Gets the amount of elapsed time while processing file number `i` in the * extractor. */ - float getExtractorElapsedSeconds(int i) { - compilation_time(this, i, 4, result) - } + float getExtractorElapsedSeconds(int i) { compilation_time(this, i, 4, result) } /** * Gets an argument passed to the extractor on this invocation. @@ -93,32 +87,24 @@ class Compilation extends @compilation { * 5 | f2.c * 6 | f3.c */ - string getArgument(int i) { - compilation_args(this, i, result) - } + string getArgument(int i) { compilation_args(this, i, result) } /** * Gets the total amount of CPU time spent processing all the files in the * front-end and extractor. */ - float getTotalCpuSeconds() { - compilation_finished(this, result, _) - } + float getTotalCpuSeconds() { compilation_finished(this, result, _) } /** * Gets the total amount of elapsed time while processing all the files in * the front-end and extractor. */ - float getTotalElapsedSeconds() { - compilation_finished(this, _, result) - } + float getTotalElapsedSeconds() { compilation_finished(this, _, result) } /** * Holds if the extractor terminated normally. Terminating with an exit * code indicating that an error occurred is considered normal * termination, but crashing due to something like a segfault is not. */ - predicate normalTermination() { - compilation_finished(this, _, _) - } + predicate normalTermination() { compilation_finished(this, _, _) } } diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 7fc675ac6a7..fa061b239cc 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -33,11 +33,9 @@ abstract class Declaration extends Locatable, @declaration { Namespace getNamespace() { result = underlyingElement(this).(Q::Declaration).getNamespace() or - exists (Parameter p - | p = this and result = p.getFunction().getNamespace()) + exists(Parameter p | p = this and result = p.getFunction().getNamespace()) or - exists (LocalVariable v - | v = this and result = v.getFunction().getNamespace()) + exists(LocalVariable v | v = this and result = v.getFunction().getNamespace()) } /** @@ -52,9 +50,7 @@ abstract class Declaration extends Locatable, @declaration { * Example: `getQualifiedName() = * "namespace1::namespace2::TemplateClass1::Class2::memberName"`. */ - string getQualifiedName() { - result = underlyingElement(this).(Q::Declaration).getQualifiedName() - } + string getQualifiedName() { result = underlyingElement(this).(Q::Declaration).getQualifiedName() } /** * DEPRECATED: Prefer `hasGlobalName` or the 2-argument or 3-argument @@ -64,9 +60,7 @@ abstract class Declaration extends Locatable, @declaration { * Holds if this declaration has the fully-qualified name `qualifiedName`. * See `getQualifiedName`. */ - predicate hasQualifiedName(string qualifiedName) { - this.getQualifiedName() = qualifiedName - } + predicate hasQualifiedName(string qualifiedName) { this.getQualifiedName() = qualifiedName } /** * Holds if this declaration has a fully-qualified name with a name-space @@ -84,8 +78,9 @@ abstract class Declaration extends Locatable, @declaration { * `hasQualifiedName("std", "vector", "size")`. */ predicate hasQualifiedName(string namespaceQualifier, string typeQualifier, string baseName) { - underlyingElement(this).(Q::Declaration) - .hasQualifiedName(namespaceQualifier, typeQualifier, baseName) + underlyingElement(this) + .(Q::Declaration) + .hasQualifiedName(namespaceQualifier, typeQualifier, baseName) } /** @@ -122,26 +117,20 @@ abstract class Declaration extends Locatable, @declaration { predicate hasName(string name) { name = this.getName() } /** Holds if this declaration has the given name in the global namespace. */ - predicate hasGlobalName(string name) { - this.hasQualifiedName("", "", name) - } + predicate hasGlobalName(string name) { this.hasQualifiedName("", "", name) } /** Gets a specifier of this declaration. */ abstract Specifier getASpecifier(); /** Holds if this declaration has a specifier with the given name. */ - predicate hasSpecifier(string name) { - this.getASpecifier().hasName(name) - } + predicate hasSpecifier(string name) { this.getASpecifier().hasName(name) } /** * Gets a declaration entry corresponding to this declaration. See the * comment above this class for an explanation of the relationship * between `Declaration` and `DeclarationEntry`. */ - DeclarationEntry getADeclarationEntry() { - none() - } + DeclarationEntry getADeclarationEntry() { none() } /** * Gets the location of a declaration entry corresponding to this @@ -153,34 +142,33 @@ abstract class Declaration extends Locatable, @declaration { * Gets the declaration entry corresponding to this declaration that is a * definition, if any. */ - DeclarationEntry getDefinition() { - none() - } + DeclarationEntry getDefinition() { none() } /** Gets the location of the definition, if any. */ abstract Location getDefinitionLocation(); /** Holds if the declaration has a definition. */ predicate hasDefinition() { exists(this.getDefinition()) } + predicate isDefined() { hasDefinition() } /** Gets the preferred location of this declaration, if any. */ - override Location getLocation() { - none() - } + override Location getLocation() { none() } /** Gets a file where this element occurs. */ File getAFile() { result = this.getADeclarationLocation().getFile() } /** Holds if this declaration is a top-level declaration. */ predicate isTopLevel() { - not (this.isMember() or - this instanceof EnumConstant or - this instanceof Parameter or - this instanceof ProxyClass or - this instanceof LocalVariable or - this instanceof TemplateParameter or - this.(UserType).isLocal()) + not ( + this.isMember() or + this instanceof EnumConstant or + this instanceof Parameter or + this instanceof ProxyClass or + this instanceof LocalVariable or + this instanceof TemplateParameter or + this.(UserType).isLocal() + ) } /** Holds if this declaration is static. */ @@ -190,34 +178,26 @@ abstract class Declaration extends Locatable, @declaration { predicate isMember() { hasDeclaringType() } /** Holds if this declaration is a member of a class/struct/union. */ - predicate hasDeclaringType() { - exists(this.getDeclaringType()) - } + predicate hasDeclaringType() { exists(this.getDeclaringType()) } /** * Gets the class where this member is declared, if it is a member. * For templates, both the template itself and all instantiations of * the template are considered to have the same declaring class. */ - Class getDeclaringType() { - this = result.getAMember() - } + Class getDeclaringType() { this = result.getAMember() } /** * Gets a template argument used to instantiate this declaration from a template. * When called on a template, this will return a template parameter. */ - final Type getATemplateArgument() { - result = getTemplateArgument(_) - } + final Type getATemplateArgument() { result = getTemplateArgument(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a * template. When called on a template, this will return the `i`th template parameter. */ - Type getTemplateArgument(int index) { - none() - } + Type getTemplateArgument(int index) { none() } /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { @@ -239,10 +219,9 @@ abstract class DeclarationEntry extends Locatable { * available), or the name declared by this entry otherwise. */ string getCanonicalName() { - if getDeclaration().isDefined() then - result = getDeclaration().getDefinition().getName() - else - result = getName() + if getDeclaration().isDefined() + then result = getDeclaration().getDefinition().getName() + else result = getName() } /** @@ -283,24 +262,21 @@ abstract class DeclarationEntry extends Locatable { /** * Holds if this declaration entry has a specifier with the given name. */ - predicate hasSpecifier(string specifier) { - getASpecifier() = specifier - } + predicate hasSpecifier(string specifier) { getASpecifier() = specifier } /** Holds if this declaration entry is a definition. */ abstract predicate isDefinition(); override string toString() { - if isDefinition() then - result = "definition of " + getName() - else if getName() = getCanonicalName() then - result = "declaration of " + getName() + if isDefinition() + then result = "definition of " + getName() else - result = "declaration of " + getCanonicalName() + " as " + getName() + if getName() = getCanonicalName() + then result = "declaration of " + getName() + else result = "declaration of " + getCanonicalName() + " as " + getName() } } - /** * A declaration that can potentially have more C++ access rights than its * enclosing element. This comprises `Class` (they have access to their own @@ -319,12 +295,10 @@ abstract class AccessHolder extends Declaration { * repeated many times in the C++14 standard, section 11.2. */ predicate inMemberOrFriendOf(Class c) { - ( - this.getEnclosingAccessHolder*() = c - ) or ( - exists(FriendDecl fd | fd.getDeclaringClass() = c | - this.getEnclosingAccessHolder*() = fd.getFriend() - ) + this.getEnclosingAccessHolder*() = c + or + exists(FriendDecl fd | fd.getDeclaringClass() = c | + this.getEnclosingAccessHolder*() = fd.getFriend() ) } @@ -356,13 +330,11 @@ abstract class AccessHolder extends Declaration { // This predicate is marked `inline` and implemented in a very particular // way. If we allowed this predicate to be fully computed, it would relate // all `AccessHolder`s to all classes, which would be too much. - // There are four rules in N4140 11.2/4. Only the one named (4.4) is // recursive, and it describes a transitive closure: intuitively, if A can // be converted to B, and B can be converted to C, then A can be converted // to C. To limit the number of tuples in the non-inline helper predicates, // we first separate the derivation of 11.2/4 into two cases: - // Derivations using only (4.1) and (4.4). Note that these derivations are // independent of `this`, which is why users of this predicate must take // care to avoid a combinatorial explosion. @@ -397,11 +369,9 @@ abstract class AccessHolder extends Declaration { */ pragma[inline] predicate canAccessMember(Declaration member, Class derived) { - this.couldAccessMember( - member.getDeclaringType(), - member.getASpecifier().(AccessSpecifier), - derived - ) + this + .couldAccessMember(member.getDeclaringType(), member.getASpecifier().(AccessSpecifier), + derived) } /** @@ -425,13 +395,10 @@ abstract class AccessHolder extends Declaration { * `memberAccess` is public. */ pragma[inline] - predicate couldAccessMember(Class memberClass, AccessSpecifier memberAccess, - Class derived) - { + predicate couldAccessMember(Class memberClass, AccessSpecifier memberAccess, Class derived) { // There are four rules in N4140 11.2/5. To limit the number of tuples in // the non-inline helper predicates, we first separate the derivation of // 11.2/5 into two cases: - // Rule (5.1) directly: the member is public, and `derived` uses public // inheritance all the way up to `memberClass`. Note that these derivations // are independent of `this`, which is why users of this predicate must @@ -486,7 +453,6 @@ private class DirectAccessHolder extends Element { isDirectPublicBaseOf(between, derived) or this.thisCanAccessClassStep(between, derived) ) - // It is possible that this predicate could be computed faster for deep // hierarchies if we can prove and utilize that all derivations of 11.2/4 // can be broken down into steps where `base` is a _direct_ base of @@ -526,17 +492,13 @@ private class DirectAccessHolder extends Element { * part of (5.3), since this further limits the number of tuples produced by * this predicate. */ - predicate thisCouldAccessMember(Class memberClass, - AccessSpecifier memberAccess, - Class derived) - { + predicate thisCouldAccessMember(Class memberClass, AccessSpecifier memberAccess, Class derived) { // Only (5.4) is recursive, and chains of invocations of (5.4) can always // be collapsed to one invocation by the transitivity of 11.2/4. // Derivations not using (5.4) can always be rewritten to have a (5.4) rule // in front because our encoding of 11.2/4 in `canAccessClass` is // reflexive. Thus, we only need to consider three cases: rule (5.4) // followed by either (5.1), (5.2) or (5.3). - // Rule (5.4), using a non-trivial derivation of 11.2/4, followed by (5.1). // If the derivation of 11.2/4 is trivial (only uses (4.1) and (4.4)), this // case can be replaced with purely (5.1) and thus does not need to be in @@ -547,16 +509,14 @@ private class DirectAccessHolder extends Element { or // Rule (5.4) followed by Rule (5.2) exists(Class between | this.(AccessHolder).canAccessClass(between, derived) | - between.accessOfBaseMember(memberClass, memberAccess) - .hasName("private") and - this.isFriendOfOrEqualTo(between) + between.accessOfBaseMember(memberClass, memberAccess).hasName("private") and + this.isFriendOfOrEqualTo(between) ) or // Rule (5.4) followed by Rule (5.3), integrating 11.4. We integrate 11.4 // here because we would otherwise generate too many tuples. This code is // very performance-sensitive, and any changes should be benchmarked on // LibreOffice. - // Rule (5.4) requires that `this.canAccessClass(between, derived)` // (implying that `derived <= between` in the class hierarchy) and that // `p <= between`. Rule 11.4 additionally requires `derived <= p`, but @@ -573,8 +533,7 @@ private class DirectAccessHolder extends Element { // bypasses `p`. Then that path must be public, or we are in case 2. exists(AccessSpecifier public | public.hasName("public") | exists(Class between, Class p | - between.accessOfBaseMember(memberClass, memberAccess) - .hasName("protected") and + between.accessOfBaseMember(memberClass, memberAccess).hasName("protected") and this.isFriendOfOrEqualTo(p) and ( // This is case 1 from above. If `p` derives privately from `between` @@ -623,9 +582,8 @@ private predicate isDirectPublicBaseOf(Class base, Class derived) { * `memberAccess` would be public when named as a member of `derived`. * This encodes N4140 11.2/5 case (5.1). */ -private predicate everyoneCouldAccessMember(Class memberClass, - AccessSpecifier memberAccess, - Class derived) -{ +private predicate everyoneCouldAccessMember( + Class memberClass, AccessSpecifier memberAccess, Class derived +) { derived.accessOfBaseMember(memberClass, memberAccess).hasName("public") } diff --git a/cpp/ql/src/semmle/code/cpp/Diagnostics.qll b/cpp/ql/src/semmle/code/cpp/Diagnostics.qll index aaa251ada34..f03f03783c1 100644 --- a/cpp/ql/src/semmle/code/cpp/Diagnostics.qll +++ b/cpp/ql/src/semmle/code/cpp/Diagnostics.qll @@ -2,7 +2,6 @@ import semmle.code.cpp.Location /** A compiler-generated error, warning or remark. */ class Diagnostic extends Locatable, @diagnostic { - /** * Gets the severity of the message, on a range from 1 to 5: 1=remark, * 2=warning, 3=discretionary error, 4=error, 5=catastrophic error. @@ -11,6 +10,7 @@ class Diagnostic extends Locatable, @diagnostic { /** Gets the error code for this compiler message. */ string getTag() { diagnostics(underlyingElement(this), _, result, _, _, _) } + predicate hasTag(string s) { this.getTag() = s } /** @@ -29,18 +29,15 @@ class Diagnostic extends Locatable, @diagnostic { override Location getLocation() { diagnostics(underlyingElement(this), _, _, _, _, result) } override string toString() { result = this.getMessage() } - } /** A compiler-generated remark (milder than a warning). */ class CompilerRemark extends Diagnostic { - CompilerRemark() { this.getSeverity() = 1 } } /** A compiler-generated warning. */ class CompilerWarning extends Diagnostic { - CompilerWarning() { this.getSeverity() = 2 } } @@ -49,18 +46,15 @@ class CompilerWarning extends Diagnostic { * be suppressed). */ class CompilerDiscretionaryError extends Diagnostic { - CompilerDiscretionaryError() { this.getSeverity() = 3 } } /** A compiler error message. */ class CompilerError extends Diagnostic { - CompilerError() { this.getSeverity() = 4 } } /** A compiler error that prevents compilation from continuing. */ class CompilerCatastrophe extends Diagnostic { - CompilerCatastrophe() { this.getSeverity() = 5 } } diff --git a/cpp/ql/src/semmle/code/cpp/Element.qll b/cpp/ql/src/semmle/code/cpp/Element.qll index 771c3a24895..7d7f95272d9 100644 --- a/cpp/ql/src/semmle/code/cpp/Element.qll +++ b/cpp/ql/src/semmle/code/cpp/Element.qll @@ -9,9 +9,7 @@ private import semmle.code.cpp.internal.ResolveClass * complete struct with the same name. */ pragma[inline] -Element mkElement(@element e) { - unresolveElement(result) = e -} +Element mkElement(@element e) { unresolveElement(result) = e } /** * INTERNAL: Do not use. @@ -38,9 +36,7 @@ pragma[inline] * need the result for an argument to a database extensional. * See `unresolveElement` for when `e` is not `this`. */ -@element underlyingElement(Element e) { - result = e -} +@element underlyingElement(Element e) { result = e } /** * A C/C++ element with no member predicates other than `toString`. Not for @@ -53,9 +49,9 @@ class ElementBase extends @element { /** Gets a textual representation of this element. */ string toString() { none() } - /** + /** * Canonical QL class corresponding to this element. - * + * * ElementBase is the root class for this predicate. */ string getCanonicalQLClass() { result = "???" } @@ -83,13 +79,10 @@ class Element extends ElementBase { * * DEPRECATED: always true. */ - deprecated - predicate fromLibrary() { this.getFile().fromLibrary() } + deprecated predicate fromLibrary() { this.getFile().fromLibrary() } /** Gets the primary location of this element. */ - Location getLocation() { - none() - } + Location getLocation() { none() } /** * Gets the source of this element: either itself or a macro that expanded @@ -105,7 +98,8 @@ class Element extends ElementBase { * expand to a bug. */ Element findRootCause() { - if (exists(MacroInvocation mi | this = mi.getAGeneratedElement())) then + if exists(MacroInvocation mi | this = mi.getAGeneratedElement()) + then exists(MacroInvocation mi | this = mi.getAGeneratedElement() and not exists(MacroInvocation closer | @@ -114,8 +108,7 @@ class Element extends ElementBase { ) and result = mi.getMacro() ) - else - result = this + else result = this } /** @@ -125,54 +118,40 @@ class Element extends ElementBase { */ Element getParentScope() { // result instanceof class - exists (Declaration m - | m = this and + exists(Declaration m | + m = this and result = m.getDeclaringType() and - not this instanceof EnumConstant) + not this instanceof EnumConstant + ) + or + exists(TemplateClass tc | this = tc.getATemplateArgument() and result = tc) or - exists (TemplateClass tc - | this = tc.getATemplateArgument() and result = tc) - // result instanceof namespace + exists(Namespace n | result = n and n.getADeclaration() = this) or - exists (Namespace n - | result = n and n.getADeclaration() = this) + exists(FriendDecl d, Namespace n | this = d and n.getADeclaration() = d and result = n) or - exists (FriendDecl d, Namespace n - | this = d and n.getADeclaration() = d and result = n) + exists(Namespace n | this = n and result = n.getParentNamespace()) or - exists (Namespace n - | this = n and result = n.getParentNamespace()) - // result instanceof stmt + exists(LocalVariable v | + this = v and + exists(DeclStmt ds | ds.getADeclaration() = v and result = ds.getParent()) + ) or - exists (LocalVariable v - | this = v and - exists (DeclStmt ds - | ds.getADeclaration() = v and result = ds.getParent())) + exists(Parameter p | this = p and result = p.getFunction()) or - exists (Parameter p - | this = p and result = p.getFunction()) + exists(GlobalVariable g, Namespace n | this = g and n.getADeclaration() = g and result = n) or - exists (GlobalVariable g, Namespace n - | this = g and n.getADeclaration() = g and result = n) + exists(EnumConstant e | this = e and result = e.getDeclaringEnum()) or - exists (EnumConstant e - | this = e and result = e.getDeclaringEnum()) - // result instanceof block|function + exists(Block b | this = b and blockscope(unresolveElement(b), unresolveElement(result))) or - exists (Block b - | this = b and blockscope(unresolveElement(b), unresolveElement(result))) + exists(TemplateFunction tf | this = tf.getATemplateArgument() and result = tf) or - exists (TemplateFunction tf - | this = tf.getATemplateArgument() and result = tf) - // result instanceof stmt - or - exists (ControlStructure s - | this = s and result = s.getParent()) - + exists(ControlStructure s | this = s and result = s.getParent()) or using_container(unresolveElement(result), underlyingElement(this)) } @@ -182,18 +161,14 @@ class Element extends ElementBase { * are entirely generated by a macro are included - for elements that * partially come from a macro, see `isAffectedByMacro`. */ - predicate isInMacroExpansion() { - inMacroExpansion(this) - } + predicate isInMacroExpansion() { inMacroExpansion(this) } /** * Holds if this element is affected in any way by a macro. All elements * that are totally or partially generated by a macro are included, so * this is a super-set of `isInMacroExpansion`. */ - predicate isAffectedByMacro() { - affectedByMacro(this) - } + predicate isAffectedByMacro() { affectedByMacro(this) } private Element getEnclosingElementPref() { enclosingfunction(underlyingElement(this), unresolveElement(result)) or @@ -206,22 +181,22 @@ class Element extends ElementBase { namequalifiers(underlyingElement(this), unresolveElement(result), _, _) or initialisers(underlyingElement(this), unresolveElement(result), _, _) or exprconv(unresolveElement(result), underlyingElement(this)) or - param_decl_bind(underlyingElement(this),_,unresolveElement(result)) or - using_container(unresolveElement(result),underlyingElement(this)) + param_decl_bind(underlyingElement(this), _, unresolveElement(result)) or + using_container(unresolveElement(result), underlyingElement(this)) } /** Gets the closest `Element` enclosing this one. */ - cached Element getEnclosingElement() { - result = getEnclosingElementPref() or + cached + Element getEnclosingElement() { + result = getEnclosingElementPref() + or + not exists(getEnclosingElementPref()) and ( - not exists(getEnclosingElementPref()) and - ( - this = result.(Class).getAMember() - or - result = exprEnclosingElement(this) - or - var_decls(underlyingElement(this), unresolveElement(result), _, _, _) - ) + this = result.(Class).getAMember() + or + result = exprEnclosingElement(this) + or + var_decls(underlyingElement(this), unresolveElement(result), _, _, _) ) } @@ -230,8 +205,7 @@ class Element extends ElementBase { * the template itself). */ predicate isFromTemplateInstantiation(Element instantiation) { - exists(Element e | - isFromTemplateInstantiationRec(e, instantiation) | + exists(Element e | isFromTemplateInstantiationRec(e, instantiation) | this = e or this.(DeclarationEntry).getDeclaration() = e ) @@ -247,8 +221,7 @@ class Element extends ElementBase { * a value of `template` for each containing template. */ predicate isFromUninstantiatedTemplate(Element template) { - exists(Element e | - isFromUninstantiatedTemplateRec(e, template) | + exists(Element e | isFromUninstantiatedTemplateRec(e, template) | this = e or this.(DeclarationEntry).getDeclaration() = e ) @@ -286,7 +259,10 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) { */ class StaticAssert extends Locatable, @static_assert { override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" } - Expr getCondition() { static_asserts(underlyingElement(this), unresolveElement(result), _, _) } - string getMessage() { static_asserts(underlyingElement(this), _, result, _) } + + Expr getCondition() { static_asserts(underlyingElement(this), unresolveElement(result), _, _) } + + string getMessage() { static_asserts(underlyingElement(this), _, result, _) } + override Location getLocation() { static_asserts(underlyingElement(this), _, _, result) } } diff --git a/cpp/ql/src/semmle/code/cpp/Enclosing.qll b/cpp/ql/src/semmle/code/cpp/Enclosing.qll index 12b62f7e354..b56f7219d07 100644 --- a/cpp/ql/src/semmle/code/cpp/Enclosing.qll +++ b/cpp/ql/src/semmle/code/cpp/Enclosing.qll @@ -3,7 +3,8 @@ import cpp /** * Gets the enclosing element of statement `s`. */ -cached Element stmtEnclosingElement(Stmt s) { +cached +Element stmtEnclosingElement(Stmt s) { result.(Function).getEntryPoint() = s or result = stmtEnclosingElement(s.getParent()) or result = exprEnclosingElement(s.getParent()) @@ -12,25 +13,42 @@ cached Element stmtEnclosingElement(Stmt s) { /** * Gets the enclosing element of expression `e`. */ -cached Element exprEnclosingElement(Expr e) { - result = exprEnclosingElement(e.getParent()) or - result = stmtEnclosingElement(e.getParent()) or - result.(Function) = e.getParent() or - result = exprEnclosingElement(e.(Conversion).getExpr()) or - exists(Initializer i | i.getExpr() = e and - if exists(i.getEnclosingStmt()) - then result = stmtEnclosingElement(i.getEnclosingStmt()) - else if i.getDeclaration() instanceof Parameter - then result = i.getDeclaration().(Parameter).getFunction() - else result = i.getDeclaration()) or - exists(Expr anc | expr_ancestor(unresolveElement(e), unresolveElement(anc)) and result = exprEnclosingElement(anc)) or - exists(Stmt anc | expr_ancestor(unresolveElement(e), unresolveElement(anc)) and result = stmtEnclosingElement(anc)) or +cached +Element exprEnclosingElement(Expr e) { + result = exprEnclosingElement(e.getParent()) + or + result = stmtEnclosingElement(e.getParent()) + or + result.(Function) = e.getParent() + or + result = exprEnclosingElement(e.(Conversion).getExpr()) + or + exists(Initializer i | + i.getExpr() = e and + if exists(i.getEnclosingStmt()) + then result = stmtEnclosingElement(i.getEnclosingStmt()) + else + if i.getDeclaration() instanceof Parameter + then result = i.getDeclaration().(Parameter).getFunction() + else result = i.getDeclaration() + ) + or + exists(Expr anc | + expr_ancestor(unresolveElement(e), unresolveElement(anc)) and result = exprEnclosingElement(anc) + ) + or + exists(Stmt anc | + expr_ancestor(unresolveElement(e), unresolveElement(anc)) and result = stmtEnclosingElement(anc) + ) + or exists(DeclarationEntry de | - expr_ancestor(unresolveElement(e), unresolveElement(de)) and - if exists(DeclStmt ds | de = ds.getADeclarationEntry()) - then exists(DeclStmt ds | - de = ds.getADeclarationEntry() and - result = stmtEnclosingElement(ds)) - else result = de.getDeclaration()) + expr_ancestor(unresolveElement(e), unresolveElement(de)) and + if exists(DeclStmt ds | de = ds.getADeclarationEntry()) + then + exists(DeclStmt ds | + de = ds.getADeclarationEntry() and + result = stmtEnclosingElement(ds) + ) + else result = de.getDeclaration() + ) } - diff --git a/cpp/ql/src/semmle/code/cpp/Enum.qll b/cpp/ql/src/semmle/code/cpp/Enum.qll index e2213b8e7ef..e3a2ef60ccc 100644 --- a/cpp/ql/src/semmle/code/cpp/Enum.qll +++ b/cpp/ql/src/semmle/code/cpp/Enum.qll @@ -18,7 +18,10 @@ private import semmle.code.cpp.internal.ResolveClass class Enum extends UserType, IntegralOrEnumType { /** Gets an enumerator of this enumeration. */ EnumConstant getAnEnumConstant() { result.getDeclaringEnum() = this } - EnumConstant getEnumConstant(int index) { enumconstants(unresolveElement(result),underlyingElement(this),index,_,_,_) } + + EnumConstant getEnumConstant(int index) { + enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _) + } override string getCanonicalQLClass() { result = "Enum" } @@ -27,12 +30,13 @@ class Enum extends UserType, IntegralOrEnumType { * be used for debugging purposes. For more information, see the comment * for `Type.explain`. */ - override string explain() { result = "enum " + this.getName() } + override string explain() { result = "enum " + this.getName() } override int getSize() { // Workaround for extractor bug CPP-348: No size information for enums. // If the extractor didn't provide a size, assume four bytes. - result = UserType.super.getSize() or + result = UserType.super.getSize() + or not exists(UserType.super.getSize()) and result = 4 } @@ -43,9 +47,7 @@ class Enum extends UserType, IntegralOrEnumType { * Holds if this enum has an enum-base [N4140 7.2]. * For example: `enum E : int`. */ - predicate hasExplicitUnderlyingType() { - derivations(_, underlyingElement(this), _, _, _) - } + predicate hasExplicitUnderlyingType() { derivations(_, underlyingElement(this), _, _, _) } /** * The type of the enum-base [N4140 7.2], if it is specified. @@ -68,9 +70,7 @@ class Enum extends UserType, IntegralOrEnumType { * ``` */ class LocalEnum extends Enum { - LocalEnum() { - isLocal() - } + LocalEnum() { isLocal() } override string getCanonicalQLClass() { result = "LocalEnum" } } @@ -88,13 +88,10 @@ class LocalEnum extends Enum { * ``` */ class NestedEnum extends Enum { - - NestedEnum() { - this.isMember() - } + NestedEnum() { this.isMember() } override string getCanonicalQLClass() { result = "NestedEnum" } - + /** Holds if this member is private. */ predicate isPrivate() { this.hasSpecifier("private") } @@ -103,7 +100,6 @@ class NestedEnum extends Enum { /** Holds if this member is public. */ predicate isPublic() { this.hasSpecifier("public") } - } /** @@ -117,9 +113,7 @@ class NestedEnum extends Enum { * ``` */ class ScopedEnum extends Enum { - ScopedEnum() { - usertypes(underlyingElement(this),_,13) - } + ScopedEnum() { usertypes(underlyingElement(this), _, 13) } override string getCanonicalQLClass() { result = "ScopedEnum" } } @@ -140,18 +134,18 @@ class EnumConstant extends Declaration, @enumconstant { /** * Gets the enumeration of which this enumerator is a member. */ - Enum getDeclaringEnum() { enumconstants(underlyingElement(this),unresolveElement(result),_,_,_,_) } + Enum getDeclaringEnum() { + enumconstants(underlyingElement(this), unresolveElement(result), _, _, _, _) + } override string getCanonicalQLClass() { result = "EnumConstant" } - - override Class getDeclaringType() { - result = this.getDeclaringEnum().getDeclaringType() - } + + override Class getDeclaringType() { result = this.getDeclaringEnum().getDeclaringType() } /** * Gets the name of this enumerator. */ - override string getName() { enumconstants(underlyingElement(this),_,_,_,result,_) } + override string getName() { enumconstants(underlyingElement(this), _, _, _, result, _) } /** * Gets the value that this enumerator is initialized to, as a @@ -161,13 +155,15 @@ class EnumConstant extends Declaration, @enumconstant { string getValue() { result = this.getInitializer().getExpr().getValue() } /** Gets the type of this enumerator. */ - Type getType() { enumconstants(underlyingElement(this),_,_,unresolveElement(result),_,_) } + Type getType() { enumconstants(underlyingElement(this), _, _, unresolveElement(result), _, _) } /** Gets the location of a declaration of this enumerator. */ override Location getADeclarationLocation() { result = this.getDefinitionLocation() } /** Gets the location of the definition of this enumerator. */ - override Location getDefinitionLocation() { enumconstants(underlyingElement(this),_,_,_,_,result) } + override Location getDefinitionLocation() { + enumconstants(underlyingElement(this), _, _, _, _, result) + } /** Gets the location of the definition of this enumerator. */ override Location getLocation() { result = this.getDefinitionLocation() } @@ -179,7 +175,9 @@ class EnumConstant extends Declaration, @enumconstant { EnumConstantAccess getAnAccess() { result.getTarget() = this } /** Gets a specifier of this enumerator. */ - override Specifier getASpecifier() { varspecifiers(underlyingElement(this),unresolveElement(result)) } + override Specifier getASpecifier() { + varspecifiers(underlyingElement(this), unresolveElement(result)) + } /** * An attribute of this enumerator. @@ -187,7 +185,5 @@ class EnumConstant extends Declaration, @enumconstant { * Note that allowing attributes on enumerators is a language extension * which is only supported by Clang. */ - Attribute getAnAttribute() { - varattributes(underlyingElement(this), unresolveElement(result)) - } + Attribute getAnAttribute() { varattributes(underlyingElement(this), unresolveElement(result)) } } diff --git a/cpp/ql/src/semmle/code/cpp/Field.qll b/cpp/ql/src/semmle/code/cpp/Field.qll index 6448ffdba42..e09aea85760 100644 --- a/cpp/ql/src/semmle/code/cpp/Field.qll +++ b/cpp/ql/src/semmle/code/cpp/Field.qll @@ -17,16 +17,13 @@ import semmle.code.cpp.exprs.Access * variables, use `MemberVariable` instead of `Field`. */ class Field extends MemberVariable { - - Field() { - fieldoffsets(underlyingElement(this),_,_) - } + Field() { fieldoffsets(underlyingElement(this), _, _) } /** * Gets the offset of this field in bytes from the start of its declaring * type (on the machine where facts were extracted). */ - int getByteOffset() { fieldoffsets(underlyingElement(this),result,_) } + int getByteOffset() { fieldoffsets(underlyingElement(this), result, _) } /** * Gets the byte offset within `mostDerivedClass` of each occurence of this @@ -37,8 +34,7 @@ class Field extends MemberVariable { * complete most-derived object. */ int getAByteOffsetIn(Class mostDerivedClass) { - result = mostDerivedClass.getABaseClassByteOffset(getDeclaringType()) + - getByteOffset() + result = mostDerivedClass.getABaseClassByteOffset(getDeclaringType()) + getByteOffset() } /** @@ -48,7 +44,7 @@ class Field extends MemberVariable { * struct S { * unsigned int a : 5; * unsigned int : 5; - * unsigned int b : 5; + * unsigned int b : 5; * }; * ``` * @@ -66,12 +62,13 @@ class Field extends MemberVariable { * which the field will be initialized, whether by an initializer list or in a * constructor. */ - final pragma[nomagic] int getInitializationOrder() { - exists(Class cls, int memberIndex | + pragma[nomagic] + final int getInitializationOrder() { + exists(Class cls, int memberIndex | this = cls.getCanonicalMember(memberIndex) and memberIndex = rank[result + 1](int index | - cls.getCanonicalMember(index).(Field).isInitializable() - ) + cls.getCanonicalMember(index).(Field).isInitializable() + ) ) } } @@ -86,13 +83,13 @@ class Field extends MemberVariable { * ``` */ class BitField extends Field { - BitField() { bitfield(underlyingElement(this),_,_) } + BitField() { bitfield(underlyingElement(this), _, _) } /** * Gets the size of this bitfield in bits (on the machine where facts * were extracted). */ - int getNumBits() { bitfield(underlyingElement(this),result,_) } + int getNumBits() { bitfield(underlyingElement(this), result, _) } /** * Gets the value which appeared after the colon in the bitfield @@ -104,18 +101,16 @@ class BitField extends Field { * `getNumBits` will give 32, whereas `getDeclaredNumBits` will give * 1234. */ - int getDeclaredNumBits() { bitfield(underlyingElement(this),_,result) } + int getDeclaredNumBits() { bitfield(underlyingElement(this), _, result) } /** * Gets the offset of this bitfield in bits from the byte identified by * getByteOffset (on the machine where facts were extracted). */ - int getBitOffset() { fieldoffsets(underlyingElement(this),_,result) } + int getBitOffset() { fieldoffsets(underlyingElement(this), _, result) } /** Holds if this bitfield is anonymous. */ - predicate isAnonymous() { - hasName("(unnamed bitfield)") - } + predicate isAnonymous() { hasName("(unnamed bitfield)") } override predicate isInitializable() { // Anonymous bitfields are not initializable. diff --git a/cpp/ql/src/semmle/code/cpp/File.qll b/cpp/ql/src/semmle/code/cpp/File.qll index a90e875cc40..60ef2d587ef 100644 --- a/cpp/ql/src/semmle/code/cpp/File.qll +++ b/cpp/ql/src/semmle/code/cpp/File.qll @@ -36,7 +36,7 @@ abstract class Container extends Locatable, @container { * * For more information see [Providing URLs](https://help.semmle.com/QL/learn-ql/ql/locations.html#providing-urls). */ - deprecated abstract string getURL(); + abstract deprecated string getURL(); /** * Gets the relative path of this file or folder from the root folder of the @@ -47,8 +47,9 @@ abstract class Container extends Locatable, @container { * if the root folder is not a reflexive, transitive parent of this container. */ string getRelativePath() { - exists (string absPath, string pref | - absPath = getAbsolutePath() and sourceLocationPrefix(pref) | + exists(string absPath, string pref | + absPath = getAbsolutePath() and sourceLocationPrefix(pref) + | absPath = pref and result = "" or absPath = pref.regexpReplaceAll("/$", "") + "/" + result and @@ -100,9 +101,7 @@ abstract class Container extends Locatable, @container { * "/tmp/x.tar.gz""gz" * */ - string getExtension() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) - } + string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -121,9 +120,7 @@ abstract class Container extends Locatable, @container { * "/tmp/x.tar.gz""x.tar" * */ - string getStem() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) - } + string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } /** Gets the parent container of this file or folder, if any. */ Container getParentContainer() { @@ -131,14 +128,10 @@ abstract class Container extends Locatable, @container { } /** Gets a file or sub-folder in this container. */ - Container getAChildContainer() { - this = result.getParentContainer() - } + Container getAChildContainer() { this = result.getParentContainer() } /** Gets a file in this container. */ - File getAFile() { - result = getAChildContainer() - } + File getAFile() { result = getAChildContainer() } /** Gets the file in this container that has the given `baseName`, if any. */ File getFile(string baseName) { @@ -147,9 +140,7 @@ abstract class Container extends Locatable, @container { } /** Gets a sub-folder in this container. */ - Folder getAFolder() { - result = getAChildContainer() - } + Folder getAFolder() { result = getAChildContainer() } /** Gets the sub-folder in this container that has the given `baseName`, if any. */ Folder getFolder(string baseName) { @@ -162,9 +153,7 @@ abstract class Container extends Locatable, @container { * * This is the absolute path of the container. */ - override string toString() { - result = getAbsolutePath() - } + override string toString() { result = getAbsolutePath() } } /** @@ -178,9 +167,7 @@ abstract class Container extends Locatable, @container { * To get the full path, use `getAbsolutePath`. */ class Folder extends Container, @folder { - override string getAbsolutePath() { - folders(underlyingElement(this), result, _) - } + override string getAbsolutePath() { folders(underlyingElement(this), result, _) } override Location getLocation() { result.getContainer() = this and @@ -193,51 +180,49 @@ class Folder extends Container, @folder { * DEPRECATED: Use `getLocation` instead. * Gets the URL of this folder. */ - deprecated override string getURL() { - result = "file://" + this.getAbsolutePath() + ":0:0:0:0" - } + deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } /** * DEPRECATED: use `getAbsolutePath` instead. * Gets the name of this folder. */ - deprecated - string getName() { folders(underlyingElement(this),result,_) } + deprecated string getName() { folders(underlyingElement(this), result, _) } /** * DEPRECATED: use `getAbsolutePath` instead. * Holds if this element is named `name`. */ - deprecated - predicate hasName(string name) { name = this.getName() } + deprecated predicate hasName(string name) { name = this.getName() } /** * DEPRECATED: use `getAbsolutePath` instead. * Gets the full name of this folder. */ - deprecated - string getFullName() { result = this.getName() } + deprecated string getFullName() { result = this.getName() } /** * DEPRECATED: use `getBaseName` instead. * Gets the last part of the folder name. */ - deprecated - string getShortName() { - exists (string longnameRaw, string longname - | folders(underlyingElement(this),_,longnameRaw) and + deprecated string getShortName() { + exists(string longnameRaw, string longname | + folders(underlyingElement(this), _, longnameRaw) and longname = longnameRaw.replaceAll("\\", "/") - | exists (int index - | result = longname.splitAt("/", index) and - not exists (longname.splitAt("/", index+1)))) + | + exists(int index | + result = longname.splitAt("/", index) and + not exists(longname.splitAt("/", index + 1)) + ) + ) } /** * DEPRECATED: use `getParentContainer` instead. * Gets the parent folder. */ - deprecated - Folder getParent() { containerparent(unresolveElement(result),underlyingElement(this)) } + deprecated Folder getParent() { + containerparent(unresolveElement(result), underlyingElement(this)) + } } /** @@ -253,13 +238,9 @@ class Folder extends Container, @folder { * `getStem` and `getExtension`. To get the full path, use `getAbsolutePath`. */ class File extends Container, @file { - override string getAbsolutePath() { - files(underlyingElement(this), result, _, _, _) - } + override string getAbsolutePath() { files(underlyingElement(this), result, _, _, _) } - override string toString() { - result = Container.super.toString() - } + override string toString() { result = Container.super.toString() } override string getCanonicalQLClass() { result = "File" } @@ -272,35 +253,25 @@ class File extends Container, @file { * DEPRECATED: Use `getLocation` instead. * Gets the URL of this file. */ - deprecated override string getURL() { - result = "file://" + this.getAbsolutePath() + ":0:0:0:0" - } + deprecated override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } /** Holds if this file was compiled as C (at any point). */ - predicate compiledAsC() { - fileannotations(underlyingElement(this),1,"compiled as c","1") - } + predicate compiledAsC() { fileannotations(underlyingElement(this), 1, "compiled as c", "1") } /** Holds if this file was compiled as C++ (at any point). */ - predicate compiledAsCpp() { - fileannotations(underlyingElement(this),1,"compiled as c++","1") - } + predicate compiledAsCpp() { fileannotations(underlyingElement(this), 1, "compiled as c++", "1") } /** * DEPRECATED: Objective-C is no longer supported. * Holds if this file was compiled as Objective C (at any point). */ - deprecated predicate compiledAsObjC() { - none() - } + deprecated predicate compiledAsObjC() { none() } /** * DEPRECATED: Objective-C is no longer supported. * Holds if this file was compiled as Objective C++ (at any point). */ - deprecated predicate compiledAsObjCpp() { - none() - } + deprecated predicate compiledAsObjCpp() { none() } /** * Holds if this file was compiled by a Microsoft compiler (at any point). @@ -315,24 +286,26 @@ class File extends Container, @file { c.getAnArgument() = "--microsoft" or c.getAnArgument().toLowerCase().replaceAll("\\", "/").matches("%/cl.exe") ) - ) or exists(File parent | + ) + or + exists(File parent | parent.compiledAsMicrosoft() and parent.getAnIncludedFile() = this ) } /** Gets a top-level element declared in this file. */ - Declaration getATopLevelDeclaration() { - result.getAFile() = this and result.isTopLevel() - } + Declaration getATopLevelDeclaration() { result.getAFile() = this and result.isTopLevel() } /** Gets a declaration in this file. */ Declaration getADeclaration() { result.getAFile() = this } /** Holds if this file uses the given macro. */ predicate usesMacro(Macro m) { - exists(MacroInvocation mi | mi.getFile() = this and - mi.getMacro() = m) + exists(MacroInvocation mi | + mi.getFile() = this and + mi.getMacro() = m + ) } /** @@ -347,23 +320,23 @@ class File extends Container, @file { * DEPRECATED: use `getParentContainer` instead. * Gets the folder which contains this file. */ - deprecated - Folder getParent() { containerparent(unresolveElement(result),underlyingElement(this)) } + deprecated Folder getParent() { + containerparent(unresolveElement(result), underlyingElement(this)) + } /** * Holds if this file may be from source. This predicate holds for all files * except the dummy file, whose name is the empty string, which contains * declarations that are built into the compiler. */ - override predicate fromSource() { numlines(underlyingElement(this),_,_,_) } + override predicate fromSource() { numlines(underlyingElement(this), _, _, _) } /** * Holds if this file may be from a library. * * DEPRECATED: For historical reasons this is true for any file. */ - deprecated override - predicate fromLibrary() { any() } + deprecated override predicate fromLibrary() { any() } /** Gets the metric file. */ MetricFile getMetrics() { result = this } @@ -373,8 +346,7 @@ class File extends Container, @file { * Gets the full name of this file, for example: * "/usr/home/me/myprogram.c". */ - deprecated - string getName() { files(underlyingElement(this),result,_,_,_) } + deprecated string getName() { files(underlyingElement(this), result, _, _, _) } /** * DEPRECATED: Use `getAbsolutePath` instead. @@ -382,16 +354,14 @@ class File extends Container, @file { * * Example usage: `f.hasName("/usr/home/me/myprogram.c")`. */ - deprecated - predicate hasName(string name) { name = this.getName() } + deprecated predicate hasName(string name) { name = this.getName() } /** * DEPRECATED: Use `getAbsolutePath` instead. * Gets the full name of this file, for example * "/usr/home/me/myprogram.c". */ - deprecated - string getFullName() { result = this.getName() } + deprecated string getFullName() { result = this.getName() } /** * Gets the remainder of the base name after the first dot character. Note @@ -405,9 +375,7 @@ class File extends Container, @file { * for example, for "file.tar.gz", this predicate will have the result * "tar.gz", while `getExtension` will have the result "gz". */ - string getExtensions() { - files(underlyingElement(this),_,_,result,_) - } + string getExtensions() { files(underlyingElement(this), _, _, result, _) } /** * DEPRECATED: Use `getBaseName` instead. @@ -415,15 +383,14 @@ class File extends Container, @file { * if the full name is "/path/to/filename.a.bcd" then the filename is * "filename.a.bcd". */ - deprecated - string getFileName() { - // [a/b.c/d/]fileName - // ^ beginAfter - exists(string fullName, int beginAfter | - fullName = this.getName() and - beginAfter = max(int i | i = -1 or fullName.charAt(i) = "/" | i) and - result = fullName.suffix(beginAfter + 1) - ) + deprecated string getFileName() { + // [a/b.c/d/]fileName + // ^ beginAfter + exists(string fullName, int beginAfter | + fullName = this.getName() and + beginAfter = max(int i | i = -1 or fullName.charAt(i) = "/" | i) and + result = fullName.suffix(beginAfter + 1) + ) } /** @@ -439,10 +406,9 @@ class File extends Container, @file { * for example, for "file.tar.gz", this predicate will have the result * "file", while `getStem` will have the result "file.tar". */ - string getShortName() { files(underlyingElement(this),_,result,_,_) } + string getShortName() { files(underlyingElement(this), _, result, _, _) } } - /** * A C/C++ header file, as determined (mainly) by file extension. * @@ -450,12 +416,20 @@ class File extends Container, @file { * pre-processor directive like `#include`), use `Include.getIncludedFile`. */ class HeaderFile extends File { - HeaderFile() { exists(string ext | ext = this.getExtension().toLowerCase() | - ext = "h" or ext = "r" - /* --- */ or ext = "hpp" or ext = "hxx" or ext = "h++" or ext = "hh" or ext = "hp" - or ext = "tcc" or ext = "tpp" or ext = "txx" or ext = "t++" /* --- --- */ + ext = "h" or + ext = "r" or + /* --- */ ext = "hpp" or + ext = "hxx" or + ext = "h++" or + ext = "hh" or + ext = "hp" or + ext = "tcc" or + ext = "tpp" or + ext = "txx" or + ext = "t++" + /* --- --- */ ) or not exists(this.getExtension()) and @@ -472,8 +446,7 @@ class HeaderFile extends File { * - a file that contains non-top level code or data that's included in an * unusual way */ - predicate noTopLevelCode() - { + predicate noTopLevelCode() { not exists(DeclarationEntry de | de.getFile() = this) and not exists(Declaration d | d.getFile() = this and d.isTopLevel()) and not exists(UsingEntry ue | ue.getFile() = this) @@ -487,12 +460,7 @@ class HeaderFile extends File { * `File.compiledAsC`. */ class CFile extends File { - - CFile() { - exists(string ext | ext = this.getExtension().toLowerCase() | - ext = "c" or ext = "i" - ) - } + CFile() { exists(string ext | ext = this.getExtension().toLowerCase() | ext = "c" or ext = "i") } override string getCanonicalQLClass() { result = "CFile" } } @@ -504,11 +472,19 @@ class CFile extends File { * `File.compiledAsCpp`. */ class CppFile extends File { - CppFile() { exists(string ext | ext = this.getExtension().toLowerCase() | - /* --- */ ext = "cpp" or ext = "cxx" or ext = "c++" or ext = "cc" or ext = "cp" - or ext = "icc" or ext = "ipp" or ext = "ixx" or ext = "i++" or ext = "ii" /* --- */ + /* --- */ ext = "cpp" or + ext = "cxx" or + ext = "c++" or + ext = "cc" or + ext = "cp" or + ext = "icc" or + ext = "ipp" or + ext = "ixx" or + ext = "i++" or + ext = "ii" + /* --- */ // Note: .C files are indistinguishable from .c files on some // file systems, so we just treat them as CFile's. ) diff --git a/cpp/ql/src/semmle/code/cpp/FriendDecl.qll b/cpp/ql/src/semmle/code/cpp/FriendDecl.qll index c1d26e92e2f..c788ea70058 100644 --- a/cpp/ql/src/semmle/code/cpp/FriendDecl.qll +++ b/cpp/ql/src/semmle/code/cpp/FriendDecl.qll @@ -22,7 +22,7 @@ class FriendDecl extends Declaration, @frienddecl { * use `getFriend`. */ override Location getADeclarationLocation() { result = this.getLocation() } - + override string getCanonicalQLClass() { result = "FriendDecl" } /** @@ -36,12 +36,10 @@ class FriendDecl extends Declaration, @frienddecl { override Location getDefinitionLocation() { result = this.getLocation() } /** Gets the location of this friend declaration. */ - override Location getLocation() { frienddecls(underlyingElement(this),_,_,result) } + override Location getLocation() { frienddecls(underlyingElement(this), _, _, result) } /** Gets a descriptive string for this friend declaration. */ - override string getName() { - result = this.getDeclaringClass().getName() + "'s friend" - } + override string getName() { result = this.getDeclaringClass().getName() + "'s friend" } /** * Friend declarations do not have specifiers. It makes no difference @@ -54,13 +52,13 @@ class FriendDecl extends Declaration, @frienddecl { * Gets the target of this friend declaration. * For example: `X` in `class A { friend class X }`. */ - AccessHolder getFriend() { frienddecls(underlyingElement(this),_,unresolveElement(result),_) } + AccessHolder getFriend() { frienddecls(underlyingElement(this), _, unresolveElement(result), _) } /** * Gets the declaring class (also known as the befriending class). * For example: `A` in `class A { friend class X }`. */ - Class getDeclaringClass() { frienddecls(underlyingElement(this),unresolveElement(result),_,_) } + Class getDeclaringClass() { frienddecls(underlyingElement(this), unresolveElement(result), _, _) } /* Holds if this declaration is a top-level declaration. */ override predicate isTopLevel() { none() } diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index dc326a2fc73..94d11d63575 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -22,7 +22,7 @@ private import semmle.code.cpp.internal.ResolveClass * in more detail in `Declaration.qll`. */ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { - override string getName() { functions(underlyingElement(this),result,_) } + override string getName() { functions(underlyingElement(this), result, _) } /** * DEPRECATED: Use `getIdentityString(Declaration)` from `semmle.code.cpp.Print` instead. @@ -43,47 +43,42 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { result = name + templateArgs + args + " -> " + getType().toString() and name = getQualifiedName() and ( - if exists(getATemplateArgument()) then ( + if exists(getATemplateArgument()) + then templateArgs = "<" + - concat(int i | - exists(getTemplateArgument(i)) | - getTemplateArgument(i).toString(), ", " order by i - ) + ">" - ) - else - templateArgs = "" + concat(int i | + exists(getTemplateArgument(i)) + | + getTemplateArgument(i).toString(), ", " order by i + ) + ">" + else templateArgs = "" ) and args = "(" + - concat(int i | - exists(getParameter(i)) | - getParameter(i).getType().toString(), ", " order by i - ) + ")" - ) + concat(int i | + exists(getParameter(i)) + | + getParameter(i).getType().toString(), ", " order by i + ) + ")" + ) } /** Gets a specifier of this function. */ override Specifier getASpecifier() { - funspecifiers(underlyingElement(this),unresolveElement(result)) - or result.hasName(getADeclarationEntry().getASpecifier()) + funspecifiers(underlyingElement(this), unresolveElement(result)) or + result.hasName(getADeclarationEntry().getASpecifier()) } /** Gets an attribute of this function. */ Attribute getAnAttribute() { funcattributes(underlyingElement(this), unresolveElement(result)) } /** Holds if this function is generated by the compiler. */ - predicate isCompilerGenerated() { - compgenerated(underlyingElement(this)) - } + predicate isCompilerGenerated() { compgenerated(underlyingElement(this)) } /** Holds if this function is inline. */ - predicate isInline() { - this.hasSpecifier("inline") - } + predicate isInline() { this.hasSpecifier("inline") } /** Holds if this function is virtual. */ - predicate isVirtual() { - this.hasSpecifier("virtual") - } + predicate isVirtual() { this.hasSpecifier("virtual") } /** * Holds if this function is deleted. @@ -96,24 +91,18 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * `Class.implicitCopyAssignmentOperatorDeleted` can be used to find * whether a class would have had those members implicitly deleted. */ - predicate isDeleted() { - function_deleted(underlyingElement(this)) - } + predicate isDeleted() { function_deleted(underlyingElement(this)) } /** * Holds if this function is explicitly defaulted with the `= default` * specifier. */ - predicate isDefaulted() { - function_defaulted(underlyingElement(this)) - } + predicate isDefaulted() { function_defaulted(underlyingElement(this)) } /** * Holds if this function is declared to be `constexpr`. */ - predicate isDeclaredConstexpr() { - this.hasSpecifier("declared_constexpr") - } + predicate isDeclaredConstexpr() { this.hasSpecifier("declared_constexpr") } /** * Holds if this function is `constexpr`. Normally, this holds if and @@ -125,20 +114,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * ``` * `g` is declared constexpr, but is not constexpr. */ - predicate isConstexpr() { - this.hasSpecifier("is_constexpr") - } + predicate isConstexpr() { this.hasSpecifier("is_constexpr") } /** * Holds if this function is declared with `__attribute__((naked))` or * `__declspec(naked)`. */ - predicate isNaked() { - getAnAttribute().hasName("naked") - } + predicate isNaked() { getAnAttribute().hasName("naked") } /** Gets the return type of this function. */ - Type getType() { function_return_type(underlyingElement(this),unresolveElement(result)) } + Type getType() { function_return_type(underlyingElement(this), unresolveElement(result)) } /** * Gets the return type of this function after specifiers have been deeply @@ -147,18 +132,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { Type getUnspecifiedType() { result = getType().getUnspecifiedType() } /** Gets the nth parameter of this function. */ - Parameter getParameter(int n) { params(unresolveElement(result),underlyingElement(this),n,_) } + Parameter getParameter(int n) { params(unresolveElement(result), underlyingElement(this), n, _) } /** Gets a parameter of this function. */ - Parameter getAParameter() { params(unresolveElement(result),underlyingElement(this),_,_) } + Parameter getAParameter() { params(unresolveElement(result), underlyingElement(this), _, _) } /** * Gets the number of parameters of this function, _not_ including any * implicit `this` parameter or any `...` varargs pseudo-parameter. */ - int getNumberOfParameters() { - result = count(this.getAParameter()) - } + int getNumberOfParameters() { result = count(this.getAParameter()) } /** * Gets the number of parameters of this function, _including_ any implicit @@ -176,26 +159,20 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * For example: for a function `int Foo(int p1, int p2)` this would * return `int p1, int p2`. */ - string getParameterString() { - result = getParameterStringFrom(0) - } + string getParameterString() { result = getParameterStringFrom(0) } private string getParameterStringFrom(int index) { - ( - index = getNumberOfParameters() and - result = "" - ) or ( - index = getNumberOfParameters() - 1 and - result = getParameter(index).getTypedName() - ) or ( - index < getNumberOfParameters() - 1 and - result = getParameter(index).getTypedName() + ", " + getParameterStringFrom(index + 1) - ) + index = getNumberOfParameters() and + result = "" + or + index = getNumberOfParameters() - 1 and + result = getParameter(index).getTypedName() + or + index < getNumberOfParameters() - 1 and + result = getParameter(index).getTypedName() + ", " + getParameterStringFrom(index + 1) } - FunctionCall getACallToThisFunction() { - result.getTarget() = this - } + FunctionCall getACallToThisFunction() { result.getTarget() = this } /** * Gets a declaration entry corresponding to this declaration. The @@ -203,14 +180,17 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * in `Declaration.qll`. */ override FunctionDeclarationEntry getADeclarationEntry() { - if fun_decls(_,underlyingElement(this),_,_,_) then - declEntry(result) + if fun_decls(_, underlyingElement(this), _, _, _) + then declEntry(result) else - exists(Function f | this.isConstructedFrom(f) and fun_decls(unresolveElement(result),unresolveElement(f),_,_,_)) + exists(Function f | + this.isConstructedFrom(f) and + fun_decls(unresolveElement(result), unresolveElement(f), _, _, _) + ) } private predicate declEntry(FunctionDeclarationEntry fde) { - fun_decls(unresolveElement(fde),underlyingElement(this),_,_,_) and + fun_decls(unresolveElement(fde), underlyingElement(this), _, _, _) and // If one .cpp file specializes a function, and another calls the // specialized function, then when extracting the second we only see an // instantiation, not the specialization. We Therefore need to ignore @@ -222,14 +202,14 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * Gets the location of a `FunctionDeclarationEntry` corresponding to this * declaration. */ - override Location getADeclarationLocation() { - result = getADeclarationEntry().getLocation() - } + override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } /** Holds if this Function is a Template specialization. */ predicate isSpecialization() { - exists(FunctionDeclarationEntry fde | fun_decls(unresolveElement(fde),underlyingElement(this),_,_,_) - and fde.isSpecialization()) + exists(FunctionDeclarationEntry fde | + fun_decls(unresolveElement(fde), underlyingElement(this), _, _, _) and + fde.isSpecialization() + ) } /** @@ -243,10 +223,9 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { /** Gets the location of the definition, if any. */ override Location getDefinitionLocation() { - if exists(getDefinition()) then - result = getDefinition().getLocation() - else - exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation()) + if exists(getDefinition()) + then result = getDefinition().getLocation() + else exists(Function f | this.isConstructedFrom(f) and result = f.getDefinition().getLocation()) } /** @@ -254,10 +233,9 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * definition, if possible.) */ override Location getLocation() { - if exists(getDefinition()) then - result = this.getDefinitionLocation() - else - result = this.getADeclarationLocation() + if exists(getDefinition()) + then result = this.getDefinitionLocation() + else result = this.getADeclarationLocation() } /** Gets a child declaration of this function. */ @@ -282,9 +260,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * `getBlock`. However in C++, the first node can also be a * `FunctionTryStmt`. */ - Stmt getEntryPoint() { - function_entry_point(underlyingElement(this), unresolveElement(result)) - } + Stmt getEntryPoint() { function_entry_point(underlyingElement(this), unresolveElement(result)) } /** * Gets the metric class. `MetricFunction` has methods for computing @@ -294,39 +270,48 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { MetricFunction getMetrics() { result = this } /** Holds if this function calls the function `f`. */ - predicate calls(Function f) { - exists(Locatable l | this.calls(f, l)) - } + predicate calls(Function f) { exists(Locatable l | this.calls(f, l)) } /** * Holds if this function calls the function `f` in the `FunctionCall` * expression `l`. */ predicate calls(Function f, Locatable l) { - exists(FunctionCall call | call.getEnclosingFunction() = this and call.getTarget() = f and call = l) - or exists(DestructorCall call | call.getEnclosingFunction() = this and call.getTarget() = f and call = l) + exists(FunctionCall call | + call.getEnclosingFunction() = this and call.getTarget() = f and call = l + ) + or + exists(DestructorCall call | + call.getEnclosingFunction() = this and call.getTarget() = f and call = l + ) } /** Holds if this function accesses a function or variable or enumerator `a`. */ - predicate accesses(Declaration a) { - exists(Locatable l | this.accesses(a, l)) - } + predicate accesses(Declaration a) { exists(Locatable l | this.accesses(a, l)) } /** * Holds if this function accesses a function or variable or enumerator `a` * in the `Access` expression `l`. */ predicate accesses(Declaration a, Locatable l) { - exists(Access access | access.getEnclosingFunction() = this and - a = access.getTarget() and access = l) + exists(Access access | + access.getEnclosingFunction() = this and + a = access.getTarget() and + access = l + ) } /** Gets a variable that is written-to in this function. */ Variable getAWrittenVariable() { - exists(ConstructorFieldInit cfi | cfi.getEnclosingFunction() = this and result = cfi.getTarget()) or - exists(VariableAccess va | va = result.getAnAccess() and - va.isUsedAsLValue() and - va.getEnclosingFunction() = this) + exists(ConstructorFieldInit cfi | + cfi.getEnclosingFunction() = this and result = cfi.getTarget() + ) + or + exists(VariableAccess va | + va = result.getAnAccess() and + va.isUsedAsLValue() and + va.getEnclosingFunction() = this + ) } /** @@ -334,26 +319,20 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * used to represent the exit node of the control flow graph, so it is * its own scope. */ - override Function getControlFlowScope() { - result = this - } + override Function getControlFlowScope() { result = this } /** * Implements `ControlFlowNode.getEnclosingStmt`. The `Function` is * used to represent the exit node of the control flow graph, so it * has no enclosing statement. */ - override Stmt getEnclosingStmt() { - none() - } + override Stmt getEnclosingStmt() { none() } /** * Holds if this function has C linkage, as specified by one of its * declaration entries. For example: `extern "C" void foo();`. */ - predicate hasCLinkage() { - getADeclarationEntry().hasCLinkage() - } + predicate hasCLinkage() { getADeclarationEntry().hasCLinkage() } /** * Holds if this function is constructed from `f` as a result @@ -370,7 +349,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * `i`th template parameter. */ override Type getTemplateArgument(int index) { - function_template_argument(underlyingElement(this),index,unresolveElement(result)) + function_template_argument(underlyingElement(this), index, unresolveElement(result)) } /** @@ -379,80 +358,62 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * several functions that are not linked together have been compiled. An * example would be a project with many 'main' functions. */ - predicate isMultiplyDefined() { - strictcount(getFile()) > 1 - } + predicate isMultiplyDefined() { strictcount(getFile()) > 1 } /** Holds if this function is a varargs function. */ - predicate isVarargs() { - hasSpecifier("varargs") - } + predicate isVarargs() { hasSpecifier("varargs") } /** Gets a type that is specified to be thrown by the function. */ - Type getAThrownType() { - result = getADeclarationEntry().getAThrownType() - } + Type getAThrownType() { result = getADeclarationEntry().getAThrownType() } /** * Gets the `i`th type specified to be thrown by the function. */ - Type getThrownType(int i) { - result = getADeclarationEntry().getThrownType(i) - } + Type getThrownType(int i) { result = getADeclarationEntry().getThrownType(i) } /** Holds if the function has an exception specification. */ - predicate hasExceptionSpecification() { - getADeclarationEntry().hasExceptionSpecification() - } + predicate hasExceptionSpecification() { getADeclarationEntry().hasExceptionSpecification() } /** Holds if this function has a `throw()` exception specification. */ - predicate isNoThrow() { - getADeclarationEntry().isNoThrow() - } + predicate isNoThrow() { getADeclarationEntry().isNoThrow() } /** Holds if this function has a `noexcept` exception specification. */ - predicate isNoExcept() { - getADeclarationEntry().isNoExcept() - } + predicate isNoExcept() { getADeclarationEntry().isNoExcept() } /** Gets a function that overloads this one. */ Function getAnOverload() { - result.getName() = getName() - and result.getNamespace() = getNamespace() - and result != this - + result.getName() = getName() and + result.getNamespace() = getNamespace() and + result != this and // If this function is declared in a class, only consider other // functions from the same class. Conversely, if this function is not // declared in a class, only consider other functions not declared in a // class. - and ( - if exists(getDeclaringType()) then - result.getDeclaringType() = getDeclaringType() - else - not exists(result.getDeclaringType()) - ) - + if exists(getDeclaringType()) + then result.getDeclaringType() = getDeclaringType() + else not exists(result.getDeclaringType()) + ) and // Instantiations and specializations don't participate in overload // resolution. - and not (this instanceof FunctionTemplateInstantiation or - result instanceof FunctionTemplateInstantiation) - and not (this instanceof FunctionTemplateSpecialization or - result instanceof FunctionTemplateSpecialization) + not ( + this instanceof FunctionTemplateInstantiation or + result instanceof FunctionTemplateInstantiation + ) and + not ( + this instanceof FunctionTemplateSpecialization or + result instanceof FunctionTemplateSpecialization + ) } /** Gets a link target which compiled or referenced this function. */ - LinkTarget getALinkTarget() { - this = result.getAFunction() - } + LinkTarget getALinkTarget() { this = result.getAFunction() } /** * Holds if this function is side-effect free (conservative * approximation). */ - predicate isSideEffectFree() { - not this.mayHaveSideEffects() - } + predicate isSideEffectFree() { not this.mayHaveSideEffects() } /** * Holds if this function may have side-effects; if in doubt, we assume it @@ -461,44 +422,68 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { predicate mayHaveSideEffects() { // If we cannot see the definition then we assume that it may have // side-effects. - if exists(this.getEntryPoint()) then ( + if exists(this.getEntryPoint()) + then // If it might be globally impure (we don't care about it modifying // temporaries) then it may have side-effects. - this.getEntryPoint().mayBeGloballyImpure() or + this.getEntryPoint().mayBeGloballyImpure() + or // Constructor initializers are separate from the entry point ... - this.(Constructor).getAnInitializer().mayBeGloballyImpure() or + this.(Constructor).getAnInitializer().mayBeGloballyImpure() + or // ... and likewise for destructors. this.(Destructor).getADestruction().mayBeGloballyImpure() - ) else not exists(string name | this.hasGlobalName(name) | - // Unless it's a function that we know is side-effect-free, it may - // have side-effects. - name = "strcmp" or name = "wcscmp" or name = "_mbscmp" or - name = "strlen" or name = "wcslen" or - name = "_mbslen" or name = "_mbslen_l" or - name = "_mbstrlen" or name = "_mbstrlen_l" or - name = "strnlen" or name = "strnlen_s" or - name = "wcsnlen" or name = "wcsnlen_s" or - name = "_mbsnlen" or name = "_mbsnlen_l" or - name = "_mbstrnlen" or name = "_mbstrnlen_l" or - name = "strncmp" or name = "wcsncmp" or - name = "_mbsncmp" or name = "_mbsncmp_l" or - name = "strchr" or name = "memchr" or name = "wmemchr" or - name = "memcmp" or name = "wmemcmp" or - name = "_memicmp" or name = "_memicmp_l" or - name = "feof" or - name = "isdigit" or name = "isxdigit" or - name = "abs" or name = "fabs" or name = "labs" or - name = "floor" or name = "ceil" or - name = "atoi" or name = "atol" or name = "atoll" or name = "atof" - ) + else + not exists(string name | this.hasGlobalName(name) | + // Unless it's a function that we know is side-effect-free, it may + // have side-effects. + name = "strcmp" or + name = "wcscmp" or + name = "_mbscmp" or + name = "strlen" or + name = "wcslen" or + name = "_mbslen" or + name = "_mbslen_l" or + name = "_mbstrlen" or + name = "_mbstrlen_l" or + name = "strnlen" or + name = "strnlen_s" or + name = "wcsnlen" or + name = "wcsnlen_s" or + name = "_mbsnlen" or + name = "_mbsnlen_l" or + name = "_mbstrnlen" or + name = "_mbstrnlen_l" or + name = "strncmp" or + name = "wcsncmp" or + name = "_mbsncmp" or + name = "_mbsncmp_l" or + name = "strchr" or + name = "memchr" or + name = "wmemchr" or + name = "memcmp" or + name = "wmemcmp" or + name = "_memicmp" or + name = "_memicmp_l" or + name = "feof" or + name = "isdigit" or + name = "isxdigit" or + name = "abs" or + name = "fabs" or + name = "labs" or + name = "floor" or + name = "ceil" or + name = "atoi" or + name = "atol" or + name = "atoll" or + name = "atof" + ) } /** * Gets the nearest enclosing AccessHolder. */ - override AccessHolder getEnclosingAccessHolder() { - result = this.getDeclaringType() - } + override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() } } /** @@ -520,22 +505,22 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { override string getCanonicalQLClass() { result = "FunctionDeclarationEntry" } /** Gets the function which is being declared or defined. */ - Function getFunction() { fun_decls(underlyingElement(this),unresolveElement(result),_,_,_) } + Function getFunction() { fun_decls(underlyingElement(this), unresolveElement(result), _, _, _) } /** Gets the name of the function. */ - override string getName() { fun_decls(underlyingElement(this),_,_,result,_) } + override string getName() { fun_decls(underlyingElement(this), _, _, result, _) } /** * Gets the return type of the function which is being declared or * defined. */ - override Type getType() { fun_decls(underlyingElement(this),_,unresolveElement(result),_,_) } + override Type getType() { fun_decls(underlyingElement(this), _, unresolveElement(result), _, _) } /** Gets the location of this declaration entry. */ - override Location getLocation() { fun_decls(underlyingElement(this),_,_,_,result) } + override Location getLocation() { fun_decls(underlyingElement(this), _, _, _, result) } /** Gets a specifier associated with this declaration entry. */ - override string getASpecifier() { fun_decl_specifiers(underlyingElement(this),result) } + override string getASpecifier() { fun_decl_specifiers(underlyingElement(this), result) } /** * Implements `Element.getEnclosingElement`. A function declaration does @@ -552,7 +537,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * static Foo foo; */ TypedefType getTypedefType() { - fun_decl_typedef_type(underlyingElement(this),unresolveElement(result)) + fun_decl_typedef_type(underlyingElement(this), unresolveElement(result)) } /** @@ -562,9 +547,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * case, catch) plus the number of branching expressions (`?`, `&&`, * `||`) plus one. */ - int getCyclomaticComplexity() { - result = 1 + cyclomaticComplexityBranches(getBlock()) - } + int getCyclomaticComplexity() { result = 1 + cyclomaticComplexityBranches(getBlock()) } /** * If this is a function definition, get the block containing the @@ -572,15 +555,17 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { */ Block getBlock() { this.isDefinition() and - result = getFunction().getBlock() and result.getFile() = this.getFile() + result = getFunction().getBlock() and + result.getFile() = this.getFile() } /** * If this is a function definition, get the number of lines of code * associated with it. */ - pragma[noopt] int getNumberOfLines() { - exists(Block b, Location l, int start, int end, int diff| b = getBlock() | + pragma[noopt] + int getNumberOfLines() { + exists(Block b, Location l, int start, int end, int diff | b = getBlock() | l = b.getLocation() and start = l.getStartLine() and end = l.getEndLine() and @@ -602,13 +587,11 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * declaration. */ ParameterDeclarationEntry getParameterDeclarationEntry(int n) { - param_decl_bind(unresolveElement(result),n,underlyingElement(this)) + param_decl_bind(unresolveElement(result), n, underlyingElement(this)) } /** Gets the number of parameters of this function declaration. */ - int getNumberOfParameters() { - result = count(this.getAParameterDeclarationEntry()) - } + int getNumberOfParameters() { result = count(this.getAParameterDeclarationEntry()) } /** * Gets a string representing the parameters of this function declaration. @@ -616,58 +599,44 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * For example: for a function 'int Foo(int p1, int p2)' this would * return 'int p1, int p2'. */ - string getParameterString() { - result = getParameterStringFrom(0) - } + string getParameterString() { result = getParameterStringFrom(0) } private string getParameterStringFrom(int index) { - ( - index = getNumberOfParameters() and - result = "" - ) or ( - index = getNumberOfParameters() - 1 and - result = getParameterDeclarationEntry(index).getTypedName() - ) or ( - index < getNumberOfParameters() - 1 and - result = getParameterDeclarationEntry(index).getTypedName() + ", " + getParameterStringFrom(index + 1) - ) + index = getNumberOfParameters() and + result = "" + or + index = getNumberOfParameters() - 1 and + result = getParameterDeclarationEntry(index).getTypedName() + or + index < getNumberOfParameters() - 1 and + result = getParameterDeclarationEntry(index).getTypedName() + ", " + + getParameterStringFrom(index + 1) } - /** Holds if this declaration entry specifies C linkage: + /** + * Holds if this declaration entry specifies C linkage: * * `extern "C" void foo();` */ - predicate hasCLinkage() { - getASpecifier() = "c_linkage" - } + predicate hasCLinkage() { getASpecifier() = "c_linkage" } /** Holds if this declaration entry has a void parameter list. */ - predicate hasVoidParamList() { - getASpecifier() = "void_param_list" - } + predicate hasVoidParamList() { getASpecifier() = "void_param_list" } /** Holds if this declaration is also a definition of its function. */ - override predicate isDefinition() { - fun_def(underlyingElement(this)) - } + override predicate isDefinition() { fun_def(underlyingElement(this)) } /** Holds if this declaration is a Template specialization. */ - predicate isSpecialization() { - fun_specialized(underlyingElement(this)) - } + predicate isSpecialization() { fun_specialized(underlyingElement(this)) } /** * Holds if this declaration is an implicit function declaration, that is, * where a function is used before it is declared (under older C standards). */ - predicate isImplicit() { - fun_implicit(underlyingElement(this)) - } + predicate isImplicit() { fun_implicit(underlyingElement(this)) } /** Gets a type that is specified to be thrown by the declared function. */ - Type getAThrownType() { - result = getThrownType(_) - } + Type getAThrownType() { result = getThrownType(_) } /** * Gets the `i`th type specified to be thrown by the declared function @@ -676,24 +645,22 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * `int`, and that with index 1 would be `float`. */ Type getThrownType(int i) { - fun_decl_throws(underlyingElement(this),i,unresolveElement(result)) + fun_decl_throws(underlyingElement(this), i, unresolveElement(result)) } /** * If this declaration has a noexcept-specification [N4140 15.4], then * this predicate returns the argument to `noexcept` if one was given. */ - Expr getNoExceptExpr() { - fun_decl_noexcept(underlyingElement(this),unresolveElement(result)) - } + Expr getNoExceptExpr() { fun_decl_noexcept(underlyingElement(this), unresolveElement(result)) } /** * Holds if the declared function has an exception specification [N4140 * 15.4]. */ predicate hasExceptionSpecification() { - fun_decl_throws(underlyingElement(this),_,_) or - fun_decl_noexcept(underlyingElement(this),_) or + fun_decl_throws(underlyingElement(this), _, _) or + fun_decl_noexcept(underlyingElement(this), _) or isNoThrow() or isNoExcept() } @@ -701,20 +668,15 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { /** * Holds if the declared function has a `throw()` exception specification. */ - predicate isNoThrow() { - fun_decl_empty_throws(underlyingElement(this)) - } + predicate isNoThrow() { fun_decl_empty_throws(underlyingElement(this)) } /** * Holds if the declared function has an empty `noexcept` exception * specification. */ - predicate isNoExcept() { - fun_decl_empty_noexcept(underlyingElement(this)) - } + predicate isNoExcept() { fun_decl_empty_noexcept(underlyingElement(this)) } } - /** * A C/C++ non-member function (a function that is not a member of any * class). For example the in the following code, `MyFunction` is a @@ -733,9 +695,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl { * ``` */ class TopLevelFunction extends Function { - TopLevelFunction() { - not this.isMember() - } + TopLevelFunction() { not this.isMember() } override string getCanonicalQLClass() { result = "TopLevelFunction" } } @@ -758,24 +718,20 @@ class TopLevelFunction extends Function { * ``` */ class MemberFunction extends Function { - MemberFunction() { - this.isMember() - } + MemberFunction() { this.isMember() } - override string getCanonicalQLClass() - { not this instanceof CopyAssignmentOperator and - not this instanceof MoveAssignmentOperator and - result = "MemberFunction" } + override string getCanonicalQLClass() { + not this instanceof CopyAssignmentOperator and + not this instanceof MoveAssignmentOperator and + result = "MemberFunction" + } /** * Gets the number of parameters of this function, including any implicit * `this` parameter. */ override int getEffectiveNumberOfParameters() { - if isStatic() then - result = getNumberOfParameters() - else - result = getNumberOfParameters() + 1 + if isStatic() then result = getNumberOfParameters() else result = getNumberOfParameters() + 1 } /** Holds if this member is private. */ @@ -788,7 +744,9 @@ class MemberFunction extends Function { predicate isPublic() { this.hasSpecifier("public") } /** Holds if this function overrides that function. */ - predicate overrides(MemberFunction that) { overrides(underlyingElement(this),unresolveElement(that)) } + predicate overrides(MemberFunction that) { + overrides(underlyingElement(this), unresolveElement(that)) + } /** Gets a directly overridden function. */ MemberFunction getAnOverriddenFunction() { this.overrides(result) } @@ -801,12 +759,12 @@ class MemberFunction extends Function { * class body. */ FunctionDeclarationEntry getClassBodyDeclarationEntry() { - if strictcount(getADeclarationEntry()) = 1 then - result = getDefinition() - else - (result = getADeclarationEntry() and result != getDefinition()) + if strictcount(getADeclarationEntry()) = 1 + then result = getDefinition() + else ( + result = getADeclarationEntry() and result != getDefinition() + ) } - } /** @@ -828,13 +786,10 @@ class MemberFunction extends Function { * ``` */ class VirtualFunction extends MemberFunction { - - VirtualFunction() { - this.hasSpecifier("virtual") or purefunctions(underlyingElement(this)) - } + VirtualFunction() { this.hasSpecifier("virtual") or purefunctions(underlyingElement(this)) } override string getCanonicalQLClass() { result = "VirtualFunction" } - + /** Holds if this virtual function is pure. */ predicate isPure() { this instanceof PureVirtualFunction } @@ -863,7 +818,6 @@ class VirtualFunction extends MemberFunction { * ``` */ class PureVirtualFunction extends VirtualFunction { - PureVirtualFunction() { purefunctions(underlyingElement(this)) } override string getCanonicalQLClass() { result = "PureVirtualFunction" } @@ -876,7 +830,7 @@ class PureVirtualFunction extends VirtualFunction { * ``` * class MyClass { * ... - * + * * int day() const { * return d; * } @@ -886,7 +840,6 @@ class PureVirtualFunction extends VirtualFunction { * ``` */ class ConstMemberFunction extends MemberFunction { - ConstMemberFunction() { this.hasSpecifier("const") } override string getCanonicalQLClass() { result = "ConstMemberFunction" } @@ -905,11 +858,10 @@ class ConstMemberFunction extends MemberFunction { * ``` */ class Constructor extends MemberFunction { - - Constructor() { functions(underlyingElement(this),_,2) } + Constructor() { functions(underlyingElement(this), _, 2) } override string getCanonicalQLClass() { result = "Constructor" } - + /** * Holds if this constructor serves as a default constructor. * @@ -917,18 +869,14 @@ class Constructor extends MemberFunction { * for constructors which have a non-zero number of formal parameters, * provided that every parameter has a default value. */ - predicate isDefault() { - forall(Parameter p | p = this.getAParameter() | p.hasInitializer()) - } + predicate isDefault() { forall(Parameter p | p = this.getAParameter() | p.hasInitializer()) } /** * Gets an entry in the constructor's initializer list, or a * compiler-generated action which initializes a base class or member * variable. */ - ConstructorInit getAnInitializer() { - result = getInitializer(_) - } + ConstructorInit getAnInitializer() { result = getInitializer(_) } /** * Gets an entry in the constructor's initializer list, or a @@ -946,6 +894,7 @@ class Constructor extends MemberFunction { */ abstract class ImplicitConversionFunction extends MemberFunction { abstract Type getSourceType(); + abstract Type getDestType(); } @@ -963,19 +912,20 @@ abstract class ImplicitConversionFunction extends MemberFunction { */ class ConversionConstructor extends Constructor, ImplicitConversionFunction { ConversionConstructor() { - strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 - and not hasSpecifier("explicit") - and not(this instanceof CopyConstructor) + strictcount(Parameter p | p = getAParameter() and not p.hasInitializer()) = 1 and + not hasSpecifier("explicit") and + not this instanceof CopyConstructor + } + + override string getCanonicalQLClass() { + not this instanceof MoveConstructor and result = "ConversionConstructor" } - override string getCanonicalQLClass() - { not this instanceof MoveConstructor and result = "ConversionConstructor" } - /** Gets the type this `ConversionConstructor` takes as input. */ override Type getSourceType() { result = this.getParameter(0).getType() } /** Gets the type this `ConversionConstructor` is a constructor of. */ - override Type getDestType() { result = this.getDeclaringType() } + override Type getDestType() { result = this.getDeclaringType() } } private predicate hasCopySignature(MemberFunction f) { @@ -1014,9 +964,7 @@ class CopyConstructor extends Constructor { hasCopySignature(this) and ( // The rest of the parameters all have default values - forall(int i | i > 0 and exists(getParameter(i)) | - getParameter(i).hasInitializer() - ) + forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer()) or // or this is a template class, in which case the default values have // not been extracted even if they exist. In that case, we assume that @@ -1028,7 +976,7 @@ class CopyConstructor extends Constructor { } override string getCanonicalQLClass() { result = "CopyConstructor" } - + /** * Holds if we cannot determine that this constructor will become a copy * constructor in all instantiations. Depending on template parameters of the @@ -1073,9 +1021,7 @@ class MoveConstructor extends Constructor { hasMoveSignature(this) and ( // The rest of the parameters all have default values - forall(int i | i > 0 and exists(getParameter(i)) | - getParameter(i).hasInitializer() - ) + forall(int i | i > 0 and exists(getParameter(i)) | getParameter(i).hasInitializer()) or // or this is a template class, in which case the default values have // not been extracted even if they exist. In that case, we assume that @@ -1087,7 +1033,7 @@ class MoveConstructor extends Constructor { } override string getCanonicalQLClass() { result = "MoveConstructor" } - + /** * Holds if we cannot determine that this constructor will become a move * constructor in all instantiations. Depending on template parameters of the @@ -1119,9 +1065,7 @@ class MoveConstructor extends Constructor { * ``` */ class NoArgConstructor extends Constructor { - NoArgConstructor() { - this.getNumberOfParameters() = 0 - } + NoArgConstructor() { this.getNumberOfParameters() = 0 } } /** @@ -1137,17 +1081,15 @@ class NoArgConstructor extends Constructor { * ``` */ class Destructor extends MemberFunction { - Destructor() { functions(underlyingElement(this),_,3) } + Destructor() { functions(underlyingElement(this), _, 3) } override string getCanonicalQLClass() { result = "Destructor" } - + /** * Gets a compiler-generated action which destructs a base class or member * variable. */ - DestructorDestruction getADestruction() { - result = getDestruction(_) - } + DestructorDestruction getADestruction() { result = getDestruction(_) } /** * Gets a compiler-generated action which destructs a base class or member @@ -1170,25 +1112,24 @@ class Destructor extends MemberFunction { * ``` */ class ConversionOperator extends MemberFunction, ImplicitConversionFunction { - - ConversionOperator() { functions(underlyingElement(this),_,4) } + ConversionOperator() { functions(underlyingElement(this), _, 4) } override string getCanonicalQLClass() { result = "ConversionOperator" } override Type getSourceType() { result = this.getDeclaringType() } - override Type getDestType() { result = this.getType() } + override Type getDestType() { result = this.getType() } } /** * A C++ user-defined operator [N4140 13.5]. */ class Operator extends Function { + Operator() { functions(underlyingElement(this), _, 5) } - Operator() { functions(underlyingElement(this),_,5) } - - override string getCanonicalQLClass() - { not this instanceof MemberFunction and result = "Operator" } + override string getCanonicalQLClass() { + not this instanceof MemberFunction and result = "Operator" + } } /** @@ -1209,10 +1150,12 @@ class Operator extends Function { class CopyAssignmentOperator extends Operator { CopyAssignmentOperator() { hasName("operator=") and - (hasCopySignature(this) or - // Unlike CopyConstructor, this member allows a non-reference - // parameter. - getParameter(0).getUnspecifiedType() = getDeclaringType() + ( + hasCopySignature(this) + or + // Unlike CopyConstructor, this member allows a non-reference + // parameter. + getParameter(0).getUnspecifiedType() = getDeclaringType() ) and not exists(this.getParameter(1)) and not exists(getATemplateArgument()) @@ -1221,7 +1164,6 @@ class CopyAssignmentOperator extends Operator { override string getCanonicalQLClass() { result = "CopyAssignmentOperator" } } - /** * A C++ move assignment operator [N4140 12.8]. For example the function * `operator=` in the following code is a `MoveAssignmentOperator`: @@ -1248,7 +1190,6 @@ class MoveAssignmentOperator extends Operator { override string getCanonicalQLClass() { result = "MoveAssignmentOperator" } } - /** * A C++ function which has a non-empty template argument list. For example * the function `myTemplateFunction` in the following code: @@ -1271,15 +1212,18 @@ class MoveAssignmentOperator extends Operator { * (non-empty) template argument list. */ class TemplateFunction extends Function { - TemplateFunction() { is_function_template(underlyingElement(this)) and exists(getATemplateArgument()) } + TemplateFunction() { + is_function_template(underlyingElement(this)) and exists(getATemplateArgument()) + } override string getCanonicalQLClass() { result = "TemplateFunction" } + /** * Gets a compiler-generated instantiation of this function template. */ Function getAnInstantiation() { - result.isConstructedFrom(this) - and not result.isSpecialization() + result.isConstructedFrom(this) and + not result.isSpecialization() } /** @@ -1290,9 +1234,7 @@ class TemplateFunction extends Function { * partial specializations, nor does it include full specializations of * such things -- see FunctionTemplateSpecialization for further details. */ - FunctionTemplateSpecialization getASpecialization() { - result.getPrimaryTemplate() = this - } + FunctionTemplateSpecialization getASpecialization() { result.getPrimaryTemplate() = this } } /** @@ -1312,9 +1254,7 @@ class TemplateFunction extends Function { class FunctionTemplateInstantiation extends Function { TemplateFunction tf; - FunctionTemplateInstantiation() { - tf.getAnInstantiation() = this - } + FunctionTemplateInstantiation() { tf.getAnInstantiation() = this } override string getCanonicalQLClass() { result = "FunctionTemplateInstantiation" } @@ -1323,9 +1263,7 @@ class FunctionTemplateInstantiation extends Function { * * Example: For `int const& std::min(int const&, int const&)`, returns `T const& min(T const&, T const&)`. */ - TemplateFunction getTemplate() { - result = tf - } + TemplateFunction getTemplate() { result = tf } } /** @@ -1361,28 +1299,22 @@ class FunctionTemplateInstantiation extends Function { * http://www.gotw.ca/publications/mill17.htm */ class FunctionTemplateSpecialization extends Function { - FunctionTemplateSpecialization() { - this.isSpecialization() - } + FunctionTemplateSpecialization() { this.isSpecialization() } override string getCanonicalQLClass() { result = "FunctionTemplateSpecialization" } - + /** * Gets the primary template for the specialization (the function template * this specializes). */ - TemplateFunction getPrimaryTemplate() { - this.isConstructedFrom(result) - } + TemplateFunction getPrimaryTemplate() { this.isConstructedFrom(result) } } /** * A GCC built-in function. For example: `__builtin___memcpy_chk`. */ class BuiltInFunction extends Function { - BuiltInFunction() { - functions(underlyingElement(this),_,6) - } + BuiltInFunction() { functions(underlyingElement(this), _, 6) } /** Gets a dummy location for the built-in function. */ override Location getLocation() { diff --git a/cpp/ql/src/semmle/code/cpp/Include.qll b/cpp/ql/src/semmle/code/cpp/Include.qll index 9187463fff5..f5e4fae619c 100644 --- a/cpp/ql/src/semmle/code/cpp/Include.qll +++ b/cpp/ql/src/semmle/code/cpp/Include.qll @@ -30,16 +30,14 @@ class Include extends PreprocessorDirective, @ppd_include { * translation unit, it is often a slight over-approximation. */ predicate provides(File l) { - exists(Include i | this.getAnInclude*() = i and i.getIncludedFile() = l) + exists(Include i | this.getAnInclude*() = i and i.getIncludedFile() = l) } /** * A `#include` which appears in the file directly included by this * `#include`. */ - Include getAnInclude() { - this.getIncludedFile() = result.getFile() - } + Include getAnInclude() { this.getIncludedFile() = result.getFile() } } /** @@ -50,9 +48,7 @@ class Include extends PreprocessorDirective, @ppd_include { * ``` */ class IncludeNext extends Include, @ppd_include_next { - override string toString() { - result = "#include_next " + getIncludeText() - } + override string toString() { result = "#include_next " + getIncludeText() } } /** @@ -64,7 +60,5 @@ class IncludeNext extends Include, @ppd_include_next { * ``` */ class Import extends Include, @ppd_objc_import { - override string toString() { - result = "#import " + getIncludeText() - } + override string toString() { result = "#import " + getIncludeText() } } diff --git a/cpp/ql/src/semmle/code/cpp/Initializer.qll b/cpp/ql/src/semmle/code/cpp/Initializer.qll index d407ba4ddee..80601f659da 100644 --- a/cpp/ql/src/semmle/code/cpp/Initializer.qll +++ b/cpp/ql/src/semmle/code/cpp/Initializer.qll @@ -16,35 +16,29 @@ import semmle.code.cpp.controlflow.ControlFlowGraph * ``` */ class Initializer extends ControlFlowNode, @initialiser { - override Location getLocation() { initialisers(underlyingElement(this),_,_,result) } + override Location getLocation() { initialisers(underlyingElement(this), _, _, result) } override string getCanonicalQLClass() { result = "Initializer" } - + /** Holds if this initializer is explicit in the source. */ - override predicate fromSource() { - not (this.getLocation() instanceof UnknownLocation) - } + override predicate fromSource() { not this.getLocation() instanceof UnknownLocation } override string toString() { - if exists(getDeclaration()) then ( - result = "initializer for " + max(getDeclaration().getName()) - ) else ( - result = "initializer" - ) + if exists(getDeclaration()) + then result = "initializer for " + max(getDeclaration().getName()) + else result = "initializer" } /** Gets the variable or enum constant being initialized. */ - Declaration getDeclaration() { initialisers(underlyingElement(this),unresolveElement(result),_,_) } + Declaration getDeclaration() { + initialisers(underlyingElement(this), unresolveElement(result), _, _) + } /** Gets the initializing expression. */ - Expr getExpr() { initialisers(underlyingElement(this),_,unresolveElement(result),_) } + Expr getExpr() { initialisers(underlyingElement(this), _, unresolveElement(result), _) } /** Gets the function containing this control-flow node. */ - override Function getControlFlowScope() { - result = this.getExpr().getEnclosingFunction() - } + override Function getControlFlowScope() { result = this.getExpr().getEnclosingFunction() } - override Stmt getEnclosingStmt() { - result = this.getExpr().getEnclosingStmt() - } + override Stmt getEnclosingStmt() { result = this.getExpr().getEnclosingStmt() } } diff --git a/cpp/ql/src/semmle/code/cpp/Iteration.qll b/cpp/ql/src/semmle/code/cpp/Iteration.qll index 5a63b5ff1bd..fd7ba60ea19 100644 --- a/cpp/ql/src/semmle/code/cpp/Iteration.qll +++ b/cpp/ql/src/semmle/code/cpp/Iteration.qll @@ -5,9 +5,7 @@ import semmle.code.cpp.Variable * mutated within the update expression of the same 'for' loop. */ class LoopCounter extends Variable { - LoopCounter() { - exists(ForStmt f | f.getAnIterationVariable() = this) - } + LoopCounter() { exists(ForStmt f | f.getAnIterationVariable() = this) } // Gets an access of this variable within loop `f`. VariableAccess getVariableAccessInLoop(ForStmt f) { @@ -17,9 +15,7 @@ class LoopCounter extends Variable { } // Gets a loop which uses this variable as its counter. - ForStmt getALoop() { - result.getAnIterationVariable() = this - } + ForStmt getALoop() { result.getAnIterationVariable() = this } } /** @@ -27,9 +23,7 @@ class LoopCounter extends Variable { * update expression of a 'for' loop. */ class LoopControlVariable extends Variable { - LoopControlVariable() { - this = loopControlVariable(_) - } + LoopControlVariable() { this = loopControlVariable(_) } // Gets an access of this variable within loop `f`. VariableAccess getVariableAccessInLoop(ForStmt f) { @@ -39,18 +33,16 @@ class LoopControlVariable extends Variable { } // Gets a loop which uses this variable as its control variable. - ForStmt getALoop() { - this = loopControlVariable(result) - } + ForStmt getALoop() { this = loopControlVariable(result) } } /** * Gets a control variable of loop `f`. */ private Variable loopControlVariable(ForStmt f) { - exists(Expr e - | result.getAnAccess().getParent*() = e - | e = f.getControllingExpr() or + exists(Expr e | result.getAnAccess().getParent*() = e | + e = f.getControllingExpr() or e = f.getInitialization().(ExprStmt).getExpr() or - e = f.getUpdate()) + e = f.getUpdate() + ) } diff --git a/cpp/ql/src/semmle/code/cpp/Linkage.qll b/cpp/ql/src/semmle/code/cpp/Linkage.qll index e968c814769..7912c9e25e1 100644 --- a/cpp/ql/src/semmle/code/cpp/Linkage.qll +++ b/cpp/ql/src/semmle/code/cpp/Linkage.qll @@ -13,46 +13,35 @@ class LinkTarget extends @link_target { /** * Gets the file which was built. */ - File getBinary() { - link_targets(this, unresolveElement(result)) - } + File getBinary() { link_targets(this, unresolveElement(result)) } /** * Holds if this is the dummy link target: if linkage information isn't * captured as part of the snapshot, then everything is grouped together * into a single dummy link target. */ - predicate isDummy() { - getBinary().getAbsolutePath() = "" - } + predicate isDummy() { getBinary().getAbsolutePath() = "" } /** Gets a textual representation of this element. */ - string toString() { - result = getBinary().getAbsolutePath() - } + string toString() { result = getBinary().getAbsolutePath() } /** * Gets a function which was compiled into this link target, or had its * declaration included by one of the translation units which contributed * to this link target. */ - Function getAFunction() { - link_parent(unresolveElement(result), this) - } + Function getAFunction() { link_parent(unresolveElement(result), this) } /** * Gets a class which had its declaration included by one of the * translation units which contributed to this link target. */ - Class getAClass() { - link_parent(unresolveElement(result), this) - } + Class getAClass() { link_parent(unresolveElement(result), this) } } /** * Holds if this database was created with the linker awareness feature * switched on. */ -cached predicate isLinkerAwareExtracted() { - exists(LinkTarget lt | not lt.isDummy()) -} +cached +predicate isLinkerAwareExtracted() { exists(LinkTarget lt | not lt.isDummy()) } diff --git a/cpp/ql/src/semmle/code/cpp/Location.qll b/cpp/ql/src/semmle/code/cpp/Location.qll index e2be4975fd3..129ffba0f74 100644 --- a/cpp/ql/src/semmle/code/cpp/Location.qll +++ b/cpp/ql/src/semmle/code/cpp/Location.qll @@ -5,36 +5,23 @@ import semmle.code.cpp.File * A location of a C/C++ artifact. */ class Location extends @location { - /** Gets the container corresponding to this location. */ - Container getContainer() { - this.fullLocationInfo(result, _, _, _, _) - } + Container getContainer() { this.fullLocationInfo(result, _, _, _, _) } /** Gets the file corresponding to this location, if any. */ - File getFile() { - result = this.getContainer() - } + File getFile() { result = this.getContainer() } /** Gets the start line of this location. */ - int getStartLine() { - this.fullLocationInfo(_, result, _, _, _) - } + int getStartLine() { this.fullLocationInfo(_, result, _, _, _) } /** Gets the start column of this location. */ - int getStartColumn() { - this.fullLocationInfo(_, _, result, _, _) - } + int getStartColumn() { this.fullLocationInfo(_, _, result, _, _) } /** Gets the end line of this location. */ - int getEndLine() { - this.fullLocationInfo(_, _, _, result, _) - } + int getEndLine() { this.fullLocationInfo(_, _, _, result, _) } /** Gets the end column of this location. */ - int getEndColumn() { - this.fullLocationInfo(_, _, _, _, result) - } + int getEndColumn() { this.fullLocationInfo(_, _, _, _, result) } /** * Gets a textual representation of this element. @@ -42,9 +29,10 @@ class Location extends @location { * The format is "file://filePath:startLine:startColumn:endLine:endColumn". */ string toString() { - exists(string filepath, int startline, int startcolumn, int endline, int endcolumn - | this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - | toUrl(filepath, startline, startcolumn, endline, endcolumn, result) + exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + | + toUrl(filepath, startline, startcolumn, endline, endcolumn, result) ) } @@ -57,10 +45,11 @@ class Location extends @location { * entity, rather than merely its path. */ predicate fullLocationInfo( - Container container, int startline, int startcolumn, int endline, int endcolumn) { - locations_default(this, unresolveElement(container), startline, startcolumn, endline, endcolumn) or - locations_expr(this, unresolveElement(container), startline, startcolumn, endline, endcolumn) or - locations_stmt(this, unresolveElement(container), startline, startcolumn, endline, endcolumn) + Container container, int startline, int startcolumn, int endline, int endcolumn + ) { + locations_default(this, unresolveElement(container), startline, startcolumn, endline, endcolumn) or + locations_expr(this, unresolveElement(container), startline, startcolumn, endline, endcolumn) or + locations_stmt(this, unresolveElement(container), startline, startcolumn, endline, endcolumn) } /** @@ -71,10 +60,11 @@ class Location extends @location { * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). */ predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn) { - exists(Container f - | this.fullLocationInfo(f,startline,startcolumn,endline,endcolumn) - | filepath = f.getAbsolutePath()) + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + exists(Container f | this.fullLocationInfo(f, startline, startcolumn, endline, endcolumn) | + filepath = f.getAbsolutePath() + ) } /** Holds if `this` comes on a line strictly before `l`. */ @@ -114,28 +104,24 @@ class Location extends @location { * A location of an element. Not used for expressions or statements, which * instead use LocationExpr and LocationStmt respectively. */ -library class LocationDefault extends Location, @location_default {} +library class LocationDefault extends Location, @location_default { } /** A location of a statement. */ -library class LocationStmt extends Location, @location_stmt {} +library class LocationStmt extends Location, @location_stmt { } /** A location of an expression. */ -library class LocationExpr extends Location, @location_expr {} +library class LocationExpr extends Location, @location_expr { } /** * Gets the length of the longest line in file `f`. */ pragma[nomagic] -private int maxCols(File f) { - result = max(Location l | l.getFile() = f | l.getEndColumn()) -} +private int maxCols(File f) { result = max(Location l | l.getFile() = f | l.getEndColumn()) } /** * A C/C++ element that has a location in a file */ -class Locatable extends Element { - -} +class Locatable extends Element { } /** * A dummy location which is used when something doesn't have a location in @@ -144,9 +130,7 @@ class Locatable extends Element { * expressions, one for statements and one for other program elements. */ class UnknownLocation extends Location { - UnknownLocation() { - getFile().getAbsolutePath() = "" - } + UnknownLocation() { getFile().getAbsolutePath() = "" } } /** @@ -154,9 +138,7 @@ class UnknownLocation extends Location { * the source code but needs to have a `Location` associated with it. */ class UnknownDefaultLocation extends UnknownLocation { - UnknownDefaultLocation() { - locations_default(this, _, 0, 0, 0, 0) - } + UnknownDefaultLocation() { locations_default(this, _, 0, 0, 0, 0) } } /** @@ -165,9 +147,7 @@ class UnknownDefaultLocation extends UnknownLocation { * with it. */ class UnknownExprLocation extends UnknownLocation { - UnknownExprLocation() { - locations_expr(this, _, 0, 0, 0, 0) - } + UnknownExprLocation() { locations_expr(this, _, 0, 0, 0, 0) } } /** @@ -175,8 +155,5 @@ class UnknownExprLocation extends UnknownLocation { * in the source code but needs to have a `Location` associated with it. */ class UnknownStmtLocation extends UnknownLocation { - UnknownStmtLocation() { - locations_stmt(this, _, 0, 0, 0, 0) - } + UnknownStmtLocation() { locations_stmt(this, _, 0, 0, 0, 0) } } - diff --git a/cpp/ql/src/semmle/code/cpp/Macro.qll b/cpp/ql/src/semmle/code/cpp/Macro.qll index 64c72f4155d..389634912b7 100644 --- a/cpp/ql/src/semmle/code/cpp/Macro.qll +++ b/cpp/ql/src/semmle/code/cpp/Macro.qll @@ -7,12 +7,11 @@ import cpp * ``` */ class Macro extends PreprocessorDirective, @ppd_define { - /** * Gets the head of this macro. For example, `MAX(x,y)` in * `#define MAX(x,y) (((x)>(y))?(x):(y))`. */ - override string getHead() { preproctext(underlyingElement(this),result,_) } + override string getHead() { preproctext(underlyingElement(this), result, _) } override string getCanonicalQLClass() { result = "Macro" } @@ -20,17 +19,15 @@ class Macro extends PreprocessorDirective, @ppd_define { * Gets the body of this macro. For example, `(((x)>(y))?(x):(y))` in * `#define MAX(x,y) (((x)>(y))?(x):(y))`. */ - string getBody() { preproctext(underlyingElement(this),_,result) } + string getBody() { preproctext(underlyingElement(this), _, result) } /** Gets an invocation of this macro. */ MacroInvocation getAnInvocation() { result.getMacro() = this } override string toString() { - if (this.getBody() = "") then ( - result = "#define " + this.getHead() - ) else ( - result = "#define " + this.getHead() + " " + this.getBody() - ) + if this.getBody() = "" + then result = "#define " + this.getHead() + else result = "#define " + this.getHead() + " " + this.getBody() } /** @@ -41,22 +38,16 @@ class Macro extends PreprocessorDirective, @ppd_define { * * DEPRECATED: This predicate has a misleading name. */ - deprecated predicate isFunctionLike() { - this.getBody().regexpMatch("[^(]*\\).*") - } + deprecated predicate isFunctionLike() { this.getBody().regexpMatch("[^(]*\\).*") } /** * Gets the name of the macro. For example, `MAX` in * `#define MAX(x,y) (((x)>(y))?(x):(y))`. */ - string getName() { - result = getHead().splitAt("(", 0) - } + string getName() { result = getHead().splitAt("(", 0) } /** Holds if the macro has name `name`. */ - predicate hasName(string name) { - getName() = name - } + predicate hasName(string name) { getName() = name } } /** @@ -66,13 +57,13 @@ class Macro extends PreprocessorDirective, @ppd_define { * int x = MACRO2; // this line contains a MacroAccess * #endif * ``` - * + * * See also `MacroInvocation`, which represents only macro accesses * that are expanded (such as in the second line of the example above). */ class MacroAccess extends Locatable, @macroinvocation { /** Gets the macro that is being accessed. */ - Macro getMacro() { macroinvocations(underlyingElement(this),unresolveElement(result),_,_) } + Macro getMacro() { macroinvocations(underlyingElement(this), unresolveElement(result), _, _) } /** * Gets the location of the outermost macro access that triggered this macro @@ -81,9 +72,7 @@ class MacroAccess extends Locatable, @macroinvocation { * location of the invocation of `C` in `P(C)` will be the whole source range * starting with `P` and ending with `)`. */ - override Location getLocation() { - result = this.getOutermostMacroAccess().getActualLocation() - } + override Location getLocation() { result = this.getOutermostMacroAccess().getActualLocation() } override string getCanonicalQLClass() { result = "MacroAccess" } @@ -92,9 +81,7 @@ class MacroAccess extends Locatable, @macroinvocation { * `exists(this.getParentInvocation())`, this yields a location either inside * a `#define` directive or inside an argument to another macro. */ - Location getActualLocation() { - macroinvocations(underlyingElement(this),_,result,_) - } + Location getActualLocation() { macroinvocations(underlyingElement(this), _, result, _) } /** * Gets the parent macro invocation, if any. For example: @@ -126,25 +113,24 @@ class MacroAccess extends Locatable, @macroinvocation { * There is only a single invocation even though `c` occurs twice; this is an * optimization for efficiency. */ - MacroInvocation getParentInvocation() { macroparent(underlyingElement(this),unresolveElement(result)) } + MacroInvocation getParentInvocation() { + macroparent(underlyingElement(this), unresolveElement(result)) + } /** * Gets the outermost `MacroAccess` along the chain of `getParentInvocation`. * If `this` has no parent, the result will be `this` itself. */ MacroAccess getOutermostMacroAccess() { - if (not exists(this.getParentInvocation())) then - result = this - else - result = this.getParentInvocation().getOutermostMacroAccess() + if not exists(this.getParentInvocation()) + then result = this + else result = this.getParentInvocation().getOutermostMacroAccess() } override string toString() { result = this.getMacro().getHead() } /** Gets the name of the accessed macro. */ - string getMacroName() { - result = getMacro().getName() - } + string getMacroName() { result = getMacro().getName() } } /** @@ -154,22 +140,22 @@ class MacroAccess extends Locatable, @macroinvocation { * int x = MACRO2; // this line contains a MacroInvocation * #endif * ``` - * + * * See also `MacroAccess`, which also represents macro accesses where the macro * is checked but not expanded (such as in the first line of the example above). */ class MacroInvocation extends MacroAccess { - MacroInvocation() { - macroinvocations(underlyingElement(this),_,_,1) - } + MacroInvocation() { macroinvocations(underlyingElement(this), _, _, 1) } override string getCanonicalQLClass() { result = "MacroInvocation" } - + /** * Gets an element that occurs in this macro invocation or a nested macro * invocation. */ - Locatable getAnExpandedElement() { inmacroexpansion(unresolveElement(result),underlyingElement(this)) } + Locatable getAnExpandedElement() { + inmacroexpansion(unresolveElement(result), underlyingElement(this)) + } /** * Gets an element that is (partially) affected by a macro @@ -178,7 +164,8 @@ class MacroInvocation extends MacroAccess { * well. */ Locatable getAnAffectedElement() { - inmacroexpansion(unresolveElement(result),underlyingElement(this)) or macrolocationbind(underlyingElement(this), result.getLocation()) + inmacroexpansion(unresolveElement(result), underlyingElement(this)) or + macrolocationbind(underlyingElement(this), result.getLocation()) } /** @@ -206,7 +193,7 @@ class MacroInvocation extends MacroAccess { */ Expr getExpr() { result = getAnExpandedElement() and - not (result.getParent() = getAnExpandedElement()) and + not result.getParent() = getAnExpandedElement() and not result instanceof Conversion } @@ -217,7 +204,7 @@ class MacroInvocation extends MacroAccess { */ Stmt getStmt() { result = getAnExpandedElement() and - not (result.getParent() = getAnExpandedElement()) + not result.getParent() = getAnExpandedElement() } /** @@ -266,9 +253,7 @@ class MacroInvocation extends MacroAccess { * See the documentation of `getUnexpandedArgument` for examples of the * differences between expanded and unexpanded arguments. */ - string getExpandedArgument(int i) { - macro_argument_expanded(underlyingElement(this), i, result) - } + string getExpandedArgument(int i) { macro_argument_expanded(underlyingElement(this), i, result) } } /** @@ -280,21 +265,15 @@ class MacroInvocation extends MacroAccess { * by a macro invocation. */ deprecated class MacroInvocationExpr extends Expr { - MacroInvocationExpr() { - exists(MacroInvocation i | this = i.getExpr()) - } + MacroInvocationExpr() { exists(MacroInvocation i | this = i.getExpr()) } /** * Gets the macro invocation of which this is the top-level expression. */ - MacroInvocation getInvocation() { - result.getExpr() = this - } + MacroInvocation getInvocation() { result.getExpr() = this } /** Gets the name of the invoked macro. */ - string getMacroName() { - result = getInvocation().getMacroName() - } + string getMacroName() { result = getInvocation().getMacroName() } } /** @@ -306,57 +285,49 @@ deprecated class MacroInvocationExpr extends Expr { * by a macro invocation. */ deprecated class MacroInvocationStmt extends Stmt { - MacroInvocationStmt() { - exists(MacroInvocation i | this = i.getStmt()) - } + MacroInvocationStmt() { exists(MacroInvocation i | this = i.getStmt()) } /** * Gets the macro invocation of which this is the top-level statement. */ - MacroInvocation getInvocation() { - result.getStmt() = this - } + MacroInvocation getInvocation() { result.getStmt() = this } /** Gets the name of the invoked macro. */ - string getMacroName() { - result = getInvocation().getMacroName() - } + string getMacroName() { result = getInvocation().getMacroName() } } /** Holds if `l` is the location of a macro. */ -predicate macroLocation(Location l) { - macrolocationbind(_, l) -} +predicate macroLocation(Location l) { macrolocationbind(_, l) } /** Holds if `element` is in the expansion of a macro. */ predicate inMacroExpansion(Locatable element) { - inmacroexpansion(unresolveElement(element),_) or - (macroLocation(element.getLocation()) and - not topLevelMacroAccess(element)) + inmacroexpansion(unresolveElement(element), _) + or + macroLocation(element.getLocation()) and + not topLevelMacroAccess(element) } /** * Holds if `ma` is a `MacroAccess` that is not nested inside another * macro invocation. */ -private predicate topLevelMacroAccess(MacroAccess ma) { - not exists(ma.getParentInvocation()) -} +private predicate topLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } /** * Holds if `element` is in the expansion of a macro from * a system header. */ predicate inSystemMacroExpansion(Locatable element) { - exists (MacroInvocation m - | element = m.getAnExpandedElement() and - not exists (m.getMacro().getLocation().getFile().getRelativePath())) + exists(MacroInvocation m | + element = m.getAnExpandedElement() and + not exists(m.getMacro().getLocation().getFile().getRelativePath()) + ) } /** Holds if `element` is affected by a macro. */ predicate affectedByMacro(Locatable element) { inMacroExpansion(element) or - affectedbymacroexpansion(unresolveElement(element),_) + affectedbymacroexpansion(unresolveElement(element), _) } /** Holds if there is a macro invocation on line `line` of file `f`. */ diff --git a/cpp/ql/src/semmle/code/cpp/NameQualifiers.qll b/cpp/ql/src/semmle/code/cpp/NameQualifiers.qll index 0587d6eb5b1..f070e041765 100644 --- a/cpp/ql/src/semmle/code/cpp/NameQualifiers.qll +++ b/cpp/ql/src/semmle/code/cpp/NameQualifiers.qll @@ -19,14 +19,10 @@ class NameQualifier extends NameQualifiableElement, @namequalifier { * Gets the expression ultimately qualified by the chain of name * qualifiers. For example, `f()` in `N1::N2::f()`. */ - Expr getExpr() { - result = getQualifiedElement+() - } + Expr getExpr() { result = getQualifiedElement+() } /** Gets a location for this name qualifier. */ - override Location getLocation() { - namequalifiers(underlyingElement(this),_,_,result) - } + override Location getLocation() { namequalifiers(underlyingElement(this), _, _, result) } /** * Gets the name qualifier that qualifies this name qualifier, if any. @@ -34,7 +30,7 @@ class NameQualifier extends NameQualifiableElement, @namequalifier { * `N2::` has a name qualifier `N1::` in the chain `N1::N2::f()`. */ override NameQualifier getNameQualifier() { - namequalifiers(unresolveElement(result),underlyingElement(this),_,_) + namequalifiers(unresolveElement(result), underlyingElement(this), _, _) } /** @@ -42,7 +38,7 @@ class NameQualifier extends NameQualifiableElement, @namequalifier { * in `N::f()`. */ NameQualifiableElement getQualifiedElement() { - namequalifiers(underlyingElement(this),unresolveElement(result),_,_) + namequalifiers(underlyingElement(this), unresolveElement(result), _, _) } /** @@ -50,23 +46,28 @@ class NameQualifier extends NameQualifiableElement, @namequalifier { * in `N::f()`. */ NameQualifyingElement getQualifyingElement() { - exists (NameQualifyingElement nqe - | namequalifiers(underlyingElement(this),_,unresolveElement(nqe),_) and + exists(NameQualifyingElement nqe | + namequalifiers(underlyingElement(this), _, unresolveElement(nqe), _) and if nqe instanceof SpecialNameQualifyingElement - then (exists (Access a - | a = getQualifiedElement() and - result = a.getTarget().getDeclaringType()) - or - exists (FunctionCall c - | c = getQualifiedElement() and - result = c.getTarget().getDeclaringType())) - else result = nqe) + then + exists(Access a | + a = getQualifiedElement() and + result = a.getTarget().getDeclaringType() + ) + or + exists(FunctionCall c | + c = getQualifiedElement() and + result = c.getTarget().getDeclaringType() + ) + else result = nqe + ) } override string toString() { - exists (NameQualifyingElement nqe - | namequalifiers(underlyingElement(this),_,unresolveElement(nqe),_) - and result = nqe.getName() + "::") + exists(NameQualifyingElement nqe | + namequalifiers(underlyingElement(this), _, unresolveElement(nqe), _) and + result = nqe.getName() + "::" + ) } } @@ -94,7 +95,7 @@ class NameQualifiableElement extends Element, @namequalifiableelement { * name qualifier of `N::f()` is `N`. */ NameQualifier getNameQualifier() { - namequalifiers(unresolveElement(result),underlyingElement(this),_,_) + namequalifiers(unresolveElement(result), underlyingElement(this), _, _) } /** @@ -113,9 +114,9 @@ class NameQualifiableElement extends Element, @namequalifiableelement { */ predicate hasSuperQualifiedName() { exists(NameQualifier nq, SpecialNameQualifyingElement snqe | - nq = getNameQualifier*() - and namequalifiers(unresolveElement(nq),_,unresolveElement(snqe),_) - and snqe.getName() = "__super" + nq = getNameQualifier*() and + namequalifiers(unresolveElement(nq), _, unresolveElement(snqe), _) and + snqe.getName() = "__super" ) } } @@ -128,7 +129,7 @@ class NameQualifiableElement extends Element, @namequalifiableelement { * namespace B { * ... * } - * + * * class C { * ... * }; @@ -142,21 +143,18 @@ class NameQualifyingElement extends Element, @namequalifyingelement { * `NameQualifyingElement` and `X::` is the `NameQualifier`. */ NameQualifier getANameQualifier() { - namequalifiers(unresolveElement(result),_,underlyingElement(this),_) + namequalifiers(unresolveElement(result), _, underlyingElement(this), _) } /** Gets the name of this namespace or user-defined type. */ - string getName() { - none() - } + string getName() { none() } } /** * A special name-qualifying element. For example: `__super`. */ -library class SpecialNameQualifyingElement extends NameQualifyingElement, @specialnamequalifyingelement { +library class SpecialNameQualifyingElement extends NameQualifyingElement, + @specialnamequalifyingelement { /** Gets the name of this special qualifying element. */ - override string getName() { - specialnamequalifyingelements(underlyingElement(this),result) - } + override string getName() { specialnamequalifyingelements(underlyingElement(this), result) } } diff --git a/cpp/ql/src/semmle/code/cpp/Namespace.qll b/cpp/ql/src/semmle/code/cpp/Namespace.qll index a69675548e0..d53fda87c2f 100644 --- a/cpp/ql/src/semmle/code/cpp/Namespace.qll +++ b/cpp/ql/src/semmle/code/cpp/Namespace.qll @@ -15,31 +15,25 @@ import semmle.code.cpp.metrics.MetricNamespace * of the source code. */ class Namespace extends NameQualifyingElement, @namespace { - /** * Gets the location of the namespace. Most namespaces do not have a * single well-defined source location, so a dummy location is returned, * unless the namespace has exactly one declaration entry. */ override Location getLocation() { - if strictcount(getADeclarationEntry()) = 1 then - result = getADeclarationEntry().getLocation() - else - ( - result instanceof UnknownDefaultLocation - ) + if strictcount(getADeclarationEntry()) = 1 + then result = getADeclarationEntry().getLocation() + else result instanceof UnknownDefaultLocation } /** Gets the simple name of this namespace. */ - override string getName() { namespaces(underlyingElement(this),result) } + override string getName() { namespaces(underlyingElement(this), result) } /** Holds if this element is named `name`. */ predicate hasName(string name) { name = this.getName() } /** Holds if this namespace is anonymous. */ - predicate isAnonymous() { - hasName("(unnamed namespace)") - } + predicate isAnonymous() { hasName("(unnamed namespace)") } /** Gets the name of the parent namespace, if it exists. */ private string getParentName() { @@ -49,27 +43,28 @@ class Namespace extends NameQualifyingElement, @namespace { /** Gets the qualified name of this namespace. For example: `a::b`. */ string getQualifiedName() { - if exists (getParentName()) - then result = getParentNamespace().getQualifiedName() + "::" + getName() - else result = getName() + if exists(getParentName()) + then result = getParentNamespace().getQualifiedName() + "::" + getName() + else result = getName() } /** Gets the parent namespace, if any. */ Namespace getParentNamespace() { - namespacembrs(unresolveElement(result),underlyingElement(this)) or - (not namespacembrs(_, underlyingElement(this)) and result instanceof GlobalNamespace) + namespacembrs(unresolveElement(result), underlyingElement(this)) + or + not namespacembrs(_, underlyingElement(this)) and result instanceof GlobalNamespace } /** Gets a child declaration of this namespace. */ - Declaration getADeclaration() { namespacembrs(underlyingElement(this),unresolveElement(result)) } + Declaration getADeclaration() { namespacembrs(underlyingElement(this), unresolveElement(result)) } /** Gets a child namespace of this namespace. */ - Namespace getAChildNamespace() { namespacembrs(underlyingElement(this),unresolveElement(result)) } + Namespace getAChildNamespace() { + namespacembrs(underlyingElement(this), unresolveElement(result)) + } /** Holds if the namespace is inline. */ - predicate isInline() { - namespace_inline(underlyingElement(this)) - } + predicate isInline() { namespace_inline(underlyingElement(this)) } /** Holds if this namespace may be from source. */ override predicate fromSource() { this.getADeclaration().fromSource() } @@ -79,8 +74,7 @@ class Namespace extends NameQualifyingElement, @namespace { * * DEPRECATED: never holds. */ - deprecated override - predicate fromLibrary() { not this.fromSource() } + deprecated override predicate fromLibrary() { not this.fromSource() } /** Gets the metric namespace. */ MetricNamespace getMetrics() { result = this } @@ -88,15 +82,10 @@ class Namespace extends NameQualifyingElement, @namespace { override string toString() { result = this.getQualifiedName() } /** Gets a declaration of (part of) this namespace. */ - NamespaceDeclarationEntry getADeclarationEntry() { - result.getNamespace() = this - } + NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this } /** Gets a file which declares (part of) this namespace. */ - File getAFile() { - result = this.getADeclarationEntry().getLocation().getFile() - } - + File getAFile() { result = this.getADeclarationEntry().getLocation().getFile() } } /** @@ -111,7 +100,9 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl { * is a one-to-many relationship between `Namespace` and * `NamespaceDeclarationEntry`. */ - Namespace getNamespace() { namespace_decls(underlyingElement(this),unresolveElement(result),_,_) } + Namespace getNamespace() { + namespace_decls(underlyingElement(this), unresolveElement(result), _, _) + } override string toString() { result = this.getNamespace().toString() } @@ -125,13 +116,13 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl { * For anonymous declarations, such as "namespace { ... }", this will * give the "namespace" token. */ - override Location getLocation() { namespace_decls(underlyingElement(this),_,result,_) } + override Location getLocation() { namespace_decls(underlyingElement(this), _, result, _) } /** * Gets the location of the namespace declaration entry's body. For * example: the "{ ... }" in "namespace N { ... }". */ - Location getBodyLocation() { namespace_decls(underlyingElement(this),_,_,result) } + Location getBodyLocation() { namespace_decls(underlyingElement(this), _, _, result) } override string getCanonicalQLClass() { result = "NamespaceDeclarationEntry" } } @@ -140,7 +131,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl { * A C++ `using` directive or `using` declaration. */ abstract class UsingEntry extends Locatable, @using { - override Location getLocation() { usings(underlyingElement(this),_,result) } + override Location getLocation() { usings(underlyingElement(this), _, result) } } /** @@ -149,17 +140,17 @@ abstract class UsingEntry extends Locatable, @using { * `using std::string;` */ class UsingDeclarationEntry extends UsingEntry { - UsingDeclarationEntry() { not exists(Namespace n | usings(underlyingElement(this),unresolveElement(n),_)) } + UsingDeclarationEntry() { + not exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _)) + } /** * Gets the declaration that is referenced by this using declaration. For * example, `std::string` in `using std::string`. */ - Declaration getDeclaration() { usings(underlyingElement(this),unresolveElement(result),_) } + Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _) } - override string toString() { - result = "using " + this.getDeclaration().toString() - } + override string toString() { result = "using " + this.getDeclaration().toString() } } /** @@ -168,17 +159,17 @@ class UsingDeclarationEntry extends UsingEntry { * `using namespace std;` */ class UsingDirectiveEntry extends UsingEntry { - UsingDirectiveEntry() { exists(Namespace n | usings(underlyingElement(this),unresolveElement(n),_)) } + UsingDirectiveEntry() { + exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _)) + } /** * Gets the namespace that is referenced by this using directive. For * example, `std` in `using namespace std`. */ - Namespace getNamespace() { usings(underlyingElement(this),unresolveElement(result),_) } + Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _) } - override string toString() { - result = "using namespace " + this.getNamespace().toString() - } + override string toString() { result = "using namespace " + this.getNamespace().toString() } } /** @@ -192,7 +183,6 @@ private predicate suppressWarningForUnused(GlobalNamespace g) { any() } * The C/C++ global namespace. */ class GlobalNamespace extends Namespace { - GlobalNamespace() { this.hasName("") } override Declaration getADeclaration() { @@ -204,31 +194,22 @@ class GlobalNamespace extends Namespace { /** Gets a child namespace of the global namespace. */ override Namespace getAChildNamespace() { suppressWarningForUnused(this) and - not (namespacembrs(unresolveElement(result), _)) + not namespacembrs(unresolveElement(result), _) } - override Namespace getParentNamespace() { - none() - } + override Namespace getParentNamespace() { none() } /** * DEPRECATED: use `getName()`. */ - deprecated string getFullName() { - result = this.getName() - } - - override string toString() { - result = "(global namespace)" - } + deprecated string getFullName() { result = this.getName() } + override string toString() { result = "(global namespace)" } } /** * The C++ `std::` namespace. */ class StdNamespace extends Namespace { - StdNamespace() { - this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace - } + StdNamespace() { this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace } } diff --git a/cpp/ql/src/semmle/code/cpp/ObjectiveC.qll b/cpp/ql/src/semmle/code/cpp/ObjectiveC.qll index aa7e9d4ddc5..5c99a47e674 100644 --- a/cpp/ql/src/semmle/code/cpp/ObjectiveC.qll +++ b/cpp/ql/src/semmle/code/cpp/ObjectiveC.qll @@ -136,9 +136,7 @@ deprecated class FinallyBlock extends Block { FinallyBlock() { none() } /** Gets the try statement corresponding to this finally block. */ - ObjcTryStmt getTryStmt() { - none() - } + ObjcTryStmt getTryStmt() { none() } } /** @@ -166,7 +164,9 @@ deprecated class Property extends Declaration { Attribute getAnAttribute() { none() } override Location getADeclarationLocation() { result = getLocation() } + override Location getDefinitionLocation() { result = getLocation() } + override Location getLocation() { none() } /** Gets the type of this property. */ diff --git a/cpp/ql/src/semmle/code/cpp/PODType03.qll b/cpp/ql/src/semmle/code/cpp/PODType03.qll index 5b47f80af97..88c9a1203aa 100644 --- a/cpp/ql/src/semmle/code/cpp/PODType03.qll +++ b/cpp/ql/src/semmle/code/cpp/PODType03.qll @@ -14,14 +14,14 @@ import cpp * types (3.9.3) are collectively called scalar types. */ predicate isScalarType03(Type t) { - exists (Type ut - | ut = t.getUnderlyingType() - | ut instanceof ArithmeticType or + exists(Type ut | ut = t.getUnderlyingType() | + ut instanceof ArithmeticType or ut instanceof Enum or ut instanceof FunctionPointerType or ut instanceof PointerToMemberType or ut instanceof PointerType or - isScalarType03(ut.(SpecifiedType).getUnspecifiedType())) + isScalarType03(ut.(SpecifiedType).getUnspecifiedType()) + ) } /** @@ -34,18 +34,20 @@ predicate isScalarType03(Type t) { * (10.3). */ predicate isAggregateClass03(Class c) { - not (c instanceof TemplateClass) and - not exists (Constructor cons - | cons.getDeclaringType() = c and - not cons.isCompilerGenerated()) and - not exists (Variable v - | v.getDeclaringType() = c and - not v.isStatic() - | v.hasSpecifier("private") or - v.hasSpecifier("protected")) and - not exists (c.getABaseClass()) and - not exists (VirtualFunction f - | f.getDeclaringType() = c) + not c instanceof TemplateClass and + not exists(Constructor cons | + cons.getDeclaringType() = c and + not cons.isCompilerGenerated() + ) and + not exists(Variable v | + v.getDeclaringType() = c and + not v.isStatic() + | + v.hasSpecifier("private") or + v.hasSpecifier("protected") + ) and + not exists(c.getABaseClass()) and + not exists(VirtualFunction f | f.getDeclaringType() = c) } /** @@ -58,10 +60,10 @@ predicate isAggregateClass03(Class c) { * (10.3). */ predicate isAggregateType03(Type t) { - exists (Type ut - | ut = t.getUnderlyingType() - | ut instanceof ArrayType or - isAggregateClass03(ut)) + exists(Type ut | ut = t.getUnderlyingType() | + ut instanceof ArrayType or + isAggregateClass03(ut) + ) } /** @@ -79,18 +81,27 @@ predicate isAggregateType03(Type t) { */ predicate isPODClass03(Class c) { isAggregateClass03(c) and - not exists (Variable v - | v.getDeclaringType() = c and - not v.isStatic() - | not isPODType03(v.getType()) or - exists (ArrayType at - | at = v.getType() and - not isPODType03(at.getBaseType())) or - v.getType() instanceof ReferenceType) and - not exists (CopyAssignmentOperator o | o.getDeclaringType() = c and - not o.isCompilerGenerated()) and - not exists (Destructor dest | dest.getDeclaringType() = c and - not dest.isCompilerGenerated()) + not exists(Variable v | + v.getDeclaringType() = c and + not v.isStatic() + | + not isPODType03(v.getType()) + or + exists(ArrayType at | + at = v.getType() and + not isPODType03(at.getBaseType()) + ) + or + v.getType() instanceof ReferenceType + ) and + not exists(CopyAssignmentOperator o | + o.getDeclaringType() = c and + not o.isCompilerGenerated() + ) and + not exists(Destructor dest | + dest.getDeclaringType() = c and + not dest.isCompilerGenerated() + ) } /** @@ -101,12 +112,14 @@ predicate isPODClass03(Class c) { * such types and cv-qualified versions of these types (3.9.3) are * collectively called POD types. */ -predicate isPODType03(Type t) -{ - exists (Type ut - | ut = t.getUnderlyingType() - | isScalarType03(ut) or - isPODClass03(ut) or - exists (ArrayType at | at = ut and isPODType03(at.getBaseType())) or - isPODType03(ut.(SpecifiedType).getUnspecifiedType())) +predicate isPODType03(Type t) { + exists(Type ut | ut = t.getUnderlyingType() | + isScalarType03(ut) + or + isPODClass03(ut) + or + exists(ArrayType at | at = ut and isPODType03(at.getBaseType())) + or + isPODType03(ut.(SpecifiedType).getUnspecifiedType()) + ) } diff --git a/cpp/ql/src/semmle/code/cpp/Parameter.qll b/cpp/ql/src/semmle/code/cpp/Parameter.qll index 01fda320d35..74326ada99c 100644 --- a/cpp/ql/src/semmle/code/cpp/Parameter.qll +++ b/cpp/ql/src/semmle/code/cpp/Parameter.qll @@ -5,7 +5,7 @@ private import semmle.code.cpp.internal.ResolveClass /** * A C/C++ function parameter or catch block parameter. For example the * function parameter `p` and the catch block parameter `e` in the following - * code: + * code: * ``` * void myFunction(int p) { * try { @@ -24,7 +24,6 @@ private import semmle.code.cpp.internal.ResolveClass * have multiple declarations. */ class Parameter extends LocalScopeVariable, @parameter { - /** * Gets the canonical name, or names, of this parameter. * @@ -36,12 +35,14 @@ class Parameter extends LocalScopeVariable, @parameter { * 3. The name "p#i" where i is the index of the parameter. */ override string getName() { - exists (VariableDeclarationEntry vde - | vde = getANamedDeclarationEntry() and result = vde.getName() - | vde.isDefinition() or not getANamedDeclarationEntry().isDefinition()) + exists(VariableDeclarationEntry vde | + vde = getANamedDeclarationEntry() and result = vde.getName() + | + vde.isDefinition() or not getANamedDeclarationEntry().isDefinition() + ) or - (not exists(getANamedDeclarationEntry()) and - result = "p#" + this.getIndex().toString()) + not exists(getANamedDeclarationEntry()) and + result = "p#" + this.getIndex().toString() } override string getCanonicalQLClass() { result = "Parameter" } @@ -52,18 +53,15 @@ class Parameter extends LocalScopeVariable, @parameter { * For example: `int p`. */ string getTypedName() { - exists (string typeString, string nameString - | (if exists(getType().getName()) - then typeString = getType().getName() - else typeString = "") - and - (if exists(getName()) - then nameString = getName() - else nameString = "") - and - (if typeString != "" and nameString != "" - then result = typeString + " " + nameString - else result = typeString + nameString)) + exists(string typeString, string nameString | + (if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and + (if exists(getName()) then nameString = getName() else nameString = "") and + ( + if typeString != "" and nameString != "" + then result = typeString + " " + nameString + else result = typeString + nameString + ) + ) } private VariableDeclarationEntry getANamedDeclarationEntry() { @@ -81,10 +79,12 @@ class Parameter extends LocalScopeVariable, @parameter { */ private VariableDeclarationEntry getAnEffectiveDeclarationEntry() { if getFunction().isConstructedFrom(_) - then exists (Function prototypeInstantiation - | prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and - getFunction().isConstructedFrom(prototypeInstantiation)) - else result = getADeclarationEntry() + then + exists(Function prototypeInstantiation | + prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and + getFunction().isConstructedFrom(prototypeInstantiation) + ) + else result = getADeclarationEntry() } /** @@ -95,11 +95,12 @@ class Parameter extends LocalScopeVariable, @parameter { * getName, but is no longer in use. */ deprecated string getNameInBlock(Block b) { - exists (ParameterDeclarationEntry pde - | pde.getFunctionDeclarationEntry().getBlock() = b and + exists(ParameterDeclarationEntry pde | + pde.getFunctionDeclarationEntry().getBlock() = b and this.getFunction().getBlock() = b and pde.getVariable() = this and - result = pde.getName()) + result = pde.getName() + ) } /** @@ -114,20 +115,22 @@ class Parameter extends LocalScopeVariable, @parameter { * Gets the function to which this parameter belongs, if it is a function * parameter. */ - override Function getFunction() { params(underlyingElement(this),unresolveElement(result),_,_) } + override Function getFunction() { + params(underlyingElement(this), unresolveElement(result), _, _) + } /** * Gets the catch block to which this parameter belongs, if it is a catch * block parameter. */ - Block getCatchBlock() { params(underlyingElement(this),unresolveElement(result),_,_) } + Block getCatchBlock() { params(underlyingElement(this), unresolveElement(result), _, _) } /** * Gets the zero-based index of this parameter. * * For catch block parameters, this is always zero. */ - int getIndex() { params(underlyingElement(this),_,result,_) } + int getIndex() { params(underlyingElement(this), _, result, _) } /** * Gets the type of this parameter. @@ -136,7 +139,7 @@ class Parameter extends LocalScopeVariable, @parameter { * as they are syntactic sugar for parameters of pointer type. The * result is an array type for such parameters. */ - override Type getType() { params(underlyingElement(this),_,_,unresolveElement(result)) } + override Type getType() { params(underlyingElement(this), _, _, unresolveElement(result)) } /** * Gets the canonical location, or locations, of this parameter. @@ -148,7 +151,9 @@ class Parameter extends LocalScopeVariable, @parameter { * of the declaration locations. */ override Location getLocation() { - exists(VariableDeclarationEntry vde | vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation() | + exists(VariableDeclarationEntry vde | + vde = getAnEffectiveDeclarationEntry() and result = vde.getLocation() + | vde.isDefinition() or not getAnEffectiveDeclarationEntry().isDefinition() ) } diff --git a/cpp/ql/src/semmle/code/cpp/Preprocessor.qll b/cpp/ql/src/semmle/code/cpp/Preprocessor.qll index b090d5fa2b1..7cf9aa60a24 100644 --- a/cpp/ql/src/semmle/code/cpp/Preprocessor.qll +++ b/cpp/ql/src/semmle/code/cpp/Preprocessor.qll @@ -8,8 +8,10 @@ import semmle.code.cpp.Element */ class PreprocessorDirective extends Locatable, @preprocdirect { override string toString() { result = "Preprocessor directive" } - override Location getLocation() { preprocdirects(underlyingElement(this),_,result) } - string getHead() { preproctext(underlyingElement(this),result,_) } + + override Location getLocation() { preprocdirects(underlyingElement(this), _, result) } + + string getHead() { preproctext(underlyingElement(this), result, _) } /** * Gets a preprocessor branching directive whose condition affects @@ -46,9 +48,9 @@ abstract class PreprocessorBranchDirective extends PreprocessorDirective { * result. */ PreprocessorBranch getIf() { - result = (PreprocessorIf)this or - result = (PreprocessorIfdef)this or - result = (PreprocessorIfndef)this or + result = this.(PreprocessorIf) or + result = this.(PreprocessorIfdef) or + result = this.(PreprocessorIfndef) or preprocpair(unresolveElement(result), underlyingElement(this)) } @@ -60,9 +62,7 @@ abstract class PreprocessorBranchDirective extends PreprocessorDirective { * directives in different translation units, then there can be more than * one result. */ - PreprocessorEndif getEndIf() { - preprocpair(unresolveElement(getIf()), unresolveElement(result)) - } + PreprocessorEndif getEndIf() { preprocpair(unresolveElement(getIf()), unresolveElement(result)) } /** * Gets the next `#elif`, `#else` or `#endif` matching this branching @@ -86,9 +86,7 @@ abstract class PreprocessorBranchDirective extends PreprocessorDirective { this = rank[result](PreprocessorBranchDirective other | other.getIf() = branch | - other - order by - other.getLocation().getStartLine() + other order by other.getLocation().getStartLine() ) } } @@ -115,9 +113,7 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch { * Holds if at least one translation unit evaluated this directive's * condition and subsequently took the branch. */ - predicate wasTaken() { - preproctrue(underlyingElement(this)) - } + predicate wasTaken() { preproctrue(underlyingElement(this)) } /** * Holds if at least one translation unit evaluated this directive's @@ -126,18 +122,14 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch { * If `#else` is the next matching directive, then this means that the * `#else` was taken instead. */ - predicate wasNotTaken() { - preprocfalse(underlyingElement(this)) - } + predicate wasNotTaken() { preprocfalse(underlyingElement(this)) } /** * Holds if this directive was either taken by all translation units * which evaluated it, or was not taken by any translation unit which * evaluated it. */ - predicate wasPredictable() { - not ( wasTaken() and wasNotTaken() ) - } + predicate wasPredictable() { not (wasTaken() and wasNotTaken()) } } /** @@ -215,9 +207,7 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef { /** * Gets the name of the macro that is undefined. */ - string getName() { - result = getHead() - } + string getName() { result = getHead() } } /** diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index 5485ef1f697..ab979d89b03 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -4,20 +4,24 @@ import cpp * Gets a string containing the scope in which this declaration is declared. */ private string getScopePrefix(Declaration decl) { - decl.isMember() and result = decl.getDeclaringType().(UserDumpType).getIdentityString() + "::" or - ( - decl.isTopLevel() and - exists (string parentName | - parentName = decl.getNamespace().getQualifiedName() and - ( - parentName != "" and result = parentName + "::" or - parentName = "" and result = "" - ) + decl.isMember() and result = decl.getDeclaringType().(UserDumpType).getIdentityString() + "::" + or + decl.isTopLevel() and + exists(string parentName | + parentName = decl.getNamespace().getQualifiedName() and + ( + parentName != "" and result = parentName + "::" + or + parentName = "" and result = "" ) - ) or + ) + or exists(UserType type | - type = decl and type.isLocal() and result = "(" + type.getEnclosingFunction().(DumpFunction).getIdentityString() + ")::" - ) or + type = decl and + type.isLocal() and + result = "(" + type.getEnclosingFunction().(DumpFunction).getIdentityString() + ")::" + ) + or decl instanceof TemplateParameter and result = "" } @@ -26,16 +30,15 @@ private string getScopePrefix(Declaration decl) { * it returns `...` for `UnknownType`, which is used to represent variable arguments. */ private string getParameterTypeString(Type parameterType) { - if parameterType instanceof UnknownType then - result = "..." - else - result = parameterType.(DumpType).getTypeIdentityString() + if parameterType instanceof UnknownType + then result = "..." + else result = parameterType.(DumpType).getTypeIdentityString() } /** * A `Declaration` extended to add methods for generating strings useful only for dumps and debugging. */ -private abstract class DumpDeclaration extends Declaration { +abstract private class DumpDeclaration extends Declaration { /** * Gets a string that uniquely identifies this declaration, suitable for use when debugging queries. Only holds for * functions, user-defined types, global and namespace-scope variables, and member variables. @@ -43,29 +46,26 @@ private abstract class DumpDeclaration extends Declaration { * This operation is very expensive, and should not be used in production queries. Consider using * `hasQualifiedName()` for identifying known declarations in production queries. */ - string getIdentityString() { - none() - } + string getIdentityString() { none() } language[monotonicAggregates] final string getTemplateArgumentsString() { - if exists(this.getATemplateArgument()) then ( + if exists(this.getATemplateArgument()) + then result = "<" + - strictconcat(int i | - exists(this.getTemplateArgument(i)) | + strictconcat(int i | + exists(this.getTemplateArgument(i)) + | this.getTemplateArgument(i).(DumpType).getTypeIdentityString(), ", " order by i - ) + ">" - ) - else - result = "" + ) + ">" + else result = "" } } /** * A `Type` extended to add methods for generating strings useful only for dumps and debugging. */ -private class DumpType extends Type -{ +private class DumpType extends Type { /** * Gets a string that uniquely identifies this type, suitable for use when debugging queries. All typedefs and * decltypes are expanded, and all symbol names are fully qualified. @@ -79,7 +79,8 @@ private class DumpType extends Type // and `getDeclaratorSuffixBeforeQualifiers()`. To create the type identity // for a `SpecifiedType`, insert the qualifiers after // `getDeclaratorSuffixBeforeQualifiers()`. - result = getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix() + result = getTypeSpecifier() + getDeclaratorPrefix() + getDeclaratorSuffixBeforeQualifiers() + + getDeclaratorSuffix() } /** @@ -93,18 +94,14 @@ private class DumpType extends Type * * This predicate is intended to be used only by the implementation of `getTypeIdentityString`. */ - string getTypeSpecifier() { - result = "" - } + string getTypeSpecifier() { result = "" } /** * Gets the portion of this type's declarator that comes before the declarator for any derived type. * * This predicate is intended to be used only by the implementation of `getTypeIdentityString`. */ - string getDeclaratorPrefix() { - result = "" - } + string getDeclaratorPrefix() { result = "" } /** * Gets the portion of this type's declarator that comes after the declarator for any derived type, but before any @@ -112,9 +109,7 @@ private class DumpType extends Type * * This predicate is intended to be used only by the implementation of `getTypeIdentityString`. */ - string getDeclaratorSuffixBeforeQualifiers() { - result = "" - } + string getDeclaratorSuffixBeforeQualifiers() { result = "" } /** * Gets the portion of this type's declarator that comes after the declarator for any derived type and after any @@ -122,49 +117,33 @@ private class DumpType extends Type * * This predicate is intended to be used only by the implementation of `getTypeIdentityString`. */ - string getDeclaratorSuffix() { - result = "" - } + string getDeclaratorSuffix() { result = "" } } private class BuiltInDumpType extends DumpType, BuiltInType { - override string getTypeSpecifier() { - result = toString() - } + override string getTypeSpecifier() { result = toString() } } private class IntegralDumpType extends BuiltInDumpType, IntegralType { - override string getTypeSpecifier() { - result = getCanonicalArithmeticType().toString() - } + override string getTypeSpecifier() { result = getCanonicalArithmeticType().toString() } } private class DerivedDumpType extends DumpType, DerivedType { - override string getTypeSpecifier() { - result = getBaseType().(DumpType).getTypeSpecifier() - } + override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } override string getDeclaratorSuffixBeforeQualifiers() { result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() } - override string getDeclaratorSuffix() { - result = getBaseType().(DumpType).getDeclaratorSuffix() - } + override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } } private class DecltypeDumpType extends DumpType, Decltype { - override string getTypeSpecifier() { - result = getBaseType().(DumpType).getTypeSpecifier() - } + override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } - override string getDeclaratorPrefix() { - result = getBaseType().(DumpType).getDeclaratorPrefix() - } + override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() } - override string getDeclaratorSuffix() { - result = getBaseType().(DumpType).getDeclaratorSuffix() - } + override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } } private class PointerIshDumpType extends DerivedDumpType { @@ -176,81 +155,65 @@ private class PointerIshDumpType extends DerivedDumpType { override string getDeclaratorPrefix() { exists(string declarator | result = getBaseType().(DumpType).getDeclaratorPrefix() + declarator and - if getBaseType().getUnspecifiedType() instanceof ArrayType then - declarator = "(" + getDeclaratorToken() + ")" - else - declarator = getDeclaratorToken() + if getBaseType().getUnspecifiedType() instanceof ArrayType + then declarator = "(" + getDeclaratorToken() + ")" + else declarator = getDeclaratorToken() ) } /** * Gets the token used when declaring this kind of type (e.g. `*`, `&`, `&&`)/ */ - string getDeclaratorToken() { - result = "" - } + string getDeclaratorToken() { result = "" } } private class PointerDumpType extends PointerIshDumpType, PointerType { - override string getDeclaratorToken() { - result = "*" - } + override string getDeclaratorToken() { result = "*" } } private class LValueReferenceDumpType extends PointerIshDumpType, LValueReferenceType { - override string getDeclaratorToken() { - result = "&" - } + override string getDeclaratorToken() { result = "&" } } private class RValueReferenceDumpType extends PointerIshDumpType, RValueReferenceType { - override string getDeclaratorToken() { - result = "&&" - } + override string getDeclaratorToken() { result = "&&" } } private class PointerToMemberDumpType extends DumpType, PointerToMemberType { - override string getTypeSpecifier() { - result = getBaseType().(DumpType).getTypeSpecifier() - } + override string getTypeSpecifier() { result = getBaseType().(DumpType).getTypeSpecifier() } override string getDeclaratorPrefix() { exists(string declarator, string parenDeclarator, Type baseType | declarator = getClass().(DumpType).getTypeIdentityString() + "::*" and result = getBaseType().(DumpType).getDeclaratorPrefix() + " " + parenDeclarator and baseType = getBaseType().getUnspecifiedType() and - if (baseType instanceof ArrayType) or (baseType instanceof RoutineType) then - parenDeclarator = "(" + declarator - else - parenDeclarator = declarator + if baseType instanceof ArrayType or baseType instanceof RoutineType + then parenDeclarator = "(" + declarator + else parenDeclarator = declarator ) } override string getDeclaratorSuffixBeforeQualifiers() { exists(Type baseType | baseType = getBaseType().getUnspecifiedType() and - if (baseType instanceof ArrayType) or (baseType instanceof RoutineType) then - result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() - else - result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + if baseType instanceof ArrayType or baseType instanceof RoutineType + then result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + else result = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() ) } - override string getDeclaratorSuffix() { - result = getBaseType().(DumpType).getDeclaratorSuffix() - } + override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } } private class ArrayDumpType extends DerivedDumpType, ArrayType { - override string getDeclaratorPrefix() { - result = getBaseType().(DumpType).getDeclaratorPrefix() - } + override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() } override string getDeclaratorSuffixBeforeQualifiers() { - if exists(getArraySize()) then - result = "[" + getArraySize().toString() + "]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() - else - result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + if exists(getArraySize()) + then + result = "[" + getArraySize().toString() + "]" + + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + else result = "[]" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() } } @@ -259,9 +222,7 @@ private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointe result = ")" + getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() } - override string getDeclaratorSuffix() { - result = getBaseType().(DumpType).getDeclaratorSuffix() - } + override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } override string getDeclaratorPrefix() { result = getBaseType().(DumpType).getDeclaratorPrefix() + "(" + getDeclaratorToken() @@ -270,33 +231,23 @@ private class FunctionPointerIshDumpType extends DerivedDumpType, FunctionPointe /** * Gets the token used when declaring this kind of type (e.g. `*`, `&`, `^`)/ */ - string getDeclaratorToken() { - result = "" - } + string getDeclaratorToken() { result = "" } } private class FunctionPointerDumpType extends FunctionPointerIshDumpType, FunctionPointerType { - override string getDeclaratorToken() { - result = "*" - } + override string getDeclaratorToken() { result = "*" } } private class FunctionReferenceDumpType extends FunctionPointerIshDumpType, FunctionReferenceType { - override string getDeclaratorToken() { - result = "&" - } + override string getDeclaratorToken() { result = "&" } } private class BlockDumpType extends FunctionPointerIshDumpType, BlockType { - override string getDeclaratorToken() { - result = "^" - } + override string getDeclaratorToken() { result = "^" } } private class RoutineDumpType extends DumpType, RoutineType { - override string getTypeSpecifier() { - result = getReturnType().(DumpType).getTypeSpecifier() - } + override string getTypeSpecifier() { result = getReturnType().(DumpType).getTypeSpecifier() } override string getDeclaratorPrefix() { result = getReturnType().(DumpType).getDeclaratorPrefix() @@ -305,14 +256,16 @@ private class RoutineDumpType extends DumpType, RoutineType { language[monotonicAggregates] override string getDeclaratorSuffixBeforeQualifiers() { result = "(" + - concat(int i | - exists(getParameterType(i)) | - getParameterTypeString(getParameterType(i)), ", " order by i - ) + ")" + concat(int i | + exists(getParameterType(i)) + | + getParameterTypeString(getParameterType(i)), ", " order by i + ) + ")" } override string getDeclaratorSuffix() { - result = getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + getReturnType().(DumpType).getDeclaratorSuffix() + result = getReturnType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + + getReturnType().(DumpType).getDeclaratorSuffix() } } @@ -320,55 +273,46 @@ private class SpecifiedDumpType extends DerivedDumpType, SpecifiedType { override string getDeclaratorPrefix() { exists(string basePrefix | basePrefix = getBaseType().(DumpType).getDeclaratorPrefix() and - if getBaseType().getUnspecifiedType() instanceof RoutineType then - result = basePrefix - else - result = basePrefix + " " + getSpecifierString().trim() + if getBaseType().getUnspecifiedType() instanceof RoutineType + then result = basePrefix + else result = basePrefix + " " + getSpecifierString().trim() ) } override string getDeclaratorSuffixBeforeQualifiers() { exists(string baseSuffix | baseSuffix = getBaseType().(DumpType).getDeclaratorSuffixBeforeQualifiers() and - if getBaseType().getUnspecifiedType() instanceof RoutineType then - result = baseSuffix + " " + getSpecifierString().trim() - else - result = baseSuffix + if getBaseType().getUnspecifiedType() instanceof RoutineType + then result = baseSuffix + " " + getSpecifierString().trim() + else result = baseSuffix ) } - override string getDeclaratorSuffix() { - result = getBaseType().(DumpType).getDeclaratorSuffix() - } + override string getDeclaratorSuffix() { result = getBaseType().(DumpType).getDeclaratorSuffix() } } private class UserDumpType extends DumpType, DumpDeclaration, UserType { override string getIdentityString() { exists(string simpleName | ( - if this instanceof Closure then ( + if this instanceof Closure + then // Parenthesize the name of the lambda because it's freeform text similar to // "lambda [] type at line 12, col. 40" // Use `min(getSimpleName())` to work around an extractor bug where a lambda can have different names // from different compilation units. simpleName = "(" + min(getSimpleName()) + ")" - ) - else - simpleName = getSimpleName() + else simpleName = getSimpleName() ) and result = getScopePrefix(this) + simpleName + getTemplateArgumentsString() ) } - override string getTypeSpecifier() { - result = getIdentityString() - } + override string getTypeSpecifier() { result = getIdentityString() } } private class DumpProxyClass extends UserDumpType, ProxyClass { - override string getIdentityString() { - result = getName() - } + override string getIdentityString() { result = getName() } } private class DumpVariable extends DumpDeclaration, Variable { @@ -376,30 +320,35 @@ private class DumpVariable extends DumpDeclaration, Variable { exists(DumpType type | (this instanceof MemberVariable or this instanceof GlobalOrNamespaceVariable) and type = this.getType() and - result = type.getTypeSpecifier() + type.getDeclaratorPrefix() + " " + getScopePrefix(this) + this.getName() + this.getTemplateArgumentsString() + type.getDeclaratorSuffixBeforeQualifiers() + type.getDeclaratorSuffix() + result = type.getTypeSpecifier() + type.getDeclaratorPrefix() + " " + getScopePrefix(this) + + this.getName() + this.getTemplateArgumentsString() + + type.getDeclaratorSuffixBeforeQualifiers() + type.getDeclaratorSuffix() ) } } private class DumpFunction extends DumpDeclaration, Function { override string getIdentityString() { - result = getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + " " + getScopePrefix(this) + getName() + getTemplateArgumentsString() + getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix() + result = getType().(DumpType).getTypeSpecifier() + getType().(DumpType).getDeclaratorPrefix() + + " " + getScopePrefix(this) + getName() + getTemplateArgumentsString() + + getDeclaratorSuffixBeforeQualifiers() + getDeclaratorSuffix() } language[monotonicAggregates] private string getDeclaratorSuffixBeforeQualifiers() { result = "(" + - concat(int i | - exists(getParameter(i).getType()) | - getParameterTypeString(getParameter(i).getType()), ", " order by i - ) + ")" + getQualifierString() + concat(int i | + exists(getParameter(i).getType()) + | + getParameterTypeString(getParameter(i).getType()), ", " order by i + ) + ")" + getQualifierString() } private string getQualifierString() { - if exists(getACVQualifier()) then + if exists(getACVQualifier()) + then result = " " + strictconcat(string qualifier | qualifier = getACVQualifier() | qualifier, " ") - else - result = "" + else result = "" } private string getACVQualifier() { @@ -408,27 +357,24 @@ private class DumpFunction extends DumpDeclaration, Function { } private string getDeclaratorSuffix() { - result = getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + getType().(DumpType).getDeclaratorSuffix() + result = getType().(DumpType).getDeclaratorSuffixBeforeQualifiers() + + getType().(DumpType).getDeclaratorSuffix() } } /** - * Gets a string that uniquely identifies this declaration, suitable for use when debugging queries. Only holds for - * functions, user-defined types, global and namespace-scope variables, and member variables. - * - * This operation is very expensive, and should not be used in production queries. Consider using `hasName()` or - * `hasQualifiedName()` for identifying known declarations in production queries. - */ -string getIdentityString(Declaration decl) { - result = decl.(DumpDeclaration).getIdentityString() -} + * Gets a string that uniquely identifies this declaration, suitable for use when debugging queries. Only holds for + * functions, user-defined types, global and namespace-scope variables, and member variables. + * + * This operation is very expensive, and should not be used in production queries. Consider using `hasName()` or + * `hasQualifiedName()` for identifying known declarations in production queries. + */ +string getIdentityString(Declaration decl) { result = decl.(DumpDeclaration).getIdentityString() } /** - * Gets a string that uniquely identifies this type, suitable for use when debugging queries. All typedefs and - * decltypes are expanded, and all symbol names are fully qualified. - * - * This operation is very expensive, and should not be used in production queries. - */ -string getTypeIdentityString(Type type) { - result = type.(DumpType).getTypeIdentityString() -} + * Gets a string that uniquely identifies this type, suitable for use when debugging queries. All typedefs and + * decltypes are expanded, and all symbol names are fully qualified. + * + * This operation is very expensive, and should not be used in production queries. + */ +string getTypeIdentityString(Type type) { result = type.(DumpType).getTypeIdentityString() } diff --git a/cpp/ql/src/semmle/code/cpp/PrintAST.ql b/cpp/ql/src/semmle/code/cpp/PrintAST.ql index e6347917945..6fc40dd0525 100644 --- a/cpp/ql/src/semmle/code/cpp/PrintAST.ql +++ b/cpp/ql/src/semmle/code/cpp/PrintAST.ql @@ -1,6 +1,6 @@ /** * @name Print AST - * @description Outputs a representation of the Abstract Syntax Tree. + * @description Outputs a representation of the Abstract Syntax Tree. * @id cpp/print-ast * @kind graph */ diff --git a/cpp/ql/src/semmle/code/cpp/PrintAST.qll b/cpp/ql/src/semmle/code/cpp/PrintAST.qll index c9f3e45fde2..a1ee1916f76 100644 --- a/cpp/ql/src/semmle/code/cpp/PrintAST.qll +++ b/cpp/ql/src/semmle/code/cpp/PrintAST.qll @@ -75,9 +75,7 @@ private Function getEnclosingFunction(Locatable ast) { * nodes for things like parameter lists and constructor init lists. */ private newtype TPrintASTNode = - TASTNode(Locatable ast) { - shouldPrintFunction(getEnclosingFunction(ast)) - } or + TASTNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) { // We create a unique node for each pair of (stmt, entry), to avoid having one node with // multiple parents due to extractor bug CPP-413. @@ -161,7 +159,6 @@ private string qlClass(ElementBase el) { //result = "["+ concat(el.getAQlClass(), ",") + "] " } - /** * A node representing an AST node. */ @@ -263,9 +260,7 @@ class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode { override DeclarationEntry ast; DeclStmt declStmt; - DeclarationEntryNode() { - this = TDeclarationEntryNode(declStmt, ast) - } + DeclarationEntryNode() { this = TDeclarationEntryNode(declStmt, ast) } override PrintASTNode getChild(int childIndex) { none() } @@ -319,7 +314,7 @@ class DeclStmtNode extends StmtNode { DeclStmtNode() { declStmt = stmt } override DeclarationEntryNode getChild(int childIndex) { - exists (DeclarationEntry entry | + exists(DeclarationEntry entry | declStmt.getDeclarationEntry(childIndex) = entry and result = TDeclarationEntryNode(declStmt, entry) ) diff --git a/cpp/ql/src/semmle/code/cpp/Specifier.qll b/cpp/ql/src/semmle/code/cpp/Specifier.qll index 56b78141b99..f58f060623d 100644 --- a/cpp/ql/src/semmle/code/cpp/Specifier.qll +++ b/cpp/ql/src/semmle/code/cpp/Specifier.qll @@ -6,7 +6,6 @@ private import semmle.code.cpp.internal.ResolveClass * `mutable`, `inline`, `virtual`, or `explicit`. */ class Specifier extends Element, @specifier { - /** Gets a dummy location for the specifier. */ override Location getLocation() { suppressUnusedThis(this) and @@ -14,9 +13,9 @@ class Specifier extends Element, @specifier { } override string getCanonicalQLClass() { result = "Specifier" } - + /** Gets the name of this specifier. */ - string getName() { specifiers(underlyingElement(this),result) } + string getName() { specifiers(underlyingElement(this), result) } /** Holds if the name of this specifier is `name`. */ predicate hasName(string name) { name = this.getName() } @@ -33,6 +32,7 @@ class FunctionSpecifier extends Specifier { this.hasName("virtual") or this.hasName("explicit") } + override string getCanonicalQLClass() { result = "FunctionSpecifier)" } } @@ -48,6 +48,7 @@ class StorageClassSpecifier extends Specifier { this.hasName("extern") or this.hasName("mutable") } + override string getCanonicalQLClass() { result = "StorageClassSpecifier" } } @@ -65,7 +66,7 @@ class AccessSpecifier extends Specifier { * Gets the visibility of a field with access specifier `this` if it is * directly inherited with access specifier `baseAccess`. For example: * - * ``` + * ``` * class A { protected int f; }; * class B : private A {}; * ``` @@ -92,14 +93,17 @@ class AccessSpecifier extends Specifier { * ``` */ AccessSpecifier accessInDirectDerived(AccessSpecifier baseAccess) { - this.getName() != "private" and ( + this.getName() != "private" and + ( // Alphabetically, "private" < "protected" < "public". This disjunction // encodes that `result` is the minimum access of `this` and // `baseAccess`. - baseAccess.getName() < this.getName() and result = baseAccess or + baseAccess.getName() < this.getName() and result = baseAccess + or baseAccess.getName() >= this.getName() and result = this ) } + override string getCanonicalQLClass() { result = "AccessSpecifier" } } @@ -129,22 +133,17 @@ class Attribute extends Element, @attribute { override string toString() { result = this.getName() } /** Gets the `i`th argument of the attribute. */ - AttributeArgument getArgument(int i) { - result.getAttribute() = this and result.getIndex() = i - } + AttributeArgument getArgument(int i) { result.getAttribute() = this and result.getIndex() = i } /** Gets an argument of the attribute. */ - AttributeArgument getAnArgument() { - result = getArgument(_) - } + AttributeArgument getAnArgument() { result = getArgument(_) } } /** * An attribute introduced by GNU's `__attribute__((name))` syntax, for * example: `__attribute__((__noreturn__))`. */ -class GnuAttribute extends Attribute, @gnuattribute { -} +class GnuAttribute extends Attribute, @gnuattribute { } /** * An attribute introduced by the C++11 standard `[[name]]` syntax, for @@ -171,8 +170,7 @@ class StdAttribute extends Attribute, @stdattribute { * An attribute introduced by Microsoft's `__declspec(name)` syntax, for * example: `__declspec(dllimport)`. */ -class Declspec extends Attribute, @declspec { -} +class Declspec extends Attribute, @declspec { } /** * An attribute introduced by Microsoft's "[name]" syntax, for example "[SA_Pre(Deref=1,Access=SA_Read)]". @@ -198,38 +196,31 @@ class AlignAs extends Attribute, @alignas { * that declares a function to accept a `printf` style format string. */ class FormatAttribute extends GnuAttribute { - FormatAttribute() { - getName() = "format" - } + FormatAttribute() { getName() = "format" } /** * Gets the archetype of this format attribute, for example * `"printf"`. */ - string getArchetype() { - result = getArgument(0).getValueText() - } + string getArchetype() { result = getArgument(0).getValueText() } /** * Gets the index in (1-based) format attribute notation associated * with the first argument of the function. */ private int firstArgumentNumber() { - if exists(MemberFunction f | f.getAnAttribute() = this and not f.isStatic()) then ( + if exists(MemberFunction f | f.getAnAttribute() = this and not f.isStatic()) + then // 1 is `this`, so the first parameter is 2 result = 2 - ) else ( - result = 1 - ) + else result = 1 } /** * Gets the (0-based) index of the format string, * according to this attribute. */ - int getFormatIndex() { - result = getArgument(1).getValueInt() - firstArgumentNumber() - } + int getFormatIndex() { result = getArgument(1).getValueInt() - firstArgumentNumber() } /** * Gets the (0-based) index of the first format argument (if any), @@ -242,6 +233,7 @@ class FormatAttribute extends GnuAttribute { not val = 0 // indicates a `vprintf` style format function with arguments not directly available. ) } + override string getCanonicalQLClass() { result = "FormatAttribute" } } @@ -254,31 +246,23 @@ class AttributeArgument extends Element, @attribute_arg { * arguments are a Microsoft feature, so only a `MicrosoftAttribute` can * have a named argument. */ - string getName() { - attribute_arg_name(underlyingElement(this), result) - } + string getName() { attribute_arg_name(underlyingElement(this), result) } /** * Gets the text for the value of this argument, if its value is * a string or a number. */ - string getValueText() { - attribute_arg_value(underlyingElement(this), result) - } + string getValueText() { attribute_arg_value(underlyingElement(this), result) } /** * Gets the value of this argument, if its value is integral. */ - int getValueInt() { - result = getValueText().toInt() - } + int getValueInt() { result = getValueText().toInt() } /** * Gets the value of this argument, if its value is a type. */ - Type getValueType() { - attribute_arg_type(underlyingElement(this), unresolveElement(result)) - } + Type getValueType() { attribute_arg_type(underlyingElement(this), unresolveElement(result)) } /** * Gets the attribute to which this is an argument. @@ -291,25 +275,23 @@ class AttributeArgument extends Element, @attribute_arg { * Gets the zero-based index of this argument in the containing * attribute's argument list. */ - int getIndex() { - attribute_args(underlyingElement(this), _, _, result, _) - } + int getIndex() { attribute_args(underlyingElement(this), _, _, result, _) } - override Location getLocation() { - attribute_args(underlyingElement(this), _, _, _, result) - } + override Location getLocation() { attribute_args(underlyingElement(this), _, _, _, result) } override string toString() { - if exists (@attribute_arg_empty self | self = underlyingElement(this)) - then result = "empty argument" - else exists (string prefix, string tail - | (if exists(getName()) - then prefix = getName() + "=" - else prefix = "") and - (if exists (@attribute_arg_type self | self = underlyingElement(this)) - then tail = getValueType().getName() - else tail = getValueText()) and - result = prefix + tail) + if exists(@attribute_arg_empty self | self = underlyingElement(this)) + then result = "empty argument" + else + exists(string prefix, string tail | + (if exists(getName()) then prefix = getName() + "=" else prefix = "") and + ( + if exists(@attribute_arg_type self | self = underlyingElement(this)) + then tail = getValueType().getName() + else tail = getValueText() + ) and + result = prefix + tail + ) } } diff --git a/cpp/ql/src/semmle/code/cpp/Struct.qll b/cpp/ql/src/semmle/code/cpp/Struct.qll index a5021c23408..6b95cdba1bd 100644 --- a/cpp/ql/src/semmle/code/cpp/Struct.qll +++ b/cpp/ql/src/semmle/code/cpp/Struct.qll @@ -4,7 +4,7 @@ import semmle.code.cpp.Class /** * A C/C++ structure or union. For example, the types `MyStruct` and `MyUnion` * in: - * ``` + * ``` * struct MyStruct { * int x, y, z; * }; @@ -16,12 +16,11 @@ import semmle.code.cpp.Class * ``` */ class Struct extends Class { - - Struct() { usertypes(underlyingElement(this),_,1) or usertypes(underlyingElement(this),_,3) } + Struct() { usertypes(underlyingElement(this), _, 1) or usertypes(underlyingElement(this), _, 3) } override string getCanonicalQLClass() { result = "Struct" } - - override string explain() { result = "struct " + this.getName() } + + override string explain() { result = "struct " + this.getName() } override predicate isDeeplyConstBelow() { any() } // No subparts } @@ -30,7 +29,7 @@ class Struct extends Class { * A C/C++ struct that is directly enclosed by a function. For example, the type * `MyLocalStruct` in: * ``` - * void myFunction() { + * void myFunction() { * struct MyLocalStruct { * int x, y, z; * }; @@ -38,12 +37,11 @@ class Struct extends Class { * ``` */ class LocalStruct extends Struct { - LocalStruct() { - isLocal() - } + LocalStruct() { isLocal() } - override string getCanonicalQLClass() - { not this instanceof LocalUnion and result = "LocalStruct" } + override string getCanonicalQLClass() { + not this instanceof LocalUnion and result = "LocalStruct" + } } /** @@ -58,12 +56,11 @@ class LocalStruct extends Struct { * ``` */ class NestedStruct extends Struct { - NestedStruct() { - this.isMember() - } + NestedStruct() { this.isMember() } - override string getCanonicalQLClass() - { not this instanceof NestedUnion and result = "NestedStruct" } + override string getCanonicalQLClass() { + not this instanceof NestedUnion and result = "NestedStruct" + } /** Holds if this member is private. */ predicate isPrivate() { this.hasSpecifier("private") } @@ -73,5 +70,4 @@ class NestedStruct extends Struct { /** Holds if this member is public. */ predicate isPublic() { this.hasSpecifier("public") } - } diff --git a/cpp/ql/src/semmle/code/cpp/TestFile.qll b/cpp/ql/src/semmle/code/cpp/TestFile.qll index c546ae04adb..4348bddf59c 100644 --- a/cpp/ql/src/semmle/code/cpp/TestFile.qll +++ b/cpp/ql/src/semmle/code/cpp/TestFile.qll @@ -18,7 +18,7 @@ private class GoogleTest extends MacroInvocation { // invocation of a macro from Google Test. this.getMacro().getFile() instanceof GoogleTestHeader } -} +} /** * The `boost/test` directory. @@ -36,8 +36,7 @@ private class BoostTestFolder extends Folder { private class BoostTest extends MacroInvocation { BoostTest() { // invocation of a macro from Boost Test. - this.getMacro().getFile().getParentContainer+() - instanceof BoostTestFolder + this.getMacro().getFile().getParentContainer+() instanceof BoostTestFolder } } @@ -45,9 +44,7 @@ private class BoostTest extends MacroInvocation { * The `cppunit` directory. */ private class CppUnitFolder extends Folder { - CppUnitFolder() { - getBaseName() = "cppunit" - } + CppUnitFolder() { getBaseName() = "cppunit" } } /** @@ -65,16 +62,13 @@ private class CppUnitClass extends Class { */ private class CppUnitTest extends Element { CppUnitTest() { - ( - // class with a base class from cppunit. - this.(Class).getABaseClass*() instanceof CppUnitClass and - - // class itself is not a part of cppunit. - not this instanceof CppUnitClass - ) or ( - // any member function of a test is also test code - this.(Function).getDeclaringType() instanceof CppUnitTest - ) + // class with a base class from cppunit. + this.(Class).getABaseClass*() instanceof CppUnitClass and + // class itself is not a part of cppunit. + not this instanceof CppUnitClass + or + // any member function of a test is also test code + this.(Function).getDeclaringType() instanceof CppUnitTest } } diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index ee66259d956..c65c4941355 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -12,9 +12,7 @@ class Type extends Locatable, @type { /** * Gets the name of this type. */ - string getName() { - none() - } + string getName() { none() } /** * Holds if this type is called `name`. @@ -32,9 +30,7 @@ class Type extends Locatable, @type { // because there is a similarly-named predicate in Declaration, and UserType // inherits from both Type and Declaration and must override it to resolve // the ambiguity. - predicate hasSpecifier(string name) { - this.getASpecifier().hasName(name) - } + predicate hasSpecifier(string name) { this.getASpecifier().hasName(name) } /** * Gets a specifier of this type, recursively looking through `typedef` and @@ -48,7 +44,7 @@ class Type extends Locatable, @type { // inherits from both Type and Declaration and must override it to resolve // the ambiguity. Specifier getASpecifier() { - typespecifiers(underlyingElement(this),unresolveElement(result)) + typespecifiers(underlyingElement(this), unresolveElement(result)) or result = this.internal_getAnAdditionalSpecifier() } @@ -56,7 +52,7 @@ class Type extends Locatable, @type { /** * Gets an attribute of this type. */ - Attribute getAnAttribute() { typeattributes(underlyingElement(this),unresolveElement(result)) } + Attribute getAnAttribute() { typeattributes(underlyingElement(this), unresolveElement(result)) } /** * Internal -- should be `protected` when QL supports such a flag. Subtypes @@ -113,26 +109,24 @@ class Type extends Locatable, @type { * Gets the size of this type in bytes. */ int getSize() { - builtintypes(underlyingElement(this), _, _, result, _, _) - or pointerishsize(underlyingElement(this), result, _) - or usertypesize(underlyingElement(this), result, _) + builtintypes(underlyingElement(this), _, _, result, _, _) or + pointerishsize(underlyingElement(this), result, _) or + usertypesize(underlyingElement(this), result, _) } /** * Gets the alignment of this type in bytes. */ int getAlignment() { - builtintypes(underlyingElement(this), _, _, _, _, result) - or pointerishsize(underlyingElement(this), _, result) - or usertypesize(underlyingElement(this), _, result) + builtintypes(underlyingElement(this), _, _, _, _, result) or + pointerishsize(underlyingElement(this), _, result) or + usertypesize(underlyingElement(this), _, result) } /** * Gets the pointer indirection level of this type. */ - int getPointerIndirectionLevel() { - result = 0 - } + int getPointerIndirectionLevel() { result = 0 } /** * Gets a detailed string representation explaining the AST of this type @@ -174,109 +168,104 @@ class Type extends Locatable, @type { // An explicit cast to a type referring to T uses T. We exclude casts within instantiations, // since they do not appear directly in the source. exists(Cast c | - not(c.isImplicit()) - and c.getType().refersTo(this) - and result = c - and not c.getEnclosingFunction().isConstructedFrom(_) + not c.isImplicit() and + c.getType().refersTo(this) and + result = c and + not c.getEnclosingFunction().isConstructedFrom(_) ) - + or // A class derivation from a type referring to T uses T. We exclude class derivations within // instantiations, since they do not appear directly in the source. - or exists(ClassDerivation cd | - cd.getBaseType().refersTo(this) - and result = cd - and not cd.getDerivedClass() instanceof ClassTemplateInstantiation + exists(ClassDerivation cd | + cd.getBaseType().refersTo(this) and + result = cd and + not cd.getDerivedClass() instanceof ClassTemplateInstantiation ) - + or // A new, new array, or placement new expression with a type that refers to T uses T. // We exclude news within instantiations, since they do not appear directly in the source. - or exists(Expr e | + exists(Expr e | ( - e instanceof NewArrayExpr - or e instanceof NewExpr - ) - and e.getType().refersTo(this) - and result = e - and not e.getEnclosingFunction().isConstructedFrom(_) + e instanceof NewArrayExpr or + e instanceof NewExpr + ) and + e.getType().refersTo(this) and + result = e and + not e.getEnclosingFunction().isConstructedFrom(_) ) - + or // The declaration of a function that returns a type referring to T uses T. We exclude // declarations of function template instantiations, since their return types do not // appear directly in the source. We also exclude constructors and destructors, since // they are indexed with a dummy return type of void that does not appear in the source. - or exists(FunctionDeclarationEntry fde, Type t | - ( - if exists(fde.getTypedefType()) then - t = fde.getTypedefType() - else - t = fde.getType() - ) - and t.refersTo(this) - and result = fde - and not fde.getDeclaration().isConstructedFrom(_) - and not(fde.getDeclaration() instanceof Constructor) - and not(fde.getDeclaration() instanceof Destructor) + exists(FunctionDeclarationEntry fde, Type t | + (if exists(fde.getTypedefType()) then t = fde.getTypedefType() else t = fde.getType()) and + t.refersTo(this) and + result = fde and + not fde.getDeclaration().isConstructedFrom(_) and + not fde.getDeclaration() instanceof Constructor and + not fde.getDeclaration() instanceof Destructor ) - + or // A function call that provides an explicit template argument that refers to T uses T. // We exclude calls within instantiations, since they do not appear directly in the source. - or exists(FunctionCall c | - c.getAnExplicitTemplateArgument().refersTo(this) - and result = c - and not c.getEnclosingFunction().isConstructedFrom(_) + exists(FunctionCall c | + c.getAnExplicitTemplateArgument().refersTo(this) and + result = c and + not c.getEnclosingFunction().isConstructedFrom(_) ) - + or // Qualifying an expression with a type that refers to T uses T. We exclude qualifiers // within instantiations, since they do not appear directly in the source. - or exists(NameQualifier nq | - nq.getQualifyingElement().(Type).refersTo(this) - and result = nq - and not nq.getExpr().getEnclosingFunction().isConstructedFrom(_) + exists(NameQualifier nq | + nq.getQualifyingElement().(Type).refersTo(this) and + result = nq and + not nq.getExpr().getEnclosingFunction().isConstructedFrom(_) ) - + or // Calculating the size of a type that refers to T uses T. We exclude sizeofs within // instantiations, since they do not appear directly in the source. - or exists(SizeofTypeOperator soto | - soto.getTypeOperand().refersTo(this) - and result = soto - and not soto.getEnclosingFunction().isConstructedFrom(_) + exists(SizeofTypeOperator soto | + soto.getTypeOperand().refersTo(this) and + result = soto and + not soto.getEnclosingFunction().isConstructedFrom(_) ) - + or // A typedef of a type that refers to T uses T. - or exists(TypeDeclarationEntry tde | - tde.getDeclaration().(TypedefType).getBaseType().refersTo(this) - and result = tde + exists(TypeDeclarationEntry tde | + tde.getDeclaration().(TypedefType).getBaseType().refersTo(this) and + result = tde ) - + or // Using something declared within a type that refers to T uses T. - or exists(UsingDeclarationEntry ude | - ude.getDeclaration().getDeclaringType().refersTo(this) - and result = ude + exists(UsingDeclarationEntry ude | + ude.getDeclaration().getDeclaringType().refersTo(this) and + result = ude ) - + or // The declaration of a variable with a type that refers to T uses T. We exclude declarations within // instantiations, since those do not appear directly in the source. - or exists(VariableDeclarationEntry vde | - vde.getType().refersTo(this) - and result = vde - and not exists(LocalScopeVariable sv | sv = vde.getDeclaration() and sv.getFunction().isConstructedFrom(_)) - and not exists(MemberVariable mv | mv = vde.getDeclaration() and mv.getDeclaringType() instanceof ClassTemplateInstantiation) + exists(VariableDeclarationEntry vde | + vde.getType().refersTo(this) and + result = vde and + not exists(LocalScopeVariable sv | + sv = vde.getDeclaration() and sv.getFunction().isConstructedFrom(_) + ) and + not exists(MemberVariable mv | + mv = vde.getDeclaration() and mv.getDeclaringType() instanceof ClassTemplateInstantiation + ) ) } /** * Holds if this type involves a reference. */ - predicate involvesReference() { - none() - } + predicate involvesReference() { none() } /** * Holds if this type involves a template parameter. */ - predicate involvesTemplateParameter() { - none() - } + predicate involvesTemplateParameter() { none() } /** * Gets this type with any typedefs resolved. For example, given @@ -284,17 +273,13 @@ class Type extends Locatable, @type { * Note that this will only work if the resolved type actually appears * on its own elsewhere in the program. */ - Type resolveTypedefs() { - result = this - } + Type resolveTypedefs() { result = this } /** * Gets the type stripped of pointers, references and cv-qualifiers, and resolving typedefs. * For example, given `typedef const C& T`, `stripType` returns `C`. */ - Type stripType() { - result = this - } + Type stripType() { result = this } override Location getLocation() { suppressUnusedThis(this) and @@ -308,7 +293,7 @@ class Type extends Locatable, @type { class BuiltInType extends Type, @builtintype { override string toString() { result = this.getName() } - override string getName() { builtintypes(underlyingElement(this),result,_,_,_,_) } + override string getName() { builtintypes(underlyingElement(this), result, _, _, _, _) } override string explain() { result = this.getName() } @@ -319,8 +304,7 @@ class BuiltInType extends Type, @builtintype { * An erroneous type. */ class ErroneousType extends BuiltInType { - - ErroneousType() { builtintypes(underlyingElement(this),_,1,_,_,_) } + ErroneousType() { builtintypes(underlyingElement(this), _, 1, _, _, _) } override string getCanonicalQLClass() { result = "ErroneousType" } } @@ -329,33 +313,39 @@ class ErroneousType extends BuiltInType { * The unknown type. */ class UnknownType extends BuiltInType { - - UnknownType() { builtintypes(underlyingElement(this),_,2,_,_,_) } + UnknownType() { builtintypes(underlyingElement(this), _, 2, _, _, _) } override string getCanonicalQLClass() { result = "UnknownType" } } private predicate isArithmeticType(@builtintype type, int kind) { builtintypes(type, _, kind, _, _, _) and - (kind >= 4) and - (kind != 34) // Exclude decltype(nullptr) + kind >= 4 and + kind != 34 // Exclude decltype(nullptr) } /** * The C/C++ arithmetic types. See 4.1.1. */ class ArithmeticType extends BuiltInType { - ArithmeticType() { - isArithmeticType(underlyingElement(this), _) - } + ArithmeticType() { isArithmeticType(underlyingElement(this), _) } override string getCanonicalQLClass() { result = "ArithmeticType" } } private predicate isIntegralType(@builtintype type, int kind) { isArithmeticType(type, kind) and - (kind < 24 or kind = 33 or (35 <= kind and kind <= 37) or - kind = 43 or kind = 44) + ( + kind < 24 + or + kind = 33 + or + 35 <= kind and kind <= 37 + or + kind = 43 + or + kind = 44 + ) } /** @@ -390,28 +380,49 @@ class IntegralOrEnumType extends Type { * signed: The explicitly signed form of the type. */ private predicate integralTypeMapping(int original, int canonical, int unsigned, int signed) { - original = 4 and canonical = 4 and unsigned = -1 and signed = -1 // bool - or original = 5 and canonical = 5 and unsigned = 6 and signed = 7 // char - or original = 6 and canonical = 6 and unsigned = 6 and signed = 7 // unsigned char - or original = 7 and canonical = 7 and unsigned = 6 and signed = 7 // signed char - or original = 8 and canonical = 8 and unsigned = 9 and signed = 10 // short - or original = 9 and canonical = 9 and unsigned = 9 and signed = 10 // unsigned short - or original = 10 and canonical = 8 and unsigned = 9 and signed = 10 // signed short - or original = 11 and canonical = 11 and unsigned = 12 and signed = 13 // int - or original = 12 and canonical = 12 and unsigned = 12 and signed = 13 // unsigned int - or original = 13 and canonical = 11 and unsigned = 12 and signed = 13 // signed int - or original = 14 and canonical = 14 and unsigned = 15 and signed = 16 // long - or original = 15 and canonical = 15 and unsigned = 15 and signed = 16 // unsigned long - or original = 16 and canonical = 14 and unsigned = 15 and signed = 16 // signed long - or original = 17 and canonical = 17 and unsigned = 18 and signed = 19 // long long - or original = 18 and canonical = 18 and unsigned = 18 and signed = 19 // unsigned long long - or original = 19 and canonical = 17 and unsigned = 18 and signed = 19 // signed long long - or original = 33 and canonical = 33 and unsigned = -1 and signed = -1 // wchar_t - or original = 35 and canonical = 35 and unsigned = 36 and signed = 37 // __int128 - or original = 36 and canonical = 36 and unsigned = 36 and signed = 37 // unsigned __int128 - or original = 37 and canonical = 35 and unsigned = 36 and signed = 37 // signed __int128 - or original = 43 and canonical = 43 and unsigned = -1 and signed = -1 // char16_t - or original = 44 and canonical = 44 and unsigned = -1 and signed = -1 // char32_t + original = 4 and canonical = 4 and unsigned = -1 and signed = -1 // bool + or + original = 5 and canonical = 5 and unsigned = 6 and signed = 7 // char + or + original = 6 and canonical = 6 and unsigned = 6 and signed = 7 // unsigned char + or + original = 7 and canonical = 7 and unsigned = 6 and signed = 7 // signed char + or + original = 8 and canonical = 8 and unsigned = 9 and signed = 10 // short + or + original = 9 and canonical = 9 and unsigned = 9 and signed = 10 // unsigned short + or + original = 10 and canonical = 8 and unsigned = 9 and signed = 10 // signed short + or + original = 11 and canonical = 11 and unsigned = 12 and signed = 13 // int + or + original = 12 and canonical = 12 and unsigned = 12 and signed = 13 // unsigned int + or + original = 13 and canonical = 11 and unsigned = 12 and signed = 13 // signed int + or + original = 14 and canonical = 14 and unsigned = 15 and signed = 16 // long + or + original = 15 and canonical = 15 and unsigned = 15 and signed = 16 // unsigned long + or + original = 16 and canonical = 14 and unsigned = 15 and signed = 16 // signed long + or + original = 17 and canonical = 17 and unsigned = 18 and signed = 19 // long long + or + original = 18 and canonical = 18 and unsigned = 18 and signed = 19 // unsigned long long + or + original = 19 and canonical = 17 and unsigned = 18 and signed = 19 // signed long long + or + original = 33 and canonical = 33 and unsigned = -1 and signed = -1 // wchar_t + or + original = 35 and canonical = 35 and unsigned = 36 and signed = 37 // __int128 + or + original = 36 and canonical = 36 and unsigned = 36 and signed = 37 // unsigned __int128 + or + original = 37 and canonical = 35 and unsigned = 36 and signed = 37 // signed __int128 + or + original = 43 and canonical = 43 and unsigned = -1 and signed = -1 // char16_t + or + original = 44 and canonical = 44 and unsigned = -1 and signed = -1 // char32_t } /** @@ -420,39 +431,42 @@ private predicate integralTypeMapping(int original, int canonical, int unsigned, class IntegralType extends ArithmeticType, IntegralOrEnumType { int kind; - IntegralType() { - isIntegralType(underlyingElement(this), kind) - } + IntegralType() { isIntegralType(underlyingElement(this), kind) } /** Holds if this integral type is signed. */ - predicate isSigned() { - builtintypes(underlyingElement(this),_,_,_,-1,_) - } + predicate isSigned() { builtintypes(underlyingElement(this), _, _, _, -1, _) } /** Holds if this integral type is unsigned. */ - predicate isUnsigned() { - builtintypes(underlyingElement(this),_,_,_,1,_) - } + predicate isUnsigned() { builtintypes(underlyingElement(this), _, _, _, 1, _) } /** Holds if this integral type is explicitly signed. */ predicate isExplicitlySigned() { - builtintypes(underlyingElement(this),_,7,_,_,_) or builtintypes(underlyingElement(this),_,10,_,_,_) or builtintypes(underlyingElement(this),_,13,_,_,_) or - builtintypes(underlyingElement(this),_,16,_,_,_) or builtintypes(underlyingElement(this),_,19,_,_,_) or - builtintypes(underlyingElement(this),_,37,_,_,_) + builtintypes(underlyingElement(this), _, 7, _, _, _) or + builtintypes(underlyingElement(this), _, 10, _, _, _) or + builtintypes(underlyingElement(this), _, 13, _, _, _) or + builtintypes(underlyingElement(this), _, 16, _, _, _) or + builtintypes(underlyingElement(this), _, 19, _, _, _) or + builtintypes(underlyingElement(this), _, 37, _, _, _) } /** Holds if this integral type is explicitly unsigned. */ predicate isExplicitlyUnsigned() { - builtintypes(underlyingElement(this),_,6,_,_,_) or builtintypes(underlyingElement(this),_,9,_,_,_) or builtintypes(underlyingElement(this),_,12,_,_,_) or - builtintypes(underlyingElement(this),_,15,_,_,_) or builtintypes(underlyingElement(this),_,18,_,_,_) or - builtintypes(underlyingElement(this),_,36,_,_,_) + builtintypes(underlyingElement(this), _, 6, _, _, _) or + builtintypes(underlyingElement(this), _, 9, _, _, _) or + builtintypes(underlyingElement(this), _, 12, _, _, _) or + builtintypes(underlyingElement(this), _, 15, _, _, _) or + builtintypes(underlyingElement(this), _, 18, _, _, _) or + builtintypes(underlyingElement(this), _, 36, _, _, _) } /** Holds if this integral type is implicitly signed. */ predicate isImplicitlySigned() { - builtintypes(underlyingElement(this),_,5,_,-1,_) or builtintypes(underlyingElement(this),_,8,_,-1,_) or builtintypes(underlyingElement(this),_,11,_,-1,_) or - builtintypes(underlyingElement(this),_,14,_,-1,_) or builtintypes(underlyingElement(this),_,17,_,-1,_) or - builtintypes(underlyingElement(this),_,35,_,-1,_) + builtintypes(underlyingElement(this), _, 5, _, -1, _) or + builtintypes(underlyingElement(this), _, 8, _, -1, _) or + builtintypes(underlyingElement(this), _, 11, _, -1, _) or + builtintypes(underlyingElement(this), _, 14, _, -1, _) or + builtintypes(underlyingElement(this), _, 17, _, -1, _) or + builtintypes(underlyingElement(this), _, 35, _, -1, _) } /** @@ -486,8 +500,7 @@ class IntegralType extends ArithmeticType, IntegralOrEnumType { * The C/C++ boolean type. See 4.2. */ class BoolType extends IntegralType { - - BoolType() { builtintypes(underlyingElement(this),_,4,_,_,_) } + BoolType() { builtintypes(underlyingElement(this), _, 4, _, _, _) } override string getCanonicalQLClass() { result = "BoolType" } } @@ -501,9 +514,7 @@ abstract class CharType extends IntegralType { } * The C/C++ char type (which is different to signed char and unsigned char). */ class PlainCharType extends CharType { - PlainCharType() { - builtintypes(underlyingElement(this),_,5,_,_,_) - } + PlainCharType() { builtintypes(underlyingElement(this), _, 5, _, _, _) } override string getCanonicalQLClass() { result = "PlainCharType" } } @@ -512,9 +523,7 @@ class PlainCharType extends CharType { * The C/C++ unsigned char type (which is different to plain char, even when chars are unsigned by default). */ class UnsignedCharType extends CharType { - UnsignedCharType() { - builtintypes(underlyingElement(this),_,6,_,_,_) - } + UnsignedCharType() { builtintypes(underlyingElement(this), _, 6, _, _, _) } override string getCanonicalQLClass() { result = "UnsignedCharType" } } @@ -523,9 +532,7 @@ class UnsignedCharType extends CharType { * The C/C++ signed char type (which is different to plain char, even when chars are signed by default). */ class SignedCharType extends CharType { - SignedCharType() { - builtintypes(underlyingElement(this),_,7,_,_,_) - } + SignedCharType() { builtintypes(underlyingElement(this), _, 7, _, _, _) } override string getCanonicalQLClass() { result = "SignedCharType" } } @@ -534,9 +541,10 @@ class SignedCharType extends CharType { * The C/C++ short types. See 4.3. */ class ShortType extends IntegralType { - ShortType() { - builtintypes(underlyingElement(this),_,8,_,_,_) or builtintypes(underlyingElement(this),_,9,_,_,_) or builtintypes(underlyingElement(this),_,10,_,_,_) + builtintypes(underlyingElement(this), _, 8, _, _, _) or + builtintypes(underlyingElement(this), _, 9, _, _, _) or + builtintypes(underlyingElement(this), _, 10, _, _, _) } override string getCanonicalQLClass() { result = "ShortType" } @@ -546,9 +554,10 @@ class ShortType extends IntegralType { * The C/C++ integer types. See 4.4. */ class IntType extends IntegralType { - IntType() { - builtintypes(underlyingElement(this),_,11,_,_,_) or builtintypes(underlyingElement(this),_,12,_,_,_) or builtintypes(underlyingElement(this),_,13,_,_,_) + builtintypes(underlyingElement(this), _, 11, _, _, _) or + builtintypes(underlyingElement(this), _, 12, _, _, _) or + builtintypes(underlyingElement(this), _, 13, _, _, _) } override string getCanonicalQLClass() { result = "IntType" } @@ -558,9 +567,10 @@ class IntType extends IntegralType { * The C/C++ long types. See 4.4. */ class LongType extends IntegralType { - LongType() { - builtintypes(underlyingElement(this),_,14,_,_,_) or builtintypes(underlyingElement(this),_,15,_,_,_) or builtintypes(underlyingElement(this),_,16,_,_,_) + builtintypes(underlyingElement(this), _, 14, _, _, _) or + builtintypes(underlyingElement(this), _, 15, _, _, _) or + builtintypes(underlyingElement(this), _, 16, _, _, _) } override string getCanonicalQLClass() { result = "LongType" } @@ -570,9 +580,10 @@ class LongType extends IntegralType { * The C/C++ long long types. See 4.4. */ class LongLongType extends IntegralType { - LongLongType() { - builtintypes(underlyingElement(this),_,17,_,_,_) or builtintypes(underlyingElement(this),_,18,_,_,_) or builtintypes(underlyingElement(this),_,19,_,_,_) + builtintypes(underlyingElement(this), _, 17, _, _, _) or + builtintypes(underlyingElement(this), _, 18, _, _, _) or + builtintypes(underlyingElement(this), _, 19, _, _, _) } override string getCanonicalQLClass() { result = "LongLongType" } @@ -582,30 +593,34 @@ class LongLongType extends IntegralType { * The GNU C __int128 types. */ class Int128Type extends IntegralType { - Int128Type() { - builtintypes(underlyingElement(this),_,35,_,_,_) or builtintypes(underlyingElement(this),_,36,_,_,_) or builtintypes(underlyingElement(this),_,37,_,_,_) + builtintypes(underlyingElement(this), _, 35, _, _, _) or + builtintypes(underlyingElement(this), _, 36, _, _, _) or + builtintypes(underlyingElement(this), _, 37, _, _, _) } - } /** * The C/C++ floating point types. See 4.5. */ class FloatingPointType extends ArithmeticType { - FloatingPointType() { - exists(int kind | builtintypes(underlyingElement(this),_,kind,_,_,_) and ((kind >= 24 and kind <= 32) or (kind = 38))) + exists(int kind | + builtintypes(underlyingElement(this), _, kind, _, _, _) and + ( + kind >= 24 and kind <= 32 + or + kind = 38 + ) + ) } - } /** * The C/C++ float type. */ class FloatType extends FloatingPointType { - - FloatType() { builtintypes(underlyingElement(this),_,24,_,_,_) } + FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) } override string getCanonicalQLClass() { result = "FloatType" } } @@ -614,8 +629,7 @@ class FloatType extends FloatingPointType { * The C/C++ double type. */ class DoubleType extends FloatingPointType { - - DoubleType() { builtintypes(underlyingElement(this),_,25,_,_,_) } + DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) } override string getCanonicalQLClass() { result = "DoubleType" } } @@ -624,8 +638,7 @@ class DoubleType extends FloatingPointType { * The C/C++ long double type. */ class LongDoubleType extends FloatingPointType { - - LongDoubleType() { builtintypes(underlyingElement(this),_,26,_,_,_) } + LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) } override string getCanonicalQLClass() { result = "LongDoubleType" } } @@ -634,58 +647,48 @@ class LongDoubleType extends FloatingPointType { * The GNU C __float128 type. */ class Float128Type extends FloatingPointType { - - Float128Type() { builtintypes(underlyingElement(this),_,38,_,_,_) } - + Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) } } /** * The GNU C _Decimal32 type. */ class Decimal32Type extends FloatingPointType { - - Decimal32Type() { builtintypes(underlyingElement(this),_,40,_,_,_) } - + Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) } } /** * The GNU C _Decimal64 type. */ class Decimal64Type extends FloatingPointType { - - Decimal64Type() { builtintypes(underlyingElement(this),_,41,_,_,_) } - + Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) } } /** * The GNU C _Decimal128 type. */ class Decimal128Type extends FloatingPointType { - - Decimal128Type() { builtintypes(underlyingElement(this),_,42,_,_,_) } - + Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) } } /** * The C/C++ void type. See 4.7. */ class VoidType extends BuiltInType { - - VoidType() { builtintypes(underlyingElement(this),_,3,_,_,_) } + VoidType() { builtintypes(underlyingElement(this), _, 3, _, _, _) } override string getCanonicalQLClass() { result = "VoidType" } } /** * The C/C++ wide character type. - * + * * Note that on some platforms `wchar_t` doesn't exist as a built-in * type but a typedef is provided. Consider using the `Wchar_t` QL * class to include these types. */ class WideCharType extends IntegralType { - - WideCharType() { builtintypes(underlyingElement(this),_,33,_,_,_) } + WideCharType() { builtintypes(underlyingElement(this), _, 33, _, _, _) } override string getCanonicalQLClass() { result = "WideCharType" } } @@ -694,8 +697,7 @@ class WideCharType extends IntegralType { * The C/C++ `char16_t` type. */ class Char16Type extends IntegralType { - - Char16Type() { builtintypes(underlyingElement(this),_,43,_,_,_) } + Char16Type() { builtintypes(underlyingElement(this), _, 43, _, _, _) } override string getCanonicalQLClass() { result = "Char16Type" } } @@ -704,8 +706,7 @@ class Char16Type extends IntegralType { * The C/C++ `char32_t` type. */ class Char32Type extends IntegralType { - - Char32Type() { builtintypes(underlyingElement(this),_,44,_,_,_) } + Char32Type() { builtintypes(underlyingElement(this), _, 44, _, _, _) } override string getCanonicalQLClass() { result = "Char32Type" } } @@ -720,7 +721,7 @@ class Char32Type extends IntegralType { * Instead, this is the unspeakable type given by `decltype(nullptr)`. */ class NullPointerType extends BuiltInType { - NullPointerType() { builtintypes(underlyingElement(this),_,34,_,_,_) } + NullPointerType() { builtintypes(underlyingElement(this), _, 34, _, _, _) } override string getCanonicalQLClass() { result = "NullPointerType" } } @@ -734,7 +735,7 @@ class NullPointerType extends BuiltInType { class DerivedType extends Type, @derivedtype { override string toString() { result = this.getName() } - override string getName() { derivedtypes(underlyingElement(this),result,_,_) } + override string getName() { derivedtypes(underlyingElement(this), result, _, _) } /** * Gets the base type of this derived type. @@ -742,21 +743,15 @@ class DerivedType extends Type, @derivedtype { * This predicate strips off one level of decoration from a type. For example, it returns `char*` for the PointerType `char**`, * `const int` for the ReferenceType `const int&`, and `long` for the SpecifiedType `volatile long`. */ - Type getBaseType() { derivedtypes(underlyingElement(this),_,_,unresolveElement(result)) } + Type getBaseType() { derivedtypes(underlyingElement(this), _, _, unresolveElement(result)) } override predicate refersToDirectly(Type t) { t = this.getBaseType() } - override predicate involvesReference() { - getBaseType().involvesReference() - } + override predicate involvesReference() { getBaseType().involvesReference() } - override predicate involvesTemplateParameter() { - getBaseType().involvesTemplateParameter() - } + override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } - override Type stripType() { - result = getBaseType().stripType() - } + override Type stripType() { result = getBaseType().stripType() } predicate isAutoReleasing() { this.hasSpecifier("__autoreleasing") or @@ -783,20 +778,15 @@ class DerivedType extends Type, @derivedtype { * An instance of the C++11 decltype operator. */ class Decltype extends Type, @decltype { - /** * The expression whose type is being obtained by this decltype. */ - Expr getExpr() { - decltypes(underlyingElement(this), unresolveElement(result), _, _) - } + Expr getExpr() { decltypes(underlyingElement(this), unresolveElement(result), _, _) } /** * The type immediately yielded by this decltype. */ - Type getBaseType() { - decltypes(underlyingElement(this), _, unresolveElement(result), _) - } + Type getBaseType() { decltypes(underlyingElement(this), _, unresolveElement(result), _) } override string getCanonicalQLClass() { result = "Decltype" } @@ -810,69 +800,39 @@ class Decltype extends Type, @decltype { * decltype((a->x)); // type is const double& * Consult the C++11 standard for more details. */ - predicate parenthesesWouldChangeMeaning() { - decltypes(underlyingElement(this), _, _, true) - } + predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) } - override Type getUnderlyingType() { - result = getBaseType().getUnderlyingType() - } + override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() } - override Type stripTopLevelSpecifiers() { - result = getBaseType().stripTopLevelSpecifiers() - } + override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } - override Type stripType() { - result = getBaseType().stripType() - } + override Type stripType() { result = getBaseType().stripType() } - override Type resolveTypedefs() { - result = getBaseType().resolveTypedefs() - } + override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() } - override Location getLocation() { - result = getExpr().getLocation() - } + override Location getLocation() { result = getExpr().getLocation() } - override string toString() { - result = "decltype(...)" - } + override string toString() { result = "decltype(...)" } - override string getName() { - none() - } + override string getName() { none() } - override int getSize() { - result = getBaseType().getSize() - } + override int getSize() { result = getBaseType().getSize() } - override int getAlignment() { - result = getBaseType().getAlignment() - } + override int getAlignment() { result = getBaseType().getAlignment() } - override int getPointerIndirectionLevel() { - result = getBaseType().getPointerIndirectionLevel() - } + override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } override string explain() { result = "decltype resulting in {" + this.getBaseType().explain() + "}" } - override predicate involvesReference() { - getBaseType().involvesReference() - } + override predicate involvesReference() { getBaseType().involvesReference() } - override predicate involvesTemplateParameter() { - getBaseType().involvesTemplateParameter() - } + override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } - override predicate isDeeplyConst() { - this.getBaseType().isDeeplyConst() - } + override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() } - override predicate isDeeplyConstBelow() { - this.getBaseType().isDeeplyConstBelow() - } + override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConstBelow() } override Specifier internal_getAnAdditionalSpecifier() { result = this.getBaseType().getASpecifier() @@ -883,8 +843,7 @@ class Decltype extends Type, @decltype { * A C/C++ pointer type. See 4.9.1. */ class PointerType extends DerivedType { - - PointerType() { derivedtypes(underlyingElement(this),_,1,_) } + PointerType() { derivedtypes(underlyingElement(this), _, 1, _) } override string getCanonicalQLClass() { result = "PointerType" } @@ -908,14 +867,13 @@ class PointerType extends DerivedType { * To distinguish between them, use the LValueReferenceType and RValueReferenceType classes. */ class ReferenceType extends DerivedType { - - ReferenceType() { derivedtypes(underlyingElement(this),_,2,_) or derivedtypes(underlyingElement(this),_,8,_) } + ReferenceType() { + derivedtypes(underlyingElement(this), _, 2, _) or derivedtypes(underlyingElement(this), _, 8, _) + } override string getCanonicalQLClass() { result = "ReferenceType" } - override int getPointerIndirectionLevel() { - result = getBaseType().getPointerIndirectionLevel() - } + override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } override string explain() { result = "reference to {" + this.getBaseType().explain() + "}" } @@ -923,9 +881,7 @@ class ReferenceType extends DerivedType { override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } - override predicate involvesReference() { - any() - } + override predicate involvesReference() { any() } override Type resolveTypedefs() { result.(ReferenceType).getBaseType() = getBaseType().resolveTypedefs() @@ -936,7 +892,7 @@ class ReferenceType extends DerivedType { * A C++11 lvalue reference type (e.g. int&). */ class LValueReferenceType extends ReferenceType { - LValueReferenceType() { derivedtypes(underlyingElement(this),_,2,_) } + LValueReferenceType() { derivedtypes(underlyingElement(this), _, 2, _) } override string getCanonicalQLClass() { result = "LValueReferenceType" } } @@ -945,7 +901,7 @@ class LValueReferenceType extends ReferenceType { * A C++11 rvalue reference type (e.g. int&&). */ class RValueReferenceType extends ReferenceType { - RValueReferenceType() { derivedtypes(underlyingElement(this),_,8,_) } + RValueReferenceType() { derivedtypes(underlyingElement(this), _, 8, _) } override string getCanonicalQLClass() { result = "RValueReferenceType" } @@ -956,8 +912,7 @@ class RValueReferenceType extends ReferenceType { * A type with specifiers. */ class SpecifiedType extends DerivedType { - - SpecifiedType() { derivedtypes(underlyingElement(this),_,3,_) } + SpecifiedType() { derivedtypes(underlyingElement(this), _, 3, _) } override string getCanonicalQLClass() { result = "SpecifiedType" } @@ -969,16 +924,20 @@ class SpecifiedType extends DerivedType { result = this.getBaseType().getPointerIndirectionLevel() } - /** Gets all the specifiers of this type as a string in a fixed order (the order - * only depends on the specifiers, not on the source program). This is intended - * for debugging queries only and is an expensive operation. */ - string getSpecifierString() { - internalSpecString(this, result, 1) + /** + * Gets all the specifiers of this type as a string in a fixed order (the order + * only depends on the specifiers, not on the source program). This is intended + * for debugging queries only and is an expensive operation. + */ + string getSpecifierString() { internalSpecString(this, result, 1) } + + override string explain() { + result = this.getSpecifierString() + "{" + this.getBaseType().explain() + "}" } - override string explain() { result = this.getSpecifierString() + "{" + this.getBaseType().explain() + "}" } - - override predicate isDeeplyConst() { this.getASpecifier().getName() = "const" and this.getBaseType().isDeeplyConstBelow() } + override predicate isDeeplyConst() { + this.getASpecifier().getName() = "const" and this.getBaseType().isDeeplyConstBelow() + } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConstBelow() } @@ -987,37 +946,34 @@ class SpecifiedType extends DerivedType { } override Type resolveTypedefs() { - result.(SpecifiedType).getBaseType() = getBaseType().resolveTypedefs() - and result.getASpecifier() = getASpecifier() + result.(SpecifiedType).getBaseType() = getBaseType().resolveTypedefs() and + result.getASpecifier() = getASpecifier() } - override Type stripTopLevelSpecifiers() { - result = getBaseType().stripTopLevelSpecifiers() - } + override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } } /** * A C/C++ array type. See 4.9.1. */ class ArrayType extends DerivedType { - - ArrayType() { derivedtypes(underlyingElement(this),_,4,_) } + ArrayType() { derivedtypes(underlyingElement(this), _, 4, _) } override string getCanonicalQLClass() { result = "ArrayType" } - - predicate hasArraySize() { arraysizes(underlyingElement(this),_,_,_) } + + predicate hasArraySize() { arraysizes(underlyingElement(this), _, _, _) } /** * Gets the number of elements in this array. Only has a result for arrays declared to be of a * constant size. See `getByteSize` for getting the number of bytes. */ - int getArraySize() { arraysizes(underlyingElement(this),result,_,_) } + int getArraySize() { arraysizes(underlyingElement(this), result, _, _) } /** * Gets the byte size of this array. Only has a result for arrays declared to be of a constant * size. See `getArraySize` for getting the number of elements. */ - int getByteSize() { arraysizes(underlyingElement(this),_,result,_) } + int getByteSize() { arraysizes(underlyingElement(this), _, result, _) } override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) } @@ -1026,15 +982,14 @@ class ArrayType extends DerivedType { * size. This predicate is a synonym for `getByteSize`. See `getArraySize` for getting the number * of elements. */ - override int getSize() { - result = this.getByteSize() - } + override int getSize() { result = this.getByteSize() } override string explain() { - if exists(this.getArraySize()) then - result = "array of " + this.getArraySize().toString() + " {" + this.getBaseType().explain() + "}" - else - result = "array of {" + this.getBaseType().explain() + "}" + if exists(this.getArraySize()) + then + result = "array of " + this.getArraySize().toString() + " {" + this.getBaseType().explain() + + "}" + else result = "array of {" + this.getBaseType().explain() + "}" } override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() } // No such thing as a const array type @@ -1052,8 +1007,7 @@ class ArrayType extends DerivedType { * an element type rather than a byte size). */ class GNUVectorType extends DerivedType { - - GNUVectorType() { derivedtypes(underlyingElement(this),_,5,_) } + GNUVectorType() { derivedtypes(underlyingElement(this), _, 5, _) } /** * Get the number of elements in this vector type. @@ -1064,7 +1018,7 @@ class GNUVectorType extends DerivedType { * the number of elements is the value in the attribute divided by the size * of a single element. */ - int getNumElements() { arraysizes(underlyingElement(this),result,_,_) } + int getNumElements() { arraysizes(underlyingElement(this), result, _, _) } override string getCanonicalQLClass() { result = "GNUVectorType" } @@ -1077,48 +1031,45 @@ class GNUVectorType extends DerivedType { * attribute, the byte size is the value in the attribute multiplied by the * byte size of a single element. */ - override int getSize() { arraysizes(underlyingElement(this),_,result,_) } + override int getSize() { arraysizes(underlyingElement(this), _, result, _) } override int getAlignment() { arraysizes(underlyingElement(this), _, _, result) } - override string explain() { result = "GNU " + getNumElements() + " element vector of {" + this.getBaseType().explain() + "}" } + override string explain() { + result = "GNU " + getNumElements() + " element vector of {" + this.getBaseType().explain() + "}" + } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } - } /** * A C/C++ pointer to function. See 7.7. */ class FunctionPointerType extends FunctionPointerIshType { - FunctionPointerType() { - derivedtypes(underlyingElement(this),_,6,_) - } + FunctionPointerType() { derivedtypes(underlyingElement(this), _, 6, _) } override string getCanonicalQLClass() { result = "FunctionPointerType" } - override int getPointerIndirectionLevel() { - result = 1 - } + override int getPointerIndirectionLevel() { result = 1 } - override string explain() { result = "pointer to {" + this.getBaseType().(RoutineType).explain() + "}" } + override string explain() { + result = "pointer to {" + this.getBaseType().(RoutineType).explain() + "}" + } } /** * A C/C++ reference to function. */ class FunctionReferenceType extends FunctionPointerIshType { - FunctionReferenceType() { - derivedtypes(underlyingElement(this),_,7,_) - } + FunctionReferenceType() { derivedtypes(underlyingElement(this), _, 7, _) } override string getCanonicalQLClass() { result = "FunctionReferenceType" } - - override int getPointerIndirectionLevel() { - result = getBaseType().getPointerIndirectionLevel() - } - override string explain() { result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}" } + override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } + + override string explain() { + result = "reference to {" + this.getBaseType().(RoutineType).explain() + "}" + } } /** @@ -1128,15 +1079,13 @@ class FunctionReferenceType extends FunctionPointerIshType { * supported by Clang, and by Apple's branch of GCC. */ class BlockType extends FunctionPointerIshType { - BlockType() { - derivedtypes(underlyingElement(this),_,10,_) - } + BlockType() { derivedtypes(underlyingElement(this), _, 10, _) } - override int getPointerIndirectionLevel() { - result = 0 - } + override int getPointerIndirectionLevel() { result = 0 } - override string explain() { result = "block of {" + this.getBaseType().(RoutineType).explain() + "}" } + override string explain() { + result = "block of {" + this.getBaseType().(RoutineType).explain() + "}" + } } /** @@ -1144,34 +1093,41 @@ class BlockType extends FunctionPointerIshType { */ class FunctionPointerIshType extends DerivedType { FunctionPointerIshType() { - derivedtypes(underlyingElement(this),_,6, _) or - derivedtypes(underlyingElement(this),_,7, _) or - derivedtypes(underlyingElement(this),_,10,_) + derivedtypes(underlyingElement(this), _, 6, _) or + derivedtypes(underlyingElement(this), _, 7, _) or + derivedtypes(underlyingElement(this), _, 10, _) } /** the return type of this function pointer type */ Type getReturnType() { - exists(RoutineType t | derivedtypes(underlyingElement(this),_,_,unresolveElement(t)) and result = t.getReturnType()) + exists(RoutineType t | + derivedtypes(underlyingElement(this), _, _, unresolveElement(t)) and + result = t.getReturnType() + ) } /** the type of the ith argument of this function pointer type */ Type getParameterType(int i) { - exists(RoutineType t | derivedtypes(underlyingElement(this),_,_,unresolveElement(t)) and result = t.getParameterType(i)) + exists(RoutineType t | + derivedtypes(underlyingElement(this), _, _, unresolveElement(t)) and + result = t.getParameterType(i) + ) } /** the type of an argument of this function pointer type */ Type getAParameterType() { - exists(RoutineType t | derivedtypes(underlyingElement(this),_,_,unresolveElement(t)) and result = t.getAParameterType()) + exists(RoutineType t | + derivedtypes(underlyingElement(this), _, _, unresolveElement(t)) and + result = t.getAParameterType() + ) } /** the number of arguments of this function pointer type */ - int getNumberOfParameters() { - result = count(int i | exists(this.getParameterType(i))) - } + int getNumberOfParameters() { result = count(int i | exists(this.getParameterType(i))) } override predicate involvesTemplateParameter() { - getReturnType().involvesTemplateParameter() - or getAParameterType().involvesTemplateParameter() + getReturnType().involvesTemplateParameter() or + getAParameterType().involvesTemplateParameter() } override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } @@ -1185,15 +1141,15 @@ class PointerToMemberType extends Type, @ptrtomember { override string toString() { result = this.getName() } override string getCanonicalQLClass() { result = "PointerToMemberType" } - + /** the name of this type */ override string getName() { result = "..:: *" } /** the base type of this pointer to member type */ - Type getBaseType() { ptrtomembers(underlyingElement(this),unresolveElement(result),_) } + Type getBaseType() { ptrtomembers(underlyingElement(this), unresolveElement(result), _) } /** the class referred by this pointer to member type */ - Type getClass() { ptrtomembers(underlyingElement(this),_,unresolveElement(result)) } + Type getClass() { ptrtomembers(underlyingElement(this), _, unresolveElement(result)) } override predicate refersToDirectly(Type t) { t = this.getBaseType() or @@ -1204,12 +1160,13 @@ class PointerToMemberType extends Type, @ptrtomember { result = 1 + this.getBaseType().getPointerIndirectionLevel() } - override string explain() { result = "pointer to member of " + this.getClass().toString() + " with type {" + this.getBaseType().explain() + "}" } - - override predicate involvesTemplateParameter() { - getBaseType().involvesTemplateParameter() + override string explain() { + result = "pointer to member of " + this.getClass().toString() + " with type {" + + this.getBaseType().explain() + "}" } + override predicate involvesTemplateParameter() { getBaseType().involvesTemplateParameter() } + override predicate isDeeplyConstBelow() { this.getBaseType().isDeeplyConst() } } @@ -1224,15 +1181,17 @@ class RoutineType extends Type, @routinetype { override string getName() { result = "..()(..)" } - Type getParameterType(int n) { routinetypeargs(underlyingElement(this),n,unresolveElement(result)) } + Type getParameterType(int n) { + routinetypeargs(underlyingElement(this), n, unresolveElement(result)) + } - Type getAParameterType() { routinetypeargs(underlyingElement(this),_,unresolveElement(result)) } + Type getAParameterType() { routinetypeargs(underlyingElement(this), _, unresolveElement(result)) } Type getReturnType() { routinetypes(underlyingElement(this), unresolveElement(result)) } override string explain() { - result = "function returning {" + this.getReturnType().explain() + - "} with arguments (" + this.explainParameters(0) + ")" + result = "function returning {" + this.getReturnType().explain() + "} with arguments (" + + this.explainParameters(0) + ")" } /** @@ -1242,13 +1201,14 @@ class RoutineType extends Type, @routinetype { * The integer argument is the index of the first parameter to explain. */ private string explainParameters(int i) { - (i = 0 and result = "" and not exists(this.getAParameterType())) + i = 0 and result = "" and not exists(this.getAParameterType()) or ( exists(this.getParameterType(i)) and - if i < max(int j | exists(this.getParameterType(j))) then + if i < max(int j | exists(this.getParameterType(j))) + then // Not the last one - result = this.getParameterType(i).explain() + "," + this.explainParameters(i+1) + result = this.getParameterType(i).explain() + "," + this.explainParameters(i + 1) else // Last parameter result = this.getParameterType(i).explain() @@ -1265,42 +1225,37 @@ class RoutineType extends Type, @routinetype { override predicate isDeeplyConstBelow() { none() } // Current limitation: no such thing as a const routine type override predicate involvesTemplateParameter() { - getReturnType().involvesTemplateParameter() - or getAParameterType().involvesTemplateParameter() + getReturnType().involvesTemplateParameter() or + getAParameterType().involvesTemplateParameter() } } /** * A C++ typename template parameter. */ -class TemplateParameter extends UserType -{ - TemplateParameter() { usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8) } +class TemplateParameter extends UserType { + TemplateParameter() { + usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8) + } override string getCanonicalQLClass() { result = "TemplateParameter" } - override predicate involvesTemplateParameter() { - any() - } + override predicate involvesTemplateParameter() { any() } } /** A C++ template template parameter, e.g. template <template <typename,typename> class T>. */ -class TemplateTemplateParameter extends TemplateParameter -{ - TemplateTemplateParameter() { - usertypes(underlyingElement(this), _, 8) - } - +class TemplateTemplateParameter extends TemplateParameter { + TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) } + override string getCanonicalQLClass() { result = "TemplateTemplateParameter" } } /** * A type representing the use of the C++11 auto keyword. */ -class AutoType extends TemplateParameter -{ +class AutoType extends TemplateParameter { AutoType() { usertypes(underlyingElement(this), "auto", 7) } - + override string getCanonicalQLClass() { result = "AutoType" } override Location getLocation() { @@ -1312,32 +1267,37 @@ class AutoType extends TemplateParameter // // Internal implementation predicates // - -private predicate allSpecifiers(int i, string s) { - s = rank[i](string t | specifiers(_, t) | t) -} +private predicate allSpecifiers(int i, string s) { s = rank[i](string t | specifiers(_, t) | t) } private predicate internalSpecString(Type t, string res, int i) { - (if allSpecifiers(i, t.getASpecifier().getName()) - then exists(string spec, string rest - | allSpecifiers(i, spec) and res = spec + " " + rest - and internalSpecString(t, rest, i+1)) - else (allSpecifiers(i, _) and internalSpecString(t, res, i+1))) - or (i = count(Specifier s) + 1 and res = "") + ( + if allSpecifiers(i, t.getASpecifier().getName()) + then + exists(string spec, string rest | + allSpecifiers(i, spec) and + res = spec + " " + rest and + internalSpecString(t, rest, i + 1) + ) + else ( + allSpecifiers(i, _) and internalSpecString(t, res, i + 1) + ) + ) + or + i = count(Specifier s) + 1 and res = "" } private predicate suppressUnusedThis(Type t) { any() } /** A source code location referring to a type */ class TypeMention extends Locatable, @type_mention { - override string toString() {result = "type mention"} - + override string toString() { result = "type mention" } + override string getCanonicalQLClass() { result = "TypeMention" } - + /** * Gets the type being referenced by this type mention. */ Type getMentionedType() { type_mentions(underlyingElement(this), unresolveElement(result), _, _) } - - override Location getLocation() { type_mentions(underlyingElement(this), _, result, _)} + + override Location getLocation() { type_mentions(underlyingElement(this), _, result, _) } } diff --git a/cpp/ql/src/semmle/code/cpp/TypedefType.qll b/cpp/ql/src/semmle/code/cpp/TypedefType.qll index 257211e224d..b7fd5f294fa 100644 --- a/cpp/ql/src/semmle/code/cpp/TypedefType.qll +++ b/cpp/ql/src/semmle/code/cpp/TypedefType.qll @@ -5,21 +5,18 @@ private import semmle.code.cpp.internal.ResolveClass * A C/C++ typedef type. See 4.9.1. */ class TypedefType extends UserType { - - TypedefType() { usertypes(underlyingElement(this),_,5) } + TypedefType() { usertypes(underlyingElement(this), _, 5) } override string getCanonicalQLClass() { result = "TypedefType" } - + /** * Gets the base type of this typedef type. */ - Type getBaseType() { typedefbase(underlyingElement(this),unresolveElement(result)) } + Type getBaseType() { typedefbase(underlyingElement(this), unresolveElement(result)) } override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() } - override Type stripTopLevelSpecifiers() { - result = getBaseType().stripTopLevelSpecifiers() - } + override Type stripTopLevelSpecifiers() { result = getBaseType().stripTopLevelSpecifiers() } override int getSize() { result = this.getBaseType().getSize() } @@ -29,7 +26,9 @@ class TypedefType extends UserType { result = this.getBaseType().getPointerIndirectionLevel() } - override string explain() { result = "typedef {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\"" } + override string explain() { + result = "typedef {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\"" + } override predicate isDeeplyConst() { this.getBaseType().isDeeplyConst() } // Just an alias @@ -39,26 +38,18 @@ class TypedefType extends UserType { result = this.getBaseType().getASpecifier() } - override predicate involvesReference() { - getBaseType().involvesReference() - } + override predicate involvesReference() { getBaseType().involvesReference() } - override Type resolveTypedefs() { - result = getBaseType().resolveTypedefs() - } + override Type resolveTypedefs() { result = getBaseType().resolveTypedefs() } - override Type stripType() { - result = getBaseType().stripType() - } + override Type stripType() { result = getBaseType().stripType() } } /** * A C++ typedef type that is directly enclosed by a function. */ class LocalTypedefType extends TypedefType { - LocalTypedefType() { - isLocal() - } + LocalTypedefType() { isLocal() } override string getCanonicalQLClass() { result = "LocalTypedefType" } } @@ -67,9 +58,7 @@ class LocalTypedefType extends TypedefType { * A C++ typedef type that is directly enclosed by a class, struct or union. */ class NestedTypedefType extends TypedefType { - NestedTypedefType() { - this.isMember() - } + NestedTypedefType() { this.isMember() } override string getCanonicalQLClass() { result = "NestedTypedefType" } diff --git a/cpp/ql/src/semmle/code/cpp/Union.qll b/cpp/ql/src/semmle/code/cpp/Union.qll index 0cbffc5dfd2..f1c033438ba 100644 --- a/cpp/ql/src/semmle/code/cpp/Union.qll +++ b/cpp/ql/src/semmle/code/cpp/Union.qll @@ -10,16 +10,14 @@ import semmle.code.cpp.Struct * }; * ``` */ -class Union extends Struct { - - Union() { usertypes(underlyingElement(this),_,3) } +class Union extends Struct { + Union() { usertypes(underlyingElement(this), _, 3) } override string getCanonicalQLClass() { result = "Union" } - override string explain() { result = "union " + this.getName() } + override string explain() { result = "union " + this.getName() } override predicate isDeeplyConstBelow() { any() } // No subparts - } /** @@ -35,9 +33,7 @@ class Union extends Struct { * ``` */ class LocalUnion extends Union { - LocalUnion() { - isLocal() - } + LocalUnion() { isLocal() } override string getCanonicalQLClass() { result = "LocalUnion" } } @@ -55,9 +51,7 @@ class LocalUnion extends Union { * ``` */ class NestedUnion extends Union { - NestedUnion() { - this.isMember() - } + NestedUnion() { this.isMember() } override string getCanonicalQLClass() { result = "NestedUnion" } @@ -69,5 +63,4 @@ class NestedUnion extends Union { /** Holds if this member is public. */ predicate isPublic() { this.hasSpecifier("public") } - } diff --git a/cpp/ql/src/semmle/code/cpp/UserType.qll b/cpp/ql/src/semmle/code/cpp/UserType.qll index 2d6e9514229..e41d3ecd664 100644 --- a/cpp/ql/src/semmle/code/cpp/UserType.qll +++ b/cpp/ql/src/semmle/code/cpp/UserType.qll @@ -12,7 +12,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ /** * Gets the name of this type. */ - override string getName() { usertypes(underlyingElement(this),result,_) } + override string getName() { usertypes(underlyingElement(this), result, _) } override string getCanonicalQLClass() { result = "UserType" } @@ -20,43 +20,30 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ * Gets the simple name of this type, without any template parameters. For example * if the name of the type is `"myType"`, the simple name is just `"myType"`. */ - string getSimpleName() { - result = getName().regexpReplaceAll("<.*", "") - } + string getSimpleName() { result = getName().regexpReplaceAll("<.*", "") } - override predicate hasName(string name) { - usertypes(underlyingElement(this),name,_) - } + override predicate hasName(string name) { usertypes(underlyingElement(this), name, _) } /** Holds if this type is anonymous. */ - predicate isAnonymous() { - getName().matches("(unnamed%") - } + predicate isAnonymous() { getName().matches("(unnamed%") } - override predicate hasSpecifier(string s) { - Type.super.hasSpecifier(s) - } - override Specifier getASpecifier() { - result = Type.super.getASpecifier() - } + override predicate hasSpecifier(string s) { Type.super.hasSpecifier(s) } + + override Specifier getASpecifier() { result = Type.super.getASpecifier() } override Location getLocation() { - if isDefined() then - result = this.getDefinitionLocation() - else - result = this.getADeclarationLocation() + if isDefined() + then result = this.getDefinitionLocation() + else result = this.getADeclarationLocation() } override TypeDeclarationEntry getADeclarationEntry() { - if type_decls(_, underlyingElement(this), _) then - type_decls(unresolveElement(result), underlyingElement(this), _) - else - exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry()) + if type_decls(_, underlyingElement(this), _) + then type_decls(unresolveElement(result), underlyingElement(this), _) + else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry()) } - override Location getADeclarationLocation() { - result = getADeclarationEntry().getLocation() - } + override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } override TypeDeclarationEntry getDefinition() { result = getADeclarationEntry() and @@ -64,26 +51,26 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ } override Location getDefinitionLocation() { - if exists(getDefinition()) then - result = getDefinition().getLocation() + if exists(getDefinition()) + then result = getDefinition().getLocation() else - exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation()) + exists(Class t | + this.(Class).isConstructedFrom(t) and result = t.getDefinition().getLocation() + ) } /** * Gets the function that directly encloses this type (if any). */ Function getEnclosingFunction() { - enclosingfunction(underlyingElement(this),unresolveElement(result)) + enclosingfunction(underlyingElement(this), unresolveElement(result)) } /** * Holds if this is a local type (that is, a type that has a directly-enclosing * function). */ - predicate isLocal() { - exists(getEnclosingFunction()) - } + predicate isLocal() { exists(getEnclosingFunction()) } /* * Dummy implementations of inherited methods. This class must not be @@ -96,9 +83,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ override string explain() { result = this.getName() } // further overridden in LocalClass - override AccessHolder getEnclosingAccessHolder() { - result = this.getDeclaringType() - } + override AccessHolder getEnclosingAccessHolder() { result = this.getDeclaringType() } } /** @@ -106,6 +91,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ */ class TypeDeclarationEntry extends DeclarationEntry, @type_decl { override UserType getDeclaration() { result = getType() } + override string getName() { result = getType().getName() } override string getCanonicalQLClass() { result = "TypeDeclarationEntry" } @@ -113,10 +99,12 @@ class TypeDeclarationEntry extends DeclarationEntry, @type_decl { /** * The type which is being declared or defined. */ - override Type getType() { type_decls(underlyingElement(this),unresolveElement(result),_) } + override Type getType() { type_decls(underlyingElement(this), unresolveElement(result), _) } + + override Location getLocation() { type_decls(underlyingElement(this), _, result) } - override Location getLocation() { type_decls(underlyingElement(this),_,result) } override predicate isDefinition() { type_def(underlyingElement(this)) } + override string getASpecifier() { none() } /** diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 9d350ae8c3e..1269efcbeaf 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -14,7 +14,6 @@ private import semmle.code.cpp.internal.ResolveClass * can have multiple declarations. */ class Variable extends Declaration, @variable { - /** Gets the initializer of this variable, if any. */ Initializer getInitializer() { result.getDeclaration() = this } @@ -30,10 +29,12 @@ class Variable extends Declaration, @variable { * this variable, such as `const` and `volatile`, are instead accessed * through `this.getType().getASpecifier()`. */ - override Specifier getASpecifier() { varspecifiers(underlyingElement(this),unresolveElement(result)) } + override Specifier getASpecifier() { + varspecifiers(underlyingElement(this), unresolveElement(result)) + } /** Gets an attribute of this variable. */ - Attribute getAnAttribute() { varattributes(underlyingElement(this),unresolveElement(result)) } + Attribute getAnAttribute() { varattributes(underlyingElement(this), unresolveElement(result)) } /** Holds if this variable is `const`. */ predicate isConst() { this.getType().isConst() } @@ -50,7 +51,7 @@ class Variable extends Declaration, @variable { /** Gets the type of this variable, after typedefs have been resolved. */ Type getUnderlyingType() { result = this.getType().getUnderlyingType() } - /** + /** * Gets the type of this variable, after specifiers have been deeply * stripped and typedefs have been resolved. */ @@ -81,28 +82,21 @@ class Variable extends Declaration, @variable { */ predicate declaredUsingAutoType() { autoderivation(underlyingElement(this), _) } - override VariableDeclarationEntry getADeclarationEntry() { - result.getDeclaration() = this - } + override VariableDeclarationEntry getADeclarationEntry() { result.getDeclaration() = this } - override Location getADeclarationLocation() { - result = getADeclarationEntry().getLocation() - } + override Location getADeclarationLocation() { result = getADeclarationEntry().getLocation() } override VariableDeclarationEntry getDefinition() { result = getADeclarationEntry() and result.isDefinition() } - override Location getDefinitionLocation() { - result = getDefinition().getLocation() - } + override Location getDefinitionLocation() { result = getDefinition().getLocation() } override Location getLocation() { - if exists(getDefinition()) then - result = this.getDefinitionLocation() - else - result = this.getADeclarationLocation() + if exists(getDefinition()) + then result = this.getDefinitionLocation() + else result = this.getADeclarationLocation() } /** @@ -112,11 +106,9 @@ class Variable extends Declaration, @variable { Expr getAnAssignedValue() { result = this.getInitializer().getExpr() or - exists (ConstructorFieldInit cfi - | cfi.getTarget() = this and result = cfi.getExpr()) + exists(ConstructorFieldInit cfi | cfi.getTarget() = this and result = cfi.getExpr()) or - exists (AssignExpr ae - | ae.getLValue().(Access).getTarget() = this and result = ae.getRValue()) + exists(AssignExpr ae | ae.getLValue().(Access).getTarget() = this and result = ae.getRValue()) or exists(AggregateLiteral l | this.getDeclaringType() = l.getType() and @@ -128,23 +120,17 @@ class Variable extends Declaration, @variable { * Gets an assignment expression that assigns to this variable. * For example: `x=...` or `x+=...`. */ - Assignment getAnAssignment() { - result.getLValue() = this.getAnAccess() - } + Assignment getAnAssignment() { result.getLValue() = this.getAnAccess() } /** * Holds if this variable is `constexpr`. */ - predicate isConstexpr() { - this.hasSpecifier("is_constexpr") - } + predicate isConstexpr() { this.hasSpecifier("is_constexpr") } /** * Holds if this variable is `thread_local`. */ - predicate isThreadLocal() { - this.hasSpecifier("is_thread_local") - } + predicate isThreadLocal() { this.hasSpecifier("is_thread_local") } /** * Holds if this variable is constructed from `v` as a result @@ -182,11 +168,11 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl { override Variable getDeclaration() { result = getVariable() } override string getCanonicalQLClass() { result = "VariableDeclarationEntry" } - + /** * Gets the variable which is being declared or defined. */ - Variable getVariable() { var_decls(underlyingElement(this),unresolveElement(result),_,_,_) } + Variable getVariable() { var_decls(underlyingElement(this), unresolveElement(result), _, _, _) } /** * Gets the name, if any, used for the variable at this declaration or @@ -205,14 +191,14 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl { * int f(int y) { return y; } * ``` */ - override string getName() { var_decls(underlyingElement(this),_,_,result,_) and result != "" } + override string getName() { var_decls(underlyingElement(this), _, _, result, _) and result != "" } /** * Gets the type of the variable which is being declared or defined. */ - override Type getType() { var_decls(underlyingElement(this),_,unresolveElement(result),_,_) } + override Type getType() { var_decls(underlyingElement(this), _, unresolveElement(result), _, _) } - override Location getLocation() { var_decls(underlyingElement(this),_,_,_,result) } + override Location getLocation() { var_decls(underlyingElement(this), _, _, _, result) } /** * Holds if this is a definition of a variable. @@ -224,7 +210,7 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl { */ override predicate isDefinition() { var_def(underlyingElement(this)) } - override string getASpecifier() { var_decl_specifiers(underlyingElement(this),result) } + override string getASpecifier() { var_decl_specifiers(underlyingElement(this), result) } } /** @@ -232,8 +218,8 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl { * of a C/C++ function. */ class ParameterDeclarationEntry extends VariableDeclarationEntry { - ParameterDeclarationEntry() { param_decl_bind(underlyingElement(this),_,_) } - + ParameterDeclarationEntry() { param_decl_bind(underlyingElement(this), _, _) } + override string getCanonicalQLClass() { result = "ParameterDeclarationEntry" } /** @@ -241,29 +227,31 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry { * description is part of. */ FunctionDeclarationEntry getFunctionDeclarationEntry() { - param_decl_bind(underlyingElement(this),_,unresolveElement(result)) + param_decl_bind(underlyingElement(this), _, unresolveElement(result)) } /** * Gets the zero-based index of this parameter. */ - int getIndex() { param_decl_bind(underlyingElement(this),result,_) } + int getIndex() { param_decl_bind(underlyingElement(this), result, _) } override string toString() { if exists(getName()) - then result = super.toString() - else exists (string idx - | idx = ((getIndex() + 1).toString() + "th") - .replaceAll("1th","1st") - .replaceAll("2th","2nd") - .replaceAll("3th","3rd") - .replaceAll("11st","11th") - .replaceAll("12nd","12th") - .replaceAll("13rd","13th") - | if exists(getCanonicalName()) - then result = "declaration of " + getCanonicalName() + - " as anonymous " + idx + " parameter" - else result = "declaration of " + idx + " parameter") + then result = super.toString() + else + exists(string idx | + idx = ((getIndex() + 1).toString() + "th") + .replaceAll("1th", "1st") + .replaceAll("2th", "2nd") + .replaceAll("3th", "3rd") + .replaceAll("11st", "11th") + .replaceAll("12nd", "12th") + .replaceAll("13rd", "13th") + | + if exists(getCanonicalName()) + then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter" + else result = "declaration of " + idx + " parameter" + ) } /** @@ -273,13 +261,11 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry { */ string getTypedName() { exists(string typeString, string nameString | - if exists(getType().getName()) then typeString = getType().getName() else typeString = "" and - if exists(getName()) then nameString = getName() else nameString = "" and - if (typeString != "" and nameString != "") then ( - result = typeString + " " + nameString - ) else ( - result = typeString + nameString - ) + (if exists(getType().getName()) then typeString = getType().getName() else typeString = "") and + (if exists(getName()) then nameString = getName() else nameString = "") and + if typeString != "" and nameString != "" + then result = typeString + " " + nameString + else result = typeString + nameString ) } } @@ -299,9 +285,8 @@ class LocalScopeVariable extends Variable, @localscopevariable { */ deprecated class StackVariable extends Variable { StackVariable() { this instanceof LocalScopeVariable } - Function getFunction() { - result = this.(LocalScopeVariable).getFunction() - } + + Function getFunction() { result = this.(LocalScopeVariable).getFunction() } } /** @@ -313,12 +298,13 @@ deprecated class StackVariable extends Variable { * A local variable can be declared by a `DeclStmt` or a `ConditionDeclExpr`. */ class LocalVariable extends LocalScopeVariable, @localvariable { - override string getName() { localvariables(underlyingElement(this),_,result) } + override string getName() { localvariables(underlyingElement(this), _, result) } - override Type getType() { localvariables(underlyingElement(this),unresolveElement(result),_) } + override Type getType() { localvariables(underlyingElement(this), unresolveElement(result), _) } override Function getFunction() { - exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result) or + exists(DeclStmt s | s.getADeclaration() = this and s.getEnclosingFunction() = result) + or exists(ConditionDeclExpr e | e.getVariable() = this and e.getEnclosingFunction() = result) } } @@ -327,9 +313,9 @@ class LocalVariable extends LocalScopeVariable, @localvariable { * A C/C++ variable which has global scope or namespace scope. */ class GlobalOrNamespaceVariable extends Variable, @globalvariable { - override string getName() { globalvariables(underlyingElement(this),_,result) } + override string getName() { globalvariables(underlyingElement(this), _, result) } - override Type getType() { globalvariables(underlyingElement(this),unresolveElement(result),_) } + override Type getType() { globalvariables(underlyingElement(this), unresolveElement(result), _) } override Element getEnclosingElement() { none() } } @@ -351,9 +337,7 @@ class NamespaceVariable extends GlobalOrNamespaceVariable { * the enclosing scope of said namespace (which may be the global scope). */ class GlobalVariable extends GlobalOrNamespaceVariable { - GlobalVariable() { - not this instanceof NamespaceVariable - } + GlobalVariable() { not this instanceof NamespaceVariable } } /** @@ -363,9 +347,7 @@ class GlobalVariable extends GlobalOrNamespaceVariable { * variables, use `Field` instead of `MemberVariable`. */ class MemberVariable extends Variable, @membervariable { - MemberVariable() { - this.isMember() - } + MemberVariable() { this.isMember() } /** Holds if this member is private. */ predicate isPrivate() { this.hasSpecifier("private") } @@ -376,36 +358,31 @@ class MemberVariable extends Variable, @membervariable { /** Holds if this member is public. */ predicate isPublic() { this.hasSpecifier("public") } - override string getName() { membervariables(underlyingElement(this),_,result) } + override string getName() { membervariables(underlyingElement(this), _, result) } override Type getType() { - if (strictcount(this.getAType()) = 1) then ( - result = this.getAType() - ) else ( - // In rare situations a member variable may have multiple types in - // different translation units. In that case, we return the unspecified - // type. - result = this.getAType().getUnspecifiedType() - ) + if strictcount(this.getAType()) = 1 + then result = this.getAType() + else + // In rare situations a member variable may have multiple types in + // different translation units. In that case, we return the unspecified + // type. + result = this.getAType().getUnspecifiedType() } /** Holds if this member is mutable. */ - predicate isMutable() { - getADeclarationEntry().hasSpecifier("mutable") - } + predicate isMutable() { getADeclarationEntry().hasSpecifier("mutable") } - private Type getAType() { membervariables(underlyingElement(this),unresolveElement(result),_) } + private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) } } /** * A C/C++ function pointer variable. * - * DEPRECATED: use `Variable.getType() instanceof FunctionPointerType` instead. + * DEPRECATED: use `Variable.getType() instanceof FunctionPointerType` instead. */ deprecated class FunctionPointerVariable extends Variable { - FunctionPointerVariable() { - this.getType() instanceof FunctionPointerType - } + FunctionPointerVariable() { this.getType() instanceof FunctionPointerType } } /** @@ -414,9 +391,7 @@ deprecated class FunctionPointerVariable extends Variable { * DEPRECATED: use `MemberVariable.getType() instanceof FunctionPointerType` instead. */ deprecated class FunctionPointerMemberVariable extends MemberVariable { - FunctionPointerMemberVariable() { - this instanceof FunctionPointerVariable - } + FunctionPointerMemberVariable() { this instanceof FunctionPointerVariable } } /** diff --git a/cpp/ql/src/semmle/code/cpp/XML.qll b/cpp/ql/src/semmle/code/cpp/XML.qll index aa9dcfb1283..76e96fa1fc0 100644 --- a/cpp/ql/src/semmle/code/cpp/XML.qll +++ b/cpp/ql/src/semmle/code/cpp/XML.qll @@ -7,15 +7,17 @@ import semmle.code.cpp.Location /** An XML element that has a location. */ abstract class XMLLocatable extends @xmllocatable { /** Gets the source location for this element. */ - Location getLocation() { xmllocations(this,result) } + Location getLocation() { xmllocations(this, result) } /** * Holds if this element has the specified location information, * including file path, start line, start column, end line and end column. */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { exists(File f, Location l | l = this.getLocation() | - locations_default(l,unresolveElement(f),startline,startcolumn,endline,endcolumn) and + locations_default(l, unresolveElement(f), startline, startcolumn, endline, endcolumn) and filepath = f.getAbsolutePath() ) } @@ -36,35 +38,31 @@ class XMLParent extends @xmlparent { abstract string getName(); /** Gets the file to which this XML parent belongs. */ - XMLFile getFile() { result = this or xmlElements(this,_,_,_,result) } + XMLFile getFile() { result = this or xmlElements(this, _, _, _, result) } /** Gets the child element at a specified index of this XML parent. */ XMLElement getChild(int index) { xmlElements(result, _, this, index, _) } /** Gets a child element of this XML parent. */ - XMLElement getAChild() { xmlElements(result,_,this,_,_) } + XMLElement getAChild() { xmlElements(result, _, this, _, _) } /** Gets a child element of this XML parent with the given `name`. */ - XMLElement getAChild(string name) { xmlElements(result,_,this,_,_) and result.hasName(name) } + XMLElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) } /** Gets a comment that is a child of this XML parent. */ - XMLComment getAComment() { xmlComments(result,_,this,_) } + XMLComment getAComment() { xmlComments(result, _, this, _) } /** Gets a character sequence that is a child of this XML parent. */ - XMLCharacters getACharactersSet() { xmlChars(result,_,this,_,_,_) } + XMLCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) } /** Gets the depth in the tree. (Overridden in XMLElement.) */ int getDepth() { result = 0 } /** Gets the number of child XML elements of this XML parent. */ - int getNumberOfChildren() { - result = count(XMLElement e | xmlElements(e,_,this,_,_)) - } + int getNumberOfChildren() { result = count(XMLElement e | xmlElements(e, _, this, _, _)) } /** Gets the number of places in the body of this XML parent where text occurs. */ - int getNumberOfCharacterSets() { - result = count(int pos | xmlChars(_,_,this,pos,_,_)) - } + int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) } /** * DEPRECATED: Internal. @@ -72,11 +70,13 @@ class XMLParent extends @xmlparent { * Append the character sequences of this XML parent from left to right, separated by a space, * up to a specified (zero-based) index. */ - deprecated - string charsSetUpTo(int n) { - (n = 0 and xmlChars(_,result,this,0,_,_)) or - (n > 0 and exists(string chars | xmlChars(_,chars,this,n,_,_) | - result = this.charsSetUpTo(n-1) + " " + chars)) + deprecated string charsSetUpTo(int n) { + n = 0 and xmlChars(_, result, this, 0, _, _) + or + n > 0 and + exists(string chars | xmlChars(_, chars, this, n, _, _) | + result = this.charsSetUpTo(n - 1) + " " + chars + ) } /** @@ -84,13 +84,15 @@ class XMLParent extends @xmlparent { * left to right, separated by a space. */ string allCharactersString() { - result = concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos) + result = concat(string chars, int pos | + xmlChars(_, chars, this, pos, _, _) + | + chars, " " order by pos + ) } /** Gets the text value contained in this XML parent. */ - string getTextValue() { - result = allCharactersString() - } + string getTextValue() { result = allCharactersString() } /** Gets a printable representation of this XML parent. */ string toString() { result = this.getName() } @@ -98,65 +100,59 @@ class XMLParent extends @xmlparent { /** An XML file. */ class XMLFile extends XMLParent, File { - XMLFile() { - xmlEncoding(this,_) - } + XMLFile() { xmlEncoding(this, _) } /** Gets a printable representation of this XML file. */ - override - string toString() { result = XMLParent.super.toString() } + override string toString() { result = XMLParent.super.toString() } /** Gets the name of this XML file. */ - override - string getName() { files(this,result,_,_,_) } + override string getName() { files(this, result, _, _, _) } /** Gets the path of this XML file. */ - string getPath() { files(this,_,result,_,_) } + string getPath() { files(this, _, result, _, _) } /** Gets the path of the folder that contains this XML file. */ string getFolder() { - result = this.getPath().substring(0, this.getPath().length()-this.getName().length()) + result = this.getPath().substring(0, this.getPath().length() - this.getName().length()) } /** Gets the encoding of this XML file. */ - string getEncoding() { xmlEncoding(this,result) } + string getEncoding() { xmlEncoding(this, result) } /** Gets the XML file itself. */ - override - XMLFile getFile() { result = this } + override XMLFile getFile() { result = this } /** Gets a top-most element in an XML file. */ XMLElement getARootElement() { result = this.getAChild() } /** Gets a DTD associated with this XML file. */ - XMLDTD getADTD() { xmlDTDs(result,_,_,_,this) } + XMLDTD getADTD() { xmlDTDs(result, _, _, _, this) } } /** A "Document Type Definition" of an XML file. */ class XMLDTD extends @xmldtd { /** Gets the name of the root element of this DTD. */ - string getRoot() { xmlDTDs(this,result,_,_,_) } + string getRoot() { xmlDTDs(this, result, _, _, _) } /** Gets the public ID of this DTD. */ - string getPublicId() { xmlDTDs(this,_,result,_,_) } + string getPublicId() { xmlDTDs(this, _, result, _, _) } /** Gets the system ID of this DTD. */ - string getSystemId() { xmlDTDs(this,_,_,result,_) } + string getSystemId() { xmlDTDs(this, _, _, result, _) } /** Holds if this DTD is public. */ - predicate isPublic() { not xmlDTDs(this,_,"",_,_) } + predicate isPublic() { not xmlDTDs(this, _, "", _, _) } /** Gets the parent of this DTD. */ - XMLParent getParent() { xmlDTDs(this,_,_,_,result) } + XMLParent getParent() { xmlDTDs(this, _, _, _, result) } /** Gets a printable representation of this DTD. */ string toString() { - (this.isPublic() and result = this.getRoot() + " PUBLIC '" + - this.getPublicId() + "' '" + - this.getSystemId() + "'") or - (not this.isPublic() and result = this.getRoot() + - " SYSTEM '" + - this.getSystemId() + "'") + this.isPublic() and + result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'" + or + not this.isPublic() and + result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'" } } @@ -166,71 +162,61 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable { predicate hasName(string name) { name = getName() } /** Gets the name of this XML element. */ - override - string getName() { xmlElements(this,result,_,_,_) } + override string getName() { xmlElements(this, result, _, _, _) } /** Gets the XML file in which this XML element occurs. */ - override - XMLFile getFile() { xmlElements(this,_,_,_,result) } + override XMLFile getFile() { xmlElements(this, _, _, _, result) } /** Gets the parent of this XML element. */ - XMLParent getParent() { xmlElements(this,_,result,_,_) } + XMLParent getParent() { xmlElements(this, _, result, _, _) } /** Gets the index of this XML element among its parent's children. */ int getIndex() { xmlElements(this, _, _, result, _) } /** Holds if this XML element has a namespace. */ - predicate hasNamespace() { xmlHasNs(this,_,_) } + predicate hasNamespace() { xmlHasNs(this, _, _) } /** Gets the namespace of this XML element, if any. */ - XMLNamespace getNamespace() { xmlHasNs(this,result,_) } + XMLNamespace getNamespace() { xmlHasNs(this, result, _) } /** Gets the index of this XML element among its parent's children. */ - int getElementPositionIndex() { xmlElements(this,_,_,result,_) } + int getElementPositionIndex() { xmlElements(this, _, _, result, _) } /** Gets the depth of this element within the XML file tree structure. */ - override - int getDepth() { result = this.getParent().getDepth() + 1 } + override int getDepth() { result = this.getParent().getDepth() + 1 } /** Gets an XML attribute of this XML element. */ XMLAttribute getAnAttribute() { result.getElement() = this } /** Gets the attribute with the specified `name`, if any. */ - XMLAttribute getAttribute(string name) { - result.getElement() = this and result.getName() = name - } + XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } /** Holds if this XML element has an attribute with the specified `name`. */ - predicate hasAttribute(string name) { - exists(XMLAttribute a| a = this.getAttribute(name)) - } + predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) } /** Gets the value of the attribute with the specified `name`, if any. */ - string getAttributeValue(string name) { - result = this.getAttribute(name).getValue() - } + string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } /** Gets a printable representation of this XML element. */ - override - string toString() { result = XMLParent.super.toString() } + override string toString() { result = XMLParent.super.toString() } } /** An attribute that occurs inside an XML element. */ class XMLAttribute extends @xmlattribute, XMLLocatable { /** Gets the name of this attribute. */ - string getName() { xmlAttrs(this,_,result,_,_,_) } + string getName() { xmlAttrs(this, _, result, _, _, _) } /** Gets the XML element to which this attribute belongs. */ - XMLElement getElement() { xmlAttrs(this,result,_,_,_,_) } + XMLElement getElement() { xmlAttrs(this, result, _, _, _, _) } /** Holds if this attribute has a namespace. */ - predicate hasNamespace() { xmlHasNs(this,_,_) } + predicate hasNamespace() { xmlHasNs(this, _, _) } /** Gets the namespace of this attribute, if any. */ - XMLNamespace getNamespace() { xmlHasNs(this,result,_) } + XMLNamespace getNamespace() { xmlHasNs(this, result, _) } /** Gets the value of this attribute. */ - string getValue() { xmlAttrs(this,_,_,result,_,_) } + string getValue() { xmlAttrs(this, _, _, result, _, _) } /** Gets a printable representation of this XML attribute. */ override string toString() { result = this.getName() + "=" + this.getValue() } @@ -239,28 +225,29 @@ class XMLAttribute extends @xmlattribute, XMLLocatable { /** A namespace used in an XML file */ class XMLNamespace extends @xmlnamespace { /** Gets the prefix of this namespace. */ - string getPrefix() { xmlNs(this,result,_,_) } + string getPrefix() { xmlNs(this, result, _, _) } /** Gets the URI of this namespace. */ - string getURI() { xmlNs(this,_,result,_) } + string getURI() { xmlNs(this, _, result, _) } /** Holds if this namespace has no prefix. */ predicate isDefault() { this.getPrefix() = "" } /** Gets a printable representation of this XML namespace. */ string toString() { - (this.isDefault() and result = this.getURI()) or - (not this.isDefault() and result = this.getPrefix() + ":" + this.getURI()) + this.isDefault() and result = this.getURI() + or + not this.isDefault() and result = this.getPrefix() + ":" + this.getURI() } } /** A comment of the form `` is an XML comment. */ class XMLComment extends @xmlcomment, XMLLocatable { /** Gets the text content of this XML comment. */ - string getText() { xmlComments(this,result,_,_) } + string getText() { xmlComments(this, result, _, _) } /** Gets the parent of this XML comment. */ - XMLParent getParent() { xmlComments(this,_,result,_) } + XMLParent getParent() { xmlComments(this, _, result, _) } /** Gets a printable representation of this XML comment. */ override string toString() { result = this.getText() } @@ -272,13 +259,13 @@ class XMLComment extends @xmlcomment, XMLLocatable { */ class XMLCharacters extends @xmlcharacters, XMLLocatable { /** Gets the content of this character sequence. */ - string getCharacters() { xmlChars(this,result,_,_,_,_) } + string getCharacters() { xmlChars(this, result, _, _, _, _) } /** Gets the parent of this character sequence. */ - XMLParent getParent() { xmlChars(this,_,result,_,_,_) } + XMLParent getParent() { xmlChars(this, _, result, _, _, _) } /** Holds if this character sequence is CDATA. */ - predicate isCDATA() { xmlChars(this,_,_,_,1,_) } + predicate isCDATA() { xmlChars(this, _, _, _, 1, _) } /** Gets a printable representation of this XML character sequence. */ override string toString() { result = this.getCharacters() } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll index ecc82ba8147..e90aea37781 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll @@ -3,8 +3,7 @@ import cpp /** * A library routine that allocates memory. */ -predicate allocationFunction(Function f) -{ +predicate allocationFunction(Function f) { exists(string name | f.hasGlobalName(name) and ( @@ -56,51 +55,74 @@ predicate allocationFunction(Function f) /** * A call to a library routine that allocates memory. */ -predicate allocationCall(FunctionCall fc) -{ +predicate allocationCall(FunctionCall fc) { allocationFunction(fc.getTarget()) and ( // realloc(ptr, 0) only frees the pointer - fc.getTarget().hasGlobalName("realloc") implies - not fc.getArgument(1).getValue() = "0" + fc.getTarget().hasGlobalName("realloc") implies not fc.getArgument(1).getValue() = "0" ) } /** * A library routine that frees memory. */ -predicate freeFunction(Function f, int argNum) -{ +predicate freeFunction(Function f, int argNum) { exists(string name | f.hasGlobalName(name) and ( - (name = "free" and argNum = 0) or - (name = "realloc" and argNum = 0) or - (name = "ExFreePoolWithTag" and argNum = 0) or - (name = "ExFreeToLookasideListEx" and argNum = 1) or - (name = "ExFreeToPagedLookasideList" and argNum = 1) or - (name = "ExFreeToNPagedLookasideList" and argNum = 1) or - (name = "ExDeleteTimer" and argNum = 0) or - (name = "IoFreeMdl" and argNum = 0) or - (name = "IoFreeWorkItem" and argNum = 0) or - (name = "IoFreeErrorLogEntry" and argNum = 0) or - (name = "MmFreeContiguousMemory" and argNum = 0) or - (name = "MmFreeContiguousMemorySpecifyCache" and argNum = 0) or - (name = "MmFreeNonCachedMemory" and argNum = 0) or - (name = "MmFreeMappingAddress" and argNum = 0) or - (name = "MmFreePagesFromMdl" and argNum = 0) or - (name = "MmUnmapReservedMapping" and argNum = 0) or - (name = "MmUnmapLockedPages" and argNum = 0) or - (name = "LocalFree" and argNum = 0) or - (name = "GlobalFree" and argNum = 0) or - (name = "HeapFree" and argNum = 2) or - (name = "VirtualFree" and argNum = 0) or - (name = "CoTaskMemFree" and argNum = 0) or - (name = "SysFreeString" and argNum = 0) or - (name = "LocalReAlloc" and argNum = 0) or - (name = "GlobalReAlloc" and argNum = 0) or - (name = "HeapReAlloc" and argNum = 2) or - (name = "CoTaskMemRealloc" and argNum = 0) + name = "free" and argNum = 0 + or + name = "realloc" and argNum = 0 + or + name = "ExFreePoolWithTag" and argNum = 0 + or + name = "ExFreeToLookasideListEx" and argNum = 1 + or + name = "ExFreeToPagedLookasideList" and argNum = 1 + or + name = "ExFreeToNPagedLookasideList" and argNum = 1 + or + name = "ExDeleteTimer" and argNum = 0 + or + name = "IoFreeMdl" and argNum = 0 + or + name = "IoFreeWorkItem" and argNum = 0 + or + name = "IoFreeErrorLogEntry" and argNum = 0 + or + name = "MmFreeContiguousMemory" and argNum = 0 + or + name = "MmFreeContiguousMemorySpecifyCache" and argNum = 0 + or + name = "MmFreeNonCachedMemory" and argNum = 0 + or + name = "MmFreeMappingAddress" and argNum = 0 + or + name = "MmFreePagesFromMdl" and argNum = 0 + or + name = "MmUnmapReservedMapping" and argNum = 0 + or + name = "MmUnmapLockedPages" and argNum = 0 + or + name = "LocalFree" and argNum = 0 + or + name = "GlobalFree" and argNum = 0 + or + name = "HeapFree" and argNum = 2 + or + name = "VirtualFree" and argNum = 0 + or + name = "CoTaskMemFree" and argNum = 0 + or + name = "SysFreeString" and argNum = 0 + or + name = "LocalReAlloc" and argNum = 0 + or + name = "GlobalReAlloc" and argNum = 0 + or + name = "HeapReAlloc" and argNum = 2 + or + name = "CoTaskMemRealloc" and argNum = 0 ) ) } @@ -108,8 +130,7 @@ predicate freeFunction(Function f, int argNum) /** * A call to a library routine that frees memory. */ -predicate freeCall(FunctionCall fc, Expr arg) -{ +predicate freeCall(FunctionCall fc, Expr arg) { exists(int argNum | freeFunction(fc.getTarget(), argNum) and arg = fc.getArgument(argNum) @@ -119,17 +140,12 @@ predicate freeCall(FunctionCall fc, Expr arg) /** * Is e some kind of allocation or deallocation (`new`, `alloc`, `realloc`, `delete`, `free` etc)? */ -predicate isMemoryManagementExpr(Expr e) { - isAllocationExpr(e) or isDeallocationExpr(e) -} +predicate isMemoryManagementExpr(Expr e) { isAllocationExpr(e) or isDeallocationExpr(e) } /** * Is e an allocation from stdlib.h (`malloc`, `realloc` etc)? */ -predicate isStdLibAllocationExpr(Expr e) -{ - allocationCall(e) -} +predicate isStdLibAllocationExpr(Expr e) { allocationCall(e) } /** * Is e some kind of allocation (`new`, `alloc`, `realloc` etc)? @@ -144,33 +160,31 @@ predicate isAllocationExpr(Expr e) { * Is e some kind of allocation (`new`, `alloc`, `realloc` etc) with a fixed size? */ predicate isFixedSizeAllocationExpr(Expr allocExpr, int size) { -exists (FunctionCall fc, string name | fc = allocExpr and name = fc.getTarget().getName() | - ( - name = "malloc" and - size = fc.getArgument(0).getValue().toInt() - ) or ( - name = "alloca" and - size = fc.getArgument(0).getValue().toInt() - ) or ( - name = "calloc" and - size = fc.getArgument(0).getValue().toInt() * fc.getArgument(1).getValue().toInt() - ) or ( - name = "realloc" and - size = fc.getArgument(1).getValue().toInt() and - size > 0 // realloc(ptr, 0) only frees the pointer - ) - ) or ( - size = allocExpr.(NewExpr).getAllocatedType().getSize() - ) or ( - size = allocExpr.(NewArrayExpr).getAllocatedType().getSize() + exists(FunctionCall fc, string name | fc = allocExpr and name = fc.getTarget().getName() | + name = "malloc" and + size = fc.getArgument(0).getValue().toInt() + or + name = "alloca" and + size = fc.getArgument(0).getValue().toInt() + or + name = "calloc" and + size = fc.getArgument(0).getValue().toInt() * fc.getArgument(1).getValue().toInt() + or + name = "realloc" and + size = fc.getArgument(1).getValue().toInt() and + size > 0 // realloc(ptr, 0) only frees the pointer ) + or + size = allocExpr.(NewExpr).getAllocatedType().getSize() + or + size = allocExpr.(NewArrayExpr).getAllocatedType().getSize() } /** * Is e some kind of deallocation (`delete`, `free`, `realloc` etc)? */ predicate isDeallocationExpr(Expr e) { - freeCall(e, _) - or e instanceof DeleteExpr - or e instanceof DeleteArrayExpr + freeCall(e, _) or + e instanceof DeleteExpr or + e instanceof DeleteArrayExpr } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Assertions.qll b/cpp/ql/src/semmle/code/cpp/commons/Assertions.qll index def0bdd60a6..a4d3669d2ea 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Assertions.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Assertions.qll @@ -17,14 +17,10 @@ abstract class Assertion extends Locatable { * may terminate the program. */ class LibcAssert extends MacroInvocation, Assertion { - - LibcAssert() { - this.getMacro().getHead() = "assert(expr)" - } + LibcAssert() { this.getMacro().getHead() = "assert(expr)" } override Expr getAsserted() { - exists(ConditionalExpr ce | this.getAGeneratedElement() = ce | - result = ce.getCondition()) + exists(ConditionalExpr ce | this.getAGeneratedElement() = ce | result = ce.getCondition()) } } @@ -33,14 +29,10 @@ class LibcAssert extends MacroInvocation, Assertion { * to be "Assert(x, y)", but further alternatives could be added. */ class MacroAssert extends MacroInvocation, Assertion { - - MacroAssert() { - this.getMacro().getHead() = "Assert(x, y)" - } + MacroAssert() { this.getMacro().getHead() = "Assert(x, y)" } override Expr getAsserted() { - exists(IfStmt i | this.getAGeneratedElement() = i | - result = i.getCondition()) + exists(IfStmt i | this.getAGeneratedElement() = i | result = i.getCondition()) } } @@ -51,12 +43,9 @@ class MacroAssert extends MacroInvocation, Assertion { * Coding Standard_. */ class RecoverableAssert extends MacroInvocation, Assertion { - RecoverableAssert() { - this.getMacro().getHead().matches("c\\_assert(%") - } + RecoverableAssert() { this.getMacro().getHead().matches("c\\_assert(%") } - private - Expr getAnAssertedExpr() { + private Expr getAnAssertedExpr() { result = this.getAGeneratedElement() and not result.getLocation().getStartColumn() = this.getLocation().getStartColumn() } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll index fe9d42c6171..5db9648124c 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Buffer.qll @@ -19,28 +19,32 @@ import semmle.code.cpp.dataflow.DataFlow * but not if it only ever occurs as * ``` * malloc(sizeof(c)) - * ``` + * ``` */ predicate memberMayBeVarSize(Class c, MemberVariable v) { exists(int i | // `v` is the last field in `c` i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and v = c.getCanonicalMember(i) and - // v is an array of size at most 1 v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 - ) and ( + ) and + ( exists(SizeofOperator so | // `sizeof(c)` is taken so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or - so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c | - + so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c + | // arithmetic is performed on the result so.getParent*() instanceof AddExpr - ) or exists(AddressOfExpr aoe | + ) + or + exists(AddressOfExpr aoe | // `&(c.v)` is taken aoe.getAddressable() = v - ) or exists(BuiltInOperationOffsetOf oo | + ) + or + exists(BuiltInOperationOffsetOf oo | // `offsetof(c, v)` using a builtin oo.getAChild().(VariableAccess).getTarget() = v ) @@ -48,69 +52,72 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) { } /** - * Get the size in bytes of the buffer pointed to by an expression (if this can be determined). + * Get the size in bytes of the buffer pointed to by an expression (if this can be determined). */ language[monotonicAggregates] int getBufferSize(Expr bufferExpr, Element why) { exists(Variable bufferVar | bufferVar = bufferExpr.(VariableAccess).getTarget() | + // buffer is a fixed size array + result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and + why = bufferVar and + not memberMayBeVarSize(_, bufferVar) and + not result = 0 // zero sized arrays are likely to have special usage, for example + or + // behaving a bit like a 'union' overlapping other fields. + // buffer is an initialized array + // e.g. int buffer[] = {1, 2, 3}; + why = bufferVar.getInitializer().getExpr() and ( - // buffer is a fixed size array - result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and - why = bufferVar and - not memberMayBeVarSize(_, bufferVar) and - not result = 0 // zero sized arrays are likely to have special usage, for example - // behaving a bit like a 'union' overlapping other fields. - ) or ( - // buffer is an initialized array - // e.g. int buffer[] = {1, 2, 3}; - why = bufferVar.getInitializer().getExpr() and - ( - why instanceof AggregateLiteral or - why instanceof StringLiteral - ) and - result = why.(Expr).getType().(ArrayType).getSize() and - not exists(bufferVar.getUnspecifiedType().(ArrayType).getSize()) - ) or exists(Class parentClass, VariableAccess parentPtr | + why instanceof AggregateLiteral or + why instanceof StringLiteral + ) and + result = why.(Expr).getType().(ArrayType).getSize() and + not exists(bufferVar.getUnspecifiedType().(ArrayType).getSize()) + or + exists(Class parentClass, VariableAccess parentPtr | // buffer is the parentPtr->bufferVar of a 'variable size struct' memberMayBeVarSize(parentClass, bufferVar) and why = bufferVar and parentPtr = bufferExpr.(VariableAccess).getQualifier() and parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and - result = - getBufferSize(parentPtr, _) + - bufferVar.getType().getSize() - - parentClass.getSize() + result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize() ) - ) or ( - // buffer is a fixed size dynamic allocation - isFixedSizeAllocationExpr(bufferExpr, result) and - why = bufferExpr - ) or exists(DataFlow::ExprNode bufferExprNode | + ) + or + // buffer is a fixed size dynamic allocation + isFixedSizeAllocationExpr(bufferExpr, result) and + why = bufferExpr + or + exists(DataFlow::ExprNode bufferExprNode | // dataflow (all sources must be the same size) bufferExprNode = DataFlow::exprNode(bufferExpr) and - result = min(Expr def | - DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) | - getBufferSize(def, _) - ) and result = max(Expr def | - DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) | - getBufferSize(def, _) - ) and - + DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) + | + getBufferSize(def, _) + ) and + result = max(Expr def | + DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) + | + getBufferSize(def, _) + ) and // find reason - exists(Expr def | - DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) | + exists(Expr def | DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) | why = def or exists(getBufferSize(def, why)) ) - ) or exists(Type bufferType | + ) + or + exists(Type bufferType | // buffer is the address of a variable why = bufferExpr.(AddressOfExpr).getAddressable() and bufferType = why.(Variable).getType() and result = bufferType.getSize() and not bufferType instanceof ReferenceType and not any(Union u).getAMemberVariable() = why - ) or exists(Union bufferType | + ) + or + exists(Union bufferType | // buffer is the address of a union member; in this case, we // take the size of the union itself rather the union member, since // it's usually OK to access that amount (e.g. clearing with memset). diff --git a/cpp/ql/src/semmle/code/cpp/commons/CommonType.qll b/cpp/ql/src/semmle/code/cpp/commons/CommonType.qll index 8d776217402..c04d2cba45e 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/CommonType.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/CommonType.qll @@ -4,7 +4,6 @@ import semmle.code.cpp.Type * The C/C++ `char*` type. */ class CharPointerType extends PointerType { - CharPointerType() { this.getBaseType() instanceof CharType } override string getCanonicalQLClass() { result = "CharPointerType" } @@ -14,18 +13,15 @@ class CharPointerType extends PointerType { * The C/C++ `int*` type. */ class IntPointerType extends PointerType { - IntPointerType() { this.getBaseType() instanceof IntType } override string getCanonicalQLClass() { result = "IntPointerType" } } - /** * The C/C++ `void*` type. */ class VoidPointerType extends PointerType { - VoidPointerType() { this.getBaseType() instanceof VoidType } override string getCanonicalQLClass() { result = "VoidPointerType" } @@ -112,7 +108,7 @@ class Wchar_t extends Type { * synonym for. Note that since `__int8` is not a distinct type, * `MicrosoftInt8Type` corresponds to an existing `IntegralType` as * well. - * + * * This class is meaningless if a Microsoft compiler was not used. */ class MicrosoftInt8Type extends IntegralType { @@ -128,7 +124,7 @@ class MicrosoftInt8Type extends IntegralType { * synonym for. Note that since `__int16` is not a distinct type, * `MicrosoftInt16Type` corresponds to an existing `IntegralType` as * well. - * + * * This class is meaningless if a Microsoft compiler was not used. */ class MicrosoftInt16Type extends IntegralType { @@ -144,7 +140,7 @@ class MicrosoftInt16Type extends IntegralType { * synonym for. Note that since `__int32` is not a distinct type, * `MicrosoftInt32Type` corresponds to an existing `IntegralType` as * well. - * + * * This class is meaningless if a Microsoft compiler was not used. */ class MicrosoftInt32Type extends IntegralType { @@ -160,7 +156,7 @@ class MicrosoftInt32Type extends IntegralType { * synonym for. Note that since `__int64` is not a distinct type, * `MicrosoftInt64Type` corresponds to an existing `IntegralType` as * well. - * + * * This class is meaningless if a Microsoft compiler was not used. */ class MicrosoftInt64Type extends IntegralType { diff --git a/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll b/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll index 0c5f91929a4..7c12cb73523 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/DateTime.qll @@ -9,8 +9,8 @@ import cpp */ class PackedTimeType extends Type { PackedTimeType() { - this.getName() = "_FILETIME" - or this.getName().matches("_FILETIME %") + this.getName() = "_FILETIME" or + this.getName().matches("_FILETIME %") } } @@ -20,25 +20,25 @@ class PackedTimeType extends Type { */ class UnpackedTimeType extends Type { UnpackedTimeType() { - this.getName() = "_SYSTEMTIME" - or this.getName() = "SYSTEMTIME" - or this.getName() = "tm" - or this.getName().matches("_SYSTEMTIME %") - or this.getName().matches("SYSTEMTIME %") - or this.getName().matches("tm %") + this.getName() = "_SYSTEMTIME" or + this.getName() = "SYSTEMTIME" or + this.getName() = "tm" or + this.getName().matches("_SYSTEMTIME %") or + this.getName().matches("SYSTEMTIME %") or + this.getName().matches("tm %") } } /** * A `FieldAccess` that would represent an access to a field on a `struct`. */ -private abstract class DateStructFieldAccess extends FieldAccess { - DateStructFieldAccess () { - exists(Field f, StructLikeClass struct | - f.getAnAccess() = this - and struct.getAField() = f - ) - } +abstract private class DateStructFieldAccess extends FieldAccess { + DateStructFieldAccess() { + exists(Field f, StructLikeClass struct | + f.getAnAccess() = this and + struct.getAField() = f + ) + } } /** @@ -49,63 +49,51 @@ abstract class DayFieldAccess extends DateStructFieldAccess { } /** * A `FieldAccess` where access is to a month field of the `struct`. */ -abstract class MonthFieldAccess extends DateStructFieldAccess {} +abstract class MonthFieldAccess extends DateStructFieldAccess { } /** * A `FieldAccess` where access is to a year field of the `struct`. */ -abstract class YearFieldAccess extends DateStructFieldAccess {} +abstract class YearFieldAccess extends DateStructFieldAccess { } /** * A `DayFieldAccess` for the `SYSTEMTIME` struct. */ class SystemTimeDayFieldAccess extends DayFieldAccess { - SystemTimeDayFieldAccess () { - this.getTarget().getName() = "wDay" - } + SystemTimeDayFieldAccess() { this.getTarget().getName() = "wDay" } } /** * A `MonthFieldAccess` for the `SYSTEMTIME` struct. */ class SystemTimeMonthFieldAccess extends MonthFieldAccess { - SystemTimeMonthFieldAccess () { - this.getTarget().getName() = "wMonth" - } + SystemTimeMonthFieldAccess() { this.getTarget().getName() = "wMonth" } } /** * A `YearFieldAccess` for the `SYSTEMTIME` struct. */ class StructSystemTimeYearFieldAccess extends YearFieldAccess { - StructSystemTimeYearFieldAccess() { - this.getTarget().getName() = "wYear" - } + StructSystemTimeYearFieldAccess() { this.getTarget().getName() = "wYear" } } /** * A `DayFieldAccess` for `struct tm`. */ class StructTmDayFieldAccess extends DayFieldAccess { - StructTmDayFieldAccess() { - this.getTarget().getName() = "tm_mday" - } + StructTmDayFieldAccess() { this.getTarget().getName() = "tm_mday" } } /** * A `MonthFieldAccess` for `struct tm`. */ class StructTmMonthFieldAccess extends MonthFieldAccess { - StructTmMonthFieldAccess() { - this.getTarget().getName() = "tm_mon" - } + StructTmMonthFieldAccess() { this.getTarget().getName() = "tm_mon" } } /** * A `YearFieldAccess` for `struct tm`. */ class StructTmYearFieldAccess extends YearFieldAccess { - StructTmYearFieldAccess() { - this.getTarget().getName() = "tm_year" - } + StructTmYearFieldAccess() { this.getTarget().getName() = "tm_year" } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Dependency.qll b/cpp/ql/src/semmle/code/cpp/commons/Dependency.qll index 49cb873fbaa..1b885fb8f5f 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Dependency.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Dependency.qll @@ -7,29 +7,22 @@ import semmle.code.cpp.Variable * Options that control the dependencies generated by * this library. */ -class DependencyOptions extends string -{ - DependencyOptions() { - this = "DependencyOptions" - } +class DependencyOptions extends string { + DependencyOptions() { this = "DependencyOptions" } /** * Holds if dependencies should only be generated in templates rather than * in both templates and instantiations, where possible. This is expensive * to compute, but tends to produce dependencies that are easier to read. */ - cached predicate preferTemplateDeps() { - any() - } + cached + predicate preferTemplateDeps() { any() } } /** * Gets the `DependencyOptions`. */ -DependencyOptions getDependencyOptions() -{ - any() -} +DependencyOptions getDependencyOptions() { any() } /** * An Element that can be the source of a transitive dependency. This is any @@ -41,7 +34,6 @@ class DependsSource extends Element { DependsSource() { // not inside a template instantiation not exists(Element other | isFromTemplateInstantiation(other)) or - // allow DeclarationEntrys of template specializations this.(DeclarationEntry).getDeclaration().(Function).isConstructedFrom(_) or this.(DeclarationEntry).getDeclaration().(Class).isConstructedFrom(_) @@ -64,17 +56,19 @@ class DependsSource extends Element { class Symbol extends DependsSource { Symbol() { ( - exists(EnumConstant ec | this = ec and not ec.getDeclaringEnum() instanceof LocalEnum) or - (this instanceof Macro and this.getFile().getAbsolutePath() != "") or - (this instanceof DeclarationEntry and - not this.(VariableDeclarationEntry).getVariable() instanceof LocalScopeVariable and - not this.(FunctionDeclarationEntry).getFunction() instanceof BuiltInFunction and - not this.(TypeDeclarationEntry).getType() instanceof LocalEnum and - not this.(TypeDeclarationEntry).getType() instanceof LocalClass and - not this.(TypeDeclarationEntry).getType() instanceof LocalTypedefType and - not this.(TypeDeclarationEntry).getType() instanceof TemplateParameter - ) or - (this instanceof NamespaceDeclarationEntry) + exists(EnumConstant ec | this = ec and not ec.getDeclaringEnum() instanceof LocalEnum) + or + this instanceof Macro and this.getFile().getAbsolutePath() != "" + or + this instanceof DeclarationEntry and + not this.(VariableDeclarationEntry).getVariable() instanceof LocalScopeVariable and + not this.(FunctionDeclarationEntry).getFunction() instanceof BuiltInFunction and + not this.(TypeDeclarationEntry).getType() instanceof LocalEnum and + not this.(TypeDeclarationEntry).getType() instanceof LocalClass and + not this.(TypeDeclarationEntry).getType() instanceof LocalTypedefType and + not this.(TypeDeclarationEntry).getType() instanceof TemplateParameter + or + this instanceof NamespaceDeclarationEntry ) } @@ -89,17 +83,15 @@ class Symbol extends DependsSource { * 2 - C/C++ link-time dependency (or transitive dependency with a link-time component) */ cached - Element getADependentElement(int category) { - dependsOnFull(result, this, category) - } + Element getADependentElement(int category) { dependsOnFull(result, this, category) } } /** * Associates a Declaration with it's DeclarationEntries, or (for a template * instantiation) with the DeclarationEntries of its template. */ -cached predicate getDeclarationEntries(Declaration decl, DeclarationEntry de) -{ +cached +predicate getDeclarationEntries(Declaration decl, DeclarationEntry de) { ( decl = de.getDeclaration() or decl.(Function).isConstructedFrom(de.getDeclaration()) or @@ -126,8 +118,7 @@ predicate dependsOnSimple(Element src, Element dest) { /** * A 'simple' dependency that might be inlined. */ -private -predicate dependsOnSimpleInline(Element src, Element dest) { +private predicate dependsOnSimpleInline(Element src, Element dest) { dependency_functionUse(src, dest) or dependency_typeUse(src, dest) or dependency_variableUse(src, dest) or @@ -144,7 +135,9 @@ predicate dependsOnSimpleInline(Element src, Element dest) { * Holds if a simple, non-template dependency exists between two Locations * specified by the parameters. */ -private predicate dependsLocation(File f1, int sl1, int sc1, int el1, int ec1, File f2, int sl2, int sc2, int el2, int ec2) { +private predicate dependsLocation( + File f1, int sl1, int sc1, int el1, int ec1, File f2, int sl2, int sc2, int el2, int ec2 +) { exists(Element src, Element dest, Location loc1, Location loc2 | dependsOnSimpleInline(src, dest) and src instanceof DependsSource and @@ -176,7 +169,9 @@ private predicate dependsNonTemplateAlternative(Location loc1, Location loc2) { src.getLocation() = loc1 and dest.getLocation() = loc2 ) and - dependsLocation(loc1.getFile(), loc1.getStartLine(), loc1.getStartColumn(), loc1.getEndLine(), loc1.getEndColumn(), loc2.getFile(), loc2.getStartLine(), loc2.getStartColumn(), loc2.getEndLine(), loc2.getEndColumn()) + dependsLocation(loc1.getFile(), loc1.getStartLine(), loc1.getStartColumn(), loc1.getEndLine(), + loc1.getEndColumn(), loc2.getFile(), loc2.getStartLine(), loc2.getStartColumn(), + loc2.getEndLine(), loc2.getEndColumn()) } /** @@ -202,7 +197,6 @@ private predicate dependsOnViaTemplate(Declaration src, Element dest) { // internal is an element in the template {function or class} instantiation that cannot // itself be a transitive dependency source internal.isFromTemplateInstantiation(src) and - // don't generate template dependencies through a member function of a template class; // these dependencies are also generated through the class, which has to be referenced // somewhere anyway. @@ -210,10 +204,8 @@ private predicate dependsOnViaTemplate(Declaration src, Element dest) { internal.isFromTemplateInstantiation(c) and src.getDeclaringType() = c ) and - // dest is anything that the internal element depends upon dependsOnSimpleInline(internal, dest) and - // is there something in the template (not the instantiation) that's generating // (better) dependencies from internal anyway? internalLocation = internal.getLocation() and @@ -233,13 +225,14 @@ predicate dependsOnTransitive(DependsSource src, Element dest) { exists(Element mid1 | // begin with a simple step dependsOnSimpleInline(src, mid1) and - // any number of recursive steps ( mid1 = dest or // mid1 is not necessarily a Declaration dependsOnViaTemplate+(mid1, dest) ) - ) or dependency_macroUse(src, dest) + ) + or + dependency_macroUse(src, dest) } /** @@ -253,12 +246,11 @@ private predicate dependsOnTDE(Element src, Type t, TypeDeclarationEntry dest) { /** * A dependency that targets a visible TypeDeclarationEntry. */ -private pragma[noopt] predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry dest) { +pragma[noopt] +private predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry dest) { dependsOnTDE(src, t, dest) and exists(File g | g = dest.getFile() | - exists(File f | f = src.getFile() | - f.getAnIncludedFile*() = g - ) + exists(File f | f = src.getFile() | f.getAnIncludedFile*() = g) ) } @@ -269,28 +261,29 @@ private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest) exists(Type t | // dependency from a Type use -> unique visible TDE dependsOnVisibleTDE(src, t, dest) and - strictcount(TypeDeclarationEntry alt | - dependsOnVisibleTDE(src, t, alt) - ) = 1 - ) or exists(TypedefType mid | + strictcount(TypeDeclarationEntry alt | dependsOnVisibleTDE(src, t, alt)) = 1 + ) + or + exists(TypedefType mid | // dependency from a TypedefType use -> any (visible) TDE dependsOnTransitive(src, mid) and - getDeclarationEntries(mid, (TypeDeclarationEntry)dest) - ) or exists(Declaration mid | + getDeclarationEntries(mid, dest.(TypeDeclarationEntry)) + ) + or + exists(Declaration mid | // dependency from a Variable / Function use -> any (visible) declaration entry dependsOnTransitive(src, mid) and not mid instanceof Type and not mid instanceof EnumConstant and - - getDeclarationEntries(mid, (DeclarationEntry)dest) and + getDeclarationEntries(mid, dest.(DeclarationEntry)) and not dest instanceof TypeDeclarationEntry - ) or exists(Declaration mid | + ) + or + exists(Declaration mid | // dependency from a Type / Variable / Function use -> any (visible) definition dependsOnTransitive(src, mid) and not mid instanceof EnumConstant and - - getDeclarationEntries(mid, (DeclarationEntry)dest) and - + getDeclarationEntries(mid, dest.(DeclarationEntry)) and // must be definition dest.(DeclarationEntry).isDefinition() ) @@ -301,39 +294,36 @@ private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest) * to fix up the results for Declarations to most reasonable DeclarationEntrys. */ private predicate dependsOnFull(DependsSource src, Symbol dest, int category) { - ( - // direct result - dependsOnTransitive(src, dest) and - category = 1 - ) or ( - // result to a visible DeclarationEntry - dependsOnDeclarationEntry(src, dest) and - src.getFile().getAnIncludedFile*() = dest.getFile() and - category = 1 - ) or exists(Declaration mid | + // direct result + dependsOnTransitive(src, dest) and + category = 1 + or + // result to a visible DeclarationEntry + dependsOnDeclarationEntry(src, dest) and + src.getFile().getAnIncludedFile*() = dest.getFile() and + category = 1 + or + exists(Declaration mid | // dependency from a Variable / Function use -> non-visible definition (link time) dependsOnTransitive(src, mid) and not mid instanceof EnumConstant and - - getDeclarationEntries(mid, (DeclarationEntry)dest) and + getDeclarationEntries(mid, dest.(DeclarationEntry)) and not dest instanceof TypeDeclarationEntry and - // must be definition dest.(DeclarationEntry).isDefinition() and - // must not be visible (else covered above) not src.getFile().getAnIncludedFile*() = dest.getFile() and - // filter out FDEs that are only defined in the dummy link target ( ( dest instanceof FunctionDeclarationEntry and isLinkerAwareExtracted() - ) implies exists(LinkTarget lt | not lt.isDummy() | + ) + implies + exists(LinkTarget lt | not lt.isDummy() | lt.getAFunction() = dest.(FunctionDeclarationEntry).getFunction() ) ) and - category = 2 ) } @@ -341,17 +331,15 @@ private predicate dependsOnFull(DependsSource src, Symbol dest, int category) { /** * A dependency caused by a function call / use. */ -private -predicate dependency_functionUse(Element src, Function dest) { +private predicate dependency_functionUse(Element src, Function dest) { funbind(unresolveElement(src), unresolveElement(dest)) } /** * A Type which refers to a UserType. */ -private cached predicate refersToUserType(Type a, UserType b) { - a.refersTo(b) -} +cached +private predicate refersToUserType(Type a, UserType b) { a.refersTo(b) } /** * A Type which refers to a type directly, without using a pointer or reference. @@ -365,7 +353,8 @@ private predicate refersToDirectlyNonPointer(Type a, Type b) { /** * A Type which refers to a UserType, but only through a pointer or reference. */ -private cached predicate refersToUserTypePointer(Type a, UserType b) { +cached +private predicate refersToUserTypePointer(Type a, UserType b) { refersToUserType(a, b) and not refersToDirectlyNonPointer*(a, b) } @@ -373,8 +362,7 @@ private cached predicate refersToUserTypePointer(Type a, UserType b) { /** * A dependency caused by a type use. */ -private -predicate dependency_typeUse(Element src, UserType dest) { +private predicate dependency_typeUse(Element src, UserType dest) { refersToUserType(typeUsedBy(src), dest) } @@ -388,40 +376,42 @@ predicate dependency_pointerTypeUse(Element src, UserType dest) { /** * The Types that must be defined for a particular Element. */ -private -Type typeUsedBy(Element src) { - ( - result = src.(VariableDeclarationEntry).getType() and not src.(VariableDeclarationEntry).getVariable().declaredUsingAutoType() - ) or ( - result = src.(FunctionDeclarationEntry).getType() - ) or ( - result = src.(Cast).getType() and not src.(Cast).isImplicit() - ) or ( - result = src.(ClassDerivation).getBaseClass() - ) or ( - result = src.(TypeDeclarationEntry).getType().(TypedefType).getBaseType() - ) or ( - result = src.(TypeDeclarationEntry).getDeclaration().(Enum).getExplicitUnderlyingType() - ) or ( - result = src.(SizeofTypeOperator).getTypeOperand() - ) or exists(Function f | +private Type typeUsedBy(Element src) { + result = src.(VariableDeclarationEntry).getType() and + not src.(VariableDeclarationEntry).getVariable().declaredUsingAutoType() + or + result = src.(FunctionDeclarationEntry).getType() + or + result = src.(Cast).getType() and not src.(Cast).isImplicit() + or + result = src.(ClassDerivation).getBaseClass() + or + result = src.(TypeDeclarationEntry).getType().(TypedefType).getBaseType() + or + result = src.(TypeDeclarationEntry).getDeclaration().(Enum).getExplicitUnderlyingType() + or + result = src.(SizeofTypeOperator).getTypeOperand() + or + exists(Function f | funbind(unresolveElement(src), unresolveElement(f)) and result = f.getATemplateArgument() - ) or ( - result = src.(NewExpr).getType() and not result.(Class).hasConstructor() - ) or ( - result = src.(NewArrayExpr).getType() and not result.(ArrayType).getBaseType().(Class).hasConstructor() - ) or ( - result = src.(DeleteExpr).getExpr().getType() and not result.(PointerType).getBaseType().(Class).hasDestructor() - ) or ( - result = src.(DeleteArrayExpr).getExpr().getType() and not result.(PointerType).getBaseType().(Class).hasDestructor() ) + or + result = src.(NewExpr).getType() and not result.(Class).hasConstructor() + or + result = src.(NewArrayExpr).getType() and + not result.(ArrayType).getBaseType().(Class).hasConstructor() + or + result = src.(DeleteExpr).getExpr().getType() and + not result.(PointerType).getBaseType().(Class).hasDestructor() + or + result = src.(DeleteArrayExpr).getExpr().getType() and + not result.(PointerType).getBaseType().(Class).hasDestructor() } /** * A dependency caused by a variable use. */ -private -predicate dependency_variableUse(VariableAccess src, Variable dest) { +private predicate dependency_variableUse(VariableAccess src, Variable dest) { src.getTarget() = dest and not dest instanceof LocalScopeVariable } @@ -429,38 +419,33 @@ predicate dependency_variableUse(VariableAccess src, Variable dest) { /** * A dependency caused by an enum constant use. */ -private -predicate dependency_enumConstantUse(EnumConstantAccess src, EnumConstant dest) { +private predicate dependency_enumConstantUse(EnumConstantAccess src, EnumConstant dest) { src.getTarget() = dest } /** * A dependency caused by a macro access. */ -private -predicate dependency_macroUse(MacroAccess src, Macro dest) { - src.getMacro() = dest -} +private predicate dependency_macroUse(MacroAccess src, Macro dest) { src.getMacro() = dest } /** * A dependency caused by a 'using' declaration 'using X::Y'. */ -private -predicate dependency_usingDeclaration(UsingDeclarationEntry src, Declaration dest) { +private predicate dependency_usingDeclaration(UsingDeclarationEntry src, Declaration dest) { src.getDeclaration() = dest } /** * A dependency caused by a 'using' directive 'using namespace X'. */ -private -predicate dependency_usingNamespace(UsingDirectiveEntry src, NamespaceDeclarationEntry dest) { +private predicate dependency_usingNamespace(UsingDirectiveEntry src, NamespaceDeclarationEntry dest) { exists(Namespace nsdecl | nsdecl = src.getNamespace() and dest.getNamespace() = nsdecl and dest.getFile().getAnIncludedFile*() = src.getFile() and ( - dest.getFile() = src.getFile() implies + dest.getFile() = src.getFile() + implies dest.getLocation().getStartLine() < src.getLocation().getStartLine() ) and none() // temporarily disabled until we have suitable UI in Architect @@ -472,13 +457,12 @@ predicate dependency_usingNamespace(UsingDirectiveEntry src, NamespaceDeclaratio * ensures that an externally defined class member has a dependency on (something in) the * class definition. */ -private -predicate dependency_outOfLineDeclaration(DeclarationEntry src, DeclarationEntry dest) { +private predicate dependency_outOfLineDeclaration(DeclarationEntry src, DeclarationEntry dest) { src.getDeclaration().hasDeclaringType() and src.isDefinition() and ( - dest.getDeclaration() = src.getDeclaration() or - + dest.getDeclaration() = src.getDeclaration() + or // also permit out of line declarations to jump from the declaration of a specialized // function to it's definition in the primary template. Note that the specialization // in this case may be on a template class parameter. @@ -491,8 +475,7 @@ predicate dependency_outOfLineDeclaration(DeclarationEntry src, DeclarationEntry * A dependency from an initialization of a (static) class member to a corresponding * declaration. */ -private -predicate dependency_outOfLineInitializer(Initializer src, DeclarationEntry dest) { +private predicate dependency_outOfLineInitializer(Initializer src, DeclarationEntry dest) { src.getDeclaration().hasDeclaringType() and dest.getDeclaration() = src.getDeclaration() and not dest.isDefinition() @@ -501,8 +484,7 @@ predicate dependency_outOfLineInitializer(Initializer src, DeclarationEntry dest /** * A dependency from a template function specialization to the general one. */ -private -predicate dependency_functionSpecialization(DeclarationEntry src, DeclarationEntry dest) { +private predicate dependency_functionSpecialization(DeclarationEntry src, DeclarationEntry dest) { exists(FunctionTemplateSpecialization fts | src.getDeclaration() = fts and dest.getDeclaration() = fts.getPrimaryTemplate() @@ -512,8 +494,7 @@ predicate dependency_functionSpecialization(DeclarationEntry src, DeclarationEnt /** * A dependency from a template class specialization to the most general one. */ -private -predicate dependency_classSpecialization(DeclarationEntry src, DeclarationEntry dest) { +private predicate dependency_classSpecialization(DeclarationEntry src, DeclarationEntry dest) { exists(ClassTemplateSpecialization cts | src.getDeclaration() = cts and dest.getDeclaration() = cts.getPrimaryTemplate() diff --git a/cpp/ql/src/semmle/code/cpp/commons/Environment.qll b/cpp/ql/src/semmle/code/cpp/commons/Environment.qll index 3a8f280d43c..e36244f4d5c 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Environment.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Environment.qll @@ -8,9 +8,7 @@ import cpp * An expression that reads from an environment variable. */ class EnvironmentRead extends Expr { - EnvironmentRead() { - readsEnvironment(this, _) - } + EnvironmentRead() { readsEnvironment(this, _) } /** * The name of the environment variable. @@ -24,9 +22,7 @@ class EnvironmentRead extends Expr { * A very short description of the source, suitable for use in * an error message. */ - string getSourceDescription() { - readsEnvironment(this, result) - } + string getSourceDescription() { readsEnvironment(this, result) } } private predicate readsEnvironment(Expr read, string sourceDescription) { @@ -34,5 +30,6 @@ private predicate readsEnvironment(Expr read, string sourceDescription) { read = call and call.getTarget().hasGlobalName(name) and (name = "getenv" or name = "secure_getenv" or name = "_wgetenv") and - sourceDescription = name) + sourceDescription = name + ) } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Exclusions.qll b/cpp/ql/src/semmle/code/cpp/commons/Exclusions.qll index 32d5ab64b45..b27f11a9ab3 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Exclusions.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Exclusions.qll @@ -22,8 +22,10 @@ private predicate functionLocation(Function f, string file, int fBlockStartLine, * Holds if the function `f` is inside a preprocessor branch that may have code in another arm. */ predicate functionDefinedInIfDef(Function f) { - exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int pbdEndLine, int fBlockStartLine, - int fBlockEndLine | + exists( + PreprocessorBranchDirective pbd, string file, int pbdStartLine, int pbdEndLine, + int fBlockStartLine, int fBlockEndLine + | functionLocation(f, file, fBlockStartLine, fBlockEndLine) and pbdLocation(pbd, file, pbdStartLine) and pbdLocation(pbd.getNext(), file, pbdEndLine) and @@ -44,14 +46,17 @@ predicate functionDefinedInIfDef(Function f) { */ predicate functionContainsDisabledCode(Function f) { // `f` contains a preprocessor branch that was not taken - exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, int fBlockEndLine | + exists( + PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, + int fBlockEndLine + | functionLocation(f, file, fBlockStartLine, fBlockEndLine) and pbdLocation(pbd, file, pbdStartLine) and pbdStartLine <= fBlockEndLine and pbdStartLine >= fBlockStartLine and ( - pbd.(PreprocessorBranch).wasNotTaken() or - + pbd.(PreprocessorBranch).wasNotTaken() + or // an else either was not taken, or it's corresponding branch // was not taken. pbd instanceof PreprocessorElse @@ -64,7 +69,10 @@ predicate functionContainsDisabledCode(Function f) { */ predicate functionContainsPreprocCode(Function f) { // `f` contains a preprocessor branch - exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, int fBlockEndLine | + exists( + PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, + int fBlockEndLine + | functionLocation(f, file, fBlockStartLine, fBlockEndLine) and pbdLocation(pbd, file, pbdStartLine) and pbdStartLine <= fBlockEndLine and diff --git a/cpp/ql/src/semmle/code/cpp/commons/File.qll b/cpp/ql/src/semmle/code/cpp/commons/File.qll index fd9d1f46f37..192918d25b3 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/File.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/File.qll @@ -3,8 +3,7 @@ import cpp /** * A call to a library function that opens a file. */ -predicate fopenCall(FunctionCall fc) -{ +predicate fopenCall(FunctionCall fc) { exists(Function f | f = fc.getTarget() | f.hasGlobalName("fopen") or f.hasGlobalName("open") or @@ -22,21 +21,18 @@ predicate fopenCall(FunctionCall fc) /** * A call to a library function that closes a file. */ -predicate fcloseCall(FunctionCall fc, Expr closed) -{ +predicate fcloseCall(FunctionCall fc, Expr closed) { exists(Function f | f = fc.getTarget() | - ( - f.hasGlobalName("fclose") and - closed = fc.getArgument(0) - ) or ( - f.hasGlobalName("close") and - closed = fc.getArgument(0) - ) or ( - f.hasGlobalName("_close") and - closed = fc.getArgument(0) - ) or ( - f.hasGlobalName("CloseHandle") and - closed = fc.getArgument(0) - ) + f.hasGlobalName("fclose") and + closed = fc.getArgument(0) + or + f.hasGlobalName("close") and + closed = fc.getArgument(0) + or + f.hasGlobalName("_close") and + closed = fc.getArgument(0) + or + f.hasGlobalName("CloseHandle") and + closed = fc.getArgument(0) ) -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/commons/NULL.qll b/cpp/ql/src/semmle/code/cpp/commons/NULL.qll index 0204d752ecc..fa6008f1379 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/NULL.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/NULL.qll @@ -2,14 +2,10 @@ import semmle.code.cpp.Macro /** A macro defining NULL. */ class NULLMacro extends Macro { - NULLMacro() { - this.getHead() = "NULL" - } + NULLMacro() { this.getHead() = "NULL" } } /** A use of the NULL macro. */ class NULL extends Literal { - NULL() { - exists(NULLMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) - } + NULL() { exists(NULLMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/NullTermination.qll b/cpp/ql/src/semmle/code/cpp/commons/NullTermination.qll index 7b27ea913a5..650e2bc9954 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/NullTermination.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/NullTermination.qll @@ -10,22 +10,20 @@ private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) ) } -/** +/** * Holds if the expression `e` may add a null terminator to the string in * variable `v`. */ predicate mayAddNullTerminator(Expr e, VariableAccess va) { // Assignment: dereferencing or array access - exists(AssignExpr ae | - e = ae | + exists(AssignExpr ae | e = ae | ( // *v = x, *v++ = x, etc. ae.getLValue().(PointerDereferenceExpr).getOperand().getAChild*() = va or // v[x] = y ae.getLValue().(ArrayExpr).getArrayBase() = va - ) - and + ) and // Rule out assignments where the assigned value is a non-zero constant not ae.getRValue().getFullyConverted().getValue().toInt() != 0 ) @@ -34,15 +32,15 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { exists(Expr e0, BasicBlock bb, int pos, BasicBlock bb0, int pos0 | mayAddNullTerminatorHelper(e, va, e0) and bb.getNode(pos) = e and - bb0.getNode(pos0) = e0 | + bb0.getNode(pos0) = e0 + | bb = bb0 and pos < pos0 or bb.getASuccessor+() = bb0 ) - // Assignment to non-stack variable or - exists(AssignExpr ae | - e = ae | + // Assignment to non-stack variable + exists(AssignExpr ae | e = ae | not ae.getLValue().(VariableAccess).getTarget() instanceof LocalScopeVariable and ae.getRValue().getAChild*() = va ) @@ -54,10 +52,14 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { e = c and f = c.getTarget() and not functionArgumentMustBeNullTerminated(f, i) and - c.getAnArgumentSubExpr(i) = va | - not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i) or - mayAddNullTerminator(_, f.getParameter(i).getAnAccess()) or - f.isVarargs() and i >= f.getNumberOfParameters() or + c.getAnArgumentSubExpr(i) = va + | + not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i) + or + mayAddNullTerminator(_, f.getParameter(i).getAnAccess()) + or + f.isVarargs() and i >= f.getNumberOfParameters() + or exists(AsmStmt s | s.getEnclosingFunction() = f) ) or @@ -74,10 +76,8 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) { * terminated. */ predicate functionArgumentMustBeNullTerminated(Function f, int i) { - ( - f.(ArrayFunction).hasArrayWithNullTerminator(i) and - f.(ArrayFunction).hasArrayInput(i) - ) + f.(ArrayFunction).hasArrayWithNullTerminator(i) and + f.(ArrayFunction).hasArrayInput(i) or f instanceof StrcatFunction and i = 0 or @@ -90,7 +90,7 @@ predicate functionArgumentMustBeNullTerminated(Function f, int i) { f.hasName("strstr") and i in [0 .. 1] } -/** +/** * Holds if `va` is a variable access where the contents must be null terminated. */ predicate variableMustBeNullTerminated(VariableAccess va) { @@ -114,7 +114,8 @@ predicate variableMustBeNullTerminated(VariableAccess va) { not exists(Expr e, BasicBlock bb1, int pos1, BasicBlock bb2, int pos2 | mayAddNullTerminator(e, p.getAnAccess()) and bb1.getNode(pos1) = e and - bb2.getNode(pos2) = use | + bb2.getNode(pos2) = use + | bb1 = bb2 and pos1 < pos2 or bb1.getASuccessor+() = bb2 diff --git a/cpp/ql/src/semmle/code/cpp/commons/PolymorphicClass.qll b/cpp/ql/src/semmle/code/cpp/commons/PolymorphicClass.qll index 46157ed54b9..91f8bc3dd09 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/PolymorphicClass.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/PolymorphicClass.qll @@ -4,7 +4,7 @@ import cpp * A C++ class or structure which (possibly by inheritance) has at least one virtual method. */ class PolymorphicClass extends Class { - PolymorphicClass() { - exists(MemberFunction f | this.getABaseClass*() = f.getDeclaringType() and f.isVirtual()) - } + PolymorphicClass() { + exists(MemberFunction f | this.getABaseClass*() = f.getDeclaringType() and f.isVirtual()) + } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index 5ac1f8bd19e..a7ab7c25b86 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -67,7 +67,7 @@ predicate variadicFormatter(Function f, int formatParamIndex) { */ class UserDefinedFormattingFunction extends FormattingFunction { override string getCanonicalQLClass() { result = "UserDefinedFormattingFunction" } - + UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _) } override int getFormatParameterIndex() { callsVariadicFormatter(this, result) } @@ -80,7 +80,7 @@ class FormattingFunctionCall extends Expr { FormattingFunctionCall() { this.(Call).getTarget() instanceof FormattingFunction } override string getCanonicalQLClass() { result = "FormattingFunctionCall" } - + /** * Gets the formatting function being called. */ diff --git a/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll b/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll index 989f16fcb27..f9d61a52792 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Scanf.qll @@ -2,13 +2,13 @@ * A library for dealing with scanf-like formatting strings. This is similar to * printf.qll but the format specification for scanf is quite different. */ + import semmle.code.cpp.Type /** * A `scanf`-like standard library function. */ -abstract class ScanfFunction extends Function -{ +abstract class ScanfFunction extends Function { /** * Gets the position at which the input string or stream parameter occurs, * if this function does not read from standard input. @@ -24,143 +24,117 @@ abstract class ScanfFunction extends Function * Holds if the default meaning of `%s` is a `wchar_t*` string * (rather than a `char*`). */ - predicate isWideCharDefault() - { - exists(getName().indexOf("wscanf")) - } + predicate isWideCharDefault() { exists(getName().indexOf("wscanf")) } } /** * The standard function `scanf` (and variations). */ -class Scanf extends ScanfFunction -{ - Scanf() - { +class Scanf extends ScanfFunction { + Scanf() { this instanceof TopLevelFunction and ( - hasName("scanf") or // scanf(format, args...) - hasName("wscanf") or // wscanf(format, args...) - hasName("_scanf_l") or // _scanf_l(format, locale, args...) - hasName("_wscanf_l") // _wscanf_l(format, locale, args...) + hasName("scanf") or // scanf(format, args...) + hasName("wscanf") or // wscanf(format, args...) + hasName("_scanf_l") or // _scanf_l(format, locale, args...) + hasName("_wscanf_l") // _wscanf_l(format, locale, args...) ) } override int getInputParameterIndex() { none() } + override int getFormatParameterIndex() { result = 0 } } /** * The standard function `fscanf` (and variations). */ -class Fscanf extends ScanfFunction -{ - Fscanf() - { +class Fscanf extends ScanfFunction { + Fscanf() { this instanceof TopLevelFunction and ( - hasName("fscanf") or // fscanf(src_stream, format, args...) - hasName("fwscanf") or // fwscanf(src_stream, format, args...) - hasName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) - hasName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) + hasName("fscanf") or // fscanf(src_stream, format, args...) + hasName("fwscanf") or // fwscanf(src_stream, format, args...) + hasName("_fscanf_l") or // _fscanf_l(src_stream, format, locale, args...) + hasName("_fwscanf_l") // _fwscanf_l(src_stream, format, locale, args...) ) } override int getInputParameterIndex() { result = 0 } + override int getFormatParameterIndex() { result = 1 } } /** * The standard function `sscanf` (and variations). */ -class Sscanf extends ScanfFunction -{ - Sscanf() - { +class Sscanf extends ScanfFunction { + Sscanf() { this instanceof TopLevelFunction and ( - hasName("sscanf") or // sscanf(src_stream, format, args...) - hasName("swscanf") or // swscanf(src, format, args...) - hasName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) - hasName("_swscanf_l") // _swscanf_l(src, format, locale, args...) + hasName("sscanf") or // sscanf(src_stream, format, args...) + hasName("swscanf") or // swscanf(src, format, args...) + hasName("_sscanf_l") or // _sscanf_l(src, format, locale, args...) + hasName("_swscanf_l") // _swscanf_l(src, format, locale, args...) ) } override int getInputParameterIndex() { result = 0 } + override int getFormatParameterIndex() { result = 1 } } /** * The standard(ish) function `snscanf` (and variations). */ -class Snscanf extends ScanfFunction -{ - Snscanf() - { +class Snscanf extends ScanfFunction { + Snscanf() { this instanceof TopLevelFunction and ( - hasName("_snscanf") or // _snscanf(src, max_amount, format, args...) - hasName("_snwscanf") // _snwscanf(src, max_amount, format, args...) - // note that the max_amount is not a limit on the output length, it's an input length - // limit used with non null-terminated strings. + hasName("_snscanf") or // _snscanf(src, max_amount, format, args...) + hasName("_snwscanf") // _snwscanf(src, max_amount, format, args...) + // note that the max_amount is not a limit on the output length, it's an input length + // limit used with non null-terminated strings. ) } override int getInputParameterIndex() { result = 0 } + override int getFormatParameterIndex() { result = 2 } } /** * A call to one of the `scanf` functions. */ -class ScanfFunctionCall extends FunctionCall -{ - ScanfFunctionCall() - { - this.getTarget() instanceof ScanfFunction - } +class ScanfFunctionCall extends FunctionCall { + ScanfFunctionCall() { this.getTarget() instanceof ScanfFunction } /** * Gets the `scanf`-like function that is called. */ - ScanfFunction getScanfFunction() - { - result = getTarget() - } + ScanfFunction getScanfFunction() { result = getTarget() } /** * Gets the position at which the input string or stream parameter occurs, * if this function call does not read from standard input. */ - int getInputParameterIndex() - { - result = getScanfFunction().getInputParameterIndex() - } + int getInputParameterIndex() { result = getScanfFunction().getInputParameterIndex() } /** * Gets the position at which the format parameter occurs. */ - int getFormatParameterIndex() - { - result = getScanfFunction().getFormatParameterIndex() - } + int getFormatParameterIndex() { result = getScanfFunction().getFormatParameterIndex() } /** * Gets the format expression used in this call. */ - Expr getFormat() - { - result = this.getArgument(this.getFormatParameterIndex()) - } + Expr getFormat() { result = this.getArgument(this.getFormatParameterIndex()) } /** * Holds if the default meaning of `%s` is a `wchar_t*` string * (rather than a `char*`). */ - predicate isWideCharDefault() - { - getScanfFunction().isWideCharDefault() - } + predicate isWideCharDefault() { getScanfFunction().isWideCharDefault() } } /** @@ -173,14 +147,10 @@ class ScanfFormatLiteral extends Expr { } /** the function call where this format string is used */ - ScanfFunctionCall getUse() { - result.getFormat() = this - } + ScanfFunctionCall getUse() { result.getFormat() = this } /** Holds if the default meaning of `%s` is a `wchar_t*` (rather than a `char*`). */ - predicate isWideCharDefault() { - getUse().getTarget().(ScanfFunction).isWideCharDefault() - } + predicate isWideCharDefault() { getUse().getTarget().(ScanfFunction).isWideCharDefault() } /** * Gets the format string itself, transformed as follows: @@ -189,30 +159,32 @@ class ScanfFormatLiteral extends Expr { * - '%*' is replaced with '_' * (%*any is matched but not assigned to an argument) */ - string getFormat() { - result = this.getValue().replaceAll("%%", "_").replaceAll("%*", "_") - } + string getFormat() { result = this.getValue().replaceAll("%%", "_").replaceAll("%*", "_") } /** * Gets the number of conversion specifiers (not counting `%%` and `%*`...). */ - int getNumConvSpec() { - result = count(this.getFormat().indexOf("%")) - } + int getNumConvSpec() { result = count(this.getFormat().indexOf("%")) } /** * Gets the position in the string at which the nth conversion specifier starts. */ int getConvSpecOffset(int n) { - n = 0 and result = this.getFormat().indexOf("%", 0, 0) - or n > 0 and exists(int p | n = p + 1 and result = this.getFormat().indexOf("%", 0, this.getConvSpecOffset(p) + 2)) + n = 0 and result = this.getFormat().indexOf("%", 0, 0) + or + n > 0 and + exists(int p | + n = p + 1 and result = this.getFormat().indexOf("%", 0, this.getConvSpecOffset(p) + 2) + ) } /** * Gets the regular expression to match each individual part of a conversion specifier. */ private string getMaxWidthRegexp() { result = "(?:[1-9][0-9]*)?" } + private string getLengthRegexp() { result = "(?:hh?|ll?|L|q|j|z|t)?" } + private string getConvCharRegexp() { result = "[aAcCdeEfFgGimnopsSuxX]" } /** @@ -223,7 +195,8 @@ class ScanfFormatLiteral extends Expr { // 2 - maximum width // 3 - length modifier // 4 - conversion character - result = "(\\%("+this.getMaxWidthRegexp()+")("+this.getLengthRegexp()+")("+this.getConvCharRegexp()+")).*" + result = "(\\%(" + this.getMaxWidthRegexp() + ")(" + this.getLengthRegexp() + ")(" + + this.getConvCharRegexp() + ")).*" } /** @@ -241,11 +214,12 @@ class ScanfFormatLiteral extends Expr { offset = this.getConvSpecOffset(n) and fmt = this.getFormat() and rst = fmt.substring(offset, fmt.length()) and - regexp = this.getConvSpecRegexp() and ( - spec = rst.regexpCapture(regexp, 1) and + regexp = this.getConvSpecRegexp() and + ( + spec = rst.regexpCapture(regexp, 1) and width = rst.regexpCapture(regexp, 2) and - len = rst.regexpCapture(regexp, 3) and - conv = rst.regexpCapture(regexp, 4) + len = rst.regexpCapture(regexp, 3) and + conv = rst.regexpCapture(regexp, 4) ) ) } @@ -253,7 +227,9 @@ class ScanfFormatLiteral extends Expr { /** * Gets the maximum width option of the nth input (empty string if none is given). */ - string getMaxWidthOpt(int n) { exists(string spec, string len, string conv | this.parseConvSpec(n, spec, result, len, conv)) } + string getMaxWidthOpt(int n) { + exists(string spec, string len, string conv | this.parseConvSpec(n, spec, result, len, conv)) + } /** * Gets the maximum width of the nth input. @@ -263,12 +239,18 @@ class ScanfFormatLiteral extends Expr { /** * Gets the length flag of the nth conversion specifier. */ - string getLength(int n) { exists(string spec, string width, string conv | this.parseConvSpec(n, spec, width, result, conv)) } + string getLength(int n) { + exists(string spec, string width, string conv | + this.parseConvSpec(n, spec, width, result, conv) + ) + } /** * Gets the conversion character of the nth conversion specifier. */ - string getConversionChar(int n) { exists(string spec, string width, string len | this.parseConvSpec(n, spec, width, len, result)) } + string getConversionChar(int n) { + exists(string spec, string width, string len | this.parseConvSpec(n, spec, width, len, result)) + } /** * Gets the maximum length of the string that can be produced by the nth @@ -276,7 +258,7 @@ class ScanfFormatLiteral extends Expr { * possible (or implemented). */ int getMaxConvertedLength(int n) { - (this.getConversionChar(n).toLowerCase() = "s") and - (result = this.getMaxWidth(n)) + this.getConversionChar(n).toLowerCase() = "s" and + result = this.getMaxWidth(n) } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll b/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll index 5c5ba9c1e4d..dce086bdd4b 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Strcat.qll @@ -2,20 +2,20 @@ import cpp /** * DEPRECATED: use `semmle.code.cpp.models.implementations.Strcat.qll` instead. - * + * * A function that concatenates the string from its second argument * to the string from its first argument, for example `strcat`. */ class StrcatFunction extends Function { StrcatFunction() { - exists(string name | name = getName()| - name = "strcat" // strcat(dst, src) - or name = "strncat" // strncat(dst, src, max_amount) - or name = "wcscat" // wcscat(dst, src) - or name = "_mbscat" // _mbscat(dst, src) - or name = "wcsncat" // wcsncat(dst, src, max_amount) - or name = "_mbsncat" // _mbsncat(dst, src, max_amount) - or name = "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) + exists(string name | name = getName() | + name = "strcat" or // strcat(dst, src) + name = "strncat" or // strncat(dst, src, max_amount) + name = "wcscat" or // wcscat(dst, src) + name = "_mbscat" or // _mbscat(dst, src) + name = "wcsncat" or // wcsncat(dst, src, max_amount) + name = "_mbsncat" or // _mbsncat(dst, src, max_amount) + name = "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) ) } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll b/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll index 2fafb53fa77..e10e52df07d 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll @@ -4,35 +4,30 @@ import semmle.code.cpp.controlflow.SSA /** * Holds if a value can flow directly from one expr to another. */ -predicate canValueFlow(Expr fromExpr, Expr toExpr) -{ - ( - // value propagated via a definition use pair - exists(Variable v, SsaDefinition def | fromExpr = def.getAnUltimateDefiningValue(v) | - toExpr = def.getAUse(v) - ) - ) or ( - // expr -> containing parenthesized expression - fromExpr = toExpr.(ParenthesisExpr).getExpr() - ) or ( - // R value -> containing assignment expression ('=' assignment) - fromExpr = toExpr.(AssignExpr).getRValue() - ) or ( - // then -> containing ternary (? :) operator - fromExpr = toExpr.(ConditionalExpr).getThen() - ) or ( - // else -> containing ternary (? :) operator - fromExpr = toExpr.(ConditionalExpr).getElse() +predicate canValueFlow(Expr fromExpr, Expr toExpr) { + // value propagated via a definition use pair + exists(Variable v, SsaDefinition def | fromExpr = def.getAnUltimateDefiningValue(v) | + toExpr = def.getAUse(v) ) + or + // expr -> containing parenthesized expression + fromExpr = toExpr.(ParenthesisExpr).getExpr() + or + // R value -> containing assignment expression ('=' assignment) + fromExpr = toExpr.(AssignExpr).getRValue() + or + // then -> containing ternary (? :) operator + fromExpr = toExpr.(ConditionalExpr).getThen() + or + // else -> containing ternary (? :) operator + fromExpr = toExpr.(ConditionalExpr).getElse() } /** * An analysed null terminated string. */ -class AnalysedString extends Expr -{ - AnalysedString() - { +class AnalysedString extends Expr { + AnalysedString() { this.getUnspecifiedType() instanceof ArrayType or this.getUnspecifiedType() instanceof PointerType } @@ -41,12 +36,14 @@ class AnalysedString extends Expr * Gets the maximum length (including null) this string can be, when this * can be calculated. */ - int getMaxLength() - { + int getMaxLength() { // take the longest AnalysedString it's value could 'flow' from; however if even one doesn't // return a value (this essentially means 'infinity') we can't return a value either. - result = max(AnalysedString expr, int toMax | (canValueFlow*(expr, this)) and (toMax = expr.(StringLiteral).getOriginalLength()) | toMax) // maximum length - and + result = max(AnalysedString expr, int toMax | + canValueFlow*(expr, this) and toMax = expr.(StringLiteral).getOriginalLength() + | + toMax + ) and // maximum length forall(AnalysedString expr | canValueFlow(expr, this) | exists(expr.getMaxLength())) // all sources return a value (recursive) } } @@ -67,7 +64,5 @@ class StrlenCall extends FunctionCall { /** * The string argument passed into this strlen-like call. */ - Expr getStringExpr() { - result = this.getArgument(0) - } + Expr getStringExpr() { result = this.getArgument(0) } } diff --git a/cpp/ql/src/semmle/code/cpp/commons/StructLikeClass.qll b/cpp/ql/src/semmle/code/cpp/commons/StructLikeClass.qll index c2282bc83a0..48a91b75f97 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/StructLikeClass.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/StructLikeClass.qll @@ -6,19 +6,20 @@ import semmle.code.cpp.Class * real encapsulation. */ class StructLikeClass extends Class { - StructLikeClass() { this instanceof Struct or - ( - forall(MemberFunction f | f = this.getAMemberFunction() | - exists(MemberVariable v | setter(v, f, this) or getter(v, f, this)) or - f instanceof Constructor or - f instanceof Destructor or - // Allow the copy and move assignment ops - still struct-like - f instanceof CopyAssignmentOperator or - f instanceof MoveAssignmentOperator - ) + forall(MemberFunction f | f = this.getAMemberFunction() | + exists(MemberVariable v | setter(v, f, this) or getter(v, f, this)) + or + f instanceof Constructor + or + f instanceof Destructor + or + // Allow the copy and move assignment ops - still struct-like + f instanceof CopyAssignmentOperator + or + f instanceof MoveAssignmentOperator ) } @@ -28,9 +29,7 @@ class StructLikeClass extends Class { * member variable of the class. In addition, it takes a single parameter of * type the type of the corresponding member variable. */ - MemberFunction getASetter(MemberVariable v) { - setter(v, result, this) - } + MemberFunction getASetter(MemberVariable v) { setter(v, result, this) } /** * Gets a getter function in this class, getting the given variable. @@ -38,10 +37,7 @@ class StructLikeClass extends Class { * member variable of the class. In addition, its return type is the type * of the corresponding member variable. */ - MemberFunction getAGetter(MemberVariable v) { - getter(v, result, this) - } - + MemberFunction getAGetter(MemberVariable v) { getter(v, result, this) } } /** @@ -49,17 +45,13 @@ class StructLikeClass extends Class { * See `StructLikeClass.getASetter`. */ predicate setter(MemberVariable v, MemberFunction f, Class c) { - f.getDeclaringType() = c and - v.getDeclaringType() = c and - f.getName().matches("set%") and - v.getAnAssignedValue().getEnclosingFunction() = f and - forall(MemberVariable v2 | - v2.getAnAssignedValue().getEnclosingFunction() = f - | - v2 = v - ) and - f.getNumberOfParameters() = 1 and - f.getParameter(0).getType().stripType() = v.getType().stripType() + f.getDeclaringType() = c and + v.getDeclaringType() = c and + f.getName().matches("set%") and + v.getAnAssignedValue().getEnclosingFunction() = f and + forall(MemberVariable v2 | v2.getAnAssignedValue().getEnclosingFunction() = f | v2 = v) and + f.getNumberOfParameters() = 1 and + f.getParameter(0).getType().stripType() = v.getType().stripType() } /** @@ -67,15 +59,11 @@ predicate setter(MemberVariable v, MemberFunction f, Class c) { * See `StructLikeClass.getAGetter`. */ predicate getter(MemberVariable v, MemberFunction f, Class c) { - f.getDeclaringType() = c and - v.getDeclaringType() = c and - f.getName().matches("get%") and - v.getAnAccess().getEnclosingFunction() = f and - forall(MemberVariable v2 | - v2.getAnAccess().getEnclosingFunction() = f - | - v2 = v - ) and - f.getNumberOfParameters() = 0 and - f.getType().stripType() = v.getType().stripType() + f.getDeclaringType() = c and + v.getDeclaringType() = c and + f.getName().matches("get%") and + v.getAnAccess().getEnclosingFunction() = f and + forall(MemberVariable v2 | v2.getAnAccess().getEnclosingFunction() = f | v2 = v) and + f.getNumberOfParameters() = 0 and + f.getType().stripType() = v.getType().stripType() } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll b/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll index 0fe8077a94e..c680cfb073e 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Synchronization.qll @@ -2,6 +2,7 @@ * Utilities for analyzing synchronization primitives, such * as mutexes and semaphores. */ + import cpp /** @@ -18,13 +19,13 @@ abstract class MutexType extends Type { /** * Holds if `fc` is a call that tries to lock mutex `arg` * of this type, but may return without success. - */ + */ abstract predicate trylockAccess(FunctionCall fc, Expr arg); /** * Holds if `fc` is a call that unlocks mutex `arg` * of this type. - */ + */ abstract predicate unlockAccess(FunctionCall fc, Expr arg); /** @@ -46,84 +47,70 @@ abstract class MutexType extends Type { } /** - * Holds if `fc` is a call that always locks any mutex of this type. + * Holds if `fc` is a call that always locks any mutex of this type. */ - FunctionCall getMustlockAccess() { - this.mustlockAccess(result, _) - } + FunctionCall getMustlockAccess() { this.mustlockAccess(result, _) } /** * Holds if `fc` is a call that tries to lock any mutex of this type, - * by may return without success. + * by may return without success. */ - FunctionCall getTrylockAccess() { - this.trylockAccess(result, _) - } + FunctionCall getTrylockAccess() { this.trylockAccess(result, _) } /** - * Holds if `fc` is a call that unlocks any mutex of this type. + * Holds if `fc` is a call that unlocks any mutex of this type. */ - FunctionCall getUnlockAccess() { - this.unlockAccess(result, _) - } + FunctionCall getUnlockAccess() { this.unlockAccess(result, _) } /** * DEPRECATED: use mustlockAccess(fc, arg) instead */ - deprecated Function getMustlockFunction() { - result = getMustlockAccess().getTarget() - } + deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() } /** * DEPRECATED: use trylockAccess(fc, arg) instead */ - deprecated Function getTrylockFunction() { - result = getTrylockAccess().getTarget() - } + deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() } /** * DEPRECATED: use lockAccess(fc, arg) instead */ - deprecated Function getLockFunction() { - result = getLockAccess().getTarget() - } + deprecated Function getLockFunction() { result = getLockAccess().getTarget() } /** * DEPRECATED: use unlockAccess(fc, arg) instead */ - deprecated Function getUnlockFunction() { - result = getUnlockAccess().getTarget() - } + deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() } } /** * A function that looks like a lock function. */ private Function mustlockCandidate() { - exists (string name - | name = result.getName() - | name = "lock" or - name.suffix(name.length() - 10) = "mutex_lock") + exists(string name | name = result.getName() | + name = "lock" or + name.suffix(name.length() - 10) = "mutex_lock" + ) } /** * A function that looks like a try-lock function. */ private Function trylockCandidate() { - exists (string name - | name = result.getName() - | name = "try_lock" or - name.suffix(name.length() - 13) = "mutex_trylock") + exists(string name | name = result.getName() | + name = "try_lock" or + name.suffix(name.length() - 13) = "mutex_trylock" + ) } /** * A function that looks like an unlock function. */ private Function unlockCandidate() { - exists (string name - | name = result.getName() - | name = "unlock" or - name.suffix(name.length() - 12) = "mutex_unlock") + exists(string name | name = result.getName() | + name = "unlock" or + name.suffix(name.length() - 12) = "mutex_unlock" + ) } /** @@ -141,14 +128,13 @@ private Class lockArgTypeCandidate(Function fcn) { /** * A class or struct type that has both a lock and an unlock function * candidate, and is therefore a mutex. - * + * * This excludes types like `std::weak_ptr` which has a lock * method, but not an unlock method, and is not a mutex.) */ class DefaultMutexType extends MutexType { DefaultMutexType() { - this = lockArgTypeCandidate(mustlockCandidate()) - and + this = lockArgTypeCandidate(mustlockCandidate()) and this = lockArgTypeCandidate(unlockCandidate()) } @@ -156,17 +142,17 @@ class DefaultMutexType extends MutexType { exists(int n | arg = fc.getArgument(n) and fc.getTarget().getParameter(n).getType().stripType() = this - ) or ( - fc.getTarget().getDeclaringType() = this and - arg = fc.getQualifier() - ) or ( - // if we're calling our own method with an implicit `this`, - // let `arg` be the function call, since we don't really have - // anything else to use. - fc.getTarget().getDeclaringType() = this and - not exists(fc.getQualifier()) and - arg = fc ) + or + fc.getTarget().getDeclaringType() = this and + arg = fc.getQualifier() + or + // if we're calling our own method with an implicit `this`, + // let `arg` be the function call, since we don't really have + // anything else to use. + fc.getTarget().getDeclaringType() = this and + not exists(fc.getQualifier()) and + arg = fc } override predicate mustlockAccess(FunctionCall fc, Expr arg) { diff --git a/cpp/ql/src/semmle/code/cpp/commons/VoidContext.qll b/cpp/ql/src/semmle/code/cpp/commons/VoidContext.qll index 652fecb419e..08def499e13 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/VoidContext.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/VoidContext.qll @@ -5,9 +5,9 @@ import semmle.code.cpp.exprs.Expr */ class Qualifier extends Expr { Qualifier() { - exists(VariableAccess a | a.getQualifier() = this) - or exists(Call c | c.getQualifier() = this) - or exists(VacuousDestructorCall v | v.getQualifier() = this) + exists(VariableAccess a | a.getQualifier() = this) or + exists(Call c | c.getQualifier() = this) or + exists(VacuousDestructorCall v | v.getQualifier() = this) } } @@ -18,21 +18,24 @@ class Qualifier extends Expr { * Expressions that are explicitly cast to void are not considered to be in void context. */ class ExprInVoidContext extends Expr { - ExprInVoidContext() { - exprInVoidContext(this) - } + ExprInVoidContext() { exprInVoidContext(this) } } private predicate exprInVoidContext(Expr e) { - ( exists(ExprStmt s | - s = e.getParent() - and not exists(StmtExpr se | - s = se.getStmt().(Block).getLastStmt())) - or exists(ConditionalExpr c | c.getThen() = e and c instanceof ExprInVoidContext) - or exists(ConditionalExpr c | c.getElse() = e and c instanceof ExprInVoidContext) - or exists(CommaExpr c | c.getLeftOperand() = e) - or exists(CommaExpr c | c.getRightOperand() = e and c instanceof ExprInVoidContext)) and - not e instanceof Qualifier and - not e.getActualType() instanceof VoidType + ( + exists(ExprStmt s | + s = e.getParent() and + not exists(StmtExpr se | s = se.getStmt().(Block).getLastStmt()) + ) + or + exists(ConditionalExpr c | c.getThen() = e and c instanceof ExprInVoidContext) + or + exists(ConditionalExpr c | c.getElse() = e and c instanceof ExprInVoidContext) + or + exists(CommaExpr c | c.getLeftOperand() = e) + or + exists(CommaExpr c | c.getRightOperand() = e and c instanceof ExprInVoidContext) + ) and + not e instanceof Qualifier and + not e.getActualType() instanceof VoidType } - diff --git a/cpp/ql/src/semmle/code/cpp/commons/unix/Constants.qll b/cpp/ql/src/semmle/code/cpp/commons/unix/Constants.qll index c3174c87b87..9a2d3d7f9c8 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/unix/Constants.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/unix/Constants.qll @@ -1,97 +1,57 @@ /** * Standard Unix constants. */ + import cpp bindingset[input] int parseOctal(string input) { - input.charAt(0) = "0" - and - result = strictsum(int ix - | ix in [0 .. input.length()] - | 8.pow(input.length() - (ix+1))*input.charAt(ix).toInt()) + input.charAt(0) = "0" and + result = strictsum(int ix | + ix in [0 .. input.length()] + | + 8.pow(input.length() - (ix + 1)) * input.charAt(ix).toInt() + ) } -int s_isuid() { - result = parseOctal("04000") -} +int s_isuid() { result = parseOctal("04000") } -int s_isgid() { - result = parseOctal("02000") -} +int s_isgid() { result = parseOctal("02000") } -int s_isvtx() { - result = parseOctal("01000") -} +int s_isvtx() { result = parseOctal("01000") } -int s_irusr() { - result = parseOctal("0400") -} +int s_irusr() { result = parseOctal("0400") } -int s_iwusr() { - result = parseOctal("0200") -} +int s_iwusr() { result = parseOctal("0200") } -int s_ixusr() { - result = parseOctal("0100") -} +int s_ixusr() { result = parseOctal("0100") } -int s_irwxu() { - result = s_irusr().bitOr(s_iwusr()).bitOr(s_ixusr()) -} +int s_irwxu() { result = s_irusr().bitOr(s_iwusr()).bitOr(s_ixusr()) } -int s_irgrp() { - result = s_irusr().bitShiftRight(3) -} +int s_irgrp() { result = s_irusr().bitShiftRight(3) } -int s_iwgrp() { - result = s_iwusr().bitShiftRight(3) -} +int s_iwgrp() { result = s_iwusr().bitShiftRight(3) } -int s_ixgrp() { - result = s_ixusr().bitShiftRight(3) -} +int s_ixgrp() { result = s_ixusr().bitShiftRight(3) } -int s_irwxg() { - result = s_irwxu().bitShiftRight(3) -} +int s_irwxg() { result = s_irwxu().bitShiftRight(3) } -int s_iroth() { - result = s_irgrp().bitShiftRight(3) -} +int s_iroth() { result = s_irgrp().bitShiftRight(3) } -int s_iwoth() { - result = s_iwgrp().bitShiftRight(3) -} +int s_iwoth() { result = s_iwgrp().bitShiftRight(3) } -int s_ixoth() { - result = s_ixgrp().bitShiftRight(3) -} +int s_ixoth() { result = s_ixgrp().bitShiftRight(3) } -int s_irwxo() { - result = s_irwxg().bitShiftRight(3) -} +int s_irwxo() { result = s_irwxg().bitShiftRight(3) } -int o_accmode() { - result = parseOctal("0003") -} +int o_accmode() { result = parseOctal("0003") } -int o_rdonly() { - result = parseOctal("00") -} +int o_rdonly() { result = parseOctal("00") } -int o_wronly() { - result = parseOctal("01") -} +int o_wronly() { result = parseOctal("01") } -int o_rdwr() { - result = parseOctal("02") -} +int o_rdwr() { result = parseOctal("02") } -int o_creat() { - result = parseOctal("0100") -} +int o_creat() { result = parseOctal("0100") } -int o_excl() { - result = parseOctal("0200") -} \ No newline at end of file +int o_excl() { result = parseOctal("0200") } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/BasicBlocks.qll b/cpp/ql/src/semmle/code/cpp/controlflow/BasicBlocks.qll index d59a27b691c..681d0b710f6 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/BasicBlocks.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/BasicBlocks.qll @@ -42,7 +42,9 @@ private import internal.ConstantExprs */ private import Cached -private cached module Cached { + +cached +private module Cached { /** * Any node that is the entry point of a primitive basic block is * also the entry point of a basic block. In addition, all nodes @@ -80,8 +82,7 @@ private cached module Cached { * reuse predicates already computed for `PrimitiveBasicBlocks`. */ private predicate equalsPrimitiveBasicBlock(BasicBlock bb) { - primitive_basic_block_entry_node(bb) - and + primitive_basic_block_entry_node(bb) and not exists(int i | i > 0 and non_primitive_basic_block_entry_node(bb.(PrimitiveBasicBlock).getNode(i)) @@ -89,34 +90,35 @@ private cached module Cached { } /** Holds if `node` is the `pos`th control-flow node in basic block `bb`. */ - cached predicate basic_block_member(ControlFlowNode node, BasicBlock bb, int pos) { + cached + predicate basic_block_member(ControlFlowNode node, BasicBlock bb, int pos) { equalsPrimitiveBasicBlock(bb) and primitive_basic_block_member(node, bb, pos) // reuse already computed relation or non_primitive_basic_block_member(node, bb, pos) } private predicate non_primitive_basic_block_member(ControlFlowNode node, BasicBlock bb, int pos) { - (not equalsPrimitiveBasicBlock(bb) and node = bb and pos = 0) + not equalsPrimitiveBasicBlock(bb) and node = bb and pos = 0 or - (not (node instanceof BasicBlock) and - exists (ControlFlowNode pred - | successors_extended(pred, node) - | non_primitive_basic_block_member(pred, bb, pos - 1))) + not node instanceof BasicBlock and + exists(ControlFlowNode pred | successors_extended(pred, node) | + non_primitive_basic_block_member(pred, bb, pos - 1) + ) } /** Gets the number of control-flow nodes in the basic block `bb`. */ - cached int bb_length(BasicBlock bb) { - if equalsPrimitiveBasicBlock(bb) then - result = bb.(PrimitiveBasicBlock).length() // reuse already computed relation - else - result = strictcount(ControlFlowNode node | basic_block_member(node, bb, _)) + cached + int bb_length(BasicBlock bb) { + if equalsPrimitiveBasicBlock(bb) + then result = bb.(PrimitiveBasicBlock).length() // reuse already computed relation + else result = strictcount(ControlFlowNode node | basic_block_member(node, bb, _)) } /** Successor relation for basic blocks. */ cached predicate bb_successor_cached(BasicBlock pred, BasicBlock succ) { exists(ControlFlowNode last | - basic_block_member(last, pred, bb_length(pred)-1) and + basic_block_member(last, pred, bb_length(pred) - 1) and last.getASuccessor() = succ ) } @@ -144,51 +146,28 @@ predicate bb_successor = bb_successor_cached/2; * ``` */ class BasicBlock extends ControlFlowNodeBase { + BasicBlock() { basic_block_entry_node(this) } - BasicBlock() { - basic_block_entry_node(this) - } + predicate contains(ControlFlowNode node) { basic_block_member(node, this, _) } - predicate contains(ControlFlowNode node) { - basic_block_member(node, this, _) - } + ControlFlowNode getNode(int pos) { basic_block_member(result, this, pos) } - ControlFlowNode getNode(int pos) { - basic_block_member(result, this, pos) - } + ControlFlowNode getANode() { basic_block_member(result, this, _) } - ControlFlowNode getANode() { - basic_block_member(result, this, _) - } + BasicBlock getASuccessor() { bb_successor(this, result) } - BasicBlock getASuccessor() { - bb_successor(this, result) - } + BasicBlock getAPredecessor() { bb_successor(result, this) } - BasicBlock getAPredecessor() { - bb_successor(result, this) - } + BasicBlock getATrueSuccessor() { result.getStart() = this.getEnd().getATrueSuccessor() } - BasicBlock getATrueSuccessor() { - result.getStart() = this.getEnd().getATrueSuccessor() - } + BasicBlock getAFalseSuccessor() { result.getStart() = this.getEnd().getAFalseSuccessor() } - BasicBlock getAFalseSuccessor() { - result.getStart() = this.getEnd().getAFalseSuccessor() - } + ControlFlowNode getEnd() { basic_block_member(result, this, bb_length(this) - 1) } - ControlFlowNode getEnd() { - basic_block_member(result, this, bb_length(this)-1) - } - - ControlFlowNode getStart() { - result = this - } + ControlFlowNode getStart() { result = this } /** Gets the number of `ControlFlowNode`s in this basic block. */ - int length() { - result = bb_length(this) - } + int length() { result = bb_length(this) } /** * Holds if this element is at the specified location. @@ -199,20 +178,21 @@ class BasicBlock extends ControlFlowNodeBase { * * Yields no result if this basic block spans multiple source files. */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { hasLocationInfoInternal(filepath, startline, startcolumn, filepath, endline, endcolumn) } - pragma[noinline] private - predicate hasLocationInfoInternal(string file, int line, int col, string endf, int endl, int endc) { - this.getStart().getLocation().hasLocationInfo(file, line, col, _, _) - and + pragma[noinline] + private predicate hasLocationInfoInternal( + string file, int line, int col, string endf, int endl, int endc + ) { + this.getStart().getLocation().hasLocationInfo(file, line, col, _, _) and this.getEnd().getLocation().hasLocationInfo(endf, _, _, endl, endc) } - Function getEnclosingFunction() { - result = this.getStart().getControlFlowScope() - } + Function getEnclosingFunction() { result = this.getStart().getControlFlowScope() } /** * Holds if this basic block is in a loop of the control-flow graph. This @@ -220,9 +200,7 @@ class BasicBlock extends ControlFlowNodeBase { * even if this basic block is syntactically inside a `while` loop if the * necessary back edges are unreachable. */ - predicate inLoop() { - this.getASuccessor+() = this - } + predicate inLoop() { this.getASuccessor+() = this } /** * DEPRECATED since version 1.11: this predicate does not match the standard @@ -233,9 +211,9 @@ class BasicBlock extends ControlFlowNodeBase { * this basic block. A typical example would be the basic block that computes * `x > 0` in an outermost loop `while (x > 0) { ... }`. */ - deprecated - predicate isLoopHeader() { - this.inLoop() and exists(BasicBlock pred | pred = this.getAPredecessor() and not pred = this.getASuccessor+()) + deprecated predicate isLoopHeader() { + this.inLoop() and + exists(BasicBlock pred | pred = this.getAPredecessor() and not pred = this.getASuccessor+()) } /** @@ -251,15 +229,13 @@ class BasicBlock extends ControlFlowNodeBase { this.(Handler).getTryStmt() = t and tryblock.isReachable() and tryblock.contains(t) - ) or + ) + or exists(BasicBlock pred | pred.getASuccessor() = this and pred.isReachable()) } /** Means `not isReachable()`. */ - predicate isUnreachable() { - not this.isReachable() - } - + predicate isUnreachable() { not this.isReachable() } } /** Correct relation for reachability of ControlFlowNodes. */ @@ -271,9 +247,7 @@ predicate unreachable(ControlFlowNode n) { * An entry point of a function. */ class EntryBasicBlock extends BasicBlock { - EntryBasicBlock() { - exists (Function f | this = f.getEntryPoint()) - } + EntryBasicBlock() { exists(Function f | this = f.getEntryPoint()) } } /** diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/ControlFlowGraph.qll b/cpp/ql/src/semmle/code/cpp/controlflow/ControlFlowGraph.qll index cd51a1d64a2..e4965cb8637 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/ControlFlowGraph.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/ControlFlowGraph.qll @@ -66,13 +66,11 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase { * taken when this expression is false. */ ControlFlowNode getAFalseSuccessor() { - falsecond_base(this,result) and + falsecond_base(this, result) and result = getASuccessor() } - BasicBlock getBasicBlock() { - result.getANode() = this - } + BasicBlock getBasicBlock() { result.getANode() = this } } import ControlFlowGraphPublic @@ -85,8 +83,7 @@ import ControlFlowGraphPublic * This class can be used as base class for classes that want to inherit the * extent of `ControlFlowNode` without inheriting its public member predicates. */ -class ControlFlowNodeBase extends ElementBase, @cfgnode { -} +class ControlFlowNodeBase extends ElementBase, @cfgnode { } predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) { truecond(unresolveElement(n1), unresolveElement(n2)) @@ -122,8 +119,7 @@ abstract class AdditionalControlFlowEdge extends ControlFlowNodeBase { * the extractor-generated control-flow graph or in a subclass of * `AdditionalControlFlowEdge`. Use this relation instead of `successors`. */ -predicate successors_extended( - ControlFlowNodeBase source, ControlFlowNodeBase target) { +predicate successors_extended(ControlFlowNodeBase source, ControlFlowNodeBase target) { successors(unresolveElement(source), unresolveElement(target)) or source.(AdditionalControlFlowEdge).getAnEdgeTarget() = target diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll index 0f5126666cf..99fb6966099 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll @@ -2,6 +2,7 @@ * Provides a simple data flow analysis to find expressions that are definitely * null or that may be null. */ + import cpp import Nullness import Dereferenced @@ -15,12 +16,15 @@ abstract class DataflowAnnotation extends string { DataflowAnnotation() { this = "pointer-null" or this = "pointer-valid" } abstract predicate isDefault(); + abstract predicate generatedOn(Expr e); + abstract predicate generatedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest); + abstract predicate killedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest); predicate marks(Expr e) { - (this.generatedOn(e) and reachable(e)) + this.generatedOn(e) and reachable(e) or this.marks(e.(AssignExpr).getRValue()) or @@ -28,32 +32,28 @@ abstract class DataflowAnnotation extends string { } predicate marks(LocalScopeVariable v, ControlFlowNode n) { - ( - v.getAnAccess().getEnclosingFunction().getBlock() = n and - this.isDefault() - ) + v.getAnAccess().getEnclosingFunction().getBlock() = n and + this.isDefault() or - ( - this.marks(n.(Initializer).getExpr()) and - v.getInitializer() = n + this.marks(n.(Initializer).getExpr()) and + v.getInitializer() = n + or + exists(ControlFlowNode pred | + this.generatedBy(v, pred, n) and + not this.killedBy(v, pred, n) and + reachable(pred) ) or exists(ControlFlowNode pred | - this.generatedBy(v, pred, n) - and not this.killedBy(v, pred, n) - and reachable(pred) + this.assignedBy(v, pred, n) and + not this.killedBy(v, pred, n) and + reachable(pred) ) or exists(ControlFlowNode pred | - this.assignedBy(v, pred, n) - and not this.killedBy(v, pred, n) - and reachable(pred) - ) - or - exists(ControlFlowNode pred | - this.preservedBy(v, pred, n) - and not this.killedBy(v, pred, n) - and reachable(pred) + this.preservedBy(v, pred, n) and + not this.killedBy(v, pred, n) and + reachable(pred) ) } @@ -86,11 +86,12 @@ class NullnessAnnotation extends DataflowAnnotation { exists(Variable v | v.getAnAccess() = e and (v instanceof GlobalVariable or v instanceof Field) and - this.isDefault()) + this.isDefault() + ) or - (e instanceof Call and this = "pointer-valid") + e instanceof Call and this = "pointer-valid" or - (nullValue(e) and this = "pointer-null") + nullValue(e) and this = "pointer-null" } override predicate killedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) { @@ -113,9 +114,7 @@ class NullnessAnnotation extends DataflowAnnotation { /** * Holds if evaluation of `op` dereferences `v`. */ -predicate deref(Variable v, Expr op) { - dereferencedByOperation(op, v.getAnAccess()) -} +predicate deref(Variable v, Expr op) { dereferencedByOperation(op, v.getAnAccess()) } /** * Holds if `call` passes `v` by reference, either with an explicit address-of @@ -128,7 +127,7 @@ predicate callByReference(Call call, Variable v) { ( arg.(AddressOfExpr).getAChild() = v.getAnAccess() or - (v.getAnAccess() = arg and arg.getConversion*() instanceof ReferenceToExpr) + v.getAnAccess() = arg and arg.getConversion*() instanceof ReferenceToExpr ) ) } @@ -137,14 +136,11 @@ predicate callByReference(Call call, Variable v) { * Holds if a simple data-flow analysis determines that `e` is definitely null. */ predicate definitelyNull(Expr e) { - "pointer-null".(NullnessAnnotation).marks(e) - and + "pointer-null".(NullnessAnnotation).marks(e) and not "pointer-valid".(NullnessAnnotation).marks(e) } /** * Holds if a simple data-flow analysis determines that `e` may be null. */ -predicate maybeNull(Expr e) { - "pointer-null".(NullnessAnnotation).marks(e) -} +predicate maybeNull(Expr e) { "pointer-null".(NullnessAnnotation).marks(e) } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/DefinitionsAndUses.qll b/cpp/ql/src/semmle/code/cpp/controlflow/DefinitionsAndUses.qll index c208e59b550..0bac436d16e 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/DefinitionsAndUses.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/DefinitionsAndUses.qll @@ -11,10 +11,8 @@ private import semmle.code.cpp.dataflow.EscapesTree */ predicate definitionUsePair(SemanticStackVariable var, Expr def, Expr use) { exists(Use u | - u = use - and - def.(Def).reaches(true, var, u) - and + u = use and + def.(Def).reaches(true, var, u) and u.getVariable(false) = var ) } @@ -23,9 +21,7 @@ predicate definitionUsePair(SemanticStackVariable var, Expr def, Expr use) { * Holds if the definition `def` of some stack variable can reach `node`, which * is a definition or use, without crossing definitions of the same variable. */ -predicate definitionReaches(Expr def, Expr node) { - def.(Def).reaches(true, _, (DefOrUse)node) -} +predicate definitionReaches(Expr def, Expr node) { def.(Def).reaches(true, _, node.(DefOrUse)) } private predicate hasAddressOfAccess(SemanticStackVariable var) { var.getAnAccess().isAddressOfAccessNonConst() @@ -39,7 +35,8 @@ private predicate hasAddressOfAccess(SemanticStackVariable var) { */ predicate useUsePair(SemanticStackVariable var, Expr first, Expr second) { ( - /* If the address of `var` is used anywhere, we require that + /* + * If the address of `var` is used anywhere, we require that * a definition of `var` can reach the first use. This is to * rule out examples such as this: * ``` @@ -50,21 +47,16 @@ predicate useUsePair(SemanticStackVariable var, Expr first, Expr second) { * use(x); // not a use-use pair with the use above * ``` */ - hasAddressOfAccess(var) - implies - definitionUsePair(var, _, first) - ) - and + + hasAddressOfAccess(var) implies definitionUsePair(var, _, first) + ) and // If `first` is both a def and a use, like `x` in `f(x)` when `f` takes a // reference parameter, it'll play the role of a use first and a def second. // We are not interested in uses that follow its role as a def. - not definition(var, first) - and + not definition(var, first) and exists(Use u | - u = second - and - first.(Use).reaches(false, var, u) - and + u = second and + first.(Use).reaches(false, var, u) and u.getVariable(false) = var ) } @@ -76,14 +68,13 @@ predicate useUsePair(SemanticStackVariable var, Expr first, Expr second) { predicate parameterUsePair(Parameter p, VariableAccess va) { not parameterIsOverwritten(_, p) and va.getTarget() = p or - exists(ParameterDef pd | pd.reaches(true, p, (Use)va)) + exists(ParameterDef pd | pd.reaches(true, p, va.(Use))) } /** * Utility class: A definition or use of a stack variable. */ -library -class DefOrUse extends ControlFlowNodeBase { +library class DefOrUse extends ControlFlowNodeBase { DefOrUse() { // Uninstantiated templates are purely syntax, and only on instantiation // will they be complete with information about types, conversions, call @@ -114,20 +105,19 @@ class DefOrUse extends ControlFlowNodeBase { */ cached predicate reaches(boolean isDef, SemanticStackVariable v, DefOrUse defOrUse) { - /* Implementation detail: this predicate and its private auxiliary + /* + * Implementation detail: this predicate and its private auxiliary * predicates are instances of the more general predicates in * LocalScopeVariableReachability.qll, and should be kept in sync. * * Unfortunately, caching of abstract predicates does not work well, so the * predicates are duplicated for now. */ - exists(BasicBlock bb, int i | - reaches_helper(isDef, v, bb, i) | + + exists(BasicBlock bb, int i | reaches_helper(isDef, v, bb, i) | exists(int j | - j > i - and - (bbDefAt(bb, j, v, defOrUse) or bbUseAt(bb, j, v, defOrUse)) - and + j > i and + (bbDefAt(bb, j, v, defOrUse) or bbUseAt(bb, j, v, defOrUse)) and not exists(int k | firstBarrierAfterThis(isDef, k, v) and k < j) ) or @@ -138,20 +128,15 @@ class DefOrUse extends ControlFlowNodeBase { private predicate firstBarrierAfterThis(boolean isDef, int j, SemanticStackVariable v) { exists(BasicBlock bb, int i | - getVariable(isDef) = v - and - bb.getNode(i) = this - and + getVariable(isDef) = v and + bb.getNode(i) = this and j = min(int k | bbBarrierAt(bb, k, v, _) and k > i) ) } } -library -class Def extends DefOrUse { - Def() { - definition(_, this) - } +library class Def extends DefOrUse { + Def() { definition(_, this) } override SemanticStackVariable getVariable(boolean isDef) { definition(result, this) and isDef = true @@ -164,8 +149,7 @@ private predicate parameterIsOverwritten(Function f, Parameter p) { definitionBarrier(p, _) } -library -class ParameterDef extends DefOrUse { +library class ParameterDef extends DefOrUse { ParameterDef() { // Optimization: parameters that are not overwritten do not require // reachability analysis @@ -173,17 +157,13 @@ class ParameterDef extends DefOrUse { } override SemanticStackVariable getVariable(boolean isDef) { - exists(Function f | parameterIsOverwritten(f, result) | this = f.getEntryPoint()) - and + exists(Function f | parameterIsOverwritten(f, result) | this = f.getEntryPoint()) and isDef = true } } -library -class Use extends DefOrUse { - Use() { - useOfVar(_, this) - } +library class Use extends DefOrUse { + Use() { useOfVar(_, this) } override SemanticStackVariable getVariable(boolean isDef) { useOfVar(result, this) and isDef = false @@ -191,20 +171,17 @@ class Use extends DefOrUse { } private predicate bbUseAt(BasicBlock bb, int i, SemanticStackVariable v, Use use) { - bb.getNode(i) = use - and + bb.getNode(i) = use and use.getVariable(false) = v } private predicate bbDefAt(BasicBlock bb, int i, SemanticStackVariable v, Def def) { - bb.getNode(i) = def - and + bb.getNode(i) = def and def.getVariable(true) = v } private predicate bbBarrierAt(BasicBlock bb, int i, SemanticStackVariable v, ControlFlowNode node) { - bb.getNode(i) = node - and + bb.getNode(i) = node and definitionBarrier(v, node) } @@ -219,9 +196,14 @@ private predicate bbBarrierAt(BasicBlock bb, int i, SemanticStackVariable v, Con * true upon entry, is skipped (including the step from `bb` to the * successor). */ -private predicate bbSuccessorEntryReachesDefOrUse(BasicBlock bb, SemanticStackVariable v, DefOrUse defOrUse, boolean skipsFirstLoopAlwaysTrueUponEntry) { +private predicate bbSuccessorEntryReachesDefOrUse( + BasicBlock bb, SemanticStackVariable v, DefOrUse defOrUse, + boolean skipsFirstLoopAlwaysTrueUponEntry +) { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | - bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) | + bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, + succSkipsFirstLoopAlwaysTrueUponEntry) + | bbEntryReachesDefOrUseLocally(succ, v, defOrUse) and succSkipsFirstLoopAlwaysTrueUponEntry = false and not excludeReachesFunction(bb.getEnclosingFunction()) @@ -231,9 +213,10 @@ private predicate bbSuccessorEntryReachesDefOrUse(BasicBlock bb, SemanticStackVa ) } -private predicate bbEntryReachesDefOrUseLocally(BasicBlock bb, SemanticStackVariable v, DefOrUse defOrUse) { - exists(int n | - bbDefAt(bb, n, v, defOrUse) or bbUseAt(bb, n, v, defOrUse) | +private predicate bbEntryReachesDefOrUseLocally( + BasicBlock bb, SemanticStackVariable v, DefOrUse defOrUse +) { + exists(int n | bbDefAt(bb, n, v, defOrUse) or bbUseAt(bb, n, v, defOrUse) | not exists(int m | m < n | bbBarrierAt(bb, m, v, _)) ) } @@ -270,15 +253,14 @@ predicate definitionBarrier(SemanticStackVariable v, ControlFlowNode barrier) { predicate definition(SemanticStackVariable v, Expr def) { def = v.getInitializer().getExpr() or - variableAccessedAsValue( - v.getAnAccess(), def.(Assignment).getLValue().getFullyConverted()) + variableAccessedAsValue(v.getAnAccess(), def.(Assignment).getLValue().getFullyConverted()) or - variableAccessedAsValue( - v.getAnAccess(), def.(CrementOperation).getOperand().getFullyConverted()) + variableAccessedAsValue(v.getAnAccess(), def.(CrementOperation).getOperand().getFullyConverted()) or exists(AsmStmt asmStmt | def = asmStmt.getAChild() and - def = v.getAnAccess().getParent*()) + def = v.getAnAccess().getParent*() + ) or definitionByReference(v.getAnAccess(), def) } @@ -288,11 +270,9 @@ predicate definition(SemanticStackVariable v, Expr def) { * the assigned expression. */ predicate exprDefinition(SemanticStackVariable v, ControlFlowNode def, Expr e) { - ( - def = v.getInitializer().getExpr() and - def = e and - not v.getType() instanceof ReferenceType - ) + def = v.getInitializer().getExpr() and + def = e and + not v.getType() instanceof ReferenceType or exists(AssignExpr assign | def = assign and @@ -302,9 +282,7 @@ predicate exprDefinition(SemanticStackVariable v, ControlFlowNode def, Expr e) { } pragma[noinline] -private predicate containsAssembly(Function f) { - f = any(AsmStmt s).getEnclosingFunction() -} +private predicate containsAssembly(Function f) { f = any(AsmStmt s).getEnclosingFunction() } /** * Holds if `va` is a variable passed by reference as argument `def`, where the @@ -320,12 +298,9 @@ private predicate containsAssembly(Function f) { */ predicate definitionByReference(VariableAccess va, Expr def) { exists(Call c, int i | - c.passesByReferenceNonConst(i, va) - and - def = c.getArgument(i) - and - forall(Function f | - f = c.getTarget() and f.hasEntryPoint() | + c.passesByReferenceNonConst(i, va) and + def = c.getArgument(i) and + forall(Function f | f = c.getTarget() and f.hasEntryPoint() | exists(f.getParameter(i).getAnAccess()) or f.isVarargs() and i >= f.getNumberOfParameters() @@ -348,9 +323,7 @@ predicate definitionByReference(VariableAccess va, Expr def) { ) } -private predicate accessInSizeof(VariableAccess use) { - use.getParent+() instanceof SizeofOperator -} +private predicate accessInSizeof(VariableAccess use) { use.getParent+() instanceof SizeofOperator } /** * Holds if `use` is a non-definition use of stack variable `v`. This will not @@ -375,9 +348,7 @@ predicate useOfVarActual(SemanticStackVariable v, VariableAccess use) { useOfVar(v, use) and exists(Expr e | variableAccessedAsValue(use, e) and - not exists(AssignExpr assign | - e = assign.getLValue().getFullyConverted() - ) + not exists(AssignExpr assign | e = assign.getLValue().getFullyConverted()) ) and // A call to a function that does not use the relevant parameter not exists(Call c, int i | @@ -389,7 +360,7 @@ predicate useOfVarActual(SemanticStackVariable v, VariableAccess use) { /** * A function that should be excluded from 'reaches' analysis. - * + * * The current implementation performs badly in some cases where a * function has both a huge number of def/uses and a huge number of * basic blocks, typically in generated code. We exclude these @@ -397,9 +368,8 @@ predicate useOfVarActual(SemanticStackVariable v, VariableAccess use) { */ private predicate excludeReachesFunction(Function f) { exists(int defOrUses | - defOrUses = - count(Def def | def.(ControlFlowNode).getControlFlowScope() = f) + - count(Use use | use.(ControlFlowNode).getControlFlowScope() = f) and + defOrUses = count(Def def | def.(ControlFlowNode).getControlFlowScope() = f) + + count(Use use | use.(ControlFlowNode).getControlFlowScope() = f) and defOrUses >= 13000 ) } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll index 54c08fc2d7f..cfd3efa91f3 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll @@ -4,27 +4,41 @@ import Nullness /** * Holds if the call `fc` will dereference argument `i`. */ -predicate callDereferences(FunctionCall fc, int i) -{ +predicate callDereferences(FunctionCall fc, int i) { exists(string name | fc.getTarget().hasGlobalName(name) and ( - (name = "bcopy" and i in [0..1]) or - (name = "memcpy" and i in [0..1]) or - (name = "memmove" and i in [0..1]) or - (name = "strcpy" and i in [0..1]) or - (name = "strncpy" and i in [0..1]) or - (name = "strdup" and i = 0) or - (name = "strndup" and i = 0) or - (name = "strlen" and i = 0) or - (name = "printf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "fprintf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "sprintf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "snprintf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "vprintf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "vfprintf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "vsprintf" and fc.getArgument(i).getType() instanceof PointerType) or - (name = "vsnprintf" and fc.getArgument(i).getType() instanceof PointerType) + name = "bcopy" and i in [0 .. 1] + or + name = "memcpy" and i in [0 .. 1] + or + name = "memmove" and i in [0 .. 1] + or + name = "strcpy" and i in [0 .. 1] + or + name = "strncpy" and i in [0 .. 1] + or + name = "strdup" and i = 0 + or + name = "strndup" and i = 0 + or + name = "strlen" and i = 0 + or + name = "printf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "fprintf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "sprintf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "snprintf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "vprintf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "vfprintf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "vsprintf" and fc.getArgument(i).getType() instanceof PointerType + or + name = "vsnprintf" and fc.getArgument(i).getType() instanceof PointerType ) ) } @@ -32,41 +46,52 @@ predicate callDereferences(FunctionCall fc, int i) /** * Holds if evaluation of `op` dereferences `e`. */ -predicate dereferencedByOperation(Expr op, Expr e) -{ +predicate dereferencedByOperation(Expr op, Expr e) { exists(PointerDereferenceExpr deref | - deref.getAChild() = e and deref = op and - not deref.getParent*() instanceof SizeofOperator) + deref.getAChild() = e and + deref = op and + not deref.getParent*() instanceof SizeofOperator + ) or - exists(CrementOperation crement | - dereferencedByOperation(e, op) and crement.getOperand() = e) + exists(CrementOperation crement | dereferencedByOperation(e, op) and crement.getOperand() = e) or exists(ArrayExpr ae | - (not ae.getParent() instanceof AddressOfExpr and - not ae.getParent*() instanceof SizeofOperator) and + ( + not ae.getParent() instanceof AddressOfExpr and + not ae.getParent*() instanceof SizeofOperator + ) and ae = op and ( - (e = ae.getArrayBase() and e.getType() instanceof PointerType) + e = ae.getArrayBase() and e.getType() instanceof PointerType or - (e = ae.getArrayOffset() and e.getType() instanceof PointerType) + e = ae.getArrayOffset() and e.getType() instanceof PointerType ) ) or exists(AddressOfExpr addof, ArrayExpr ae | - dereferencedByOperation(addof, op) and addof.getOperand() = ae and + dereferencedByOperation(addof, op) and + addof.getOperand() = ae and (e = ae.getArrayBase() or e = ae.getArrayOffset()) and - e.getType() instanceof PointerType) + e.getType() instanceof PointerType + ) or exists(UnaryArithmeticOperation arithop | - dereferencedByOperation(arithop, op) and e = arithop.getAnOperand() and e.getType() instanceof PointerType) + dereferencedByOperation(arithop, op) and + e = arithop.getAnOperand() and + e.getType() instanceof PointerType + ) or exists(BinaryArithmeticOperation arithop | - dereferencedByOperation(arithop, op) and e = arithop.getAnOperand() and e.getType() instanceof PointerType) + dereferencedByOperation(arithop, op) and + e = arithop.getAnOperand() and + e.getType() instanceof PointerType + ) or - exists(FunctionCall fc, int i | - (callDereferences(fc, i) or functionCallDereferences(fc, i)) - and e = fc.getArgument(i) and op = fc) + (callDereferences(fc, i) or functionCallDereferences(fc, i)) and + e = fc.getArgument(i) and + op = fc + ) or // ptr->Field e = op.(FieldAccess).getQualifier() and isClassPointerType(e.getType()) @@ -82,14 +107,10 @@ private predicate isClassPointerType(Type t) { /** * Holds if `e` will be dereferenced after being evaluated. */ -predicate dereferenced(Expr e) -{ - dereferencedByOperation(_, e) -} +predicate dereferenced(Expr e) { dereferencedByOperation(_, e) } pragma[noinline] -private predicate functionCallDereferences(FunctionCall fc, int i) -{ +private predicate functionCallDereferences(FunctionCall fc, int i) { functionDereferences(fc.getTarget(), i) } @@ -97,11 +118,11 @@ private predicate functionCallDereferences(FunctionCall fc, int i) * Holds if the body of a function `f` is likely to dereference its `i`th * parameter unconditionally. This analysis does not account for reassignment. */ -predicate functionDereferences(Function f, int i) -{ +predicate functionDereferences(Function f, int i) { exists(VariableAccess access, Parameter p | p = f.getParameter(i) and dereferenced(access) and access = p.getAnAccess() and - not checkedValid(p, access)) + not checkedValid(p, access) + ) } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Dominance.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Dominance.qll index f9e1ecdceee..3abe68e0442 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Dominance.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Dominance.qll @@ -7,40 +7,40 @@ * and only for nodes reachable from the entry point. Unreachable nodes are not * part the dominance relation. */ -import cpp +import cpp /** * In rare cases, the same node is used in multiple control-flow scopes. This * confuses the dominance analysis, so this predicate is used to exclude them. */ -private predicate -hasMultiScopeNode(Function f) { - exists (ControlFlowNode node | - node.getControlFlowScope() = f - and node.getControlFlowScope() != f) +private predicate hasMultiScopeNode(Function f) { + exists(ControlFlowNode node | + node.getControlFlowScope() = f and + node.getControlFlowScope() != f + ) } /** Holds if `entry` is the entry point of a function. */ predicate functionEntry(ControlFlowNode entry) { - exists (Function function | - function.getEntryPoint() = entry - and not hasMultiScopeNode(function)) + exists(Function function | + function.getEntryPoint() = entry and + not hasMultiScopeNode(function) + ) } /** Holds if `exit` is the exit node of a function. */ predicate functionExit(ControlFlowNode exit) { - exists (Function function | - function = exit - and not hasMultiScopeNode(function)) + exists(Function function | + function = exit and + not hasMultiScopeNode(function) + ) } /** * Holds if `dest` is an immediate successor of `src` in the control-flow graph. */ -private predicate nodeSucc(ControlFlowNode src, ControlFlowNode dest) { - src.getASuccessor() = dest -} +private predicate nodeSucc(ControlFlowNode src, ControlFlowNode dest) { src.getASuccessor() = dest } /** * Holds if `pred` is an immediate predecessor of `src` in the control-flow graph. @@ -53,13 +53,15 @@ private predicate nodePred(ControlFlowNode src, ControlFlowNode pred) { * Holds if `dominator` is an immediate dominator of `node` in the control-flow * graph. */ -predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) = idominance(functionEntry/1,nodeSucc/2)(_, dominator, node) +predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) = + idominance(functionEntry/1, nodeSucc/2)(_, dominator, node) /** * Holds if `postDominator` is an immediate post-dominator of `node` in the control-flow * graph. */ -predicate iPostDominates(ControlFlowNode postDominator, ControlFlowNode node) = idominance(functionExit/1,nodePred/2)(_, postDominator, node) +predicate iPostDominates(ControlFlowNode postDominator, ControlFlowNode node) = + idominance(functionExit/1, nodePred/2)(_, postDominator, node) /** * Holds if `dominator` is a strict dominator of `node` in the control-flow @@ -101,32 +103,31 @@ predicate postDominates(ControlFlowNode postDominator, ControlFlowNode node) { * Holds if `dominator` is an immediate dominator of `node` in the control-flow * graph of basic blocks. */ -predicate bbIDominates(BasicBlock dom, BasicBlock node) = idominance(functionEntry/1, bb_successor/2)(_, dom, node) +predicate bbIDominates(BasicBlock dom, BasicBlock node) = + idominance(functionEntry/1, bb_successor/2)(_, dom, node) /** * Holds if `pred` is a predecessor of `succ` in the control-flow graph of * basic blocks. */ -private predicate bb_predecessor(BasicBlock succ, BasicBlock pred) { - bb_successor(pred, succ) -} +private predicate bb_predecessor(BasicBlock succ, BasicBlock pred) { bb_successor(pred, succ) } /** Holds if `exit` is an `ExitBasicBlock`. */ -private predicate bb_exit(ExitBasicBlock exit) { - any() -} +private predicate bb_exit(ExitBasicBlock exit) { any() } /** * Holds if `postDominator` is an immediate post-dominator of `node` in the control-flow * graph of basic blocks. */ -predicate bbIPostDominates(BasicBlock pDom, BasicBlock node) = idominance(bb_exit/1, bb_predecessor/2)(_, pDom, node) +predicate bbIPostDominates(BasicBlock pDom, BasicBlock node) = + idominance(bb_exit/1, bb_predecessor/2)(_, pDom, node) /** * Holds if `dominator` is a strict dominator of `node` in the control-flow * graph of basic blocks. Being strict means that `dominator != node`. */ -pragma[nomagic] // magic prevents fastTC +// magic prevents fastTC +pragma[nomagic] predicate bbStrictlyDominates(BasicBlock dominator, BasicBlock node) { bbIDominates+(dominator, node) } @@ -135,7 +136,8 @@ predicate bbStrictlyDominates(BasicBlock dominator, BasicBlock node) { * Holds if `postDominator` is a strict post-dominator of `node` in the control-flow * graph of basic blocks. Being strict means that `postDominator != node`. */ -pragma[nomagic] // magic prevents fastTC +// magic prevents fastTC +pragma[nomagic] predicate bbStrictlyPostDominates(BasicBlock postDominator, BasicBlock node) { bbIPostDominates+(postDominator, node) } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Guards.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Guards.qll index 08bc038b793..3164f44e451 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Guards.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Guards.qll @@ -8,107 +8,119 @@ import semmle.code.cpp.controlflow.Dominance * operands of logical operators but not switch statements. */ class GuardCondition extends Expr { + GuardCondition() { is_condition(this) } - GuardCondition() { - is_condition(this) - } + /** + * Holds if this condition controls `block`, meaning that `block` is only + * entered if the value of this condition is `testIsTrue`. + * + * Illustration: + * + * ``` + * [ (testIsTrue) ] + * [ this ----------------succ ---- controlled ] + * [ | | ] + * [ (testIsFalse) | ------ ... ] + * [ other ] + * ``` + * + * The predicate holds if all paths to `controlled` go via the `testIsTrue` + * edge of the control-flow graph. In other words, the `testIsTrue` edge + * must dominate `controlled`. This means that `controlled` must be + * dominated by both `this` and `succ` (the target of the `testIsTrue` + * edge). It also means that any other edge into `succ` must be a back-edge + * from a node which is dominated by `succ`. + * + * The short-circuit boolean operations have slightly surprising behavior + * here: because the operation itself only dominates one branch (due to + * being short-circuited) then it will only control blocks dominated by the + * true (for `&&`) or false (for `||`) branch. + */ + cached + predicate controls(BasicBlock controlled, boolean testIsTrue) { + // This condition must determine the flow of control; that is, this + // node must be a top-level condition. + this.controlsBlock(controlled, testIsTrue) + or + exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs | + this = binop and + lhs = binop.getLeftOperand() and + rhs = binop.getRightOperand() and + lhs.controls(controlled, testIsTrue) and + rhs.controls(controlled, testIsTrue) + ) + or + exists(GuardCondition ne, GuardCondition operand | + this = operand and + operand = ne.(NotExpr).getOperand() and + ne.controls(controlled, testIsTrue.booleanNot()) + ) + } - /** - * Holds if this condition controls `block`, meaning that `block` is only - * entered if the value of this condition is `testIsTrue`. - * - * Illustration: - * - * ``` - * [ (testIsTrue) ] - * [ this ----------------succ ---- controlled ] - * [ | | ] - * [ (testIsFalse) | ------ ... ] - * [ other ] - * ``` - * - * The predicate holds if all paths to `controlled` go via the `testIsTrue` - * edge of the control-flow graph. In other words, the `testIsTrue` edge - * must dominate `controlled`. This means that `controlled` must be - * dominated by both `this` and `succ` (the target of the `testIsTrue` - * edge). It also means that any other edge into `succ` must be a back-edge - * from a node which is dominated by `succ`. - * - * The short-circuit boolean operations have slightly surprising behavior - * here: because the operation itself only dominates one branch (due to - * being short-circuited) then it will only control blocks dominated by the - * true (for `&&`) or false (for `||`) branch. - */ - cached predicate controls(BasicBlock controlled, boolean testIsTrue) { - // This condition must determine the flow of control; that is, this - // node must be a top-level condition. - this.controlsBlock(controlled, testIsTrue) + /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ + cached + predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { + compares_lt(this, left, right, k, isLessThan, testIsTrue) + } + + /** + * Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. + * If `isLessThan = false` then this implies `left >= right + k`. + */ + cached + predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { + exists(boolean testIsTrue | + compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) + ) + } + + /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ + cached + predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { + compares_eq(this, left, right, k, areEqual, testIsTrue) + } + + /** + * Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. + * If `areEqual = false` then this implies `left != right + k`. + */ + cached + predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { + exists(boolean testIsTrue | + compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) + ) + } + + /** + * Holds if this condition controls `block`, meaning that `block` is only + * entered if the value of this condition is `testIsTrue`. This helper + * predicate does not necessarily hold for binary logical operations like + * `&&` and `||`. See the detailed explanation on predicate `controls`. + */ + private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) { + exists(BasicBlock thisblock | thisblock.contains(this) | + exists(BasicBlock succ | + testIsTrue = true and succ = this.getATrueSuccessor() or - exists (BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs - | this = binop and - lhs = binop.getLeftOperand() and - rhs = binop.getRightOperand() and - lhs.controls(controlled, testIsTrue) and - rhs.controls(controlled, testIsTrue)) - or - exists (GuardCondition ne, GuardCondition operand - | this = operand and - operand = ne.(NotExpr).getOperand() and - ne.controls(controlled, testIsTrue.booleanNot())) - } - - /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ - cached predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { - compares_lt(this, left, right, k, isLessThan, testIsTrue) - } - - /** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. - * If `isLessThan = false` then this implies `left >= right + k`. */ - cached predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { - exists(boolean testIsTrue | - compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) + testIsTrue = false and succ = this.getAFalseSuccessor() + | + bbDominates(succ, controlled) and + forall(BasicBlock pred | pred.getASuccessor() = succ | + pred = thisblock or bbDominates(succ, pred) or not reachable(pred) ) - } - - /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ - cached predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - compares_eq(this, left, right, k, areEqual, testIsTrue) - } - - /** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. - * If `areEqual = false` then this implies `left != right + k`. */ - cached predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { - exists(boolean testIsTrue | - compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) - ) - } - - /** - * Holds if this condition controls `block`, meaning that `block` is only - * entered if the value of this condition is `testIsTrue`. This helper - * predicate does not necessarily hold for binary logical operations like - * `&&` and `||`. See the detailed explanation on predicate `controls`. - */ - private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) { - exists(BasicBlock thisblock - | thisblock.contains(this) - | exists(BasicBlock succ - | testIsTrue = true and succ = this.getATrueSuccessor() or - testIsTrue = false and succ = this.getAFalseSuccessor() - | bbDominates(succ, controlled) and - forall(BasicBlock pred - | pred.getASuccessor() = succ - | pred = thisblock or bbDominates(succ, pred) or not reachable(pred)))) - } + ) + ) + } } private predicate is_condition(Expr guard) { - guard.isCondition() or - is_condition(guard.(BinaryLogicalOperation).getAnOperand()) or - exists(NotExpr cond | is_condition(cond) and cond.getOperand() = guard) + guard.isCondition() + or + is_condition(guard.(BinaryLogicalOperation).getAnOperand()) + or + exists(NotExpr cond | is_condition(cond) and cond.getOperand() = guard) } - /* * Simplification of equality expressions: * Simplify conditions in the source to the canonical form l op r + k. @@ -119,81 +131,110 @@ private predicate is_condition(Expr guard) { * * Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`. */ -private predicate compares_eq(Expr test, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - /* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */ - exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) | - areEqual = true and testIsTrue = eq or areEqual = false and testIsTrue = eq.booleanNot() - ) +private predicate compares_eq( + Expr test, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue +) { + /* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */ + exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) | + areEqual = true and testIsTrue = eq or - logical_comparison_eq(test, left, right, k, areEqual, testIsTrue) - or - /* a == b + k => b == a - k */ - exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue)) - or - complex_eq(test, left, right, k, areEqual, testIsTrue) - or - /* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */ - exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | - compares_eq(test.(NotExpr).getOperand(), left, right, k, areEqual, isFalse) - ) + areEqual = false and testIsTrue = eq.booleanNot() + ) + or + logical_comparison_eq(test, left, right, k, areEqual, testIsTrue) + or + /* a == b + k => b == a - k */ + exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue)) + or + complex_eq(test, left, right, k, areEqual, testIsTrue) + or + /* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */ + exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | + compares_eq(test.(NotExpr).getOperand(), left, right, k, areEqual, isFalse) + ) } -/** If `test => part` and `part => left == right + k` then `test => left == right + k`. - Similarly for the case where `test` is false. */ -private -predicate logical_comparison_eq(BinaryLogicalOperation test, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - exists(boolean partIsTrue, Expr part | - test.impliesValue(part, partIsTrue, testIsTrue) | - compares_eq(part, left, right, k, areEqual, partIsTrue) - ) +/** + * If `test => part` and `part => left == right + k` then `test => left == right + k`. + * Similarly for the case where `test` is false. + */ +private predicate logical_comparison_eq( + BinaryLogicalOperation test, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue +) { + exists(boolean partIsTrue, Expr part | test.impliesValue(part, partIsTrue, testIsTrue) | + compares_eq(part, left, right, k, areEqual, partIsTrue) + ) } /** Rearrange various simple comparisons into `left == right + k` form. */ -private predicate simple_comparison_eq(ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual) { - left = cmp.getLeftOperand() and cmp.getOperator() = "==" and right = cmp.getRightOperand() and k = 0 and areEqual = true - or - left = cmp.getLeftOperand() and cmp.getOperator() = "!=" and right = cmp.getRightOperand() and k = 0 and areEqual = false +private predicate simple_comparison_eq( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual +) { + left = cmp.getLeftOperand() and + cmp.getOperator() = "==" and + right = cmp.getRightOperand() and + k = 0 and + areEqual = true + or + left = cmp.getLeftOperand() and + cmp.getOperator() = "!=" and + right = cmp.getRightOperand() and + k = 0 and + areEqual = false } -private predicate complex_eq(ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - sub_eq(cmp, left, right, k, areEqual, testIsTrue) - or - add_eq(cmp, left, right, k, areEqual, testIsTrue) +private predicate complex_eq( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue +) { + sub_eq(cmp, left, right, k, areEqual, testIsTrue) + or + add_eq(cmp, left, right, k, areEqual, testIsTrue) } - // left - x == right + c => left == right + (c+x) // left == (right - x) + c => left == right + (c-x) -private predicate sub_eq(ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - exists(SubExpr lhs, int c, int x | compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and - left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand()) - and k = c + x - ) - or - exists(SubExpr rhs, int c, int x | compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and - right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand()) - and k = c - x - ) +private predicate sub_eq( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue +) { + exists(SubExpr lhs, int c, int x | + compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and + left = lhs.getLeftOperand() and + x = int_value(lhs.getRightOperand()) and + k = c + x + ) + or + exists(SubExpr rhs, int c, int x | + compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and + right = rhs.getLeftOperand() and + x = int_value(rhs.getRightOperand()) and + k = c - x + ) } // left + x == right + c => left == right + (c-x) // left == (right + x) + c => left == right + (c+x) -private predicate add_eq(ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - exists(AddExpr lhs, int c, int x | compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and - (left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand()) - or - left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand()) - ) - and k = c - x - ) - or - exists(AddExpr rhs, int c, int x | compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and - (right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand()) - or - right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand()) - ) - and k = c + x - ) +private predicate add_eq( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue +) { + exists(AddExpr lhs, int c, int x | + compares_eq(cmp, lhs, right, c, areEqual, testIsTrue) and + ( + left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand()) + or + left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand()) + ) and + k = c - x + ) + or + exists(AddExpr rhs, int c, int x | + compares_eq(cmp, left, rhs, c, areEqual, testIsTrue) and + ( + right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand()) + or + right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand()) + ) and + k = c + x + ) } /* @@ -202,110 +243,137 @@ private predicate add_eq(ComparisonOperation cmp, Expr left, Expr right, int k, */ /** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */ -private predicate compares_lt(Expr test, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue) { - /* In the simple case, the test is the comparison, so isLt = testIsTrue */ - simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true - or - simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false - or - logical_comparison_lt(test, left, right, k, isLt, testIsTrue) - or - complex_lt(test, left, right, k, isLt, testIsTrue) - or - /* (not (left < right + k)) => (left >= right + k) */ - exists(boolean isGe | isLt = isGe.booleanNot() | - compares_ge(test, left, right, k, isGe, testIsTrue) - ) - or - /* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */ - exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | - compares_lt(test.(NotExpr).getOperand(), left, right, k, isLt, isFalse) - ) +private predicate compares_lt( + Expr test, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue +) { + /* In the simple case, the test is the comparison, so isLt = testIsTrue */ + simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true + or + simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false + or + logical_comparison_lt(test, left, right, k, isLt, testIsTrue) + or + complex_lt(test, left, right, k, isLt, testIsTrue) + or + /* (not (left < right + k)) => (left >= right + k) */ + exists(boolean isGe | isLt = isGe.booleanNot() | + compares_ge(test, left, right, k, isGe, testIsTrue) + ) + or + /* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */ + exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | + compares_lt(test.(NotExpr).getOperand(), left, right, k, isLt, isFalse) + ) } /** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */ -private predicate compares_ge(Expr test, Expr left, Expr right, int k, boolean isGe, boolean testIsTrue) { - exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue)) +private predicate compares_ge( + Expr test, Expr left, Expr right, int k, boolean isGe, boolean testIsTrue +) { + exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue)) } -/** If `test => part` and `part => left < right + k` then `test => left < right + k`. - Similarly for the case where `test` evaluates false. */ -private -predicate logical_comparison_lt(BinaryLogicalOperation test, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue) { - exists(boolean partIsTrue, Expr part | - test.impliesValue(part, partIsTrue, testIsTrue) | - compares_lt(part, left, right, k, isLt, partIsTrue) - ) +/** + * If `test => part` and `part => left < right + k` then `test => left < right + k`. + * Similarly for the case where `test` evaluates false. + */ +private predicate logical_comparison_lt( + BinaryLogicalOperation test, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue +) { + exists(boolean partIsTrue, Expr part | test.impliesValue(part, partIsTrue, testIsTrue) | + compares_lt(part, left, right, k, isLt, partIsTrue) + ) } /** Rearrange various simple comparisons into `left < right + k` form. */ private predicate simple_comparison_lt(ComparisonOperation cmp, Expr left, Expr right, int k) { - left = cmp.getLeftOperand() and cmp.getOperator() = "<" and right = cmp.getRightOperand() and k = 0 - or - left = cmp.getLeftOperand() and cmp.getOperator() = "<=" and right = cmp.getRightOperand() and k = 1 - or - right = cmp.getLeftOperand() and cmp.getOperator() = ">" and left = cmp.getRightOperand() and k = 0 - or - right = cmp.getLeftOperand() and cmp.getOperator() = ">=" and left = cmp.getRightOperand() and k = 1 + left = cmp.getLeftOperand() and + cmp.getOperator() = "<" and + right = cmp.getRightOperand() and + k = 0 + or + left = cmp.getLeftOperand() and + cmp.getOperator() = "<=" and + right = cmp.getRightOperand() and + k = 1 + or + right = cmp.getLeftOperand() and + cmp.getOperator() = ">" and + left = cmp.getRightOperand() and + k = 0 + or + right = cmp.getLeftOperand() and + cmp.getOperator() = ">=" and + left = cmp.getRightOperand() and + k = 1 } -private predicate complex_lt(ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue) { - sub_lt(cmp, left, right, k, isLt, testIsTrue) - or - add_lt(cmp, left, right, k, isLt, testIsTrue) +private predicate complex_lt( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue +) { + sub_lt(cmp, left, right, k, isLt, testIsTrue) + or + add_lt(cmp, left, right, k, isLt, testIsTrue) } - // left - x < right + c => left < right + (c+x) // left < (right - x) + c => left < right + (c-x) -private predicate sub_lt(ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue) { - exists(SubExpr lhs, int c, int x | compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and - left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand()) - and k = c + x - ) - or - exists(SubExpr rhs, int c, int x | compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and - right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand()) - and k = c - x - ) +private predicate sub_lt( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue +) { + exists(SubExpr lhs, int c, int x | + compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and + left = lhs.getLeftOperand() and + x = int_value(lhs.getRightOperand()) and + k = c + x + ) + or + exists(SubExpr rhs, int c, int x | + compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and + right = rhs.getLeftOperand() and + x = int_value(rhs.getRightOperand()) and + k = c - x + ) } // left + x < right + c => left < right + (c-x) // left < (right + x) + c => left < right + (c+x) -private predicate add_lt(ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue) { - exists(AddExpr lhs, int c, int x | compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and - (left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand()) - or - left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand()) - ) - and k = c - x - ) - or - exists(AddExpr rhs, int c, int x | compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and - (right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand()) - or - right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand()) - ) - and k = c + x - ) +private predicate add_lt( + ComparisonOperation cmp, Expr left, Expr right, int k, boolean isLt, boolean testIsTrue +) { + exists(AddExpr lhs, int c, int x | + compares_lt(cmp, lhs, right, c, isLt, testIsTrue) and + ( + left = lhs.getLeftOperand() and x = int_value(lhs.getRightOperand()) + or + left = lhs.getRightOperand() and x = int_value(lhs.getLeftOperand()) + ) and + k = c - x + ) + or + exists(AddExpr rhs, int c, int x | + compares_lt(cmp, left, rhs, c, isLt, testIsTrue) and + ( + right = rhs.getLeftOperand() and x = int_value(rhs.getRightOperand()) + or + right = rhs.getRightOperand() and x = int_value(rhs.getLeftOperand()) + ) and + k = c + x + ) } /** The int value of integer constant expression. */ private int int_value(Expr e) { - e.getUnderlyingType() instanceof IntegralType - and - result = e.getValue().toInt() + e.getUnderlyingType() instanceof IntegralType and + result = e.getValue().toInt() } /** An `SsaDefinition` with an additional predicate `isLt`. */ class GuardedSsa extends SsaDefinition { - - /** Holds if this `SsaDefinition` is guarded such that `this(var) < gt + k` is `testIsTrue` in `block`. */ - predicate isLt(LocalScopeVariable var, Expr gt, int k, BasicBlock block, boolean testIsTrue) { - exists(Expr luse, GuardCondition test | this.getAUse(var) = luse | - test.ensuresLt(luse, gt, k, block, testIsTrue) - ) - } - + /** Holds if this `SsaDefinition` is guarded such that `this(var) < gt + k` is `testIsTrue` in `block`. */ + predicate isLt(LocalScopeVariable var, Expr gt, int k, BasicBlock block, boolean testIsTrue) { + exists(Expr luse, GuardCondition test | this.getAUse(var) = luse | + test.ensuresLt(luse, gt, k, block, testIsTrue) + ) + } } - diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll index 031d2e8b15b..1f7b3b09946 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/IRGuards.qll @@ -16,22 +16,21 @@ private predicate isUnreachedBlock(IRBlock block) { * A Boolean condition in the AST that guards one or more basic blocks. This includes * operands of logical operators but not switch statements. */ -cached class GuardCondition extends Expr { - cached GuardCondition() { +cached +class GuardCondition extends Expr { + cached + GuardCondition() { exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression()) or // no binary operators in the IR - exists(GuardCondition gc | - this.(BinaryLogicalOperation).getAnOperand()= gc - ) + exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) or // the IR short-circuits if(!x) - ( - // don't produce a guard condition for `y = !x` and other non-short-circuited cases - not exists (Instruction inst | this.getFullyConverted() = inst.getAST()) and - exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAST()) - ) + // don't produce a guard condition for `y = !x` and other non-short-circuited cases + not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and + exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAST()) } + /** * Holds if this condition controls `block`, meaning that `block` is only * entered if the value of this condition is `testIsTrue`. @@ -58,31 +57,34 @@ cached class GuardCondition extends Expr { * being short-circuited) then it will only control blocks dominated by the * true (for `&&`) or false (for `||`) branch. */ - cached predicate controls(BasicBlock controlled, boolean testIsTrue) { - none() - } - + cached + predicate controls(BasicBlock controlled, boolean testIsTrue) { none() } + /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ - cached predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { + cached + predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { none() } - /** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. - * If `isLessThan = false` then this implies `left >= right + k`. */ - cached predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { - none() - } + /** + * Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. + * If `isLessThan = false` then this implies `left >= right + k`. + */ + cached + predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { none() } /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ - cached predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { + cached + predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { none() } - /** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. - * If `areEqual = false` then this implies `left != right + k`. */ - cached predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { - none() - } + /** + * Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. + * If `areEqual = false` then this implies `left != right + k`. + */ + cached + predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { none() } } /** @@ -90,40 +92,41 @@ cached class GuardCondition extends Expr { */ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { GuardConditionFromBinaryLogicalOperator() { - exists(GuardCondition gc | - this.(BinaryLogicalOperation).getAnOperand()= gc - ) + exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc) } - + override predicate controls(BasicBlock controlled, boolean testIsTrue) { - exists (BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs - | this = binop and + exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs | + this = binop and lhs = binop.getLeftOperand() and rhs = binop.getRightOperand() and lhs.controls(controlled, testIsTrue) and - rhs.controls(controlled, testIsTrue)) + rhs.controls(controlled, testIsTrue) + ) } - + override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { exists(boolean partIsTrue, GuardCondition part | - this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue) | + this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue) + | part.comparesLt(left, right, k, isLessThan, partIsTrue) ) } - + override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { exists(boolean testIsTrue | comparesLt(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) ) } - + override predicate comparesEq(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { exists(boolean partIsTrue, GuardCondition part | - this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue) | + this.(BinaryLogicalOperation).impliesValue(part, partIsTrue, testIsTrue) + | part.comparesEq(left, right, k, isLessThan, partIsTrue) ) } - + override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { exists(boolean testIsTrue | comparesEq(left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) @@ -137,99 +140,103 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition { */ private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr { GuardConditionFromShortCircuitNot() { - not exists (Instruction inst | this.getFullyConverted() = inst.getAST()) and + not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and exists(IRGuardCondition ir | getOperand() = ir.getAST()) } - + override predicate controls(BasicBlock controlled, boolean testIsTrue) { getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot()) } - + override predicate comparesLt(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { getOperand().(GuardCondition).comparesLt(left, right, k, areEqual, testIsTrue.booleanNot()) } - + override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean testIsTrue) { getOperand().(GuardCondition).ensuresLt(left, right, k, block, testIsTrue.booleanNot()) } - + override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot()) } - + override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean testIsTrue) { getOperand().(GuardCondition).ensuresEq(left, right, k, block, testIsTrue.booleanNot()) } } + /** * A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR * instruction. */ private class GuardConditionFromIR extends GuardCondition { IRGuardCondition ir; - - GuardConditionFromIR() { - this = ir.getUnconvertedResultExpression() + + GuardConditionFromIR() { this = ir.getUnconvertedResultExpression() } + + override predicate controls(BasicBlock controlled, boolean testIsTrue) { + // This condition must determine the flow of control; that is, this + // node must be a top-level condition. + this.controlsBlock(controlled, testIsTrue) } - override predicate controls(BasicBlock controlled, boolean testIsTrue) { - // This condition must determine the flow of control; that is, this - // node must be a top-level condition. - this.controlsBlock(controlled, testIsTrue) - } - /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ - override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { - exists(Instruction li, Instruction ri | - li.getUnconvertedResultExpression() = left and - ri.getUnconvertedResultExpression() = right and - ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue) - ) - } + /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ + override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) { + exists(Instruction li, Instruction ri | + li.getUnconvertedResultExpression() = left and + ri.getUnconvertedResultExpression() = right and + ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue) + ) + } - /** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. - * If `isLessThan = false` then this implies `left >= right + k`. */ - override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { - exists(Instruction li, Instruction ri, boolean testIsTrue | - li.getUnconvertedResultExpression() = left and - ri.getUnconvertedResultExpression() = right and - ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue) and - this.controls(block, testIsTrue) - ) - } + /** + * Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. + * If `isLessThan = false` then this implies `left >= right + k`. + */ + override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) { + exists(Instruction li, Instruction ri, boolean testIsTrue | + li.getUnconvertedResultExpression() = left and + ri.getUnconvertedResultExpression() = right and + ir.comparesLt(li.getAUse(), ri.getAUse(), k, isLessThan, testIsTrue) and + this.controls(block, testIsTrue) + ) + } - /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ - override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { - exists(Instruction li, Instruction ri | - li.getUnconvertedResultExpression() = left and - ri.getUnconvertedResultExpression() = right and - ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue) - ) - } + /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ + override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) { + exists(Instruction li, Instruction ri | + li.getUnconvertedResultExpression() = left and + ri.getUnconvertedResultExpression() = right and + ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue) + ) + } - /** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. - * If `areEqual = false` then this implies `left != right + k`. */ - override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { - exists(Instruction li, Instruction ri, boolean testIsTrue | - li.getUnconvertedResultExpression() = left and - ri.getUnconvertedResultExpression() = right and - ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue) and - this.controls(block, testIsTrue) - ) - } + /** + * Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. + * If `areEqual = false` then this implies `left != right + k`. + */ + override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) { + exists(Instruction li, Instruction ri, boolean testIsTrue | + li.getUnconvertedResultExpression() = left and + ri.getUnconvertedResultExpression() = right and + ir.comparesEq(li.getAUse(), ri.getAUse(), k, areEqual, testIsTrue) and + this.controls(block, testIsTrue) + ) + } - /** - * Holds if this condition controls `block`, meaning that `block` is only - * entered if the value of this condition is `testIsTrue`. This helper - * predicate does not necessarily hold for binary logical operations like - * `&&` and `||`. See the detailed explanation on predicate `controls`. - */ - private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) { - exists(IRBlock irb | - forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and - irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled and - not isUnreachedBlock(irb) - ) - } + /** + * Holds if this condition controls `block`, meaning that `block` is only + * entered if the value of this condition is `testIsTrue`. This helper + * predicate does not necessarily hold for binary logical operations like + * `&&` and `||`. See the detailed explanation on predicate `controls`. + */ + private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) { + exists(IRBlock irb | + forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and + irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled and + not isUnreachedBlock(irb) + ) + } } /** @@ -238,152 +245,179 @@ private class GuardConditionFromIR extends GuardCondition { * don't have an explicit representation in the IR, and therefore will not appear as * IRGuardConditions. */ -cached class IRGuardCondition extends Instruction { - ConditionalBranchInstruction branch; - - cached IRGuardCondition() { - branch = get_branch_for_condition(this) - } +cached +class IRGuardCondition extends Instruction { + ConditionalBranchInstruction branch; - /** - * Holds if this condition controls `block`, meaning that `block` is only - * entered if the value of this condition is `testIsTrue`. - * - * Illustration: - * - * ``` - * [ (testIsTrue) ] - * [ this ----------------succ ---- controlled ] - * [ | | ] - * [ (testIsFalse) | ------ ... ] - * [ other ] - * ``` - * - * The predicate holds if all paths to `controlled` go via the `testIsTrue` - * edge of the control-flow graph. In other words, the `testIsTrue` edge - * must dominate `controlled`. This means that `controlled` must be - * dominated by both `this` and `succ` (the target of the `testIsTrue` - * edge). It also means that any other edge into `succ` must be a back-edge - * from a node which is dominated by `succ`. - * - * The short-circuit boolean operations have slightly surprising behavior - * here: because the operation itself only dominates one branch (due to - * being short-circuited) then it will only control blocks dominated by the - * true (for `&&`) or false (for `||`) branch. - */ - cached predicate controls(IRBlock controlled, boolean testIsTrue) { - // This condition must determine the flow of control; that is, this - // node must be a top-level condition. - this.controlsBlock(controlled, testIsTrue) - or - exists (IRGuardCondition ne - | this = ne.(LogicalNotInstruction).getUnary() and - ne.controls(controlled, testIsTrue.booleanNot())) - } + cached + IRGuardCondition() { branch = get_branch_for_condition(this) } - cached predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) { - pred.getASuccessor() = succ and - controls(pred, testIsTrue) + /** + * Holds if this condition controls `block`, meaning that `block` is only + * entered if the value of this condition is `testIsTrue`. + * + * Illustration: + * + * ``` + * [ (testIsTrue) ] + * [ this ----------------succ ---- controlled ] + * [ | | ] + * [ (testIsFalse) | ------ ... ] + * [ other ] + * ``` + * + * The predicate holds if all paths to `controlled` go via the `testIsTrue` + * edge of the control-flow graph. In other words, the `testIsTrue` edge + * must dominate `controlled`. This means that `controlled` must be + * dominated by both `this` and `succ` (the target of the `testIsTrue` + * edge). It also means that any other edge into `succ` must be a back-edge + * from a node which is dominated by `succ`. + * + * The short-circuit boolean operations have slightly surprising behavior + * here: because the operation itself only dominates one branch (due to + * being short-circuited) then it will only control blocks dominated by the + * true (for `&&`) or false (for `||`) branch. + */ + cached + predicate controls(IRBlock controlled, boolean testIsTrue) { + // This condition must determine the flow of control; that is, this + // node must be a top-level condition. + this.controlsBlock(controlled, testIsTrue) + or + exists(IRGuardCondition ne | + this = ne.(LogicalNotInstruction).getUnary() and + ne.controls(controlled, testIsTrue.booleanNot()) + ) + } + + cached + predicate controlsEdge(IRBlock pred, IRBlock succ, boolean testIsTrue) { + pred.getASuccessor() = succ and + controls(pred, testIsTrue) + or + hasBranchEdge(succ, testIsTrue) and + branch.getCondition() = this and + branch.getBlock() = pred + } + + /** + * Holds if `branch` jumps directly to `succ` when this condition is `testIsTrue`. + * + * This predicate is intended to help with situations in which an inference can only be made + * based on an edge between a block with multiple successors and a block with multiple + * predecessors. For example, in the following situation, an inference can be made about the + * value of `x` at the end of the `if` statement, but there is no block which is controlled by + * the `if` statement when `x >= y`. + * ``` + * if (x < y) { + * x = y; + * } + * return x; + * ``` + */ + private predicate hasBranchEdge(IRBlock succ, boolean testIsTrue) { + branch.getCondition() = this and + ( + testIsTrue = true and + succ.getFirstInstruction() = branch.getTrueSuccessor() or - hasBranchEdge(succ, testIsTrue) and - branch.getCondition() = this and - branch.getBlock() = pred - } + testIsTrue = false and + succ.getFirstInstruction() = branch.getFalseSuccessor() + ) + } + /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ + cached + predicate comparesLt(Operand left, Operand right, int k, boolean isLessThan, boolean testIsTrue) { + compares_lt(this, left, right, k, isLessThan, testIsTrue) + } - /** - * Holds if `branch` jumps directly to `succ` when this condition is `testIsTrue`. - * - * This predicate is intended to help with situations in which an inference can only be made - * based on an edge between a block with multiple successors and a block with multiple - * predecessors. For example, in the following situation, an inference can be made about the - * value of `x` at the end of the `if` statement, but there is no block which is controlled by - * the `if` statement when `x >= y`. - * ``` - * if (x < y) { - * x = y; - * } - * return x; - * ``` - */ - private predicate hasBranchEdge(IRBlock succ, boolean testIsTrue) { - branch.getCondition() = this and - ( - testIsTrue = true and - succ.getFirstInstruction() = branch.getTrueSuccessor() + /** + * Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. + * If `isLessThan = false` then this implies `left >= right + k`. + */ + cached + predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean isLessThan) { + exists(boolean testIsTrue | + compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) + ) + } + + /** + * Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from + * `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`. + */ + cached + predicate ensuresLtEdge( + Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean isLessThan + ) { + exists(boolean testIsTrue | + compares_lt(this, left, right, k, isLessThan, testIsTrue) and + this.controlsEdge(pred, succ, testIsTrue) + ) + } + + /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ + cached + predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) { + compares_eq(this, left, right, k, areEqual, testIsTrue) + } + + /** + * Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. + * If `areEqual = false` then this implies `left != right + k`. + */ + cached + predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) { + exists(boolean testIsTrue | + compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) + ) + } + + /** + * Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from + * `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`. + */ + cached + predicate ensuresEqEdge( + Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean areEqual + ) { + exists(boolean testIsTrue | + compares_eq(this, left, right, k, areEqual, testIsTrue) and + this.controlsEdge(pred, succ, testIsTrue) + ) + } + + /** + * Holds if this condition controls `block`, meaning that `block` is only + * entered if the value of this condition is `testIsTrue`. This helper + * predicate does not necessarily hold for binary logical operations like + * `&&` and `||`. See the detailed explanation on predicate `controls`. + */ + private predicate controlsBlock(IRBlock controlled, boolean testIsTrue) { + not isUnreachedBlock(controlled) and + exists(IRBlock branchBlock | branchBlock.getAnInstruction() = branch | + exists(IRBlock succ | + testIsTrue = true and succ.getFirstInstruction() = branch.getTrueSuccessor() or - testIsTrue = false and - succ.getFirstInstruction() = branch.getFalseSuccessor() + testIsTrue = false and succ.getFirstInstruction() = branch.getFalseSuccessor() + | + branch.getCondition() = this and + succ.dominates(controlled) and + forall(IRBlock pred | pred.getASuccessor() = succ | + pred = branchBlock or succ.dominates(pred) or not pred.isReachableFromFunctionEntry() + ) ) - } - - /** Holds if (determined by this guard) `left < right + k` evaluates to `isLessThan` if this expression evaluates to `testIsTrue`. */ - cached predicate comparesLt(Operand left, Operand right, int k, boolean isLessThan, boolean testIsTrue) { - compares_lt(this, left, right, k, isLessThan, testIsTrue) - } - - /** Holds if (determined by this guard) `left < right + k` must be `isLessThan` in `block`. - * If `isLessThan = false` then this implies `left >= right + k`. */ - cached predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean isLessThan) { - exists(boolean testIsTrue | - compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controls(block, testIsTrue) - ) - } - - /** Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from - * `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`. */ - cached predicate ensuresLtEdge(Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean isLessThan) { - exists(boolean testIsTrue | - compares_lt(this, left, right, k, isLessThan, testIsTrue) and this.controlsEdge(pred, succ, testIsTrue) - ) - } - - /** Holds if (determined by this guard) `left == right + k` evaluates to `areEqual` if this expression evaluates to `testIsTrue`. */ - cached predicate comparesEq(Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) { - compares_eq(this, left, right, k, areEqual, testIsTrue) - } - - /** Holds if (determined by this guard) `left == right + k` must be `areEqual` in `block`. - * If `areEqual = false` then this implies `left != right + k`. */ - cached predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) { - exists(boolean testIsTrue | - compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controls(block, testIsTrue) - ) - } - /** Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from - * `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`. */ - cached predicate ensuresEqEdge(Operand left, Operand right, int k, IRBlock pred, IRBlock succ, boolean areEqual) { - exists(boolean testIsTrue | - compares_eq(this, left, right, k, areEqual, testIsTrue) and this.controlsEdge(pred, succ, testIsTrue) - ) - } - - /** - * Holds if this condition controls `block`, meaning that `block` is only - * entered if the value of this condition is `testIsTrue`. This helper - * predicate does not necessarily hold for binary logical operations like - * `&&` and `||`. See the detailed explanation on predicate `controls`. - */ - private predicate controlsBlock(IRBlock controlled, boolean testIsTrue) { - not isUnreachedBlock(controlled) and - exists(IRBlock branchBlock - | branchBlock.getAnInstruction() = branch - | exists(IRBlock succ - | testIsTrue = true and succ.getFirstInstruction() = branch.getTrueSuccessor() - or - testIsTrue = false and succ.getFirstInstruction() = branch.getFalseSuccessor() - | branch.getCondition() = this and - succ.dominates(controlled) and - forall(IRBlock pred - | pred.getASuccessor() = succ - | pred = branchBlock or succ.dominates(pred) or not pred.isReachableFromFunctionEntry()))) - } + ) + } } private ConditionalBranchInstruction get_branch_for_condition(Instruction guard) { result.getCondition() = guard or - exists(LogicalNotInstruction cond | result = get_branch_for_condition(cond) and cond.getUnary() = guard) + exists(LogicalNotInstruction cond | + result = get_branch_for_condition(cond) and cond.getUnary() = guard + ) } /** @@ -391,158 +425,211 @@ private ConditionalBranchInstruction get_branch_for_condition(Instruction guard) * * Beware making mistaken logical implications here relating `areEqual` and `testIsTrue`. */ -private predicate compares_eq(Instruction test, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) { - /* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */ - exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) | - areEqual = true and testIsTrue = eq or areEqual = false and testIsTrue = eq.booleanNot() - ) - // I think this is handled by forwarding in controlsBlock. - //or - //logical_comparison_eq(test, left, right, k, areEqual, testIsTrue) +private predicate compares_eq( + Instruction test, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue +) { + /* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */ + exists(boolean eq | simple_comparison_eq(test, left, right, k, eq) | + areEqual = true and testIsTrue = eq or - /* a == b + k => b == a - k */ - exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue)) - or - complex_eq(test, left, right, k, areEqual, testIsTrue) - or - /* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */ - exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | - compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, isFalse) - ) + areEqual = false and testIsTrue = eq.booleanNot() + ) + or + // I think this is handled by forwarding in controlsBlock. + //or + //logical_comparison_eq(test, left, right, k, areEqual, testIsTrue) + /* a == b + k => b == a - k */ + exists(int mk | k = -mk | compares_eq(test, right, left, mk, areEqual, testIsTrue)) + or + complex_eq(test, left, right, k, areEqual, testIsTrue) + or + /* (x is true => (left == right + k)) => (!x is false => (left == right + k)) */ + exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | + compares_eq(test.(LogicalNotInstruction).getUnary(), left, right, k, areEqual, isFalse) + ) } /** Rearrange various simple comparisons into `left == right + k` form. */ -private predicate simple_comparison_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual) { - left = cmp.getLeftOperand() and cmp instanceof CompareEQInstruction and right = cmp.getRightOperand() and k = 0 and areEqual = true - or - left = cmp.getLeftOperand() and cmp instanceof CompareNEInstruction and right = cmp.getRightOperand() and k = 0 and areEqual = false +private predicate simple_comparison_eq( + CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual +) { + left = cmp.getLeftOperand() and + cmp instanceof CompareEQInstruction and + right = cmp.getRightOperand() and + k = 0 and + areEqual = true + or + left = cmp.getLeftOperand() and + cmp instanceof CompareNEInstruction and + right = cmp.getRightOperand() and + k = 0 and + areEqual = false } -private predicate complex_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) { - sub_eq(cmp, left, right, k, areEqual, testIsTrue) - or - add_eq(cmp, left, right, k, areEqual, testIsTrue) +private predicate complex_eq( + CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue +) { + sub_eq(cmp, left, right, k, areEqual, testIsTrue) + or + add_eq(cmp, left, right, k, areEqual, testIsTrue) } - -/* Simplification of inequality expressions +/* + * Simplification of inequality expressions * Simplify conditions in the source to the canonical form l < r + k. */ /** Holds if `left < right + k` evaluates to `isLt` given that test is `testIsTrue`. */ -private predicate compares_lt(Instruction test, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) { - /* In the simple case, the test is the comparison, so isLt = testIsTrue */ - simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true - or - simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false - or - complex_lt(test, left, right, k, isLt, testIsTrue) - or - /* (not (left < right + k)) => (left >= right + k) */ - exists(boolean isGe | isLt = isGe.booleanNot() | - compares_ge(test, left, right, k, isGe, testIsTrue) - ) - or - /* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */ - exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | - compares_lt(test.(LogicalNotInstruction).getUnary(), left, right, k, isLt, isFalse) - ) +private predicate compares_lt( + Instruction test, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue +) { + /* In the simple case, the test is the comparison, so isLt = testIsTrue */ + simple_comparison_lt(test, left, right, k) and isLt = true and testIsTrue = true + or + simple_comparison_lt(test, left, right, k) and isLt = false and testIsTrue = false + or + complex_lt(test, left, right, k, isLt, testIsTrue) + or + /* (not (left < right + k)) => (left >= right + k) */ + exists(boolean isGe | isLt = isGe.booleanNot() | + compares_ge(test, left, right, k, isGe, testIsTrue) + ) + or + /* (x is true => (left < right + k)) => (!x is false => (left < right + k)) */ + exists(boolean isFalse | testIsTrue = isFalse.booleanNot() | + compares_lt(test.(LogicalNotInstruction).getUnary(), left, right, k, isLt, isFalse) + ) } /** `(a < b + k) => (b > a - k) => (b >= a + (1-k))` */ -private predicate compares_ge(Instruction test, Operand left, Operand right, int k, boolean isGe, boolean testIsTrue) { - exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue)) +private predicate compares_ge( + Instruction test, Operand left, Operand right, int k, boolean isGe, boolean testIsTrue +) { + exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, testIsTrue)) } /** Rearrange various simple comparisons into `left < right + k` form. */ private predicate simple_comparison_lt(CompareInstruction cmp, Operand left, Operand right, int k) { - left = cmp.getLeftOperand() and cmp instanceof CompareLTInstruction and right = cmp.getRightOperand() and k = 0 - or - left = cmp.getLeftOperand() and cmp instanceof CompareLEInstruction and right = cmp.getRightOperand() and k = 1 - or - right = cmp.getLeftOperand() and cmp instanceof CompareGTInstruction and left = cmp.getRightOperand() and k = 0 - or - right = cmp.getLeftOperand() and cmp instanceof CompareGEInstruction and left = cmp.getRightOperand() and k = 1 + left = cmp.getLeftOperand() and + cmp instanceof CompareLTInstruction and + right = cmp.getRightOperand() and + k = 0 + or + left = cmp.getLeftOperand() and + cmp instanceof CompareLEInstruction and + right = cmp.getRightOperand() and + k = 1 + or + right = cmp.getLeftOperand() and + cmp instanceof CompareGTInstruction and + left = cmp.getRightOperand() and + k = 0 + or + right = cmp.getLeftOperand() and + cmp instanceof CompareGEInstruction and + left = cmp.getRightOperand() and + k = 1 } -private predicate complex_lt(CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) { - sub_lt(cmp, left, right, k, isLt, testIsTrue) - or - add_lt(cmp, left, right, k, isLt, testIsTrue) +private predicate complex_lt( + CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue +) { + sub_lt(cmp, left, right, k, isLt, testIsTrue) + or + add_lt(cmp, left, right, k, isLt, testIsTrue) } - // left - x < right + c => left < right + (c+x) // left < (right - x) + c => left < right + (c-x) -private predicate sub_lt(CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) { - exists(SubInstruction lhs, int c, int x | compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and - left = lhs.getLeftOperand() and x = int_value(lhs.getRight()) - and k = c + x - ) - or - exists(SubInstruction rhs, int c, int x | compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and - right = rhs.getLeftOperand() and x = int_value(rhs.getRight()) - and k = c - x - ) +private predicate sub_lt( + CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue +) { + exists(SubInstruction lhs, int c, int x | + compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and + left = lhs.getLeftOperand() and + x = int_value(lhs.getRight()) and + k = c + x + ) + or + exists(SubInstruction rhs, int c, int x | + compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and + right = rhs.getLeftOperand() and + x = int_value(rhs.getRight()) and + k = c - x + ) } // left + x < right + c => left < right + (c-x) // left < (right + x) + c => left < right + (c+x) -private predicate add_lt(CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue) { - exists(AddInstruction lhs, int c, int x | compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and - (left = lhs.getLeftOperand() and x = int_value(lhs.getRight()) - or - left = lhs.getRightOperand() and x = int_value(lhs.getLeft()) - ) - and k = c - x - ) - or - exists(AddInstruction rhs, int c, int x | compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and - (right = rhs.getLeftOperand() and x = int_value(rhs.getRight()) - or - right = rhs.getRightOperand() and x = int_value(rhs.getLeft()) - ) - and k = c + x - ) +private predicate add_lt( + CompareInstruction cmp, Operand left, Operand right, int k, boolean isLt, boolean testIsTrue +) { + exists(AddInstruction lhs, int c, int x | + compares_lt(cmp, lhs.getAUse(), right, c, isLt, testIsTrue) and + ( + left = lhs.getLeftOperand() and x = int_value(lhs.getRight()) + or + left = lhs.getRightOperand() and x = int_value(lhs.getLeft()) + ) and + k = c - x + ) + or + exists(AddInstruction rhs, int c, int x | + compares_lt(cmp, left, rhs.getAUse(), c, isLt, testIsTrue) and + ( + right = rhs.getLeftOperand() and x = int_value(rhs.getRight()) + or + right = rhs.getRightOperand() and x = int_value(rhs.getLeft()) + ) and + k = c + x + ) } - // left - x == right + c => left == right + (c+x) // left == (right - x) + c => left == right + (c-x) -private predicate sub_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) { - exists(SubInstruction lhs, int c, int x | compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and - left = lhs.getLeftOperand() and x = int_value(lhs.getRight()) - and k = c + x - ) - or - exists(SubInstruction rhs, int c, int x | compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and - right = rhs.getLeftOperand() and x = int_value(rhs.getRight()) - and k = c - x - ) +private predicate sub_eq( + CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue +) { + exists(SubInstruction lhs, int c, int x | + compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and + left = lhs.getLeftOperand() and + x = int_value(lhs.getRight()) and + k = c + x + ) + or + exists(SubInstruction rhs, int c, int x | + compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and + right = rhs.getLeftOperand() and + x = int_value(rhs.getRight()) and + k = c - x + ) } - // left + x == right + c => left == right + (c-x) // left == (right + x) + c => left == right + (c+x) -private predicate add_eq(CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue) { - exists(AddInstruction lhs, int c, int x | compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and - (left = lhs.getLeftOperand() and x = int_value(lhs.getRight()) - or - left = lhs.getRightOperand() and x = int_value(lhs.getLeft()) - ) - and k = c - x - ) - or - exists(AddInstruction rhs, int c, int x | compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and - (right = rhs.getLeftOperand() and x = int_value(rhs.getRight()) - or - right = rhs.getRightOperand() and x = int_value(rhs.getLeft()) - ) - and k = c + x - ) +private predicate add_eq( + CompareInstruction cmp, Operand left, Operand right, int k, boolean areEqual, boolean testIsTrue +) { + exists(AddInstruction lhs, int c, int x | + compares_eq(cmp, lhs.getAUse(), right, c, areEqual, testIsTrue) and + ( + left = lhs.getLeftOperand() and x = int_value(lhs.getRight()) + or + left = lhs.getRightOperand() and x = int_value(lhs.getLeft()) + ) and + k = c - x + ) + or + exists(AddInstruction rhs, int c, int x | + compares_eq(cmp, left, rhs.getAUse(), c, areEqual, testIsTrue) and + ( + right = rhs.getLeftOperand() and x = int_value(rhs.getRight()) + or + right = rhs.getRightOperand() and x = int_value(rhs.getLeft()) + ) and + k = c + x + ) } /** The int value of integer constant expression. */ -private int int_value(Instruction i) { - result = i.(IntegerConstantInstruction).getValue().toInt() -} +private int int_value(Instruction i) { result = i.(IntegerConstantInstruction).getValue().toInt() } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll b/cpp/ql/src/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll index d839a4cc67b..117854d39e6 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/LocalScopeVariableReachability.qll @@ -58,23 +58,23 @@ abstract class LocalScopeVariableReachability extends string { * accounts for loops where the condition is provably true upon entry. */ predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { - /* Implementation detail: the predicates in this class are a generalization of + /* + * Implementation detail: the predicates in this class are a generalization of * those in DefinitionsAndUses.qll, and should be kept in sync. * * Unfortunately, caching of abstract predicates does not work well, so the * predicates in DefinitionsAndUses.qll cannot use this library. */ + exists(BasicBlock bb, int i | isSource(source, v) and bb.getNode(i) = source and - not bb.isUnreachable() | + not bb.isUnreachable() + | exists(int j | - j > i - and - sink = bb.getNode(j) - and - isSink(sink, v) - and + j > i and + sink = bb.getNode(j) and + isSink(sink, v) and not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) ) or @@ -83,9 +83,14 @@ abstract class LocalScopeVariableReachability extends string { ) } - private predicate bbSuccessorEntryReaches(BasicBlock bb, SemanticStackVariable v, ControlFlowNode node, boolean skipsFirstLoopAlwaysTrueUponEntry) { + private predicate bbSuccessorEntryReaches( + BasicBlock bb, SemanticStackVariable v, ControlFlowNode node, + boolean skipsFirstLoopAlwaysTrueUponEntry + ) { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | - bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) | + bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, + succSkipsFirstLoopAlwaysTrueUponEntry) + | bbEntryReachesLocally(succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or @@ -94,7 +99,9 @@ abstract class LocalScopeVariableReachability extends string { ) } - private predicate bbEntryReachesLocally(BasicBlock bb, SemanticStackVariable v, ControlFlowNode node) { + private predicate bbEntryReachesLocally( + BasicBlock bb, SemanticStackVariable v, ControlFlowNode node + ) { exists(int n | node = bb.getNode(n) and isSink(node, v) @@ -138,20 +145,20 @@ private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, Control * being found to be `false` and `skipsLoop` is `true`. Non-concluding edges * within a complex loop condition are not matched by this predicate. */ -private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(BasicBlock pred, BasicBlock succ, boolean skipsLoop) { +private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor( + BasicBlock pred, BasicBlock succ, boolean skipsLoop +) { exists(Expr cond | loopConditionAlwaysTrueUponEntry(_, cond) and cond.getAChild*() = pred.getEnd() and succ = pred.getASuccessor() and not cond.getAChild*() = succ.getStart() and ( - ( - succ = pred.getAFalseSuccessor() and - skipsLoop = true - ) or ( - succ = pred.getATrueSuccessor() and - skipsLoop = false - ) + succ = pred.getAFalseSuccessor() and + skipsLoop = true + or + succ = pred.getATrueSuccessor() and + skipsLoop = false ) ) } @@ -170,7 +177,10 @@ private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(BasicBlock pred, B * is provably true upon entry, then `succ` is not allowed to skip * that loop (`succSkipsFirstLoopAlwaysTrueUponEntry = false`). */ -predicate bbSuccessorEntryReachesLoopInvariant(BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry, boolean succSkipsFirstLoopAlwaysTrueUponEntry) { +predicate bbSuccessorEntryReachesLoopInvariant( + BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry, + boolean succSkipsFirstLoopAlwaysTrueUponEntry +) { succ = pred.getASuccessor() and (succSkipsFirstLoopAlwaysTrueUponEntry = true or succSkipsFirstLoopAlwaysTrueUponEntry = false) and ( @@ -180,16 +190,18 @@ predicate bbSuccessorEntryReachesLoopInvariant(BasicBlock pred, BasicBlock succ, // regardless of the value of `succSkipsFirstLoopAlwaysTrueUponEntry`. bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, predSkipsFirstLoopAlwaysTrueUponEntry) or + // The edge from `pred` to `succ` is _not_ from a loop condition provably + // true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry` + // and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same. + not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, _) and + succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and + // Moreover, if `pred` contains the entry point of a loop where the + // condition is provably true upon entry, then `succ` is not allowed + // to skip that loop, and hence `succSkipsFirstLoopAlwaysTrueUponEntry = false`. ( - // The edge from `pred` to `succ` is _not_ from a loop condition provably - // true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry` - // and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same. - not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, _) and - succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and - // Moreover, if `pred` contains the entry point of a loop where the - // condition is provably true upon entry, then `succ` is not allowed - // to skip that loop, and hence `succSkipsFirstLoopAlwaysTrueUponEntry = false`. - (bbLoopEntryConditionAlwaysTrueAt(pred, _, _) implies succSkipsFirstLoopAlwaysTrueUponEntry = false) + bbLoopEntryConditionAlwaysTrueAt(pred, _, _) + implies + succSkipsFirstLoopAlwaysTrueUponEntry = false ) ) } @@ -255,9 +267,11 @@ abstract class LocalScopeVariableReachabilityWithReassignment extends LocalScope } /** - * As `reaches`, but also specifies the last variable it was reassigned to (`v0`). + * As `reaches`, but also specifies the last variable it was reassigned to (`v0`). */ - predicate reachesTo(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0) { + predicate reachesTo( + ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0 + ) { exists(ControlFlowNode def | actualSourceReaches(source, v, def, v0) and LocalScopeVariableReachability.super.reaches(def, v0, sink) and @@ -265,16 +279,21 @@ abstract class LocalScopeVariableReachabilityWithReassignment extends LocalScope ) } - private predicate actualSourceReaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0) { + private predicate actualSourceReaches( + ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0 + ) { isSourceActual(source, v) and def = source and v0 = v or exists(ControlFlowNode source1, SemanticStackVariable v1 | - actualSourceReaches(source, v, source1, v1) | + actualSourceReaches(source, v, source1, v1) + | reassignment(source1, v1, def, v0) ) } - private predicate reassignment(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0) { + private predicate reassignment( + ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0 + ) { LocalScopeVariableReachability.super.reaches(source, v, def) and exprDefinition(v0, def, v.getAnAccess()) } @@ -311,22 +330,24 @@ abstract class LocalScopeVariableReachabilityExt extends string { abstract predicate isSink(ControlFlowNode node, LocalScopeVariable v); /** `node` is a barrier for the reachability analysis using variable `v` and starting from `source`. */ - abstract predicate isBarrier(ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v); + abstract predicate isBarrier( + ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v + ); /** See `LocalScopeVariableReachability.reaches`. */ predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) { exists(BasicBlock bb, int i | isSource(source, v) and bb.getNode(i) = source and - not bb.isUnreachable() | + not bb.isUnreachable() + | exists(int j | - j > i - and - sink = bb.getNode(j) - and - isSink(sink, v) - and - not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k in [i .. j - 1]) + j > i and + sink = bb.getNode(j) and + isSink(sink, v) and + not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | + k in [i .. j - 1] + ) ) or not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and @@ -334,10 +355,15 @@ abstract class LocalScopeVariableReachabilityExt extends string { ) } - private predicate bbSuccessorEntryReaches(ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node, boolean skipsFirstLoopAlwaysTrueUponEntry) { + private predicate bbSuccessorEntryReaches( + ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node, + boolean skipsFirstLoopAlwaysTrueUponEntry + ) { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | - bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) and - not isBarrier(source, bb.getEnd(), succ.getStart(), v) | + bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, + succSkipsFirstLoopAlwaysTrueUponEntry) and + not isBarrier(source, bb.getEnd(), succ.getStart(), v) + | bbEntryReachesLocally(source, succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or @@ -346,11 +372,12 @@ abstract class LocalScopeVariableReachabilityExt extends string { ) } - private predicate bbEntryReachesLocally(ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node) { + private predicate bbEntryReachesLocally( + ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node + ) { isSource(source, v) and - exists(int n | - node = bb.getNode(n) and isSink(node, v) | + exists(int n | node = bb.getNode(n) and isSink(node, v) | not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) ) } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll index 9b35fda199f..54b14aadd9d 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll @@ -4,15 +4,12 @@ import DefinitionsAndUses /** * A C/C++ literal whose value is considered null. */ -abstract class NullValue extends Expr -{ -} +abstract class NullValue extends Expr { } /** * A C/C++ literal whose value is zero. */ -class Zero extends NullValue -{ +class Zero extends NullValue { Zero() { this.(Literal).getValue() = "0" } } @@ -20,35 +17,48 @@ class Zero extends NullValue * Holds if `var` is null when `checkExpr` evaluates to a true value. */ cached -predicate nullCheckExpr(Expr checkExpr, Variable var) -{ +predicate nullCheckExpr(Expr checkExpr, Variable var) { exists(LocalScopeVariable v, AnalysedExpr expr | var = v and checkExpr = expr | exists(NotExpr notexpr, AnalysedExpr child | - expr = notexpr and notexpr.getOperand() = child and validCheckExpr(child, v)) + expr = notexpr and notexpr.getOperand() = child and validCheckExpr(child, v) + ) or exists(EQExpr eq, AnalysedExpr child, NullValue zero, int i | - expr = eq and eq.getChild(i) = child and - validCheckExpr(child, v) and eq.getChild(1-i) = zero) + expr = eq and + eq.getChild(i) = child and + validCheckExpr(child, v) and + eq.getChild(1 - i) = zero + ) or exists(NEExpr neq, AnalysedExpr child, NullValue zero, int i | - expr = neq and neq.getChild(i) = child and - nullCheckExpr(child, v) and neq.getChild(1-i) = zero) + expr = neq and + neq.getChild(i) = child and + nullCheckExpr(child, v) and + neq.getChild(1 - i) = zero + ) or exists(LogicalAndExpr op, AnalysedExpr child | - expr = op and op.getRightOperand() = child and - nullCheckExpr(child, v)) + expr = op and + op.getRightOperand() = child and + nullCheckExpr(child, v) + ) or exists(AssignExpr assign, AnalysedExpr child | - expr = assign and assign.getRValue() = child and - nullCheckExpr(child, v) and not expr.isDef(v)) + expr = assign and + assign.getRValue() = child and + nullCheckExpr(child, v) and + not expr.isDef(v) + ) or exists(FunctionCall fc, AnalysedExpr child | expr = fc and fc.getTarget().hasGlobalName("__builtin_expect") and - fc.getArgument(0) = child and nullCheckExpr(child, v)) + fc.getArgument(0) = child and + nullCheckExpr(child, v) + ) ) } @@ -56,8 +66,7 @@ predicate nullCheckExpr(Expr checkExpr, Variable var) * Holds if `var` is non-null when `checkExpr` evaluates to a true value. */ cached -predicate validCheckExpr(Expr checkExpr, Variable var) -{ +predicate validCheckExpr(Expr checkExpr, Variable var) { exists(AnalysedExpr expr, LocalScopeVariable v | v = var and expr = checkExpr @@ -67,28 +76,42 @@ predicate validCheckExpr(Expr checkExpr, Variable var) expr.isDef(v) or exists(NotExpr notexpr, AnalysedExpr child | - expr = notexpr and notexpr.getOperand() = child and nullCheckExpr(child, v)) + expr = notexpr and notexpr.getOperand() = child and nullCheckExpr(child, v) + ) or exists(EQExpr eq, AnalysedExpr child, NullValue zero, int i | - expr = eq and eq.getChild(i) = child and - nullCheckExpr(child, v) and eq.getChild(1-i) = zero) + expr = eq and + eq.getChild(i) = child and + nullCheckExpr(child, v) and + eq.getChild(1 - i) = zero + ) or exists(NEExpr neq, AnalysedExpr child, NullValue zero, int i | - expr = neq and neq.getChild(i) = child and - validCheckExpr(child, v) and neq.getChild(1-i) = zero) + expr = neq and + neq.getChild(i) = child and + validCheckExpr(child, v) and + neq.getChild(1 - i) = zero + ) or exists(LogicalAndExpr op, AnalysedExpr child | - expr = op and op.getRightOperand() = child and - validCheckExpr(child, v)) + expr = op and + op.getRightOperand() = child and + validCheckExpr(child, v) + ) or exists(AssignExpr assign, AnalysedExpr child | - expr = assign and assign.getRValue() = child and - validCheckExpr(child, v) and not expr.isDef(v)) + expr = assign and + assign.getRValue() = child and + validCheckExpr(child, v) and + not expr.isDef(v) + ) or exists(FunctionCall fc, AnalysedExpr child | expr = fc and fc.getTarget().hasGlobalName("__builtin_expect") and - fc.getArgument(0) = child and validCheckExpr(child, v)) + fc.getArgument(0) = child and + validCheckExpr(child, v) + ) ) } @@ -97,31 +120,25 @@ predicate validCheckExpr(Expr checkExpr, Variable var) * information about the role of this expression in nullness checks. */ class AnalysedExpr extends Expr { - /** * Holds if `v` is null when this expression evaluates to a true value. */ - predicate isNullCheck(LocalScopeVariable v) { - nullCheckExpr(this, v) - } + predicate isNullCheck(LocalScopeVariable v) { nullCheckExpr(this, v) } /** * Holds if `v` is non-null when this expression evaluates to a true value. */ - predicate isValidCheck(LocalScopeVariable v) { - validCheckExpr(this, v) - } + predicate isValidCheck(LocalScopeVariable v) { validCheckExpr(this, v) } /** * Gets a successor of `this` in the control flow graph, where that successor * is among the nodes to which control may flow when `this` tests `v` to be * _null_. */ - ControlFlowNode getNullSuccessor(LocalScopeVariable v) - { - (this.isNullCheck(v) and result = this.getATrueSuccessor()) + ControlFlowNode getNullSuccessor(LocalScopeVariable v) { + this.isNullCheck(v) and result = this.getATrueSuccessor() or - (this.isValidCheck(v) and result = this.getAFalseSuccessor()) + this.isValidCheck(v) and result = this.getAFalseSuccessor() } /** @@ -129,29 +146,25 @@ class AnalysedExpr extends Expr { * is among the nodes to which control may flow when `this` tests `v` to be * _not null_. */ - ControlFlowNode getNonNullSuccessor(LocalScopeVariable v) - { - (this.isNullCheck(v) and result = this.getAFalseSuccessor()) + ControlFlowNode getNonNullSuccessor(LocalScopeVariable v) { + this.isNullCheck(v) and result = this.getAFalseSuccessor() or - (this.isValidCheck(v) and result = this.getATrueSuccessor()) + this.isValidCheck(v) and result = this.getATrueSuccessor() } /** * DEPRECATED: Use `getNonNullSuccessor` instead, which does the same. */ - deprecated - ControlFlowNode getValidSuccessor(LocalScopeVariable v) - { - (this.isValidCheck(v) and result = this.getATrueSuccessor()) + deprecated ControlFlowNode getValidSuccessor(LocalScopeVariable v) { + this.isValidCheck(v) and result = this.getATrueSuccessor() or - (this.isNullCheck(v) and result = this.getAFalseSuccessor()) + this.isNullCheck(v) and result = this.getAFalseSuccessor() } /** * Holds if this is a `VariableAccess` of `v` nested inside a condition. */ - predicate isUse(LocalScopeVariable v) - { + predicate isUse(LocalScopeVariable v) { this.inCondition() and this = v.getAnAccess() } @@ -159,8 +172,7 @@ class AnalysedExpr extends Expr { /** * Holds if this is an `Assignment` to `v` nested inside a condition. */ - predicate isDef(LocalScopeVariable v) - { + predicate isDef(LocalScopeVariable v) { this.inCondition() and this.(Assignment).getLValue() = v.getAnAccess() } @@ -169,8 +181,7 @@ class AnalysedExpr extends Expr { * Holds if `this` occurs at or below the controlling expression of an `if`, * `while`, `?:`, or similar. */ - predicate inCondition() - { + predicate inCondition() { this.isCondition() or this.getParent().(AnalysedExpr).inCondition() } @@ -180,12 +191,9 @@ class AnalysedExpr extends Expr { * Holds if `var` is likely to be null at `node`. */ cached -predicate checkedNull(Variable var, ControlFlowNode node) -{ +predicate checkedNull(Variable var, ControlFlowNode node) { exists(LocalScopeVariable v | v = var | - exists(AnalysedExpr e | - e.getNullSuccessor(v) = node - ) + exists(AnalysedExpr e | e.getNullSuccessor(v) = node) or exists(ControlFlowNode pred | pred = node.getAPredecessor() and @@ -199,12 +207,9 @@ predicate checkedNull(Variable var, ControlFlowNode node) * Holds if `var` is likely to be non-null at `node`. */ cached -predicate checkedValid(Variable var, ControlFlowNode node) -{ +predicate checkedValid(Variable var, ControlFlowNode node) { exists(LocalScopeVariable v | v = var | - exists(AnalysedExpr e | - e.getNonNullSuccessor(v) = node - ) + exists(AnalysedExpr e | e.getNonNullSuccessor(v) = node) or exists(ControlFlowNode pred | pred = node.getAPredecessor() and @@ -218,8 +223,7 @@ predicate checkedValid(Variable var, ControlFlowNode node) * Holds if `val` is a null literal or a call to a function that may return a * null literal. */ -predicate nullValue(Expr val) -{ +predicate nullValue(Expr val) { val instanceof NullValue or callMayReturnNull(val) @@ -231,51 +235,53 @@ predicate nullValue(Expr val) * Holds if the evaluation of `n` may have the effect of, directly or * indirectly, assigning a null literal to `var`. */ -predicate nullInit(Variable v, ControlFlowNode n) -{ +predicate nullInit(Variable v, ControlFlowNode n) { exists(Initializer init | - init = n and nullValue(init.getExpr()) and - v.getInitializer() = init) + init = n and + nullValue(init.getExpr()) and + v.getInitializer() = init + ) or exists(AssignExpr assign | - assign = n and nullValue(assign.getRValue()) and - assign.getLValue() = v.getAnAccess()) + assign = n and + nullValue(assign.getRValue()) and + assign.getLValue() = v.getAnAccess() + ) } /** * Holds if `call` may, directly or indirectly, evaluate to a null literal. */ -predicate callMayReturnNull(Call call) -{ +predicate callMayReturnNull(Call call) { exists(Options opts | - if opts.overrideReturnsNull(call) then - opts.returnsNull(call) - else - mayReturnNull(call.(FunctionCall).getTarget()) + if opts.overrideReturnsNull(call) + then opts.returnsNull(call) + else mayReturnNull(call.(FunctionCall).getTarget()) ) } /** * Holds if `f` may, directly or indirectly, return a null literal. */ -predicate mayReturnNull(Function f) -{ +predicate mayReturnNull(Function f) { f.hasGlobalName("malloc") or f.hasGlobalName("calloc") or -// f.hasGlobalName("strchr") -// or -// f.hasGlobalName("strstr") -// or + // f.hasGlobalName("strchr") + // or + // f.hasGlobalName("strstr") + // or exists(ReturnStmt ret | nullValue(ret.getExpr()) and - ret.getEnclosingFunction() = f) + ret.getEnclosingFunction() = f + ) or exists(ReturnStmt ret, Expr returned, ControlFlowNode init, LocalScopeVariable v | ret.getExpr() = returned and nullInit(v, init) and definitionUsePair(v, init, returned) and - not(checkedValid(v, returned)) and - ret.getEnclosingFunction() = f) + not checkedValid(v, returned) and + ret.getEnclosingFunction() = f + ) } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/SSA.qll b/cpp/ql/src/semmle/code/cpp/controlflow/SSA.qll index 495b6df4900..9f7c1c88b24 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/SSA.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/SSA.qll @@ -3,7 +3,7 @@ import semmle.code.cpp.controlflow.Dominance import SSAUtils library class StandardSSA extends SSAHelper { - StandardSSA() { this = 0 } + StandardSSA() { this = 0 } } /** @@ -19,147 +19,137 @@ library class StandardSSA extends SSAHelper { * statically seen to be unreachable. */ class SsaDefinition extends ControlFlowNodeBase { + SsaDefinition() { exists(StandardSSA x | x.ssa_defn(_, this, _, _)) } - SsaDefinition() { - exists(StandardSSA x | x.ssa_defn(_, this, _, _)) - } + /** + * Gets a variable corresponding to an SSA LocalScopeVariable defined by + * this definition. + */ + LocalScopeVariable getAVariable() { exists(StandardSSA x | x.ssa_defn(result, this, _, _)) } - /** - * Gets a variable corresponding to an SSA LocalScopeVariable defined by - * this definition. - */ - LocalScopeVariable getAVariable() { - exists(StandardSSA x | x.ssa_defn(result, this, _, _)) - } + /** + * Gets a string representation of the SSA variable represented by the pair + * (this, v). + */ + string toString(LocalScopeVariable v) { exists(StandardSSA x | result = x.toString(this, v)) } - /** - * Gets a string representation of the SSA variable represented by the pair - * (this, v). - */ - string toString(LocalScopeVariable v) { - exists(StandardSSA x | result = x.toString(this, v)) - } + /** Gets a use of the SSA variable represented by the pair (this, v). */ + VariableAccess getAUse(LocalScopeVariable v) { + exists(StandardSSA x | result = x.getAUse(this, v)) + } - /** Gets a use of the SSA variable represented by the pair (this, v). */ - VariableAccess getAUse(LocalScopeVariable v) { - exists(StandardSSA x | result = x.getAUse(this, v)) - } + /** + * Gets the control-flow node for this definition. This will usually be the + * control-flow node that assigns to this variable as a side effect, but + * there are some exceptions. If `this` is defined by initialization, the + * result is the value of `Initializer.getExpr()` for that initialization. + * If `this` is a function parameter (see `definedByParameter`), the result + * will be the function entry point. If `this` variable is defined by being + * passed as a reference in a function call, including overloaded + * operators, the result will be the `VariableAccess` expression for this + * parameter. If `this` is a phi node (see `isPhiNode`), the result will be + * the node where control flow is joined from multiple paths. + */ + ControlFlowNode getDefinition() { result = this } - /** - * Gets the control-flow node for this definition. This will usually be the - * control-flow node that assigns to this variable as a side effect, but - * there are some exceptions. If `this` is defined by initialization, the - * result is the value of `Initializer.getExpr()` for that initialization. - * If `this` is a function parameter (see `definedByParameter`), the result - * will be the function entry point. If `this` variable is defined by being - * passed as a reference in a function call, including overloaded - * operators, the result will be the `VariableAccess` expression for this - * parameter. If `this` is a phi node (see `isPhiNode`), the result will be - * the node where control flow is joined from multiple paths. - */ - ControlFlowNode getDefinition() { - result = this - } + BasicBlock getBasicBlock() { result.contains(getDefinition()) } - BasicBlock getBasicBlock() { - result.contains(getDefinition()) - } + /** Holds if this definition is a phi node for variable `v`. */ + predicate isPhiNode(LocalScopeVariable v) { + exists(StandardSSA x | x.phi_node(v, this.(BasicBlock))) + } - /** Holds if this definition is a phi node for variable `v`. */ - predicate isPhiNode(LocalScopeVariable v) { - exists(StandardSSA x | x.phi_node(v, (BasicBlock)this)) - } + Location getLocation() { result = this.(ControlFlowNode).getLocation() } - Location getLocation() { - result = this.(ControlFlowNode).getLocation() - } + /** Holds if the SSA variable `(this, p)` is defined by parameter `p`. */ + predicate definedByParameter(Parameter p) { this = p.getFunction().getEntryPoint() } - /** Holds if the SSA variable `(this, p)` is defined by parameter `p`. */ - predicate definedByParameter(Parameter p) { - this = p.getFunction().getEntryPoint() - } + /** + * Holds if the SSA variable `(result, v)` is an input to the phi definition + * `(this, v)`. + */ + SsaDefinition getAPhiInput(LocalScopeVariable v) { + this.isPhiNode(v) and + result.reachesEndOfBB(v, this.(BasicBlock).getAPredecessor()) + } - /** - * Holds if the SSA variable `(result, v)` is an input to the phi definition - * `(this, v)`. - */ - SsaDefinition getAPhiInput(LocalScopeVariable v) { - this.isPhiNode(v) - and - result.reachesEndOfBB(v, this.(BasicBlock).getAPredecessor()) - } + /** + * Gets the expression assigned to the SSA variable `(this, v)`, if any, + * when it is not a phi definition. The following is an exhaustive list of + * expressions that may be the result of this predicate. + * + * - The contained expression of an `Initializer`. + * - The right-hand side of an `AssignExpr`. + * - An `AssignOperation`. + * - A `CrementOperation`. + * + * In all cases except `PostfixCrementOperation`, the variable `v` will be + * equal to the result of this predicate after evaluation of + * `this.getDefinition()`. + * + * If the SSA variable is defined in other ways than those four (such as + * function parameters or `f(&x)`) there is no result. These cases are + * instead covered via `definedByParameter` and `getDefinition`, + * respectively. + */ + Expr getDefiningValue(LocalScopeVariable v) { + exists(ControlFlowNode def | def = this.getDefinition() | + def = v.getInitializer().getExpr() and def = result + or + exists(AssignExpr assign | + def = assign and + assign.getLValue() = v.getAnAccess() and + result = assign.getRValue() + ) + or + exists(AssignOperation assign | + def = assign and + assign.getLValue() = v.getAnAccess() and + result = assign + ) + or + exists(CrementOperation crement | + def = crement and + crement.getOperand() = v.getAnAccess() and + result = crement + ) + ) + } - /** - * Gets the expression assigned to the SSA variable `(this, v)`, if any, - * when it is not a phi definition. The following is an exhaustive list of - * expressions that may be the result of this predicate. - * - * - The contained expression of an `Initializer`. - * - The right-hand side of an `AssignExpr`. - * - An `AssignOperation`. - * - A `CrementOperation`. - * - * In all cases except `PostfixCrementOperation`, the variable `v` will be - * equal to the result of this predicate after evaluation of - * `this.getDefinition()`. - * - * If the SSA variable is defined in other ways than those four (such as - * function parameters or `f(&x)`) there is no result. These cases are - * instead covered via `definedByParameter` and `getDefinition`, - * respectively. - */ - Expr getDefiningValue(LocalScopeVariable v) { - exists(ControlFlowNode def | def = this.getDefinition() | - def = v.getInitializer().getExpr() and def = result - or - exists(AssignExpr assign | def = assign and - assign.getLValue() = v.getAnAccess() and result = assign.getRValue() - ) - or - exists(AssignOperation assign | def = assign and - assign.getLValue() = v.getAnAccess() and result = assign - ) - or - exists(CrementOperation crement | def = crement and - crement.getOperand() = v.getAnAccess() and result = crement - ) - ) - } + /** Holds if `(this, v)` reaches the end of basic block `b`. */ + predicate reachesEndOfBB(LocalScopeVariable v, BasicBlock b) { + exists(StandardSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b)) + } - /** Holds if `(this, v)` reaches the end of basic block `b`. */ - predicate reachesEndOfBB(LocalScopeVariable v, BasicBlock b) { - exists(StandardSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b)) - } + /** + * Gets a definition that ultimately defines this variable and is not + * itself a phi node. + */ + SsaDefinition getAnUltimateSsaDefinition(LocalScopeVariable v) { + result = this.getAPhiInput(v).getAnUltimateSsaDefinition(v) + or + v = this.getAVariable() and + not this.isPhiNode(v) and + result = this + } - /** - * Gets a definition that ultimately defines this variable and is not - * itself a phi node. - */ - SsaDefinition getAnUltimateSsaDefinition(LocalScopeVariable v) { - result = this.getAPhiInput(v).getAnUltimateSsaDefinition(v) - or - v = this.getAVariable() and - not this.isPhiNode(v) and - result = this - } + /** + * Gets a possible defining expression for `v` at this SSA definition, + * recursing backwards through phi definitions. Not all definitions have a + * defining expression---see the documentation for `getDefiningValue`. + */ + Expr getAnUltimateDefiningValue(LocalScopeVariable v) { + result = this.getAnUltimateSsaDefinition(v).getDefiningValue(v) + } - /** - * Gets a possible defining expression for `v` at this SSA definition, - * recursing backwards through phi definitions. Not all definitions have a - * defining expression---see the documentation for `getDefiningValue`. - */ - Expr getAnUltimateDefiningValue(LocalScopeVariable v) { - result = this.getAnUltimateSsaDefinition(v).getDefiningValue(v) - } - - /** - * DEPRECATED: this is the old name for `getAnUltimateDefiningValue`. The - * name was confusing as it seemed analogous to `getDefinition` rather than - * `getDefiningValue`. The SSA libraries for other languages use the name - * `getAnUltimateSsaDefinition` to refer to a predicate named - * `getAnUltimateSsaDefinition` in this class. - */ - deprecated Expr getAnUltimateDefinition(LocalScopeVariable v) { - result = this.getAnUltimateDefiningValue(v) - } + /** + * DEPRECATED: this is the old name for `getAnUltimateDefiningValue`. The + * name was confusing as it seemed analogous to `getDefinition` rather than + * `getDefiningValue`. The SSA libraries for other languages use the name + * `getAnUltimateSsaDefinition` to refer to a predicate named + * `getAnUltimateSsaDefinition` in this class. + */ + deprecated Expr getAnUltimateDefinition(LocalScopeVariable v) { + result = this.getAnUltimateDefiningValue(v) + } } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/SSAUtils.qll b/cpp/ql/src/semmle/code/cpp/controlflow/SSAUtils.qll index 402e6e97826..5501fb0a394 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/SSAUtils.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/SSAUtils.qll @@ -12,12 +12,12 @@ import semmle.code.cpp.rangeanalysis.RangeSSA // must be imported for proper cac * bbDominates(x, w.getAPredecessor()) and not bbStrictlyDominates(x, w) */ private predicate dominanceFrontier(BasicBlock x, BasicBlock w) { - x = w.getAPredecessor() and not bbIDominates(x, w) - or - exists(BasicBlock prev | dominanceFrontier(prev, w) | - bbIDominates(x, prev) and - not bbIDominates(x, w) - ) + x = w.getAPredecessor() and not bbIDominates(x, w) + or + exists(BasicBlock prev | dominanceFrontier(prev, w) | + bbIDominates(x, prev) and + not bbIDominates(x, w) + ) } /** @@ -25,21 +25,25 @@ private predicate dominanceFrontier(BasicBlock x, BasicBlock w) { * static variables. */ predicate var_definition(LocalScopeVariable v, ControlFlowNode node) { - not v.isStatic() - and - not addressTakenVariable(v) - and - not unreachable(node) - and - (if isReferenceVar(v) - then // Assignments to reference variables modify the referenced - // value, not the reference itself. So reference variables only - // have two kinds of definition: initializers and parameters. - node = v.getInitializer().getExpr() - else definition(v, node)) - or - v instanceof Parameter and exists(BasicBlock b | b.getStart() = node and not exists(b.getAPredecessor()) and - b = v.(Parameter).getFunction().getEntryPoint()) + not v.isStatic() and + not addressTakenVariable(v) and + not unreachable(node) and + ( + if isReferenceVar(v) + then + // Assignments to reference variables modify the referenced + // value, not the reference itself. So reference variables only + // have two kinds of definition: initializers and parameters. + node = v.getInitializer().getExpr() + else definition(v, node) + ) + or + v instanceof Parameter and + exists(BasicBlock b | + b.getStart() = node and + not exists(b.getAPredecessor()) and + b = v.(Parameter).getFunction().getEntryPoint() + ) } /** @@ -48,25 +52,23 @@ predicate var_definition(LocalScopeVariable v, ControlFlowNode node) { * any moment. */ private predicate addressTakenVariable(LocalScopeVariable var) { - // If the type of the variable is a reference type, then it is safe (as - // far as SSA is concerned) to take its address, because this does not - // enable the variable to be modified indirectly. Obviously the - // referenced value can change, but that is not the same thing as - // changing which value the reference points to. SSA tracks the latter, - // but the target of a reference is immutable so reference variables - // always have exactly one definition. - not isReferenceVar(var) - and - - // Find a VariableAccess that takes the address of `var`. - exists (VariableAccess va - | va = var.getAnAccess() and - va.isAddressOfAccessNonConst() and - // If the address is passed to a function then we will trust that it - // is only used to modify the variable for the duration of the - // function call. - not exists(Call call | call.passesByReferenceNonConst(_, va)) - ) + // If the type of the variable is a reference type, then it is safe (as + // far as SSA is concerned) to take its address, because this does not + // enable the variable to be modified indirectly. Obviously the + // referenced value can change, but that is not the same thing as + // changing which value the reference points to. SSA tracks the latter, + // but the target of a reference is immutable so reference variables + // always have exactly one definition. + not isReferenceVar(var) and + // Find a VariableAccess that takes the address of `var`. + exists(VariableAccess va | + va = var.getAnAccess() and + va.isAddressOfAccessNonConst() and + // If the address is passed to a function then we will trust that it + // is only used to modify the variable for the duration of the + // function call. + not exists(Call call | call.passesByReferenceNonConst(_, va)) + ) } private predicate isReferenceVar(LocalScopeVariable v) { @@ -82,204 +84,218 @@ private predicate variableUpdate(LocalScopeVariable v, ControlFlowNode n, BasicB } private predicate ssa_use(LocalScopeVariable v, VariableAccess node, BasicBlock b, int index) { - useOfVar(v, node) and b.getNode(index) = node + useOfVar(v, node) and b.getNode(index) = node } private predicate live_at_start_of_bb(LocalScopeVariable v, BasicBlock b) { - exists (int i | ssa_use(v, _, b, i) | - not exists (int j | variableUpdate(v, _, b, j) | j < i)) - or - (live_at_exit_of_bb(v, b) and not variableUpdate(v, _, b, _)) + exists(int i | ssa_use(v, _, b, i) | not exists(int j | variableUpdate(v, _, b, j) | j < i)) + or + live_at_exit_of_bb(v, b) and not variableUpdate(v, _, b, _) } pragma[noinline] private predicate live_at_exit_of_bb(LocalScopeVariable v, BasicBlock b) { - live_at_start_of_bb(v, b.getASuccessor()) + live_at_start_of_bb(v, b.getASuccessor()) } /** Common SSA logic for standard SSA and range-analysis SSA. */ -cached library class SSAHelper extends int { - /* 0 = StandardSSA, 1 = RangeSSA */ - cached SSAHelper() { this in [0 .. 1] } +cached +library class SSAHelper extends int { + /* 0 = StandardSSA, 1 = RangeSSA */ + cached + SSAHelper() { this in [0 .. 1] } - /** - * Override to insert a custom phi node for variable `v` at the start of - * basic block `b`. - */ - cached predicate custom_phi_node(LocalScopeVariable v, BasicBlock b) { none() } + /** + * Override to insert a custom phi node for variable `v` at the start of + * basic block `b`. + */ + cached + predicate custom_phi_node(LocalScopeVariable v, BasicBlock b) { none() } - /** - * Remove any custom phi nodes that are invalid. - */ - private predicate sanitized_custom_phi_node(LocalScopeVariable v, BasicBlock b) { - custom_phi_node(v,b) and - not addressTakenVariable(v) and - not isReferenceVar(v) and - b.isReachable() - } + /** + * Remove any custom phi nodes that are invalid. + */ + private predicate sanitized_custom_phi_node(LocalScopeVariable v, BasicBlock b) { + custom_phi_node(v, b) and + not addressTakenVariable(v) and + not isReferenceVar(v) and + b.isReachable() + } - /** - * Holds if there is a phi node for variable `v` at the start of basic block - * `b`. - */ - cached predicate phi_node(LocalScopeVariable v, BasicBlock b) { - frontier_phi_node(v,b) or sanitized_custom_phi_node(v,b) - } + /** + * Holds if there is a phi node for variable `v` at the start of basic block + * `b`. + */ + cached + predicate phi_node(LocalScopeVariable v, BasicBlock b) { + frontier_phi_node(v, b) or sanitized_custom_phi_node(v, b) + } - /** - * A phi node is required for variable `v` at the start of basic block `b` - * if there exists a basic block `x` such that `b` is in the dominance - * frontier of `x` and `v` is defined in `x` (including phi-nodes as - * definitions). This is known as the iterated dominance frontier. See - * Modern Compiler Implementation by Andrew Appel. - */ - private predicate frontier_phi_node(LocalScopeVariable v, BasicBlock b) { - exists(BasicBlock x | dominanceFrontier(x, b) and ssa_defn_rec(v, x)) - /* We can also eliminate those nodes where the variable is not live on any incoming edge */ - and live_at_start_of_bb(v, b) - } + /** + * A phi node is required for variable `v` at the start of basic block `b` + * if there exists a basic block `x` such that `b` is in the dominance + * frontier of `x` and `v` is defined in `x` (including phi-nodes as + * definitions). This is known as the iterated dominance frontier. See + * Modern Compiler Implementation by Andrew Appel. + */ + private predicate frontier_phi_node(LocalScopeVariable v, BasicBlock b) { + exists(BasicBlock x | dominanceFrontier(x, b) and ssa_defn_rec(v, x)) and + /* We can also eliminate those nodes where the variable is not live on any incoming edge */ + live_at_start_of_bb(v, b) + } - private predicate ssa_defn_rec(LocalScopeVariable v, BasicBlock b) { - phi_node(v, b) - or - variableUpdate(v, _, b, _) - } - - /** - * Holds if `v` is defined, for the purpose of SSA, at `node`, which is at - * position `index` in block `b`. This includes definitions from phi nodes. - */ - cached predicate ssa_defn(LocalScopeVariable v, ControlFlowNode node, BasicBlock b, int index) { - phi_node(v, b) and b.getStart() = node and index = -1 - or - variableUpdate(v, node, b, index) - } + private predicate ssa_defn_rec(LocalScopeVariable v, BasicBlock b) { + phi_node(v, b) + or + variableUpdate(v, _, b, _) + } - /* - * The construction of SSA form ensures that each use of a variable is - * dominated by its definition. A definition of an SSA variable therefore - * reaches a `ControlFlowNode` if it is the _closest_ SSA variable definition - * that dominates the node. If two definitions dominate a node then one must - * dominate the other, so therefore the definition of _closest_ is given by the - * dominator tree. Thus, reaching definitions can be calculated in terms of - * dominance. - */ + /** + * Holds if `v` is defined, for the purpose of SSA, at `node`, which is at + * position `index` in block `b`. This includes definitions from phi nodes. + */ + cached + predicate ssa_defn(LocalScopeVariable v, ControlFlowNode node, BasicBlock b, int index) { + phi_node(v, b) and b.getStart() = node and index = -1 + or + variableUpdate(v, node, b, index) + } - /** - * A ranking of the indices `i` at which there is an SSA definition or use of - * `v` in the basic block `b`. - * - * Basic block indices are translated to rank indices in order to skip - * irrelevant indices at which there is no definition or use when traversing - * basic blocks. - */ - private predicate defUseRank(LocalScopeVariable v, BasicBlock b, int rankix, int i) { - i = rank[rankix](int j | ssa_defn(v, _, b, j) or ssa_use(v, _, b, j)) - } + /* + * The construction of SSA form ensures that each use of a variable is + * dominated by its definition. A definition of an SSA variable therefore + * reaches a `ControlFlowNode` if it is the _closest_ SSA variable definition + * that dominates the node. If two definitions dominate a node then one must + * dominate the other, so therefore the definition of _closest_ is given by the + * dominator tree. Thus, reaching definitions can be calculated in terms of + * dominance. + */ - /** - * Gets the maximum rank index for the given variable `v` and basic block - * `b`. This will be the number of defs/uses of `v` in `b` plus one, where - * the extra rank at the end represents a position past the last node in - * the block. - */ - private int lastRank(LocalScopeVariable v, BasicBlock b) { - result = max(int rankix | defUseRank(v, b, rankix, _)) + 1 - } + /** + * A ranking of the indices `i` at which there is an SSA definition or use of + * `v` in the basic block `b`. + * + * Basic block indices are translated to rank indices in order to skip + * irrelevant indices at which there is no definition or use when traversing + * basic blocks. + */ + private predicate defUseRank(LocalScopeVariable v, BasicBlock b, int rankix, int i) { + i = rank[rankix](int j | ssa_defn(v, _, b, j) or ssa_use(v, _, b, j)) + } - /** - * Holds if SSA variable `(v, def)` is defined at rank index `rankix` in - * basic block `b`. - */ - private predicate ssaDefRank(LocalScopeVariable v, ControlFlowNode def, BasicBlock b, int rankix) { - exists(int i - | ssa_defn(v, def, b, i) and - defUseRank(v, b, rankix, i)) - } + /** + * Gets the maximum rank index for the given variable `v` and basic block + * `b`. This will be the number of defs/uses of `v` in `b` plus one, where + * the extra rank at the end represents a position past the last node in + * the block. + */ + private int lastRank(LocalScopeVariable v, BasicBlock b) { + result = max(int rankix | defUseRank(v, b, rankix, _)) + 1 + } - /** - * Holds if SSA variable `(v, def)` reaches the rank index `rankix` in its - * own basic block `b` before being overwritten by another definition of - * `v` that comes _at or after_ the reached node. Reaching a node means - * that the definition is visible to any _use_ at that node. - */ - private predicate ssaDefReachesRank(LocalScopeVariable v, ControlFlowNode def, BasicBlock b, int rankix) { - // A definition should not reach its own node unless a loop allows it. - // When nodes are both definitions and uses for the same variable, the - // use is understood to happen _before_ the definition. Phi nodes are - // at rankidx -1 and will therefore always reach the first node in the - // basic block. - ssaDefRank(v, def, b, rankix-1) - or - (ssaDefReachesRank(v, def, b, rankix-1) and - rankix <= lastRank(v, b) and // Without this, the predicate would be infinite. - not ssaDefRank(v, _, b, rankix-1)) // Range is inclusive of but not past next def. - } + /** + * Holds if SSA variable `(v, def)` is defined at rank index `rankix` in + * basic block `b`. + */ + private predicate ssaDefRank(LocalScopeVariable v, ControlFlowNode def, BasicBlock b, int rankix) { + exists(int i | + ssa_defn(v, def, b, i) and + defUseRank(v, b, rankix, i) + ) + } - /** Holds if SSA variable `(v, def)` reaches the end of block `b`. */ - cached predicate ssaDefinitionReachesEndOfBB(LocalScopeVariable v, ControlFlowNode def, BasicBlock b) { - (live_at_exit_of_bb(v, b) and ssaDefReachesRank(v, def, b, lastRank(v, b))) - or - exists (BasicBlock idom | - ssaDefinitionReachesEndOfBB(v, def, idom) and - noDefinitionsSinceIDominator(v, idom, b) - ) - } + /** + * Holds if SSA variable `(v, def)` reaches the rank index `rankix` in its + * own basic block `b` before being overwritten by another definition of + * `v` that comes _at or after_ the reached node. Reaching a node means + * that the definition is visible to any _use_ at that node. + */ + private predicate ssaDefReachesRank( + LocalScopeVariable v, ControlFlowNode def, BasicBlock b, int rankix + ) { + // A definition should not reach its own node unless a loop allows it. + // When nodes are both definitions and uses for the same variable, the + // use is understood to happen _before_ the definition. Phi nodes are + // at rankidx -1 and will therefore always reach the first node in the + // basic block. + ssaDefRank(v, def, b, rankix - 1) + or + ssaDefReachesRank(v, def, b, rankix - 1) and + rankix <= lastRank(v, b) and // Without this, the predicate would be infinite. + not ssaDefRank(v, _, b, rankix - 1) // Range is inclusive of but not past next def. + } - /** - * Helper predicate for ssaDefinitionReachesEndOfBB. If there is no - * definition of `v` in basic block `b`, then any definition of `v` - * that reaches the end of `idom` (the immediate dominator of `b`) also - * reaches the end of `b`. - */ - pragma[noinline] - private predicate noDefinitionsSinceIDominator(LocalScopeVariable v, BasicBlock idom, BasicBlock b) { - bbIDominates(idom, b) and // It is sufficient to traverse the dominator graph, cf. discussion above. - live_at_exit_of_bb(v, b) and - not ssa_defn(v, _, b, _) - } + /** Holds if SSA variable `(v, def)` reaches the end of block `b`. */ + cached + predicate ssaDefinitionReachesEndOfBB(LocalScopeVariable v, ControlFlowNode def, BasicBlock b) { + live_at_exit_of_bb(v, b) and ssaDefReachesRank(v, def, b, lastRank(v, b)) + or + exists(BasicBlock idom | + ssaDefinitionReachesEndOfBB(v, def, idom) and + noDefinitionsSinceIDominator(v, idom, b) + ) + } - /** - * Holds if SSA variable `(v, def)` reaches `use` within the same basic - * block, where `use` is a `VariableAccess` of `v`. - */ - private predicate ssaDefinitionReachesUseWithinBB(LocalScopeVariable v, ControlFlowNode def, Expr use) { - exists (BasicBlock b, int rankix, int i - | ssaDefReachesRank(v, def, b, rankix) and - defUseRank(v, b, rankix, i) and - ssa_use(v, use, b, i)) - } + /** + * Helper predicate for ssaDefinitionReachesEndOfBB. If there is no + * definition of `v` in basic block `b`, then any definition of `v` + * that reaches the end of `idom` (the immediate dominator of `b`) also + * reaches the end of `b`. + */ + pragma[noinline] + private predicate noDefinitionsSinceIDominator(LocalScopeVariable v, BasicBlock idom, BasicBlock b) { + bbIDominates(idom, b) and // It is sufficient to traverse the dominator graph, cf. discussion above. + live_at_exit_of_bb(v, b) and + not ssa_defn(v, _, b, _) + } - /** - * Holds if SSA variable `(v, def)` reaches the control-flow node `use`. - */ - private - predicate ssaDefinitionReaches(LocalScopeVariable v, ControlFlowNode def, Expr use) { - ssaDefinitionReachesUseWithinBB(v, def, use) or - exists (BasicBlock b - | ssa_use(v, use, b, _) and - ssaDefinitionReachesEndOfBB(v, def, b.getAPredecessor()) and - not ssaDefinitionReachesUseWithinBB(v, _, use)) - } + /** + * Holds if SSA variable `(v, def)` reaches `use` within the same basic + * block, where `use` is a `VariableAccess` of `v`. + */ + private predicate ssaDefinitionReachesUseWithinBB( + LocalScopeVariable v, ControlFlowNode def, Expr use + ) { + exists(BasicBlock b, int rankix, int i | + ssaDefReachesRank(v, def, b, rankix) and + defUseRank(v, b, rankix, i) and + ssa_use(v, use, b, i) + ) + } - /** - * Gets a string representation of the SSA variable represented by the pair - * `(node, v)`. - */ - cached string toString(ControlFlowNode node, LocalScopeVariable v) { - if phi_node(v, (BasicBlock)node) then - result = "SSA phi(" + v.getName() + ")" - else - (ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")") - } + /** + * Holds if SSA variable `(v, def)` reaches the control-flow node `use`. + */ + private predicate ssaDefinitionReaches(LocalScopeVariable v, ControlFlowNode def, Expr use) { + ssaDefinitionReachesUseWithinBB(v, def, use) + or + exists(BasicBlock b | + ssa_use(v, use, b, _) and + ssaDefinitionReachesEndOfBB(v, def, b.getAPredecessor()) and + not ssaDefinitionReachesUseWithinBB(v, _, use) + ) + } - /** - * Holds if SSA variable `(v, def)` reaches `result`, where `result` is an - * access of `v`. - */ - cached VariableAccess getAUse(ControlFlowNode def, LocalScopeVariable v) { - ssaDefinitionReaches(v, def, result) - and - ssa_use(v, result, _, _) - } + /** + * Gets a string representation of the SSA variable represented by the pair + * `(node, v)`. + */ + cached + string toString(ControlFlowNode node, LocalScopeVariable v) { + if phi_node(v, node.(BasicBlock)) + then result = "SSA phi(" + v.getName() + ")" + else ( + ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")" + ) + } + + /** + * Holds if SSA variable `(v, def)` reaches `result`, where `result` is an + * access of `v`. + */ + cached + VariableAccess getAUse(ControlFlowNode def, LocalScopeVariable v) { + ssaDefinitionReaches(v, def, result) and + ssa_use(v, result, _, _) + } } diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/StackVariableReachability.qll b/cpp/ql/src/semmle/code/cpp/controlflow/StackVariableReachability.qll index 8ebf850cd5b..b8ffa3344f6 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/StackVariableReachability.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/StackVariableReachability.qll @@ -5,7 +5,7 @@ import cpp * * A reachability analysis for control-flow nodes involving stack variables. */ -deprecated abstract class StackVariableReachability extends string { +abstract deprecated class StackVariableReachability extends string { bindingset[this] StackVariableReachability() { length() >= 0 } @@ -45,23 +45,23 @@ deprecated abstract class StackVariableReachability extends string { * accounts for loops where the condition is provably true upon entry. */ predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) { - /* Implementation detail: the predicates in this class are a generalization of + /* + * Implementation detail: the predicates in this class are a generalization of * those in DefinitionsAndUses.qll, and should be kept in sync. * * Unfortunately, caching of abstract predicates does not work well, so the * predicates in DefinitionsAndUses.qll cannot use this library. */ + exists(BasicBlock bb, int i | isSource(source, v) and bb.getNode(i) = source and - not bb.isUnreachable() | + not bb.isUnreachable() + | exists(int j | - j > i - and - sink = bb.getNode(j) - and - isSink(sink, v) - and + j > i and + sink = bb.getNode(j) and + isSink(sink, v) and not exists(int k | isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1]) ) or @@ -70,9 +70,13 @@ deprecated abstract class StackVariableReachability extends string { ) } - private predicate bbSuccessorEntryReaches(BasicBlock bb, StackVariable v, ControlFlowNode node, boolean skipsFirstLoopAlwaysTrueUponEntry) { + private predicate bbSuccessorEntryReaches( + BasicBlock bb, StackVariable v, ControlFlowNode node, boolean skipsFirstLoopAlwaysTrueUponEntry + ) { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | - bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) | + bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, + succSkipsFirstLoopAlwaysTrueUponEntry) + | bbEntryReachesLocally(succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or @@ -82,8 +86,7 @@ deprecated abstract class StackVariableReachability extends string { } private predicate bbEntryReachesLocally(BasicBlock bb, StackVariable v, ControlFlowNode node) { - exists(int n | - node = bb.getNode(n) and isSink(node, v) | + exists(int n | node = bb.getNode(n) and isSink(node, v) | not exists(int m | m < n | isBarrier(bb.getNode(m), v)) ) } @@ -115,15 +118,14 @@ private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, Control * of `pred`, and `skipsLoop` indicates whether `succ` is the false-successor * of `pred`. */ -private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(BasicBlock pred, BasicBlock succ, boolean skipsLoop) { +private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor( + BasicBlock pred, BasicBlock succ, boolean skipsLoop +) { succ = pred.getASuccessor() and exists(ControlFlowNode last | last = pred.getEnd() and loopConditionAlwaysTrueUponEntry(_, last) and - if succ = pred.getAFalseSuccessor() then - skipsLoop = true - else - skipsLoop = false + if succ = pred.getAFalseSuccessor() then skipsLoop = true else skipsLoop = false ) } @@ -144,8 +146,10 @@ private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(BasicBlock pred, B * is provably true upon entry, then `succ` is not allowed to skip * that loop (`succSkipsFirstLoopAlwaysTrueUponEntry = false`). */ -deprecated -predicate bbSuccessorEntryReachesLoopInvariant(BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry, boolean succSkipsFirstLoopAlwaysTrueUponEntry) { +deprecated predicate bbSuccessorEntryReachesLoopInvariant( + BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry, + boolean succSkipsFirstLoopAlwaysTrueUponEntry +) { succ = pred.getASuccessor() and (succSkipsFirstLoopAlwaysTrueUponEntry = true or succSkipsFirstLoopAlwaysTrueUponEntry = false) and ( @@ -155,16 +159,18 @@ predicate bbSuccessorEntryReachesLoopInvariant(BasicBlock pred, BasicBlock succ, // regardless of the value of `succSkipsFirstLoopAlwaysTrueUponEntry`. bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, predSkipsFirstLoopAlwaysTrueUponEntry) or + // The edge from `pred` to `succ` is _not_ from a loop condition provably + // true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry` + // and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same. + not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, _, _) and + succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and + // Moreover, if `pred` contains the entry point of a loop where the + // condition is provably true upon entry, then `succ` is not allowed + // to skip that loop, and hence `succSkipsFirstLoopAlwaysTrueUponEntry = false`. ( - // The edge from `pred` to `succ` is _not_ from a loop condition provably - // true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry` - // and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same. - not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, _, _) and - succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and - // Moreover, if `pred` contains the entry point of a loop where the - // condition is provably true upon entry, then `succ` is not allowed - // to skip that loop, and hence `succSkipsFirstLoopAlwaysTrueUponEntry = false`. - (bbLoopEntryConditionAlwaysTrueAt(pred, _, _) implies succSkipsFirstLoopAlwaysTrueUponEntry = false) + bbLoopEntryConditionAlwaysTrueAt(pred, _, _) + implies + succSkipsFirstLoopAlwaysTrueUponEntry = false ) ) } @@ -176,7 +182,7 @@ predicate bbSuccessorEntryReachesLoopInvariant(BasicBlock pred, BasicBlock succ, * Unlike `StackVariableReachability`, this analysis takes variable * reassignments into account. */ -deprecated abstract class StackVariableReachabilityWithReassignment extends StackVariableReachability { +abstract deprecated class StackVariableReachabilityWithReassignment extends StackVariableReachability { bindingset[this] StackVariableReachabilityWithReassignment() { length() >= 0 } @@ -227,9 +233,11 @@ deprecated abstract class StackVariableReachabilityWithReassignment extends Stac } /** - * As `reaches`, but also specifies the last variable it was reassigned to (`v0`). + * As `reaches`, but also specifies the last variable it was reassigned to (`v0`). */ - predicate reachesTo(ControlFlowNode source, StackVariable v, ControlFlowNode sink, StackVariable v0) { + predicate reachesTo( + ControlFlowNode source, StackVariable v, ControlFlowNode sink, StackVariable v0 + ) { exists(ControlFlowNode def | actualSourceReaches(source, v, def, v0) and StackVariableReachability.super.reaches(def, v0, sink) and @@ -237,16 +245,19 @@ deprecated abstract class StackVariableReachabilityWithReassignment extends Stac ) } - private predicate actualSourceReaches(ControlFlowNode source, StackVariable v, ControlFlowNode def, StackVariable v0) { + private predicate actualSourceReaches( + ControlFlowNode source, StackVariable v, ControlFlowNode def, StackVariable v0 + ) { isSourceActual(source, v) and def = source and v0 = v or - exists(ControlFlowNode source1, StackVariable v1 | - actualSourceReaches(source, v, source1, v1) | + exists(ControlFlowNode source1, StackVariable v1 | actualSourceReaches(source, v, source1, v1) | reassignment(source1, v1, def, v0) ) } - private predicate reassignment(ControlFlowNode source, StackVariable v, ControlFlowNode def, StackVariable v0) { + private predicate reassignment( + ControlFlowNode source, StackVariable v, ControlFlowNode def, StackVariable v0 + ) { StackVariableReachability.super.reaches(source, v, def) and exprDefinition(v0, def, v.getAnAccess()) } @@ -273,7 +284,7 @@ deprecated abstract class StackVariableReachabilityWithReassignment extends Stac * edges rather than nodes and is therefore parameterized by the original * source node as well. */ -deprecated abstract class StackVariableReachabilityExt extends string { +abstract deprecated class StackVariableReachabilityExt extends string { bindingset[this] StackVariableReachabilityExt() { length() >= 0 } @@ -284,22 +295,24 @@ deprecated abstract class StackVariableReachabilityExt extends string { abstract predicate isSink(ControlFlowNode node, StackVariable v); /** `node` is a barrier for the reachability analysis using variable `v` and starting from `source`. */ - abstract predicate isBarrier(ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, StackVariable v); + abstract predicate isBarrier( + ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, StackVariable v + ); /** See `StackVariableReachability.reaches`. */ predicate reaches(ControlFlowNode source, StackVariable v, ControlFlowNode sink) { exists(BasicBlock bb, int i | isSource(source, v) and bb.getNode(i) = source and - not bb.isUnreachable() | + not bb.isUnreachable() + | exists(int j | - j > i - and - sink = bb.getNode(j) - and - isSink(sink, v) - and - not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k in [i .. j - 1]) + j > i and + sink = bb.getNode(j) and + isSink(sink, v) and + not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | + k in [i .. j - 1] + ) ) or not exists(int k | isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and @@ -307,10 +320,15 @@ deprecated abstract class StackVariableReachabilityExt extends string { ) } - private predicate bbSuccessorEntryReaches(ControlFlowNode source, BasicBlock bb, StackVariable v, ControlFlowNode node, boolean skipsFirstLoopAlwaysTrueUponEntry) { + private predicate bbSuccessorEntryReaches( + ControlFlowNode source, BasicBlock bb, StackVariable v, ControlFlowNode node, + boolean skipsFirstLoopAlwaysTrueUponEntry + ) { exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry | - bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, succSkipsFirstLoopAlwaysTrueUponEntry) and - not isBarrier(source, bb.getEnd(), succ.getStart(), v) | + bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry, + succSkipsFirstLoopAlwaysTrueUponEntry) and + not isBarrier(source, bb.getEnd(), succ.getStart(), v) + | bbEntryReachesLocally(source, succ, v, node) and succSkipsFirstLoopAlwaysTrueUponEntry = false or @@ -319,11 +337,12 @@ deprecated abstract class StackVariableReachabilityExt extends string { ) } - private predicate bbEntryReachesLocally(ControlFlowNode source, BasicBlock bb, StackVariable v, ControlFlowNode node) { + private predicate bbEntryReachesLocally( + ControlFlowNode source, BasicBlock bb, StackVariable v, ControlFlowNode node + ) { isSource(source, v) and - exists(int n | - node = bb.getNode(n) and isSink(node, v) | + exists(int n | node = bb.getNode(n) and isSink(node, v) | not exists(int m | m < n | isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v)) ) } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll b/cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll index 93ac33be2f0..dafcd1fdd97 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll @@ -6,11 +6,11 @@ // internal use by the data flow library. Having an extra copy prevents // non-monotonic recursion errors in queries that use both the data flow // library and the `SubBasicBlocks` library. - /** * Provides the `SubBasicBlock` class, used for partitioning basic blocks in * smaller pieces. */ + import cpp /** @@ -47,27 +47,21 @@ class SubBasicBlock extends ControlFlowNodeBase { } /** Gets the basic block in which this `SubBasicBlock` is contained. */ - BasicBlock getBasicBlock() { - result = this.(ControlFlowNode).getBasicBlock() - } + BasicBlock getBasicBlock() { result = this.(ControlFlowNode).getBasicBlock() } /** * Holds if this `SubBasicBlock` comes first in its basic block. This is the * only condition under which a `SubBasicBlock` may have multiple * predecessors. */ - predicate firstInBB() { - exists(BasicBlock bb | this.getRankInBasicBlock(bb) = 1) - } + predicate firstInBB() { exists(BasicBlock bb | this.getRankInBasicBlock(bb) = 1) } /** * Holds if this `SubBasicBlock` comes last in its basic block. This is the * only condition under which a `SubBasicBlock` may have multiple successors. */ predicate lastInBB() { - exists(BasicBlock bb | - this.getRankInBasicBlock(bb) = countSubBasicBlocksInBasicBlock(bb) - ) + exists(BasicBlock bb | this.getRankInBasicBlock(bb) = countSubBasicBlocksInBasicBlock(bb)) } /** @@ -86,23 +80,17 @@ class SubBasicBlock extends ControlFlowNodeBase { * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based * position. */ - deprecated int getPosInBasicBlock(BasicBlock bb) { - result = getRankInBasicBlock(bb) - 1 - } + deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 } pragma[noinline] - private int getIndexInBasicBlock(BasicBlock bb) { - this = bb.getNode(result) - } + private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } /** Gets a successor in the control-flow graph of `SubBasicBlock`s. */ SubBasicBlock getASuccessor() { this.lastInBB() and result = this.getBasicBlock().getASuccessor() or - exists(BasicBlock bb | - result.getRankInBasicBlock(bb) = this.getRankInBasicBlock(bb) + 1 - ) + exists(BasicBlock bb | result.getRankInBasicBlock(bb) = this.getRankInBasicBlock(bb) + 1) } /** @@ -130,23 +118,17 @@ class SubBasicBlock extends ControlFlowNodeBase { pragma[nomagic] private int outerToInnerIndex(BasicBlock bb, int indexInBB) { indexInBB = result + this.getIndexInBasicBlock(bb) and - result = [ 0 .. this.getNumberOfNodes() - 1 ] + result = [0 .. this.getNumberOfNodes() - 1] } /** Gets a control-flow node in this `SubBasicBlock`. */ - ControlFlowNode getANode() { - result = this.getNode(_) - } + ControlFlowNode getANode() { result = this.getNode(_) } /** Holds if `this` contains `node`. */ - predicate contains(ControlFlowNode node) { - node = this.getANode() - } + predicate contains(ControlFlowNode node) { node = this.getANode() } /** Gets a predecessor in the control-flow graph of `SubBasicBlock`s. */ - SubBasicBlock getAPredecessor() { - result.getASuccessor() = this - } + SubBasicBlock getAPredecessor() { result.getASuccessor() = this } /** * Gets a node such that the control-flow edge `(this, result)` may be taken @@ -181,19 +163,13 @@ class SubBasicBlock extends ControlFlowNodeBase { } /** Gets the last control-flow node in this `SubBasicBlock`. */ - ControlFlowNode getEnd() { - result = this.getNode(this.getNumberOfNodes() - 1) - } + ControlFlowNode getEnd() { result = this.getNode(this.getNumberOfNodes() - 1) } /** Gets the first control-flow node in this `SubBasicBlock`. */ - ControlFlowNode getStart() { - result = this - } + ControlFlowNode getStart() { result = this } pragma[noinline] - Function getEnclosingFunction() { - result = this.getStart().getControlFlowScope() - } + Function getEnclosingFunction() { result = this.getStart().getControlFlowScope() } } /** Gets the number of `SubBasicBlock`s in the given basic block. */ diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/internal/CFG.qll b/cpp/ql/src/semmle/code/cpp/controlflow/internal/CFG.qll index 32873763e99..3200987c347 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/internal/CFG.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/internal/CFG.qll @@ -480,9 +480,7 @@ private Node getControlOrderChildDense(Node n, int i) { result = rank[i + 1](Node child, int childIdx | child = getControlOrderChildSparse(n, childIdx) | - child - order by - childIdx + child order by childIdx ) } @@ -990,7 +988,8 @@ private predicate subEdgeIncludingDestructors(Pos p1, Node n1, Node n2, Pos p2) exists(int maxCallIndex | maxCallIndex = max(int i | exists(getSynthesisedDestructorCallAfterNode(n, i))) and p1.nodeBeforeDestructors(n1, n) and - p2.nodeAt(n2, getSynthesisedDestructorCallAfterNode(n, maxCallIndex).getQualifier())) + p2.nodeAt(n2, getSynthesisedDestructorCallAfterNode(n, maxCallIndex).getQualifier()) + ) or // call(i+1) -> access(i) exists(int i | @@ -1054,7 +1053,6 @@ private class LogicalAndLikeExpr extends ShortCircuitOperator, LogicalAndExpr { /** An expression whose control flow is the same as `||`. */ private class LogicalOrLikeExpr extends ShortCircuitOperator { Expr left; - Expr right; LogicalOrLikeExpr() { @@ -1079,9 +1077,7 @@ private class LogicalOrLikeExpr extends ShortCircuitOperator { /** An expression whose control flow is the same as `b ? x : y`. */ private class ConditionalLikeExpr extends ShortCircuitOperator { Expr condition; - Expr thenExpr; - Expr elseExpr; ConditionalLikeExpr() { @@ -1353,6 +1349,7 @@ private predicate conditionalSuccessor(Node n1, boolean truth, Node n2) { normalGroupMember(targetNode, targetPos, n2) ) } + import Cached cached diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll b/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll index 8fb45bd255b..43b1a76c837 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll @@ -1,39 +1,38 @@ import cpp private import PrimitiveBasicBlocks + private class Node = ControlFlowNodeBase; + import Cached cached private module Cached { /** A call to a function known not to return. */ cached - predicate aborting(FunctionCall c) { - not potentiallyReturningFunctionCall(c) - } + predicate aborting(FunctionCall c) { not potentiallyReturningFunctionCall(c) } /** * Functions that are known not to return. This is normally because the function * exits the program or longjmps to another location. */ cached - predicate abortingFunction(Function f) { - not potentiallyReturningFunction(f) - } + predicate abortingFunction(Function f) { not potentiallyReturningFunction(f) } /** * An adapted version of the `successors_extended` relation that excludes * impossible control-flow edges - flow will never occur along these * edges, so it is safe (and indeed sensible) to remove them. */ - cached predicate successors_adapted(Node pred, Node succ) { - successors_extended(pred, succ) - and possiblePredecessor(pred) - and not impossibleFalseEdge(pred, succ) - and not impossibleTrueEdge(pred, succ) - and not impossibleSwitchEdge(pred, succ) - and not impossibleDefaultSwitchEdge(pred, succ) - and not impossibleFunctionReturn(pred, succ) - and not getOptions().exprExits(pred) + cached + predicate successors_adapted(Node pred, Node succ) { + successors_extended(pred, succ) and + possiblePredecessor(pred) and + not impossibleFalseEdge(pred, succ) and + not impossibleTrueEdge(pred, succ) and + not impossibleSwitchEdge(pred, succ) and + not impossibleDefaultSwitchEdge(pred, succ) and + not impossibleFunctionReturn(pred, succ) and + not getOptions().exprExits(pred) } /** @@ -53,19 +52,16 @@ private module Cached { * `if` statement as a whole is reachable. */ cached - predicate reachable(ControlFlowNode n) - { + predicate reachable(ControlFlowNode n) { // Okay to use successors_extended directly here reachableRecursive(n) or - (not successors_extended(_,n) and not successors_extended(n,_)) + not successors_extended(_, n) and not successors_extended(n, _) } /** Holds if `condition` always evaluates to a nonzero value. */ cached - predicate conditionAlwaysTrue(Expr condition) { - conditionAlways(condition, true) - } + predicate conditionAlwaysTrue(Expr condition) { conditionAlways(condition, true) } /** Holds if `condition` always evaluates to zero. */ cached @@ -89,8 +85,7 @@ private module Cached { } private predicate conditionAlways(Expr condition, boolean b) { - exists(ConditionEvaluator x, int val | - val = x.getValue(condition) | + exists(ConditionEvaluator x, int val | val = x.getValue(condition) | val != 0 and b = true or val = 0 and b = false @@ -100,7 +95,8 @@ private predicate conditionAlways(Expr condition, boolean b) { private predicate loopConditionAlwaysUponEntry(ControlFlowNode loop, Expr condition, boolean b) { exists(LoopEntryConditionEvaluator x, int val | x.isLoopEntry(condition, loop) and - val = x.getValue(condition) | + val = x.getValue(condition) + | val != 0 and b = true or val = 0 and b = false @@ -114,8 +110,7 @@ private predicate potentiallyReturningFunctionCall(FunctionCall fc) { /** A function that *may* return; if in doubt, we assume it may. */ private predicate potentiallyReturningFunction(Function f) { - not getOptions().exits(f) - and + not getOptions().exits(f) and ( nonAnalyzableFunction(f) or @@ -142,10 +137,12 @@ private predicate nonAnalyzableFunction(Function f) { * faster than transitive closure of the much larger `successors_extended` * relation). */ + not exists(PrimitiveBasicBlock bb1, int pos1, PrimitiveBasicBlock bb2, int pos2 | f.getEntryPoint() = bb1.getNode(pos1) and - f = bb2.getNode(pos2) | - (bb1 = bb2 and pos2 > pos1) + f = bb2.getNode(pos2) + | + bb1 = bb2 and pos2 > pos1 or bb1.getASuccessor+() = bb2 ) @@ -155,18 +152,18 @@ private predicate nonAnalyzableFunction(Function f) { * If a condition is provably true, then control-flow edges to its false successors are impossible. */ private predicate impossibleFalseEdge(Expr condition, Node succ) { - conditionAlwaysTrue(condition) - and falsecond_base(condition,succ) - and not truecond_base(condition,succ) + conditionAlwaysTrue(condition) and + falsecond_base(condition, succ) and + not truecond_base(condition, succ) } /** * If a condition is provably false, then control-flow edges to its true successors are impossible. */ private predicate impossibleTrueEdge(Expr condition, Node succ) { - conditionAlwaysFalse(condition) - and truecond_base(condition,succ) - and not falsecond_base(condition,succ) + conditionAlwaysFalse(condition) and + truecond_base(condition, succ) and + not falsecond_base(condition, succ) } /** @@ -197,16 +194,20 @@ private Node getASwitchExpr(SwitchStmt switch, Block switchBlock) { private predicate impossibleSwitchEdge(Block switchBlock, SwitchCase sc) { not sc instanceof DefaultCase and exists(SwitchStmt switch | - switch = sc.getSwitchStmt() - and switch.getStmt() = switchBlock - // If all of the successors have known values, and none of those - // values are in our range, then this edge is impossible. - and forall(Node n | - n = getASwitchExpr(switch, switchBlock) | - exists(int switchValue | - switchValue = getSwitchValue(n) - and (switchValue < sc.getExpr().(CompileTimeConstantInt).getIntValue() or - switchValue > switchCaseRangeEnd(sc))))) + switch = sc.getSwitchStmt() and + switch.getStmt() = switchBlock and + // If all of the successors have known values, and none of those + // values are in our range, then this edge is impossible. + forall(Node n | n = getASwitchExpr(switch, switchBlock) | + exists(int switchValue | + switchValue = getSwitchValue(n) and + ( + switchValue < sc.getExpr().(CompileTimeConstantInt).getIntValue() or + switchValue > switchCaseRangeEnd(sc) + ) + ) + ) + ) } /** @@ -215,17 +216,19 @@ private predicate impossibleSwitchEdge(Block switchBlock, SwitchCase sc) { */ private predicate impossibleDefaultSwitchEdge(Block switchBlock, DefaultCase dc) { exists(SwitchStmt switch | - switch = dc.getSwitchStmt() - and switch.getStmt() = switchBlock - // If all of the successors lead to other switch cases - // then this edge is impossible. - and forall(Node n | - n = getASwitchExpr(switch, switchBlock) | - exists(SwitchCase sc, int val | - sc.getSwitchStmt() = switch and - val = getSwitchValue(n) and - val >= sc.getExpr().(CompileTimeConstantInt).getIntValue() and - val <= switchCaseRangeEnd(sc)))) + switch = dc.getSwitchStmt() and + switch.getStmt() = switchBlock and + // If all of the successors lead to other switch cases + // then this edge is impossible. + forall(Node n | n = getASwitchExpr(switch, switchBlock) | + exists(SwitchCase sc, int val | + sc.getSwitchStmt() = switch and + val = getSwitchValue(n) and + val >= sc.getExpr().(CompileTimeConstantInt).getIntValue() and + val <= switchCaseRangeEnd(sc) + ) + ) + ) } /** @@ -234,8 +237,7 @@ private predicate impossibleDefaultSwitchEdge(Block switchBlock, DefaultCase dc) * a lightweight `potentiallyReturningFunction`- reachability of return * statements is not checked. */ -private predicate nonReturningFunction(Function f) -{ +private predicate nonReturningFunction(Function f) { exists(f.getBlock()) and not exists(ReturnStmt ret | ret.getEnclosingFunction() = f) and not getOptions().exits(f) @@ -268,8 +270,7 @@ private predicate possiblePredecessor(Node pred) { * the call to `f` is not reachable in `if (0) f();` even if the * `if` statement as a whole is reachable. */ -private predicate reachableRecursive(ControlFlowNode n) -{ +private predicate reachableRecursive(ControlFlowNode n) { exists(Function f | f.getEntryPoint() = n) or n instanceof Handler @@ -284,19 +285,13 @@ private predicate compileTimeConstantInt(Expr e, int val) { } library class CompileTimeConstantInt extends Expr { - CompileTimeConstantInt() { - compileTimeConstantInt(this, _) - } + CompileTimeConstantInt() { compileTimeConstantInt(this, _) } - int getIntValue() { - compileTimeConstantInt(this, result) - } + int getIntValue() { compileTimeConstantInt(this, result) } } library class CompileTimeVariableExpr extends Expr { - CompileTimeVariableExpr() { - not compileTimeConstantInt(this, _) - } + CompileTimeVariableExpr() { not compileTimeConstantInt(this, _) } } /** A helper class for evaluation of expressions. */ @@ -307,6 +302,7 @@ library class ExprEvaluator extends int { * 2 = WhileLoopEntryConditionEvaluator, * 3 = ForLoopEntryConditionEvaluator */ + ExprEvaluator() { this in [0 .. 3] } /** `e` is an expression for which we want to calculate a value. */ @@ -344,7 +340,6 @@ library class ExprEvaluator extends int { predicate allowVariableWithoutInitializer(Expr e, Variable v) { none() } /* Internal implementation predicates below */ - /** * `req` is an expression for which a value is required to be evaluated in * order to calculate a value for interesting expression `e`. `sub` @@ -356,8 +351,7 @@ library class ExprEvaluator extends int { predicate interestingInternal(Expr e, Expr req, boolean sub) { interesting(e) and req = e and sub = true or - exists(Expr mid | - interestingInternal(e, mid, sub) | + exists(Expr mid | interestingInternal(e, mid, sub) | req = mid.(NotExpr).getOperand() or req = mid.(BinaryLogicalOperation).getAnOperand() or req = mid.(RelationalOperation).getAnOperand() or @@ -388,34 +382,34 @@ library class ExprEvaluator extends int { private predicate interestingVariableAccess(Expr e, VariableAccess va, Variable v, boolean sub) { interestingInternal(e, va, sub) and v = getVariableTarget(va) and - (v.hasInitializer() or sub = true and allowVariableWithoutInitializer(e, v)) and + ( + v.hasInitializer() + or + sub = true and allowVariableWithoutInitializer(e, v) + ) and tractableVariable(v) and - forall(StmtParent def | - nonAnalyzableVariableDefinition(v, def) | + forall(StmtParent def | nonAnalyzableVariableDefinition(v, def) | sub = true and ignoreNonAnalyzableVariableDefinition(e, v, def) ) } private predicate interestingFunction(Expr e, Function f) { - exists(FunctionCall fc | - interestingInternal(e, fc, _) | - f = fc.getTarget() - and not obviouslyNonConstant(f) - and not f.getUnspecifiedType() instanceof VoidType + exists(FunctionCall fc | interestingInternal(e, fc, _) | + f = fc.getTarget() and + not obviouslyNonConstant(f) and + not f.getUnspecifiedType() instanceof VoidType ) } /** Gets the value of subexpressions `req` for expression `e`, if any. */ private int getValueInternal(Expr e, Expr req) { ( - interestingInternal(e, req, true) - and + interestingInternal(e, req, true) and ( result = req.(CompileTimeConstantInt).getIntValue() or - result = getCompoundValue(e, (CompileTimeVariableExpr)req) - ) - and + result = getCompoundValue(e, req.(CompileTimeVariableExpr)) + ) and ( req.getUnderlyingType().(IntegralType).isSigned() or result >= 0 @@ -425,113 +419,128 @@ library class ExprEvaluator extends int { /** Gets the value of compound subexpressions `val` for expression `e`, if any. */ private int getCompoundValue(Expr e, CompileTimeVariableExpr val) { - interestingInternal(e, val, true) - and + interestingInternal(e, val, true) and ( - exists(NotExpr req | - req = val | - result = 1 and getValueInternal(e, req.getOperand()) = 0 or + exists(NotExpr req | req = val | + result = 1 and getValueInternal(e, req.getOperand()) = 0 + or result = 0 and getValueInternal(e, req.getOperand()) != 0 ) or - exists(LogicalAndExpr req | - req = val | - result = 1 and getValueInternal(e, req.getLeftOperand()) != 0 and getValueInternal(e, req.getRightOperand()) != 0 or + exists(LogicalAndExpr req | req = val | + result = 1 and + getValueInternal(e, req.getLeftOperand()) != 0 and + getValueInternal(e, req.getRightOperand()) != 0 + or result = 0 and getValueInternal(e, req.getAnOperand()) = 0 ) or - exists(LogicalOrExpr req | - req = val | - result = 1 and getValueInternal(e, req.getAnOperand()) != 0 or - result = 0 and getValueInternal(e, req.getLeftOperand()) = 0 and getValueInternal(e, req.getRightOperand()) = 0 + exists(LogicalOrExpr req | req = val | + result = 1 and getValueInternal(e, req.getAnOperand()) != 0 + or + result = 0 and + getValueInternal(e, req.getLeftOperand()) = 0 and + getValueInternal(e, req.getRightOperand()) = 0 ) or - exists(LTExpr req | - req = val | - result = 1 and getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) or - result = 0 and getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) + exists(LTExpr req | req = val | + result = 1 and + getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) + or + result = 0 and + getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) ) or - exists(GTExpr req | - req = val | - result = 1 and getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) or - result = 0 and getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) + exists(GTExpr req | req = val | + result = 1 and + getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) + or + result = 0 and + getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) ) or - exists(LEExpr req | - req = val | - result = 1 and getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) or - result = 0 and getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) + exists(LEExpr req | req = val | + result = 1 and + getValueInternal(e, req.getLeftOperand()) <= getValueInternal(e, req.getRightOperand()) + or + result = 0 and + getValueInternal(e, req.getLeftOperand()) > getValueInternal(e, req.getRightOperand()) ) or - exists(GEExpr req | - req = val | - result = 1 and getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) or - result = 0 and getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) + exists(GEExpr req | req = val | + result = 1 and + getValueInternal(e, req.getLeftOperand()) >= getValueInternal(e, req.getRightOperand()) + or + result = 0 and + getValueInternal(e, req.getLeftOperand()) < getValueInternal(e, req.getRightOperand()) ) or - exists(EQExpr req | - req = val | - result = 1 and getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) or - result = 0 and getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) + exists(EQExpr req | req = val | + result = 1 and + getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) + or + result = 0 and + getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) ) or - exists(NEExpr req | - req = val | - result = 0 and getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) or - result = 1 and getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) + exists(NEExpr req | req = val | + result = 0 and + getValueInternal(e, req.getLeftOperand()) = getValueInternal(e, req.getRightOperand()) + or + result = 1 and + getValueInternal(e, req.getLeftOperand()) != getValueInternal(e, req.getRightOperand()) ) or - exists(AddExpr req | - req = val | - result = getValueInternal(e, req.getLeftOperand()) + getValueInternal(e, req.getRightOperand()) + exists(AddExpr req | req = val | + result = getValueInternal(e, req.getLeftOperand()) + + getValueInternal(e, req.getRightOperand()) ) or - exists(SubExpr req | - req = val | - result = getValueInternal(e, req.getLeftOperand()) - getValueInternal(e, req.getRightOperand()) + exists(SubExpr req | req = val | + result = getValueInternal(e, req.getLeftOperand()) - + getValueInternal(e, req.getRightOperand()) ) or - exists(MulExpr req | - req = val | - result = getValueInternal(e, req.getLeftOperand()) * getValueInternal(e, req.getRightOperand()) + exists(MulExpr req | req = val | + result = getValueInternal(e, req.getLeftOperand()) * + getValueInternal(e, req.getRightOperand()) ) or - exists(RemExpr req | - req = val | - result = getValueInternal(e, req.getLeftOperand()) % getValueInternal(e, req.getRightOperand()) + exists(RemExpr req | req = val | + result = getValueInternal(e, req.getLeftOperand()) % + getValueInternal(e, req.getRightOperand()) ) or - exists(DivExpr req | - req = val | - result = getValueInternal(e, req.getLeftOperand()) / getValueInternal(e, req.getRightOperand()) + exists(DivExpr req | req = val | + result = getValueInternal(e, req.getLeftOperand()) / + getValueInternal(e, req.getRightOperand()) ) or - exists(AssignExpr req | - req = val | - result = getValueInternal(e, req.getRValue()) + exists(AssignExpr req | req = val | result = getValueInternal(e, req.getRValue())) + or + result = getVariableValue(e, val.(VariableAccess)) + or + exists(FunctionCall call | call = val and not callWithMultipleTargets(call) | + result = getFunctionValue(call.getTarget()) ) - or - result = getVariableValue(e, (VariableAccess)val) - or - exists(FunctionCall call | - call = val and not callWithMultipleTargets(call) | - result = getFunctionValue(call.getTarget())) ) } language[monotonicAggregates] private int getVariableValue(Expr e, VariableAccess va) { exists(Variable v | - interestingVariableAccess(e, va, v, true) - and + interestingVariableAccess(e, va, v, true) and // All assignments must have the same int value - result = min(Expr value | value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value) | - getValueInternalNonSubExpr(value) - ) and - result = max(Expr value | value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value) | - getValueInternalNonSubExpr(value) - ) + result = min(Expr value | + value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value) + | + getValueInternalNonSubExpr(value) + ) and + result = max(Expr value | + value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value) + | + getValueInternalNonSubExpr(value) + ) ) } @@ -560,13 +569,11 @@ library class ExprEvaluator extends int { * omitted). */ private int getValueInternalNonSubExpr(Expr req) { - interestingInternal(_, req, false) - and + interestingInternal(_, req, false) and ( result = req.(CompileTimeConstantInt).getIntValue() or - result = getCompoundValueNonSubExpr((CompileTimeVariableExpr)req) - ) - and + result = getCompoundValueNonSubExpr(req.(CompileTimeVariableExpr)) + ) and ( req.getUnderlyingType().(IntegralType).isSigned() or result >= 0 @@ -575,95 +582,120 @@ library class ExprEvaluator extends int { private int getCompoundValueNonSubExpr(CompileTimeVariableExpr val) { ( - exists(NotExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getOperand()) = 0 or + exists(NotExpr req | req = val | + result = 1 and getValueInternalNonSubExpr(req.getOperand()) = 0 + or result = 0 and getValueInternalNonSubExpr(req.getOperand()) != 0 ) or - exists(LogicalAndExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and getValueInternalNonSubExpr(req.getRightOperand()) != 0 or + exists(LogicalAndExpr req | req = val | + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) != 0 and + getValueInternalNonSubExpr(req.getRightOperand()) != 0 + or result = 0 and getValueInternalNonSubExpr(req.getAnOperand()) = 0 ) or - exists(LogicalOrExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getAnOperand()) != 0 or - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and getValueInternalNonSubExpr(req.getRightOperand()) = 0 + exists(LogicalOrExpr req | req = val | + result = 1 and getValueInternalNonSubExpr(req.getAnOperand()) != 0 + or + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) = 0 and + getValueInternalNonSubExpr(req.getRightOperand()) = 0 ) or - exists(LTExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) < getValueInternalNonSubExpr(req.getRightOperand()) or - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) >= getValueInternalNonSubExpr(req.getRightOperand()) + exists(LTExpr req | req = val | + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) < getValueInternalNonSubExpr(req + .getRightOperand()) + or + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) >= getValueInternalNonSubExpr(req + .getRightOperand()) ) or - exists(GTExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) > getValueInternalNonSubExpr(req.getRightOperand()) or - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) <= getValueInternalNonSubExpr(req.getRightOperand()) + exists(GTExpr req | req = val | + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) > getValueInternalNonSubExpr(req + .getRightOperand()) + or + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) <= getValueInternalNonSubExpr(req + .getRightOperand()) ) or - exists(LEExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) <= getValueInternalNonSubExpr(req.getRightOperand()) or - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) > getValueInternalNonSubExpr(req.getRightOperand()) + exists(LEExpr req | req = val | + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) <= getValueInternalNonSubExpr(req + .getRightOperand()) + or + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) > getValueInternalNonSubExpr(req + .getRightOperand()) ) or - exists(GEExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) >= getValueInternalNonSubExpr(req.getRightOperand()) or - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) < getValueInternalNonSubExpr(req.getRightOperand()) + exists(GEExpr req | req = val | + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) >= getValueInternalNonSubExpr(req + .getRightOperand()) + or + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) < getValueInternalNonSubExpr(req + .getRightOperand()) ) or - exists(EQExpr req | - req = val | - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) = getValueInternalNonSubExpr(req.getRightOperand()) or - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) != getValueInternalNonSubExpr(req.getRightOperand()) + exists(EQExpr req | req = val | + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) = getValueInternalNonSubExpr(req + .getRightOperand()) + or + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) != getValueInternalNonSubExpr(req + .getRightOperand()) ) or - exists(NEExpr req | - req = val | - result = 0 and getValueInternalNonSubExpr(req.getLeftOperand()) = getValueInternalNonSubExpr(req.getRightOperand()) or - result = 1 and getValueInternalNonSubExpr(req.getLeftOperand()) != getValueInternalNonSubExpr(req.getRightOperand()) + exists(NEExpr req | req = val | + result = 0 and + getValueInternalNonSubExpr(req.getLeftOperand()) = getValueInternalNonSubExpr(req + .getRightOperand()) + or + result = 1 and + getValueInternalNonSubExpr(req.getLeftOperand()) != getValueInternalNonSubExpr(req + .getRightOperand()) ) or - exists(AddExpr req | - req = val | - result = getValueInternalNonSubExpr(req.getLeftOperand()) + getValueInternalNonSubExpr(req.getRightOperand()) + exists(AddExpr req | req = val | + result = getValueInternalNonSubExpr(req.getLeftOperand()) + + getValueInternalNonSubExpr(req.getRightOperand()) ) or - exists(SubExpr req | - req = val | - result = getValueInternalNonSubExpr(req.getLeftOperand()) - getValueInternalNonSubExpr(req.getRightOperand()) + exists(SubExpr req | req = val | + result = getValueInternalNonSubExpr(req.getLeftOperand()) - + getValueInternalNonSubExpr(req.getRightOperand()) ) or - exists(MulExpr req | - req = val | - result = getValueInternalNonSubExpr(req.getLeftOperand()) * getValueInternalNonSubExpr(req.getRightOperand()) + exists(MulExpr req | req = val | + result = getValueInternalNonSubExpr(req.getLeftOperand()) * + getValueInternalNonSubExpr(req.getRightOperand()) ) or - exists(RemExpr req | - req = val | - result = getValueInternalNonSubExpr(req.getLeftOperand()) % getValueInternalNonSubExpr(req.getRightOperand()) + exists(RemExpr req | req = val | + result = getValueInternalNonSubExpr(req.getLeftOperand()) % + getValueInternalNonSubExpr(req.getRightOperand()) ) or - exists(DivExpr req | - req = val | - result = getValueInternalNonSubExpr(req.getLeftOperand()) / getValueInternalNonSubExpr(req.getRightOperand()) + exists(DivExpr req | req = val | + result = getValueInternalNonSubExpr(req.getLeftOperand()) / + getValueInternalNonSubExpr(req.getRightOperand()) ) or - exists(AssignExpr req | - req = val | - result = getValueInternalNonSubExpr(req.getRValue()) - ) + exists(AssignExpr req | req = val | result = getValueInternalNonSubExpr(req.getRValue())) or result = getVariableValueNonSubExpr(val.(VariableAccess)) or - exists(FunctionCall call | - call = val and not callWithMultipleTargets(call) | - result = getFunctionValue(call.getTarget())) + exists(FunctionCall call | call = val and not callWithMultipleTargets(call) | + result = getFunctionValue(call.getTarget()) + ) ) } @@ -681,8 +713,7 @@ library class ExprEvaluator extends int { pragma[noopt] private int getMinVariableValueNonSubExpr(VariableAccess va) { exists(Variable v | - interestingVariableAccess(_, va, v, false) - and + interestingVariableAccess(_, va, v, false) and result = min(Expr value | value = v.getAnAssignedValue() | getValueInternalNonSubExpr(value)) ) } @@ -718,8 +749,7 @@ private predicate callWithMultipleTargets(FunctionCall call) { // Folded predicate for proper join-order private Variable getVariableTarget(VariableAccess va) { - result = va.getTarget() - and + result = va.getTarget() and (result instanceof LocalVariable or result instanceof GlobalOrNamespaceVariable) } @@ -731,8 +761,7 @@ private Variable getVariableTarget(VariableAccess va) { private predicate nonAnalyzableVariableDefinition(Variable v, StmtParent def) { def.(AddressOfExpr).getAddressable() = v or - exists(VariableAccess va | - va.getTarget() = v | + exists(VariableAccess va | va.getTarget() = v | definitionByReference(va, def) or def.(CrementOperation).getAnOperand() = va @@ -778,14 +807,17 @@ private Expr parameterAccess(Parameter p) { */ private predicate obviouslyNonConstant(Function f) { // May return multiple distinct constant values - 1 < strictcount(Expr e, string value | returnStmt(f, e) and value = e.getValue()) or + 1 < strictcount(Expr e, string value | returnStmt(f, e) and value = e.getValue()) + or // May return a parameter without reassignment exists(Parameter p, Expr ret | returnStmt(f, ret) and p = f.getAParameter() and - not exists(p.getAnAssignedValue()) | + not exists(p.getAnAssignedValue()) + | ret = parameterAccess(p) - ) or + ) + or // May return a value for which this analysis cannot infer a constant value exists(Expr ret | returnStmt(f, ret) | nonComputableConstant(ret)) or @@ -820,8 +852,8 @@ private predicate asmStmtMayDefineVariable(AsmStmt asm, Variable v) { private predicate returnStmt(Function f, Expr value) { exists(ReturnStmt ret | - ret.getEnclosingFunction() = f - and value = ret.getExpr() + ret.getEnclosingFunction() = f and + value = ret.getExpr() ) } @@ -840,14 +872,10 @@ library class ConditionEvaluator extends ExprEvaluator { library class SwitchEvaluator extends ExprEvaluator { SwitchEvaluator() { this = 1 } - override predicate interesting(Expr e) { - e = getASwitchExpr(_, _) - } + override predicate interesting(Expr e) { e = getASwitchExpr(_, _) } } -private int getSwitchValue(Expr e) { - exists(SwitchEvaluator x | result = x.getValue(e)) -} +private int getSwitchValue(Expr e) { exists(SwitchEvaluator x | result = x.getValue(e)) } /** A helper class for evaluation of loop entry conditions. */ library class LoopEntryConditionEvaluator extends ExprEvaluator { @@ -864,8 +892,7 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { private predicate isLoopBodyDescendant(Expr e, StmtParent s) { isLoopBody(e, s) or - exists(StmtParent mid | - isLoopBodyDescendant(e, mid) | + exists(StmtParent mid | isLoopBodyDescendant(e, mid) | s = mid.(Stmt).getAChild() or s = mid.(Expr).getAChild() ) @@ -879,10 +906,7 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { } private predicate maybeInterestingVariable(Expr e, Variable v) { - exists(VariableAccess va | - interestingSubExpr(e, va) | - va.getTarget() = v - ) + exists(VariableAccess va | interestingSubExpr(e, va) | va.getTarget() = v) } /** @@ -897,12 +921,13 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { maybeInterestingVariable(e, v) and (valueOrDef = v.getAnAssignedValue() or nonAnalyzableVariableDefinition(v, valueOrDef)) and isLoopBodyDescendant(e, valueOrDef) and - /* Use primitive basic blocks in reachability analysis for better performance. + /* + * Use primitive basic blocks in reachability analysis for better performance. * This is similar to the pattern used in e.g. `DefinitionsAndUses` and * `LocalScopeVariableReachability`. */ - exists(PrimitiveBasicBlock bb1, int pos1 | - bb1.getNode(pos1) = valueOrDef | + + exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef | // Reaches in same basic block exists(int pos2 | loopEntryAt(bb1, pos2, e) and @@ -938,8 +963,7 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { private predicate bbReachesLoopEntry(PrimitiveBasicBlock bb, Expr e, Variable v) { bbReachesLoopEntryLocally(bb, e, v) or - exists(PrimitiveBasicBlock succ | - succ = bb.getASuccessor() | + exists(PrimitiveBasicBlock succ | succ = bb.getASuccessor() | bbReachesLoopEntry(succ, e, v) and not assignmentAt(bb, _, v) ) @@ -1030,19 +1054,12 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator { library class WhileLoopEntryConditionEvaluator extends LoopEntryConditionEvaluator { WhileLoopEntryConditionEvaluator() { this = 2 } - override predicate interesting(Expr e) { - exists(WhileStmt while | e = while.getCondition()) - } + override predicate interesting(Expr e) { exists(WhileStmt while | e = while.getCondition()) } - override predicate isLoopEntry(Expr e, Node cfn) { - cfn.(WhileStmt).getCondition() = e - } + override predicate isLoopEntry(Expr e, Node cfn) { cfn.(WhileStmt).getCondition() = e } override predicate isLoopBody(Expr e, StmtParent s) { - exists(WhileStmt while | - e = while.getCondition() | - s = while.getStmt() - ) + exists(WhileStmt while | e = while.getCondition() | s = while.getStmt()) } } @@ -1050,17 +1067,12 @@ library class WhileLoopEntryConditionEvaluator extends LoopEntryConditionEvaluat library class ForLoopEntryConditionEvaluator extends LoopEntryConditionEvaluator { ForLoopEntryConditionEvaluator() { this = 3 } - override predicate interesting(Expr e) { - exists(ForStmt for | e = for.getCondition()) - } + override predicate interesting(Expr e) { exists(ForStmt for | e = for.getCondition()) } - override predicate isLoopEntry(Expr e, Node cfn) { - cfn.(ForStmt).getCondition() = e - } + override predicate isLoopEntry(Expr e, Node cfn) { cfn.(ForStmt).getCondition() = e } override predicate isLoopBody(Expr e, StmtParent s) { - exists(ForStmt for | - e = for.getCondition() | + exists(ForStmt for | e = for.getCondition() | s = for.getUpdate() or s = for.getStmt() ) @@ -1112,7 +1124,8 @@ private predicate forLoopInitializesVariable(ForStmt for, Variable v, Expr e) { exists(DeclStmt decl, Expr init, Variable v1 | decl = for.getInitialization() and v1 = decl.getADeclaration() and - init = v1.getInitializer().getExpr() | + init = v1.getInitializer().getExpr() + | e = init and v = v1 or assignsValue(init, v, e) diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll b/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll index f9f82c53349..34bff013022 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/internal/PrimitiveBasicBlocks.qll @@ -3,6 +3,7 @@ * This library defines `PrimitiveBasicBlock`s, an intermediate stage in the * computation of `BasicBlock`s. */ + /* * Unlike `BasicBlock`s, `PrimitiveBasicBlock`s are constructed using * the primitive `successors_extended` relation only. That is, impossible @@ -16,41 +17,42 @@ * (e.g, `primitive_basic_block_entry_node`), as most `BasicBlock`s * will coincide with `PrimitiveBasicBlock`s. */ + import cpp + private class Node = ControlFlowNodeBase; import Cached -private cached module Cached { + +cached +private module Cached { /** Holds if `node` is the entry node of a primitive basic block. */ cached predicate primitive_basic_block_entry_node(Node node) { // The entry point of the CFG is the start of a BB. - exists (Function f | f.getEntryPoint() = node) - + exists(Function f | f.getEntryPoint() = node) + or // If the node has more than one predecessor, // or the node's predecessor has more than one successor, // then the node is the start of a new primitive basic block. - or strictcount(Node pred | successors_extended(pred, node)) > 1 or exists(ControlFlowNode pred | successors_extended(pred, node) | strictcount(ControlFlowNode other | successors_extended(pred, other)) > 1 ) - + or // If the node has zero predecessors then it is the start of // a BB. However, the C++ AST contains many nodes with zero // predecessors and zero successors, which are not members of // the CFG. So we exclude all of those trivial BBs by requiring // that the node have at least one successor. + not successors_extended(_, node) and successors_extended(node, _) or - (not successors_extended(_, node) and successors_extended(node, _)) - // An exception handler is always the start of a new basic block. We // don't generate edges for [possible] exceptions, but in practice control // flow could reach the handler from anywhere inside the try block that // could throw an exception of a corresponding type. A `Handler` usually // needs to be considered reachable (see also `BasicBlock.isReachable`). - or node instanceof Handler } @@ -81,7 +83,7 @@ private cached module Cached { cached predicate primitive_bb_successor(PrimitiveBasicBlock pred, PrimitiveBasicBlock succ) { exists(Node last | - primitive_basic_block_member(last, pred, primitive_bb_length(pred)-1) and + primitive_basic_block_member(last, pred, primitive_bb_length(pred) - 1) and successors_extended(last, succ) ) } @@ -92,32 +94,17 @@ private cached module Cached { * the primitive `successors_extended` relation only. */ class PrimitiveBasicBlock extends Node { + PrimitiveBasicBlock() { primitive_basic_block_entry_node(this) } - PrimitiveBasicBlock() { - primitive_basic_block_entry_node(this) - } + predicate contains(Node node) { primitive_basic_block_member(node, this, _) } - predicate contains(Node node) { - primitive_basic_block_member(node, this, _) - } + Node getNode(int pos) { primitive_basic_block_member(result, this, pos) } - Node getNode(int pos) { - primitive_basic_block_member(result, this, pos) - } + Node getANode() { primitive_basic_block_member(result, this, _) } - Node getANode() { - primitive_basic_block_member(result, this, _) - } + PrimitiveBasicBlock getASuccessor() { primitive_bb_successor(this, result) } - PrimitiveBasicBlock getASuccessor() { - primitive_bb_successor(this, result) - } + PrimitiveBasicBlock getAPredecessor() { primitive_bb_successor(result, this) } - PrimitiveBasicBlock getAPredecessor() { - primitive_bb_successor(result, this) - } - - int length() { - result = primitive_bb_length(this) - } + int length() { result = primitive_bb_length(this) } } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll index 3425e9b9901..109be647f72 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow.qll @@ -16,6 +16,7 @@ * `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type * `DataFlow::Node`. */ + import cpp module DataFlow { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow2.qll index c651ead3b01..91c7bdc80a9 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow2.qll @@ -8,6 +8,7 @@ * * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. */ + import cpp module DataFlow2 { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow3.qll index 53293eb2f22..b1360a1247f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow3.qll @@ -8,6 +8,7 @@ * * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. */ + import cpp module DataFlow3 { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow4.qll index c4963e46a7b..f92f87b4a0f 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/DataFlow4.qll @@ -8,6 +8,7 @@ * * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. */ + import cpp module DataFlow4 { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/EscapesTree.qll b/cpp/ql/src/semmle/code/cpp/dataflow/EscapesTree.qll index a5efd20d58c..57fc56ea5f6 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/EscapesTree.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/EscapesTree.qll @@ -3,6 +3,7 @@ * may escape an _expression tree_, meaning that it is assigned to a variable, * passed to a function, or similar. */ + private import cpp /** @@ -13,9 +14,11 @@ private import cpp private predicate stdIdentityFunction(Function f) { f.getNamespace().getParentNamespace() instanceof GlobalNamespace and f.getNamespace().getName() = "std" and - ( f.getName() = "move" + ( + f.getName() = "move" or - f.getName() = "forward" ) + f.getName() = "forward" + ) } private predicate lvalueToLvalueStepPure(Expr lvalueIn, Expr lvalueOut) { @@ -39,8 +42,7 @@ private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) { lvalueToLvalueStepPure(lvalueIn, lvalueOut) or // C++ only - lvalueIn = lvalueOut.(PrefixCrementOperation).getOperand() - .getFullyConverted() + lvalueIn = lvalueOut.(PrefixCrementOperation).getOperand().getFullyConverted() or // C++ only lvalueIn = lvalueOut.(Assignment).getLValue().getFullyConverted() @@ -49,8 +51,7 @@ private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) { private predicate pointerToLvalueStep(Expr pointerIn, Expr lvalueOut) { pointerIn = lvalueOut.(ArrayExpr).getArrayBase().getFullyConverted() or - pointerIn = lvalueOut.(PointerDereferenceExpr) - .getOperand().getFullyConverted() + pointerIn = lvalueOut.(PointerDereferenceExpr).getOperand().getFullyConverted() or pointerIn = lvalueOut.(PointerFieldAccess).getQualifier().getFullyConverted() } @@ -98,9 +99,9 @@ private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) { private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) { referenceOut = any(FunctionCall call | - stdIdentityFunction(call.getTarget()) and - referenceIn = call.getArgument(0).getFullyConverted() - ) + stdIdentityFunction(call.getTarget()) and + referenceIn = call.getArgument(0).getFullyConverted() + ) or referenceIn.getConversion() = referenceOut.(Cast) or @@ -205,8 +206,7 @@ private predicate valueMayEscapeMutablyAt(Expr e) { ) } -private -predicate addressFromVariableAccess(VariableAccess va, Expr e) { +private predicate addressFromVariableAccess(VariableAccess va, Expr e) { pointerFromVariableAccess(va, e) or referenceFromVariableAccess(va, e) @@ -224,7 +224,9 @@ predicate addressFromVariableAccess(VariableAccess va, Expr e) { } import EscapesTree_Cached -private cached module EscapesTree_Cached { + +cached +private module EscapesTree_Cached { /** * Holds if `e` is a fully-converted expression that evaluates to an address * derived from the address of `va` and is stored in a variable or passed @@ -248,7 +250,8 @@ private cached module EscapesTree_Cached { * not interested in the value referred to by references should exclude * variable accesses to reference-typed values. */ - cached predicate variableAddressEscapesTree(VariableAccess va, Expr e) { + cached + predicate variableAddressEscapesTree(VariableAccess va, Expr e) { valueMayEscapeAt(e) and addressFromVariableAccess(va, e) } @@ -277,7 +280,8 @@ private cached module EscapesTree_Cached { * interested in the value referred to by references should exclude variable * accesses to reference-typed values. */ - cached predicate variableAddressEscapesTreeNonConst(VariableAccess va, Expr e) { + cached + predicate variableAddressEscapesTreeNonConst(VariableAccess va, Expr e) { valueMayEscapeMutablyAt(e) and addressFromVariableAccess(va, e) } @@ -296,7 +300,8 @@ private cached module EscapesTree_Cached { * the reference rather than the reference itself. The expression `e` may be a * `Conversion`. */ - cached predicate variableAccessedAsValue(VariableAccess va, Expr e) { + cached + predicate variableAccessedAsValue(VariableAccess va, Expr e) { lvalueFromVariableAccess(va, e) and not lvalueToLvalueStepPure(e, _) and not lvalueToPointerStep(e, _) and diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll b/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll index fd65f87990a..626e50925f9 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll @@ -12,6 +12,7 @@ * Recursive use of `DataFlow{2..4}::Configuration` is always disallowed, so no * import is needed for those. */ + import cpp private import semmle.code.cpp.dataflow.DataFlow @@ -22,8 +23,7 @@ private import semmle.code.cpp.dataflow.DataFlow * it should be replaced by using more than one copy of the data flow library. * Four copies are available: `DataFlow` through `DataFlow4`. */ -private abstract -class ConfigurationRecursionPrevention extends DataFlow::Configuration { +abstract private class ConfigurationRecursionPrevention extends DataFlow::Configuration { bindingset[this] ConfigurationRecursionPrevention() { any() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/StackAddress.qll b/cpp/ql/src/semmle/code/cpp/dataflow/StackAddress.qll index 4e772eb77f5..d0694a12932 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/StackAddress.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/StackAddress.qll @@ -1,7 +1,8 @@ -/** +/** * Provides utilities for determining which expressions contain * stack addresses. */ + import cpp import semmle.code.cpp.controlflow.SSA @@ -36,8 +37,7 @@ import semmle.code.cpp.controlflow.SSA * parameter. This information is only used to improve the quality of the * error messages. */ -predicate stackPointerFlowsToUse( - Expr use, Type useType, Expr source, boolean isLocal) { +predicate stackPointerFlowsToUse(Expr use, Type useType, Expr source, boolean isLocal) { // Arrays in C are convertible to pointers. For example, if the type of x // is int[10] then it is convertible to int*. The same rule applies to // multidimensional arrays: if the type of y is int[2][3][4], then it is @@ -45,70 +45,67 @@ predicate stackPointerFlowsToUse( // hood when we index an array. For example, x[5] is equivalent to // *(x+5), so x is first converted to a pointer and then the pointer // arithmetic is applied to the pointer. - exists (ArrayType arrayType - | stackReferenceFlowsToUse(use, arrayType, source, isLocal) and - useType = getExprPtrType(use.getConversion()).getBaseType()) + exists(ArrayType arrayType | + stackReferenceFlowsToUse(use, arrayType, source, isLocal) and + useType = getExprPtrType(use.getConversion()).getBaseType() + ) or // Address of: &x - stackReferenceFlowsToUse( - use.(AddressOfExpr).getOperand(), useType, source, isLocal) + stackReferenceFlowsToUse(use.(AddressOfExpr).getOperand(), useType, source, isLocal) or // Pointer subtract: if p is a pointer to a stack address, then p-1 is // too. - stackPointerFlowsToUse( - use.(PointerSubExpr).getLeftOperand(), useType, source, isLocal) + stackPointerFlowsToUse(use.(PointerSubExpr).getLeftOperand(), useType, source, isLocal) or // Pointer add: if p is a pointer to a stack address, then p+1 is too. - stackPointerFlowsToUse( - use.(PointerAddExpr).getAnOperand(), useType, source, isLocal) + stackPointerFlowsToUse(use.(PointerAddExpr).getAnOperand(), useType, source, isLocal) or // Indirect use of a stack address. - exists (SsaDefinition def, LocalScopeVariable var - | stackPointerFlowsToDef(def, var, useType, source, isLocal) and - use = def.getAUse(var)) + exists(SsaDefinition def, LocalScopeVariable var | + stackPointerFlowsToDef(def, var, useType, source, isLocal) and + use = def.getAUse(var) + ) or // Use of a stack address which arrived via one of the function's // parameters. We do not use the original pointer source here because it // could lead to an extremely large number of results if the function has // many callers. Instead we set `source` to the use of the parameter. - exists (SsaDefinition def, Parameter param - | pointerParamFlowsToDef(def, param, useType) and + exists(SsaDefinition def, Parameter param | + pointerParamFlowsToDef(def, param, useType) and use = def.getAUse(param) and source = use and - isLocal = false) + isLocal = false + ) or // Similar to the parameter case above. If a member function is called // on an object which is allocated on the stack, then the "this" pointer // contains a stack address. - exists (ThisExpr thisExpr - | use = thisExpr and + exists(ThisExpr thisExpr | + use = thisExpr and memberFcnMightRunOnStack(thisExpr.getEnclosingFunction(), useType) and source = use and - isLocal = false) + isLocal = false + ) } /** * Helper function for stackPointerFlowsToUse. Gets the type of a pointer * expression. */ -cached private PointerType getExprPtrType(Expr use) { - result = use.getUnspecifiedType() -} +cached +private PointerType getExprPtrType(Expr use) { result = use.getUnspecifiedType() } -predicate stackReferenceFlowsToUse( - Expr use, Type useType, Expr source, boolean isLocal) { +predicate stackReferenceFlowsToUse(Expr use, Type useType, Expr source, boolean isLocal) { // Stack variables - exists (LocalScopeVariable var - | not var.isStatic() and + exists(LocalScopeVariable var | + not var.isStatic() and use = source and source = var.getAnAccess() and isLocal = true and - // If the type of the variable is a reference type, such as int&, then // we need to look at its definition to determine whether it contains a // stack reference. This is handled by stackReferenceFlowsToDef, below. not isReferenceVariable(var) and - // There is a subtlety relating to ArrayType which is hidden by the // simplicity of the line below. Consider this example: // @@ -122,39 +119,42 @@ predicate stackReferenceFlowsToUse( // a PointerType for `p`. Luckily, this conversion happens // automatically when the variable is used. So we get the correct type // provided that we get it from `use` rather than from `var`. - useType = use.getUnspecifiedType()) + useType = use.getUnspecifiedType() + ) or // Accessing the field of a class, struct, or union. - exists (FieldAccess access, Class classType - | use = access and useType = access.getUnspecifiedType() - | // Handle both x.f and x->f: + exists(FieldAccess access, Class classType | + use = access and useType = access.getUnspecifiedType() + | + // Handle both x.f and x->f: stackReferenceFlowsToUse(access.getQualifier(), classType, source, isLocal) or - stackPointerFlowsToUse(access.getQualifier(), classType, source, isLocal)) + stackPointerFlowsToUse(access.getQualifier(), classType, source, isLocal) + ) or // Array indexing: x[i]. // Note that array types are converted to pointers in // stackPointerFlowsToUse. - stackPointerFlowsToUse( - use.(ArrayExpr).getArrayBase(), useType, source, isLocal) + stackPointerFlowsToUse(use.(ArrayExpr).getArrayBase(), useType, source, isLocal) or // Pointer dereference: *x - stackPointerFlowsToUse( - use.(PointerDereferenceExpr).getOperand(), useType, source, isLocal) + stackPointerFlowsToUse(use.(PointerDereferenceExpr).getOperand(), useType, source, isLocal) or // Indirect use of a stack reference, via a reference variable. - exists (SsaDefinition def, LocalScopeVariable var - | stackReferenceFlowsToDef(def, var, useType, source, isLocal) and - use = def.getAUse(var)) + exists(SsaDefinition def, LocalScopeVariable var | + stackReferenceFlowsToDef(def, var, useType, source, isLocal) and + use = def.getAUse(var) + ) or // Use of a stack reference which arrived via one of the function's // parameters. We do not use the original reference source here because // it could lead to an extremely large number of results if the function // has many callers. Instead we set `source` to the use of the parameter. - exists (SsaDefinition def, Parameter param - | referenceParamFlowsToDef(def, param, useType) and + exists(SsaDefinition def, Parameter param | + referenceParamFlowsToDef(def, param, useType) and use = def.getAUse(param) and source = use and - isLocal = false) + isLocal = false + ) } /** @@ -162,20 +162,19 @@ predicate stackReferenceFlowsToUse( * addresses through SSA definitions. */ predicate stackPointerFlowsToDef( - SsaDefinition def, LocalScopeVariable var, - Type useType, Expr source, boolean isLocal) { - stackPointerFlowsToUse( - def.getDefiningValue(var), useType, source, isLocal) + SsaDefinition def, LocalScopeVariable var, Type useType, Expr source, boolean isLocal +) { + stackPointerFlowsToUse(def.getDefiningValue(var), useType, source, isLocal) or // Increment/decrement operators. - exists (VariableAccess access - | access = def.(CrementOperation).getOperand() and + exists(VariableAccess access | + access = def.(CrementOperation).getOperand() and var = access.getTarget() and - stackPointerFlowsToUse(access, useType, source, isLocal)) + stackPointerFlowsToUse(access, useType, source, isLocal) + ) or // Transitive closure over phi definitions. - stackPointerFlowsToDef( - def.getAPhiInput(var), var, useType, source, isLocal) + stackPointerFlowsToDef(def.getAPhiInput(var), var, useType, source, isLocal) } /** @@ -185,8 +184,8 @@ predicate stackPointerFlowsToDef( * int&, rather than pointers. */ predicate stackReferenceFlowsToDef( - SsaDefinition def, LocalScopeVariable var, - Type useType, Expr source, boolean isLocal) { + SsaDefinition def, LocalScopeVariable var, Type useType, Expr source, boolean isLocal +) { // Check that the type of the variable is a reference type and delegate // the rest of the work to stackReferenceFlowsToDef_Impl. isReferenceVariable(var) and @@ -198,20 +197,19 @@ predicate stackReferenceFlowsToDef( * predicate. */ predicate stackReferenceFlowsToDef_Impl( - SsaDefinition def, LocalScopeVariable var, - Type useType, Expr source, boolean isLocal) { - stackReferenceFlowsToUse( - def.getDefiningValue(var), useType, source, isLocal) + SsaDefinition def, LocalScopeVariable var, Type useType, Expr source, boolean isLocal +) { + stackReferenceFlowsToUse(def.getDefiningValue(var), useType, source, isLocal) or // Increment/decrement operators. - exists (VariableAccess access - | access = def.(CrementOperation).getOperand() and + exists(VariableAccess access | + access = def.(CrementOperation).getOperand() and var = access.getTarget() and - stackReferenceFlowsToUse(access, useType, source, isLocal)) + stackReferenceFlowsToUse(access, useType, source, isLocal) + ) or // Transitive closure over phi definitions. - stackReferenceFlowsToDef( - def.getAPhiInput(var), var, useType, source, isLocal) + stackReferenceFlowsToDef(def.getAPhiInput(var), var, useType, source, isLocal) } /** The type of the variable is a reference type, such as int&. */ @@ -225,15 +223,14 @@ predicate isReferenceVariable(LocalScopeVariable var) { * predicate is very similar to stackPointerFlowsToDef but they cannot be * merged, because we cannot identify a sensible source expression here. */ -predicate pointerParamFlowsToDef( - SsaDefinition def, Parameter param, Type useType) { +predicate pointerParamFlowsToDef(SsaDefinition def, Parameter param, Type useType) { // Only include a parameter definition if we can find a call site which // might pass it a stack address. - exists (FunctionCall call - | call.getTarget() = param.getFunction() and - stackPointerFlowsToUse( - call.getArgument(param.getIndex()), useType, _, _) and - def.definedByParameter(param)) + exists(FunctionCall call | + call.getTarget() = param.getFunction() and + stackPointerFlowsToUse(call.getArgument(param.getIndex()), useType, _, _) and + def.definedByParameter(param) + ) or // Transitive closure over phi definitions. pointerParamFlowsToDef(def.getAPhiInput(param), param, useType) @@ -245,15 +242,14 @@ predicate pointerParamFlowsToDef( * predicate is very similar to stackPointerFlowsToDef but they cannot be * merged, because we cannot identify a sensible source expression here. */ -predicate referenceParamFlowsToDef( - SsaDefinition def, Parameter param, Type useType) { +predicate referenceParamFlowsToDef(SsaDefinition def, Parameter param, Type useType) { // Only include a parameter definition if we can find a call site which // might pass it a stack reference. - exists (FunctionCall call - | call.getTarget() = param.getFunction() and - stackReferenceFlowsToUse( - call.getArgument(param.getIndex()), useType, _, _) and - def.definedByParameter(param)) + exists(FunctionCall call | + call.getTarget() = param.getFunction() and + stackReferenceFlowsToUse(call.getArgument(param.getIndex()), useType, _, _) and + def.definedByParameter(param) + ) or // Transitive closure over phi definitions. referenceParamFlowsToDef(def.getAPhiInput(param), param, useType) @@ -264,20 +260,18 @@ predicate referenceParamFlowsToDef( * is allocated on the stack. */ predicate memberFcnMightRunOnStack(MemberFunction fcn, Type useType) { - exists (FunctionCall call - | call.getTarget() = fcn - | // Call of the form `x.f()` where `x` is allocated on the stack. + exists(FunctionCall call | call.getTarget() = fcn | + // Call of the form `x.f()` where `x` is allocated on the stack. stackReferenceFlowsToUse(call.getQualifier(), useType, _, _) - or // Call of the form `x->f()` where `x` is allocated on the stack. - stackPointerFlowsToUse(call.getQualifier(), useType, _, _)) - + stackPointerFlowsToUse(call.getQualifier(), useType, _, _) + ) or // Constructor calls need to be treated as a special case, because // `call.getQualifier()` is empty. - (constructorMightRunOnStack(fcn) and - useType = fcn.getDeclaringType().getUnspecifiedType()) + constructorMightRunOnStack(fcn) and + useType = fcn.getDeclaringType().getUnspecifiedType() } /** @@ -288,17 +282,18 @@ predicate memberFcnMightRunOnStack(MemberFunction fcn, Type useType) { * kinds of initializers to consider. */ predicate constructorMightRunOnStack(Constructor constructor) { - exists (ConstructorCall call - | call.getTarget() = constructor - | // Call to a constructor from a stack variable's initializer. - exists (LocalScopeVariable var | var.getInitializer().getExpr() = call) - + exists(ConstructorCall call | call.getTarget() = constructor | + // Call to a constructor from a stack variable's initializer. + exists(LocalScopeVariable var | var.getInitializer().getExpr() = call) or // Call to a constructor from another constructor which might // also run on the stack. - (constructorMightRunOnStack(call.getEnclosingFunction()) and - (call instanceof ConstructorDirectInit or + constructorMightRunOnStack(call.getEnclosingFunction()) and + ( + call instanceof ConstructorDirectInit or call instanceof ConstructorVirtualInit or call instanceof ConstructorDelegationInit or - exists (ConstructorFieldInit init | init.getExpr() = call)))) + exists(ConstructorFieldInit init | init.getExpr() = call) + ) + ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll b/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll index a40579adde1..895bbdc7e22 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/TaintTracking.qll @@ -14,6 +14,7 @@ * tracking, call `TaintTracking::localTaint` or * `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`. */ + import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow2 @@ -24,6 +25,5 @@ module TaintTracking { /** * DEPRECATED: Use TaintTracking2::Configuration instead. */ - deprecated - class Configuration2 = TaintTracking2::Configuration; + deprecated class Configuration2 = TaintTracking2::Configuration; } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 8702b868c96..ed007554d4c 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -14,7 +14,6 @@ private Node getInstanceArgument(Call call) { /** An argument to a call. */ private class Argument extends Expr { Call call; - int pos; Argument() { call.getArgument(pos) = this } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index c7456c714d9..fe32a498ea8 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -191,7 +191,6 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode { */ class DefinitionByReferenceNode extends PartialDefinitionNode { VariableAccess va; - Expr argument; DefinitionByReferenceNode() { @@ -300,7 +299,6 @@ private class ObjectInitializerNode extends PostUpdateNode, TExprNode { } override PreObjectInitializerNode getPreUpdateNode() { result = pre } - // No override of `toString` since these nodes already have a `toString` from // their overlap with `ExprNode`. } @@ -403,8 +401,7 @@ private module ThisFlow { // negative offset in the first basic block, between the // `ImplicitParameterNode` and the first statement. exists(Constructor constructor, int i | - thisNode.(PreConstructorInitThis).getConstructorFieldInit() = - constructor.getInitializer(i) and + thisNode.(PreConstructorInitThis).getConstructorFieldInit() = constructor.getInitializer(i) and result = -2147483648 + 1 + i and b = thisNode.getFunction().getBlock() ) @@ -599,17 +596,11 @@ private module FieldFlow { private class FieldConfiguration extends Configuration { FieldConfiguration() { this = "FieldConfiguration" } - override predicate isSource(Node source) { - storeStep(source, _, _) - } + override predicate isSource(Node source) { storeStep(source, _, _) } - override predicate isSink(Node sink) { - readStep(_, _, sink) - } + override predicate isSink(Node sink) { readStep(_, _, sink) } - override predicate isBarrier(Node node) { - node instanceof ParameterNode - } + override predicate isBarrier(Node node) { node instanceof ParameterNode } override predicate isBarrierOut(Node node) { node.asExpr().getParent() instanceof ReturnStmt @@ -619,9 +610,7 @@ private module FieldFlow { } predicate fieldFlow(Node node1, Node node2) { - exists(FieldConfiguration cfg | - cfg.hasFlow(node1, node2) - ) and + exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and // This configuration should not be able to cross function boundaries, but // we double-check here just to be sure. node1.getFunction() = node2.getFunction() diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll index 74e96d8d063..4183d73e6f5 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -1,6 +1,7 @@ /** * Provides a class for handling variables in the data flow analysis. */ + import cpp private import semmle.code.cpp.controlflow.SSA private import semmle.code.cpp.dataflow.internal.SubBasicBlocks @@ -18,7 +19,8 @@ private import semmle.code.cpp.dataflow.internal.SubBasicBlocks * member predicates explains how a `FlowVar` relates to syntactic constructs of * the language. */ -cached class FlowVar extends TFlowVar { +cached +class FlowVar extends TFlowVar { /** * Gets a `VariableAccess` that _may_ take its value from `this`. Consider * the following snippet. @@ -35,7 +37,8 @@ cached class FlowVar extends TFlowVar { * corresponding to `x = 1`. The `x` in `x = 1` is not considered to be an * access. */ - cached abstract VariableAccess getAnAccess(); + cached + abstract VariableAccess getAnAccess(); /** * Holds if this `FlowVar` corresponds to a modification occurring when `node` is @@ -49,15 +52,18 @@ cached class FlowVar extends TFlowVar { * `node instanceof PostCrementOperation` is an exception to the rule that * `this` contains the value of `e` after the evaluation of `node`. */ - cached abstract predicate definedByExpr(Expr e, ControlFlowNode node); + cached + abstract predicate definedByExpr(Expr e, ControlFlowNode node); /** * Holds if this `FlowVar` corresponds to the data written by a call that * passes a variable as argument `arg`. */ - cached abstract predicate definedByReference(Expr arg); + cached + abstract predicate definedByReference(Expr arg); - cached abstract predicate definedPartiallyAt(Expr e); + cached + abstract predicate definedPartiallyAt(Expr e); /** * Holds if this `FlowVar` corresponds to the initial value of `v`. The following @@ -70,13 +76,16 @@ cached class FlowVar extends TFlowVar { * local variable is always overwritten before it is used, there is no * `FlowVar` instance for the uninitialized value of that variable. */ - cached abstract predicate definedByInitialValue(LocalScopeVariable v); + cached + abstract predicate definedByInitialValue(LocalScopeVariable v); /** Gets a textual representation of this element. */ - cached abstract string toString(); + cached + abstract string toString(); /** Gets the location of this element. */ - cached abstract Location getLocation(); + cached + abstract Location getLocation(); } /** @@ -117,8 +126,10 @@ private module PartialDefinitions { ControlFlowNode node; PartialDefinition() { - this = TExplicitFieldStoreQualifier(definedExpr, node) or - this = TExplicitCallQualifier(definedExpr, _) and node = definedExpr or + this = TExplicitFieldStoreQualifier(definedExpr, node) + or + this = TExplicitCallQualifier(definedExpr, _) and node = definedExpr + or this = TReferenceArgument(definedExpr, node) } @@ -197,6 +208,7 @@ private module PartialDefinitions { ) } } + import PartialDefinitions private import FlowVar_internal @@ -230,9 +242,7 @@ module FlowVar_internal { // always executes at least once, we give it special treatment in // `BlockVar`, somewhat analogous to unrolling the first iteration of the // loop. - not exists(AlwaysTrueUponEntryLoop loop | - loop.alwaysAssignsBeforeLeavingCondition(_, _, v) - ) and + not exists(AlwaysTrueUponEntryLoop loop | loop.alwaysAssignsBeforeLeavingCondition(_, _, v)) and // The SSA library has a theoretically accurate treatment of reference types, // treating them as immutable, but for data flow it gives better results in // practice to make the variable synonymous with its contents. @@ -243,9 +253,7 @@ module FlowVar_internal { * Holds if `sbb` is the `SubBasicBlock` where `v` receives its initial value. * See the documentation for `FlowVar.definedByInitialValue`. */ - predicate blockVarDefinedByVariable( - SubBasicBlock sbb, LocalScopeVariable v) - { + predicate blockVarDefinedByVariable(SubBasicBlock sbb, LocalScopeVariable v) { sbb = v.(Parameter).getFunction().getEntryPoint() or exists(DeclStmt declStmt | @@ -259,8 +267,7 @@ module FlowVar_internal { TSsaVar(SsaDefinition def, LocalScopeVariable v) { fullySupportedSsaVariable(v) and v = def.getAVariable() - } - or + } or TBlockVar(SubBasicBlock sbb, Variable v) { not fullySupportedSsaVariable(v) and not v instanceof Field and // Fields are interprocedural data flow, not local @@ -281,7 +288,6 @@ module FlowVar_internal { */ class SsaVar extends TSsaVar, FlowVar { SsaDefinition def; - LocalScopeVariable v; SsaVar() { this = TSsaVar(def, v) } @@ -291,7 +297,8 @@ module FlowVar_internal { // the data flow library will never see those, and the `FlowVar` library // is only meant to be used by the data flow library. this.isNonPhi() and - ( // This base case could be included in the transitive case by changing + ( + // This base case could be included in the transitive case by changing // `+` to `*`, but that's slower because it goes through the `TSsaVar` // indirection. result = def.getAUse(v) @@ -308,9 +315,11 @@ module FlowVar_internal { override predicate definedByExpr(Expr e, ControlFlowNode node) { e = def.getDefiningValue(v) and - (if def.getDefinition() = v.getInitializer().getExpr() - then node = v.getInitializer() - else node = def.getDefinition()) + ( + if def.getDefinition() = v.getInitializer().getExpr() + then node = v.getInitializer() + else node = def.getDefinition() + ) } override predicate definedByReference(Expr arg) { @@ -361,7 +370,6 @@ module FlowVar_internal { */ class BlockVar extends TBlockVar, FlowVar { SubBasicBlock sbb; - Variable v; BlockVar() { this = TBlockVar(sbb, v) } @@ -411,15 +419,15 @@ module FlowVar_internal { override string toString() { exists(Expr e | this.definedByExpr(e, _) and - result = "assignment to "+ v + result = "assignment to " + v ) or this.definedByInitialValue(_) and - result = "initial value of "+ v + result = "initial value of " + v or exists(Expr arg | this.definedByReference(arg) and - result = "definition by reference of "+ v + result = "definition by reference of " + v ) or exists(Expr partialDef | @@ -432,16 +440,14 @@ module FlowVar_internal { not this.definedByInitialValue(_) and not this.definedByReference(_) and not this.definedPartiallyAt(_) and - result = "undefined "+ v + result = "undefined " + v } override Location getLocation() { result = sbb.getStart().getLocation() } } /** Type-specialized version of `getEnclosingElement`. */ - private ControlFlowNode getCFNParent(ControlFlowNode node) { - result = node.getEnclosingElement() - } + private ControlFlowNode getCFNParent(ControlFlowNode node) { result = node.getEnclosingElement() } /** * A for-loop or while-loop whose condition is always true upon entry but not @@ -532,11 +538,9 @@ module FlowVar_internal { * be used outside the loop. */ predicate skipLoop( - SubBasicBlock sbbInside, SubBasicBlock sbbOutside, - SubBasicBlock sbbDef, Variable v + SubBasicBlock sbbInside, SubBasicBlock sbbOutside, SubBasicBlock sbbDef, Variable v ) { - exists(AlwaysTrueUponEntryLoop loop, - BasicBlock bbInside, BasicBlock bbOutside | + exists(AlwaysTrueUponEntryLoop loop, BasicBlock bbInside, BasicBlock bbOutside | loop.alwaysAssignsBeforeLeavingCondition(bbInside, bbOutside, v) and bbInside = sbbInside.getBasicBlock() and bbOutside = sbbOutside.getBasicBlock() and @@ -661,18 +665,18 @@ module FlowVar_internal { forall(VariableAccess va | va.getTarget() = v and readAccess(va) - | dominatedByOverwrite(v, va) + | + dominatedByOverwrite(v, va) ) } /** Holds if `va` accesses `v` and is dominated by an overwrite of `v`. */ - predicate dominatedByOverwrite(UninitializedLocalVariable v, - VariableAccess va) - { + predicate dominatedByOverwrite(UninitializedLocalVariable v, VariableAccess va) { exists(BasicBlock bb, int vaIndex | va = bb.getNode(vaIndex) and va.getTarget() = v - | vaIndex > indexOfFirstOverwriteInBB(v, bb) + | + vaIndex > indexOfFirstOverwriteInBB(v, bb) or bbStrictlyDominates(getAnOverwritingBB(v), bb) ) @@ -721,35 +725,34 @@ module FlowVar_internal { ) { // Together, the two following cases cover `Assignment` node = any(AssignExpr ae | - va = ae.getLValue() and - v = va.getTarget() and - assignedExpr = ae.getRValue() - ) + va = ae.getLValue() and + v = va.getTarget() and + assignedExpr = ae.getRValue() + ) or node = any(AssignOperation ao | - va = ao.getLValue() and - v = va.getTarget() and - // Here and in the `PrefixCrementOperation` case, we say that the assigned - // expression is the operation itself. For example, we say that `x += 1` - // assigns `x += 1` to `x`. The justification is that after this operation, - // `x` will contain the same value that `x += 1` evaluated to. - assignedExpr = ao - ) + va = ao.getLValue() and + v = va.getTarget() and + // Here and in the `PrefixCrementOperation` case, we say that the assigned + // expression is the operation itself. For example, we say that `x += 1` + // assigns `x += 1` to `x`. The justification is that after this operation, + // `x` will contain the same value that `x += 1` evaluated to. + assignedExpr = ao + ) or // This case does not add further data flow paths, except if a // `PrefixCrementOperation` is itself a source node = any(CrementOperation op | - va = op.getOperand() and - v = va.getTarget() and - assignedExpr = op - ) + va = op.getOperand() and + v = va.getTarget() and + assignedExpr = op + ) } /** * Holds if `v` is initialized to have value `assignedExpr`. */ - predicate initializer(LocalVariable v, Expr assignedExpr) - { + predicate initializer(LocalVariable v, Expr assignedExpr) { assignedExpr = v.getInitializer().getExpr() } @@ -776,9 +779,7 @@ module FlowVar_internal { */ class DataFlowSubBasicBlockCutNode extends SubBasicBlockCutNode { DataFlowSubBasicBlockCutNode() { - exists(Variable v | - not fullySupportedSsaVariable(v) - | + exists(Variable v | not fullySupportedSsaVariable(v) | assignmentLikeOperation(this, v, _, _) or this = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart() @@ -790,4 +791,5 @@ module FlowVar_internal { ) } } -} /* module FlowVar_internal */ +} +/* module FlowVar_internal */ diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll index 93ac33be2f0..dafcd1fdd97 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll @@ -6,11 +6,11 @@ // internal use by the data flow library. Having an extra copy prevents // non-monotonic recursion errors in queries that use both the data flow // library and the `SubBasicBlocks` library. - /** * Provides the `SubBasicBlock` class, used for partitioning basic blocks in * smaller pieces. */ + import cpp /** @@ -47,27 +47,21 @@ class SubBasicBlock extends ControlFlowNodeBase { } /** Gets the basic block in which this `SubBasicBlock` is contained. */ - BasicBlock getBasicBlock() { - result = this.(ControlFlowNode).getBasicBlock() - } + BasicBlock getBasicBlock() { result = this.(ControlFlowNode).getBasicBlock() } /** * Holds if this `SubBasicBlock` comes first in its basic block. This is the * only condition under which a `SubBasicBlock` may have multiple * predecessors. */ - predicate firstInBB() { - exists(BasicBlock bb | this.getRankInBasicBlock(bb) = 1) - } + predicate firstInBB() { exists(BasicBlock bb | this.getRankInBasicBlock(bb) = 1) } /** * Holds if this `SubBasicBlock` comes last in its basic block. This is the * only condition under which a `SubBasicBlock` may have multiple successors. */ predicate lastInBB() { - exists(BasicBlock bb | - this.getRankInBasicBlock(bb) = countSubBasicBlocksInBasicBlock(bb) - ) + exists(BasicBlock bb | this.getRankInBasicBlock(bb) = countSubBasicBlocksInBasicBlock(bb)) } /** @@ -86,23 +80,17 @@ class SubBasicBlock extends ControlFlowNodeBase { * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based * position. */ - deprecated int getPosInBasicBlock(BasicBlock bb) { - result = getRankInBasicBlock(bb) - 1 - } + deprecated int getPosInBasicBlock(BasicBlock bb) { result = getRankInBasicBlock(bb) - 1 } pragma[noinline] - private int getIndexInBasicBlock(BasicBlock bb) { - this = bb.getNode(result) - } + private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } /** Gets a successor in the control-flow graph of `SubBasicBlock`s. */ SubBasicBlock getASuccessor() { this.lastInBB() and result = this.getBasicBlock().getASuccessor() or - exists(BasicBlock bb | - result.getRankInBasicBlock(bb) = this.getRankInBasicBlock(bb) + 1 - ) + exists(BasicBlock bb | result.getRankInBasicBlock(bb) = this.getRankInBasicBlock(bb) + 1) } /** @@ -130,23 +118,17 @@ class SubBasicBlock extends ControlFlowNodeBase { pragma[nomagic] private int outerToInnerIndex(BasicBlock bb, int indexInBB) { indexInBB = result + this.getIndexInBasicBlock(bb) and - result = [ 0 .. this.getNumberOfNodes() - 1 ] + result = [0 .. this.getNumberOfNodes() - 1] } /** Gets a control-flow node in this `SubBasicBlock`. */ - ControlFlowNode getANode() { - result = this.getNode(_) - } + ControlFlowNode getANode() { result = this.getNode(_) } /** Holds if `this` contains `node`. */ - predicate contains(ControlFlowNode node) { - node = this.getANode() - } + predicate contains(ControlFlowNode node) { node = this.getANode() } /** Gets a predecessor in the control-flow graph of `SubBasicBlock`s. */ - SubBasicBlock getAPredecessor() { - result.getASuccessor() = this - } + SubBasicBlock getAPredecessor() { result.getASuccessor() = this } /** * Gets a node such that the control-flow edge `(this, result)` may be taken @@ -181,19 +163,13 @@ class SubBasicBlock extends ControlFlowNodeBase { } /** Gets the last control-flow node in this `SubBasicBlock`. */ - ControlFlowNode getEnd() { - result = this.getNode(this.getNumberOfNodes() - 1) - } + ControlFlowNode getEnd() { result = this.getNode(this.getNumberOfNodes() - 1) } /** Gets the first control-flow node in this `SubBasicBlock`. */ - ControlFlowNode getStart() { - result = this - } + ControlFlowNode getStart() { result = this } pragma[noinline] - Function getEnclosingFunction() { - result = this.getStart().getControlFlowScope() - } + Function getEnclosingFunction() { result = this.getStart().getControlFlowScope() } } /** Gets the number of `SubBasicBlock`s in the given basic block. */ diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll index 93910382cee..2343bc7a5c3 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -7,6 +7,7 @@ * propagates from `x` to `x + 100`, but it does not propagate from `x` to `x > * 100` since we consider a single bit of information to be too little. */ + private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.Taint @@ -63,9 +64,7 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT // computes a different value, so we have to add that ourselves for taint // tracking. The flow from expression `x` into `x++` etc. is handled in the // case above. - exprTo = DataFlow::getAnAccessToAssignedVariable( - exprFrom.(PostfixCrementOperation) - ) + exprTo = DataFlow::getAnAccessToAssignedVariable(exprFrom.(PostfixCrementOperation)) ) or // Taint can flow through modeled functions @@ -76,9 +75,7 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT * Holds if taint may propagate from `source` to `sink` in zero or more local * (intra-procedural) steps. */ -predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { - localTaintStep*(source, sink) -} +predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) } /** * Holds if taint can flow from `e1` to `e2` in zero or more @@ -126,9 +123,7 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { call.getTarget() = f and argOut = call.getArgument(argOutIndex) and outModel.isOutParameterPointer(argOutIndex) and - exists(int argInIndex, FunctionInput inModel | - f.hasDataFlow(inModel, outModel) - | + exists(int argInIndex, FunctionInput inModel | f.hasDataFlow(inModel, outModel) | // Taint flows from a pointer to a dereference, which DataFlow does not handle // memcpy(&dest_var, tainted_ptr, len) inModel.isInParameterPointer(argInIndex) and @@ -140,9 +135,7 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) { call.getTarget() = f and argOut = call.getArgument(argOutIndex) and outModel.isOutParameterPointer(argOutIndex) and - exists(int argInIndex, FunctionInput inModel | - f.hasTaintFlow(inModel, outModel) - | + exists(int argInIndex, FunctionInput inModel | f.hasTaintFlow(inModel, outModel) | inModel.isInParameterPointer(argInIndex) and exprIn = call.getArgument(argInIndex) or diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Access.qll b/cpp/ql/src/semmle/code/cpp/exprs/Access.qll index 1278277b09b..cf8c2ad5998 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Access.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Access.qll @@ -10,12 +10,9 @@ abstract class Access extends Expr, NameQualifiableElement { /** Gets the accessed function, variable, or enum constant. */ abstract Declaration getTarget(); - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } override string toString() { none() } } @@ -56,11 +53,11 @@ class VariableAccess extends Access, @varaccess { * It does not include accesses on the right-hand side of an assignment, even if they could appear on the left-hand side of some assignment. */ predicate isUsedAsLValue() { - exists(Assignment a | a.getLValue() = this) - or exists(CrementOperation c | c.getOperand() = this) - or exists(AddressOfExpr addof | addof.getOperand() = this) - or exists(ReferenceToExpr rte | this.getConversion() = rte) - or exists(ArrayToPointerConversion atpc | this.getConversion() = atpc) + exists(Assignment a | a.getLValue() = this) or + exists(CrementOperation c | c.getOperand() = this) or + exists(AddressOfExpr addof | addof.getOperand() = this) or + exists(ReferenceToExpr rte | this.getConversion() = rte) or + exists(ArrayToPointerConversion atpc | this.getConversion() = atpc) } /** @@ -68,9 +65,11 @@ class VariableAccess extends Access, @varaccess { * for instance by an assignment or increment/decrement operator. */ predicate isModified() { - exists(Assignment a | a.getLValue() = this) - or exists(CrementOperation c | c.getOperand() = this) - or exists(FunctionCall c | c.getQualifier() = this and c.getTarget().hasName("operator=")) + exists(Assignment a | a.getLValue() = this) + or + exists(CrementOperation c | c.getOperand() = this) + or + exists(FunctionCall c | c.getQualifier() = this and c.getTarget().hasName("operator=")) } /** Holds if this variable access is an rvalue. */ @@ -98,16 +97,16 @@ class VariableAccess extends Access, @varaccess { /** Gets a textual representation of this variable access. */ override string toString() { - if exists(this.getTarget()) then - result = this.getTarget().getName() - else - result = "variable access" + if exists(this.getTarget()) + then result = this.getTarget().getName() + else result = "variable access" } override predicate mayBeImpure() { this.getQualifier().mayBeImpure() or this.getTarget().getType().isVolatile() } + override predicate mayBeGloballyImpure() { this.getQualifier().mayBeGloballyImpure() or this.getTarget().getType().isVolatile() @@ -118,9 +117,7 @@ class VariableAccess extends Access, @varaccess { * in such a way that the address might escape. This can be either explicit, * for example `&x`, or implicit, for example `T& y = x`. */ - predicate isAddressOfAccess() { - variableAddressEscapesTree(this, _) - } + predicate isAddressOfAccess() { variableAddressEscapesTree(this, _) } /** * Holds if this access is used to get the address of the underlying variable @@ -128,9 +125,7 @@ class VariableAccess extends Access, @varaccess { * non-const data. This can be either explicit, for example `&x`, or * implicit, for example `T& y = x`. */ - predicate isAddressOfAccessNonConst() { - variableAddressEscapesTreeNonConst(this, _) - } + predicate isAddressOfAccessNonConst() { variableAddressEscapesTreeNonConst(this, _) } } /** @@ -151,10 +146,12 @@ class FieldAccess extends VariableAccess { */ class PointerFieldAccess extends FieldAccess { override string getCanonicalQLClass() { result = "PointerFieldAccess" } + PointerFieldAccess() { - exists (PointerType t - | t = getQualifier().getFullyConverted().getUnspecifiedType() and - t.getBaseType() instanceof Class) + exists(PointerType t | + t = getQualifier().getFullyConverted().getUnspecifiedType() and + t.getBaseType() instanceof Class + ) } } @@ -166,10 +163,8 @@ class PointerFieldAccess extends FieldAccess { */ class DotFieldAccess extends FieldAccess { override string getCanonicalQLClass() { result = "DotFieldAccess" } - DotFieldAccess() { - exists (Class c - | c = getQualifier().getFullyConverted().getUnspecifiedType()) - } + + DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) } } /** @@ -178,9 +173,8 @@ class DotFieldAccess extends FieldAccess { */ class ReferenceFieldAccess extends DotFieldAccess { override string getCanonicalQLClass() { result = "ReferenceFieldAccess" } - ReferenceFieldAccess() { - exprHasReferenceConversion(this.getQualifier()) - } + + ReferenceFieldAccess() { exprHasReferenceConversion(this.getQualifier()) } } /** @@ -189,9 +183,8 @@ class ReferenceFieldAccess extends DotFieldAccess { */ class ValueFieldAccess extends DotFieldAccess { override string getCanonicalQLClass() { result = "ValueFieldAccess" } - ValueFieldAccess() { - not exprHasReferenceConversion(this.getQualifier()) - } + + ValueFieldAccess() { not exprHasReferenceConversion(this.getQualifier()) } } /** @@ -215,9 +208,7 @@ private predicate referenceConversion(Conversion c) { * In this example, the type of `x` is `MyStruct&`, but it gets implicitly * converted to `MyStruct` in the expression `x.field`. */ -private predicate exprHasReferenceConversion(Expr e) { - referenceConversion(e.getConversion+()) -} +private predicate exprHasReferenceConversion(Expr e) { referenceConversion(e.getConversion+()) } /** * A field access of a field of `this`. The access has no qualifier because @@ -231,18 +222,15 @@ private predicate exprHasReferenceConversion(Expr e) { */ class ImplicitThisFieldAccess extends FieldAccess { override string getCanonicalQLClass() { result = "ImplicitThisFieldAccess" } - ImplicitThisFieldAccess() { - not exists (this.getQualifier()) - } + + ImplicitThisFieldAccess() { not exists(this.getQualifier()) } } /** * A C/C++ function access expression. */ class FunctionAccess extends Access, @routineexpr { - FunctionAccess() { - not iscall(underlyingElement(this),_) - } + FunctionAccess() { not iscall(underlyingElement(this), _) } override string getCanonicalQLClass() { result = "FunctionAccess" } @@ -251,10 +239,9 @@ class FunctionAccess extends Access, @routineexpr { /** Gets a textual representation of this function access. */ override string toString() { - if exists(this.getTarget()) then - result = this.getTarget().getName() - else - result = "function access" + if exists(this.getTarget()) + then result = this.getTarget().getName() + else result = "function access" } } @@ -272,9 +259,7 @@ class FunctionAccess extends Access, @routineexpr { * an add expression, which in turn has two ParamAccessForType children. */ class ParamAccessForType extends Expr, @param_ref { - override string toString() { - result = "param access" - } + override string toString() { result = "param access" } } /** @@ -283,9 +268,8 @@ class ParamAccessForType extends Expr, @param_ref { */ class TypeName extends Expr, @type_operand { override string getCanonicalQLClass() { result = "TypeName" } - override string toString() { - result = this.getType().getName() - } + + override string toString() { result = this.getType().getName() } } /** @@ -315,9 +299,11 @@ class ArrayExpr extends Expr, @subscriptexpr { * for instance by an assignment or an increment/decrement operation. */ predicate isModified() { - exists(Assignment a | a.getLValue() = this) - or exists(CrementOperation c | c.getOperand() = this) - or exists(FunctionCall c | c.getQualifier() = this and c.getTarget().hasName("operator=")) + exists(Assignment a | a.getLValue() = this) + or + exists(CrementOperation c | c.getOperand() = this) + or + exists(FunctionCall c | c.getQualifier() = this and c.getTarget().hasName("operator=")) } override string toString() { result = "access to array" } @@ -328,6 +314,7 @@ class ArrayExpr extends Expr, @subscriptexpr { this.getArrayBase().getFullyConverted().getType().(DerivedType).getBaseType().isVolatile() or this.getArrayOffset().getFullyConverted().getType().(DerivedType).getBaseType().isVolatile() } + override predicate mayBeGloballyImpure() { this.getArrayBase().mayBeGloballyImpure() or this.getArrayOffset().mayBeGloballyImpure() or diff --git a/cpp/ql/src/semmle/code/cpp/exprs/ArithmeticOperation.qll b/cpp/ql/src/semmle/code/cpp/exprs/ArithmeticOperation.qll index 855869bb464..48af2b539c7 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/ArithmeticOperation.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/ArithmeticOperation.qll @@ -3,8 +3,7 @@ import semmle.code.cpp.exprs.Expr /** * A C/C++ arithmetic operation. */ -abstract class UnaryArithmeticOperation extends UnaryOperation { -} +abstract class UnaryArithmeticOperation extends UnaryOperation { } /** * A C/C++ unary minus expression. @@ -13,7 +12,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr { override string getOperator() { result = "-" } override string getCanonicalQLClass() { result = "UnaryMinusExpr" } - + override int getPrecedence() { result = 15 } } @@ -24,7 +23,7 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr { override string getOperator() { result = "+" } override string getCanonicalQLClass() { result = "UnaryPlusExpr" } - + override int getPrecedence() { result = 15 } } @@ -42,15 +41,15 @@ class ConjugationExpr extends UnaryArithmeticOperation, @conjugation { * or `operator--`. */ abstract class CrementOperation extends UnaryArithmeticOperation { - override predicate mayBeImpure() { - any() - } + override predicate mayBeImpure() { any() } + override predicate mayBeGloballyImpure() { not exists(VariableAccess va, LocalScopeVariable v | - va = this.getOperand() - and v = va.getTarget() - and not va.getConversion+() instanceof ReferenceDereferenceExpr - and not v.isStatic()) + va = this.getOperand() and + v = va.getTarget() and + not va.getConversion+() instanceof ReferenceDereferenceExpr and + not v.isStatic() + ) } } @@ -59,32 +58,28 @@ abstract class CrementOperation extends UnaryArithmeticOperation { * * Note that this doesn't include calls to user-defined `operator++`. */ -abstract class IncrementOperation extends CrementOperation { -} +abstract class IncrementOperation extends CrementOperation { } /** * A C/C++ `--` expression (either prefix or postfix). * * Note that this doesn't include calls to user-defined `operator--`. */ -abstract class DecrementOperation extends CrementOperation { -} +abstract class DecrementOperation extends CrementOperation { } /** * A C/C++ `++` or `--` prefix expression. * * Note that this doesn't include calls to user-defined operators. */ -abstract class PrefixCrementOperation extends CrementOperation { -} +abstract class PrefixCrementOperation extends CrementOperation { } /** * A C/C++ `++` or `--` postfix expression. * * Note that this doesn't include calls to user-defined operators. */ -abstract class PostfixCrementOperation extends CrementOperation { -} +abstract class PostfixCrementOperation extends CrementOperation { } /** * A C/C++ prefix increment expression, as in `++x`. @@ -95,7 +90,7 @@ class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preinc override string getOperator() { result = "++" } override string getCanonicalQLClass() { result = "PrefixIncrExpr" } - + override int getPrecedence() { result = 15 } } @@ -108,7 +103,7 @@ class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predec override string getOperator() { result = "--" } override string getCanonicalQLClass() { result = "PrefixDecrExpr" } - + override int getPrecedence() { result = 15 } } @@ -121,7 +116,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post override string getOperator() { result = "++" } override string getCanonicalQLClass() { result = "PostfixIncrExpr" } - + override int getPrecedence() { result = 16 } override string toString() { result = "... " + getOperator() } @@ -136,7 +131,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post override string getOperator() { result = "--" } override string getCanonicalQLClass() { result = "PostfixDecrExpr" } - + override int getPrecedence() { result = 16 } override string toString() { result = "... " + getOperator() } @@ -159,8 +154,7 @@ class ImaginaryPartExpr extends UnaryArithmeticOperation, @imagpartexpr { /** * A C/C++ binary arithmetic operation. */ -abstract class BinaryArithmeticOperation extends BinaryOperation { -} +abstract class BinaryArithmeticOperation extends BinaryOperation { } /** * A C/C++ add expression. @@ -169,7 +163,7 @@ class AddExpr extends BinaryArithmeticOperation, @addexpr { override string getOperator() { result = "+" } override string getCanonicalQLClass() { result = "AddExpr" } - + override int getPrecedence() { result = 12 } } @@ -180,7 +174,7 @@ class SubExpr extends BinaryArithmeticOperation, @subexpr { override string getOperator() { result = "-" } override string getCanonicalQLClass() { result = "SubExpr" } - + override int getPrecedence() { result = 12 } } @@ -191,7 +185,7 @@ class MulExpr extends BinaryArithmeticOperation, @mulexpr { override string getOperator() { result = "*" } override string getCanonicalQLClass() { result = "MulExpr" } - + override int getPrecedence() { result = 13 } } @@ -202,7 +196,7 @@ class DivExpr extends BinaryArithmeticOperation, @divexpr { override string getOperator() { result = "/" } override string getCanonicalQLClass() { result = "DivExpr" } - + override int getPrecedence() { result = 13 } } @@ -213,7 +207,7 @@ class RemExpr extends BinaryArithmeticOperation, @remexpr { override string getOperator() { result = "%" } override string getCanonicalQLClass() { result = "RemExpr" } - + override int getPrecedence() { result = 13 } } @@ -288,8 +282,7 @@ class MaxExpr extends BinaryArithmeticOperation, @maxexpr { /** * A C/C++ pointer arithmetic operation. */ -abstract class PointerArithmeticOperation extends BinaryArithmeticOperation { -} +abstract class PointerArithmeticOperation extends BinaryArithmeticOperation { } /** * A C/C++ pointer add expression. @@ -298,7 +291,7 @@ class PointerAddExpr extends PointerArithmeticOperation, @paddexpr { override string getOperator() { result = "+" } override string getCanonicalQLClass() { result = "PointerAddExpr" } - + override int getPrecedence() { result = 12 } } @@ -309,7 +302,7 @@ class PointerSubExpr extends PointerArithmeticOperation, @psubexpr { override string getOperator() { result = "-" } override string getCanonicalQLClass() { result = "PointerSubExpr" } - + override int getPrecedence() { result = 12 } } @@ -320,6 +313,6 @@ class PointerDiffExpr extends PointerArithmeticOperation, @pdiffexpr { override string getOperator() { result = "-" } override string getCanonicalQLClass() { result = "PointerDiffExpr" } - + override int getPrecedence() { result = 12 } } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Assignment.qll b/cpp/ql/src/semmle/code/cpp/exprs/Assignment.qll index c2c2b044173..c0a42d60315 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Assignment.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Assignment.qll @@ -9,20 +9,22 @@ import semmle.code.cpp.exprs.BitwiseOperation */ abstract class Assignment extends Operation { /** Gets the lvalue of this assignment. */ - Expr getLValue() { this.hasChild(result,0) } + Expr getLValue() { this.hasChild(result, 0) } /** Gets the rvalue of this assignment. */ - Expr getRValue() { this.hasChild(result,1) } + Expr getRValue() { this.hasChild(result, 1) } override int getPrecedence() { result = 2 } override predicate mayBeGloballyImpure() { - this.getRValue().mayBeGloballyImpure() or + this.getRValue().mayBeGloballyImpure() + or not exists(VariableAccess va, LocalScopeVariable v | - va = this.getLValue() - and v = va.getTarget() - and not va.getConversion+() instanceof ReferenceDereferenceExpr - and not v.isStatic()) + va = this.getLValue() and + v = va.getTarget() and + not va.getConversion+() instanceof ReferenceDereferenceExpr and + not v.isStatic() + ) } } @@ -33,7 +35,7 @@ class AssignExpr extends Assignment, @assignexpr { override string getOperator() { result = "=" } override string getCanonicalQLClass() { result = "AssignExpr" } - + /** Gets a textual representation of this assignment. */ override string toString() { result = "... = ..." } } @@ -49,15 +51,14 @@ abstract class AssignOperation extends Assignment { * A non-overloaded arithmetic assignment operation on a non-pointer lvalue: * `+=`, `-=`, `*=`, `/=` and `%=`. */ -abstract class AssignArithmeticOperation extends AssignOperation { -} +abstract class AssignArithmeticOperation extends AssignOperation { } /** * A non-overloaded `+=` assignment expression on a non-pointer lvalue. */ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr { override string getCanonicalQLClass() { result = "AssignAddExpr" } - + override string getOperator() { result = "+=" } } @@ -66,7 +67,7 @@ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr { */ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr { override string getCanonicalQLClass() { result = "AssignSubExpr" } - + override string getOperator() { result = "-=" } } @@ -75,7 +76,7 @@ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr { */ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr { override string getCanonicalQLClass() { result = "AssignMulExpr" } - + override string getOperator() { result = "*=" } } @@ -84,7 +85,7 @@ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr { */ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr { override string getCanonicalQLClass() { result = "AssignDivExpr" } - + override string getOperator() { result = "/=" } } @@ -93,7 +94,7 @@ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr { */ class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr { override string getCanonicalQLClass() { result = "AssignRemExpr" } - + override string getOperator() { result = "%=" } } @@ -101,15 +102,14 @@ class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr { * A non-overloaded bitwise assignment operation: * `&=`, `|=`, `^=`, `<<=`, and `>>=`. */ -abstract class AssignBitwiseOperation extends AssignOperation { -} +abstract class AssignBitwiseOperation extends AssignOperation { } /** * A non-overloaded `&=` assignment expression. */ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr { override string getCanonicalQLClass() { result = "AssignAndExpr" } - + override string getOperator() { result = "&=" } } @@ -118,7 +118,7 @@ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr { */ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr { override string getCanonicalQLClass() { result = "AssignOrExpr" } - + override string getOperator() { result = "|=" } } @@ -127,7 +127,7 @@ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr { */ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr { override string getCanonicalQLClass() { result = "AssignXorExpr" } - + override string getOperator() { result = "^=" } } @@ -136,7 +136,7 @@ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr { */ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr { override string getCanonicalQLClass() { result = "AssignLShiftExpr" } - + override string getOperator() { result = "<<=" } } @@ -145,7 +145,7 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr { */ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr { override string getCanonicalQLClass() { result = "AssignRShiftExpr" } - + override string getOperator() { result = ">>=" } } @@ -154,7 +154,7 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr { */ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr { override string getCanonicalQLClass() { result = "AssignPointerAddExpr" } - + override string getOperator() { result = "+=" } } @@ -163,7 +163,7 @@ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr { */ class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr { override string getCanonicalQLClass() { result = "AssignPointerSubExpr" } - + override string getOperator() { result = "-=" } } @@ -180,8 +180,7 @@ class ConditionDeclExpr extends Expr, @condition_decl { * * Gets the access using the condition for this declaration. */ - deprecated - Expr getExpr() { result = this.getChild(0) } + deprecated Expr getExpr() { result = this.getChild(0) } override string getCanonicalQLClass() { result = "ConditionDeclExpr" } @@ -198,7 +197,7 @@ class ConditionDeclExpr extends Expr, @condition_decl { Expr getInitializingExpr() { result = this.getVariable().getInitializer().getExpr() } /** Gets the variable that is declared. */ - Variable getVariable() { condition_decl_bind(underlyingElement(this),unresolveElement(result)) } + Variable getVariable() { condition_decl_bind(underlyingElement(this), unresolveElement(result)) } override string toString() { result = "(condition decl)" } } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/BitwiseOperation.qll b/cpp/ql/src/semmle/code/cpp/exprs/BitwiseOperation.qll index c7fbcc62ffa..8e6c9979b97 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/BitwiseOperation.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/BitwiseOperation.qll @@ -3,8 +3,7 @@ import semmle.code.cpp.exprs.Expr /** * A C/C++ unary bitwise operation. */ -abstract class UnaryBitwiseOperation extends UnaryOperation { -} +abstract class UnaryBitwiseOperation extends UnaryOperation { } /** * A C/C++ complement expression. @@ -20,9 +19,7 @@ class ComplementExpr extends UnaryBitwiseOperation, @complementexpr { /** * A C/C++ binary bitwise operation. */ -abstract class BinaryBitwiseOperation extends BinaryOperation { -} - +abstract class BinaryBitwiseOperation extends BinaryOperation { } /** * A C/C++ left shift expression. @@ -75,6 +72,6 @@ class BitwiseXorExpr extends BinaryBitwiseOperation, @xorexpr { override string getOperator() { result = "^" } override int getPrecedence() { result = 7 } - + override string getCanonicalQLClass() { result = "BitwiseXorExpr" } } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll b/cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll index 13275a4864b..b87f15e6454 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll @@ -286,9 +286,10 @@ class BuiltInOperationBuiltInConvertVector extends BuiltInOperation, @builtincon class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation, @builtinaddressof { /** Gets the function or variable whose address is taken. */ Declaration getAddressable() { - result = this.getOperand().(Access).getTarget() - // this handles the case where we are taking the address of a reference variable - or result = this.getOperand().(ReferenceDereferenceExpr).getChild(0).(Access).getTarget() + result = this.getOperand().(Access).getTarget() + or + // this handles the case where we are taking the address of a reference variable + result = this.getOperand().(ReferenceDereferenceExpr).getChild(0).(Access).getTarget() } override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInAddressOf" } @@ -299,7 +300,8 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation, /** * The `__is_trivially_constructible` type trait. */ -class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation, @istriviallyconstructibleexpr { +class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation, + @istriviallyconstructibleexpr { override string toString() { result = "__is_trivially_constructible" } override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyConstructible" } @@ -380,7 +382,8 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr /** * The `__has_trivial_move_constructor` type trait. */ -class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation, @hastrivialmoveconstructorexpr { +class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation, + @hastrivialmoveconstructorexpr { override string toString() { result = "__has_trivial_move_constructor" } override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialMoveConstructor" } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll index 472f776d429..882918316f6 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll @@ -12,16 +12,14 @@ abstract class Call extends Expr, NameQualifiableElement { * retrieve actuals. */ int getNumberOfArguments() { result = count(this.getAnArgument()) } - + /** * Holds if this call has a qualifier. * * For example, `ptr->f()` has a qualifier, whereas plain `f()` does not. */ - predicate hasQualifier() { - exists(Expr e | this.getChild(-1) = e) - } - + predicate hasQualifier() { exists(Expr e | this.getChild(-1) = e) } + /** * Gets the expression to the left of the function name or function pointer variable name. * @@ -29,26 +27,20 @@ abstract class Call extends Expr, NameQualifiableElement { * For the call to `f` in `ptr->f()`, this gives `ptr`. * For the call to `f` in `(*ptr).f()`, this gives `(*ptr)`. */ - Expr getQualifier() { - result = this.getChild(-1) - } + Expr getQualifier() { result = this.getChild(-1) } /** * Gets an argument for this call. */ - Expr getAnArgument() { - exists(int i | result = this.getChild(i) and i >= 0) - } + Expr getAnArgument() { exists(int i | result = this.getChild(i) and i >= 0) } /** * Gets the nth argument for this call. * * The range of `n` is from `0` to `getNumberOfArguments() - 1`. */ - Expr getArgument(int n) { - result = this.getChild(n) and n >= 0 - } - + Expr getArgument(int n) { result = this.getChild(n) and n >= 0 } + /** * Gets a sub expression of the argument at position `index`. If the * argument itself contains calls, such calls will be considered @@ -62,10 +54,10 @@ abstract class Call extends Expr, NameQualifiableElement { result = getArgument(index) or exists(Expr mid | - mid = getAnArgumentSubExpr(index) - and not mid instanceof Call - and not mid instanceof SizeofOperator - and result = mid.getAChild() + mid = getAnArgumentSubExpr(index) and + not mid instanceof Call and + not mid instanceof SizeofOperator and + result = mid.getAChild() ) } @@ -81,9 +73,9 @@ abstract class Call extends Expr, NameQualifiableElement { abstract Function getTarget(); override int getPrecedence() { result = 16 } - + override string toString() { none() } - + /** * Holds if this call passes the variable accessed by `va` by * reference as the `i`th argument. @@ -127,10 +119,7 @@ abstract class Call extends Expr, NameQualifiableElement { * by reference to const. */ predicate passesByReferenceNonConst(int i, VariableAccess va) { - variableAddressEscapesTreeNonConst( - va, - this.getArgument(i).getFullyConverted() - ) + variableAddressEscapesTreeNonConst(va, this.getArgument(i).getFullyConverted()) } } @@ -145,67 +134,53 @@ abstract class Call extends Expr, NameQualifiableElement { * 5. Base class initializers in constructors. */ class FunctionCall extends Call, @funbindexpr { - FunctionCall() { - iscall(underlyingElement(this),_) - } + FunctionCall() { iscall(underlyingElement(this), _) } override string getCanonicalQLClass() { result = "FunctionCall" } - + /** Gets an explicit template argument for this call. */ - Type getAnExplicitTemplateArgument() { - result = getExplicitTemplateArgument(_) - } + Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } /** Gets a template argument for this call. */ - Type getATemplateArgument() { - result = getTarget().getATemplateArgument() - } + Type getATemplateArgument() { result = getTarget().getATemplateArgument() } /** Gets the nth explicit template argument for this call. */ Type getExplicitTemplateArgument(int n) { - n < getNumberOfExplicitTemplateArguments() - and result = getTemplateArgument(n) + n < getNumberOfExplicitTemplateArguments() and + result = getTemplateArgument(n) } /** Gets the number of explicit template arguments for this call. */ int getNumberOfExplicitTemplateArguments() { - if numtemplatearguments(underlyingElement(this),_) then - numtemplatearguments(underlyingElement(this),result) - else - result = 0 + if numtemplatearguments(underlyingElement(this), _) + then numtemplatearguments(underlyingElement(this), result) + else result = 0 } /** Gets the number of template arguments for this call. */ - int getNumberOfTemplateArguments() { - result = count(int i | exists(getTemplateArgument(i))) - } + int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } /** Gets the nth template argument for this call (indexed from 0). */ - Type getTemplateArgument(int n) { - result = getTarget().getTemplateArgument(n) - } + Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { exists(int i | - exists(getTemplateArgument(i)) - and not exists(getExplicitTemplateArgument(i)) + exists(getTemplateArgument(i)) and + not exists(getExplicitTemplateArgument(i)) ) } /** Holds if a template argument list was provided for this call. */ - predicate hasTemplateArgumentList() { - numtemplatearguments(underlyingElement(this),_) - } + predicate hasTemplateArgumentList() { numtemplatearguments(underlyingElement(this), _) } /** * Gets the `RoutineType` of the call target as visible at the call site. For * constructor calls, this predicate instead gets the `Class` of the constructor * being called. */ - private - Type getTargetType() { result = Call.super.getType().stripType() } - + private Type getTargetType() { result = Call.super.getType().stripType() } + /** * Gets the expected return type of the function called by this call. * @@ -215,12 +190,11 @@ class FunctionCall extends Call, @funbindexpr { * visible at the call site. */ Type getExpectedReturnType() { - if getTargetType() instanceof RoutineType then - result = getTargetType().(RoutineType).getReturnType() - else - result = getTarget().getType() + if getTargetType() instanceof RoutineType + then result = getTargetType().(RoutineType).getReturnType() + else result = getTarget().getType() } - + /** * Gets the expected type of the nth parameter of the function called by this call. * @@ -230,10 +204,9 @@ class FunctionCall extends Call, @funbindexpr { * was visible at the call site. */ Type getExpectedParameterType(int n) { - if getTargetType() instanceof RoutineType then - result = getTargetType().(RoutineType).getParameterType(n) - else - result = getTarget().getParameter(n).getType() + if getTargetType() instanceof RoutineType + then result = getTargetType().(RoutineType).getParameterType(n) + else result = getTarget().getParameter(n).getType() } /** @@ -242,8 +215,8 @@ class FunctionCall extends Call, @funbindexpr { * In the case of virtual function calls, the result is the most-specific function in the override tree (as * determined by the compiler) such that the target at runtime will be one of result.getAnOverridingFunction*(). */ - override Function getTarget() { funbind(underlyingElement(this),unresolveElement(result)) } - + override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) } + /** * Gets the type of this expression, that is, the return type of the function being called. */ @@ -254,24 +227,19 @@ class FunctionCall extends Call, @funbindexpr { * * Note that this holds even in cases where a sufficiently clever compiler could perform static dispatch. */ - predicate isVirtual() { - iscall(underlyingElement(this),1) - } + predicate isVirtual() { iscall(underlyingElement(this), 1) } /** * Holds if the target of this function call was found by argument-dependent lookup and wouldn't have been * found by any other means. */ - predicate isOnlyFoundByADL() { - iscall(underlyingElement(this),2) - } + predicate isOnlyFoundByADL() { iscall(underlyingElement(this), 2) } /** Gets a textual representation of this function call. */ override string toString() { - if exists(getTarget()) then - result = "call to " + this.getTarget().getName() - else - result = "call to unknown function" + if exists(getTarget()) + then result = "call to " + this.getTarget().getName() + else result = "call to unknown function" } override predicate mayBeImpure() { @@ -280,6 +248,7 @@ class FunctionCall extends Call, @funbindexpr { isVirtual() or getTarget().getAnAttribute().getName() = "weak" } + override predicate mayBeGloballyImpure() { this.getChild(_).mayBeGloballyImpure() or this.getTarget().mayHaveSideEffects() or @@ -293,8 +262,8 @@ class FunctionCall extends Call, @funbindexpr { */ class OverloadedPointerDereferenceExpr extends FunctionCall { OverloadedPointerDereferenceExpr() { - getTarget().hasName("operator*") - and getTarget().getEffectiveNumberOfParameters() = 1 + getTarget().hasName("operator*") and + getTarget().getEffectiveNumberOfParameters() = 1 } /** @@ -307,17 +276,28 @@ class OverloadedPointerDereferenceExpr extends FunctionCall { override predicate mayBeImpure() { FunctionCall.super.mayBeImpure() and - (this.getExpr().mayBeImpure() or - not exists(Class declaring | - this.getTarget().getDeclaringType().isConstructedFrom*(declaring) | - declaring.getNamespace() instanceof StdNamespace)) + ( + this.getExpr().mayBeImpure() + or + not exists(Class declaring | + this.getTarget().getDeclaringType().isConstructedFrom*(declaring) + | + declaring.getNamespace() instanceof StdNamespace + ) + ) } + override predicate mayBeGloballyImpure() { FunctionCall.super.mayBeGloballyImpure() and - (this.getExpr().mayBeGloballyImpure() or - not exists(Class declaring | - this.getTarget().getDeclaringType().isConstructedFrom*(declaring) | - declaring.getNamespace() instanceof StdNamespace)) + ( + this.getExpr().mayBeGloballyImpure() + or + not exists(Class declaring | + this.getTarget().getDeclaringType().isConstructedFrom*(declaring) + | + declaring.getNamespace() instanceof StdNamespace + ) + ) } } @@ -325,19 +305,21 @@ class OverloadedPointerDereferenceExpr extends FunctionCall { * An instance of operator [] applied to a user-defined type. */ class OverloadedArrayExpr extends FunctionCall { - OverloadedArrayExpr() { - getTarget().hasName("operator[]") - } - + OverloadedArrayExpr() { getTarget().hasName("operator[]") } + /** * Gets the expression being subscripted. */ - Expr getArrayBase() { if exists(this.getQualifier()) then result = this.getQualifier() else result = this.getChild(0) } + Expr getArrayBase() { + if exists(this.getQualifier()) then result = this.getQualifier() else result = this.getChild(0) + } /** * Gets the expression giving the index. */ - Expr getArrayOffset() { if exists(this.getQualifier()) then result = this.getChild(0) else result = this.getChild(1) } + Expr getArrayOffset() { + if exists(this.getQualifier()) then result = this.getChild(0) else result = this.getChild(1) + } } /** @@ -348,21 +330,18 @@ class ExprCall extends Call, @callexpr { * Gets the expression which yields the function pointer to call. */ Expr getExpr() { result = this.getChild(0) } - + override string getCanonicalQLClass() { result = "ExprCall" } - override Expr getAnArgument() { - exists(int i | result = this.getChild(i) and i >= 1) - } + override Expr getAnArgument() { exists(int i | result = this.getChild(i) and i >= 1) } + override Expr getArgument(int index) { - result = this.getChild(index+1) and index in [0..this.getNumChild()-2] + result = this.getChild(index + 1) and index in [0 .. this.getNumChild() - 2] } override string toString() { result = "call to expression" } - override Function getTarget() { - none() - } + override Function getTarget() { none() } } /** @@ -376,9 +355,7 @@ class VariableCall extends ExprCall { /** * Gets the variable which yields the function pointer to call. */ - Variable getVariable() { - this.getExpr().(VariableAccess).getTarget() = result - } + Variable getVariable() { this.getExpr().(VariableAccess).getTarget() = result } } /** @@ -386,7 +363,7 @@ class VariableCall extends ExprCall { */ class ConstructorCall extends FunctionCall { ConstructorCall() { super.getTarget() instanceof Constructor } - + override string getCanonicalQLClass() { result = "ConstructorCall" } /** Gets the constructor being called. */ @@ -426,7 +403,7 @@ class ReThrowExpr extends ThrowExpr { */ class DestructorCall extends FunctionCall { DestructorCall() { super.getTarget() instanceof Destructor } - + override string getCanonicalQLClass() { result = "DestructorCall" } /** Gets the destructor being called. */ @@ -500,8 +477,8 @@ class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit */ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit { /** Gets the field being initialized. */ - Field getTarget() { varbind(underlyingElement(this),unresolveElement(result)) } - + Field getTarget() { varbind(underlyingElement(this), unresolveElement(result)) } + override string getCanonicalQLClass() { result = "ConstructorFieldInit" } /** @@ -511,17 +488,12 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit { * constructor, but more complex expressions can also occur. */ Expr getExpr() { result = this.getChild(0) } - - override string toString() { - result = "constructor init of field " + getTarget().getName() - } - override predicate mayBeImpure() { - this.getExpr().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + override string toString() { result = "constructor init of field " + getTarget().getName() } + + override predicate mayBeImpure() { this.getExpr().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } } /** @@ -565,15 +537,14 @@ class DestructorVirtualDestruction extends DestructorBaseDestruction, @dtorvirtu */ class DestructorFieldDestruction extends DestructorDestruction, @dtorfielddestruct { /** Gets the field being destructed. */ - Field getTarget() { varbind(underlyingElement(this),unresolveElement(result)) } - + Field getTarget() { varbind(underlyingElement(this), unresolveElement(result)) } + override string getCanonicalQLClass() { result = "DestructorFieldDestruction" } /** Gets the compiler-generated call to the variable's destructor. */ DestructorCall getExpr() { result = this.getChild(0) } - + override string toString() { - result = "destructor field destruction of " - + this.getTarget().getName() + result = "destructor field destruction of " + this.getTarget().getName() } } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Cast.qll b/cpp/ql/src/semmle/code/cpp/exprs/Cast.qll index c7a9c662557..df34515bd46 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Cast.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Cast.qll @@ -14,12 +14,9 @@ abstract class Conversion extends Expr { /** Holds if this conversion is an implicit conversion. */ predicate isImplicit() { this.isCompilerGenerated() } - override predicate mayBeImpure() { - this.getExpr().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getExpr().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } } /** @@ -42,9 +39,7 @@ abstract class Cast extends Conversion, @cast { * Gets a string describing the semantic conversion operation being performed by * this cast. */ - string getSemanticConversionString() { - result = "unknown conversion" - } + string getSemanticConversionString() { result = "unknown conversion" } } /** @@ -149,9 +144,7 @@ class ArithmeticConversion extends Cast { isArithmeticOrEnum(getExpr().getUnspecifiedType()) } - override string getSemanticConversionString() { - result = "arithmetic conversion" - } + override string getSemanticConversionString() { result = "arithmetic conversion" } } /** @@ -163,11 +156,11 @@ class IntegralConversion extends ArithmeticConversion { isIntegralOrEnum(getExpr().getUnspecifiedType()) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "IntegralConversion" } - - override string getSemanticConversionString() { - result = "integral conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "IntegralConversion" } + + override string getSemanticConversionString() { result = "integral conversion" } } /** @@ -179,11 +172,11 @@ class FloatingPointConversion extends ArithmeticConversion { getExpr().getUnspecifiedType() instanceof FloatingPointType } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "FloatingPointConversion" } - - override string getSemanticConversionString() { - result = "floating point conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "FloatingPointConversion" } + + override string getSemanticConversionString() { result = "floating point conversion" } } /** @@ -195,11 +188,11 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion { getExpr().getUnspecifiedType() instanceof FloatingPointType } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "FloatingPointToIntegralConversion" } - - override string getSemanticConversionString() { - result = "floating point to integral conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "FloatingPointToIntegralConversion" } + + override string getSemanticConversionString() { result = "floating point to integral conversion" } } /** @@ -211,11 +204,11 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion { isIntegralOrEnum(getExpr().getUnspecifiedType()) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "IntegralToFloatingPointConversion" } - - override string getSemanticConversionString() { - result = "integral to floating point conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "IntegralToFloatingPointConversion" } + + override string getSemanticConversionString() { result = "integral to floating point conversion" } } /** @@ -231,17 +224,17 @@ class PointerConversion extends Cast { isPointerOrNullPointer(getExpr().getUnspecifiedType()) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "PointerConversion" } - - override string getSemanticConversionString() { - result = "pointer conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "PointerConversion" } + + override string getSemanticConversionString() { result = "pointer conversion" } } /** * A conversion from one pointer-to-member type to another. The conversion * does not modify the value of the pointer-to-member. For pointer-to-member - * conversions involving casts between base and derived classes, see + * conversions involving casts between base and derived classes, see * `PointerToMemberBaseClassConversion` and `PointerToMemberDerivedClassConversion`. */ class PointerToMemberConversion extends Cast { @@ -261,11 +254,11 @@ class PointerToMemberConversion extends Cast { ) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "PointerToMemberConversion" } - - override string getSemanticConversionString() { - result = "pointer-to-member conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "PointerToMemberConversion" } + + override string getSemanticConversionString() { result = "pointer-to-member conversion" } } /** @@ -278,11 +271,11 @@ class PointerToIntegralConversion extends Cast { isPointerOrNullPointer(getExpr().getUnspecifiedType()) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "PointerToIntegralConversion" } - - override string getSemanticConversionString() { - result = "pointer to integral conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "PointerToIntegralConversion" } + + override string getSemanticConversionString() { result = "pointer to integral conversion" } } /** @@ -295,11 +288,11 @@ class IntegralToPointerConversion extends Cast { isIntegralOrEnum(getExpr().getUnspecifiedType()) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "IntegralToPointerConversion" } - - override string getSemanticConversionString() { - result = "integral to pointer conversion" + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "IntegralToPointerConversion" } + + override string getSemanticConversionString() { result = "integral to pointer conversion" } } /** @@ -307,15 +300,11 @@ class IntegralToPointerConversion extends Cast { * false, or nullptr. Returns `true` otherwise. */ class BoolConversion extends Cast { - BoolConversion() { - conversionkinds(underlyingElement(this), 1) - } + BoolConversion() { conversionkinds(underlyingElement(this), 1) } override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "BoolConversion" } - - override string getSemanticConversionString() { - result = "conversion to bool" - } + + override string getSemanticConversionString() { result = "conversion to bool" } } /** @@ -328,10 +317,8 @@ class VoidConversion extends Cast { } override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "VoidConversion" } - - override string getSemanticConversionString() { - result = "conversion to void" - } + + override string getSemanticConversionString() { result = "conversion to void" } } /** @@ -362,14 +349,14 @@ class InheritanceConversion extends Cast { * derived class. */ Class getBaseClass() { - none() // Overridden by subclasses + none() // Overridden by subclasses } /** * Gets the derived class of the conversion. */ Class getDerivedClass() { - none() // Overridden by subclasses + none() // Overridden by subclasses } } @@ -394,30 +381,22 @@ private Class getConversionClass(Expr expr) { * glvalue of a direct or virtual base class. */ class BaseClassConversion extends InheritanceConversion { - BaseClassConversion() { - conversionkinds(underlyingElement(this), 2) + BaseClassConversion() { conversionkinds(underlyingElement(this), 2) } + + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "BaseClassConversion" } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "BaseClassConversion" } - - override string getSemanticConversionString() { - result = "base class conversion" - } + override string getSemanticConversionString() { result = "base class conversion" } - override Class getBaseClass() { - result = getConversionClass(this) - } + override Class getBaseClass() { result = getConversionClass(this) } - override Class getDerivedClass() { - result = getConversionClass(getExpr()) - } + override Class getDerivedClass() { result = getConversionClass(getExpr()) } /** * Holds if this conversion is to a virtual base class. */ - predicate isVirtual() { - getDerivation().isVirtual() or not exists(getDerivation()) - } + predicate isVirtual() { getDerivation().isVirtual() or not exists(getDerivation()) } } /** @@ -425,23 +404,17 @@ class BaseClassConversion extends InheritanceConversion { * to a direct derived class. */ class DerivedClassConversion extends InheritanceConversion { - DerivedClassConversion() { - conversionkinds(underlyingElement(this), 3) + DerivedClassConversion() { conversionkinds(underlyingElement(this), 3) } + + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "DerivedClassConversion" } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "DerivedClassConversion" } + override string getSemanticConversionString() { result = "derived class conversion" } - override string getSemanticConversionString() { - result = "derived class conversion" - } + override Class getBaseClass() { result = getConversionClass(getExpr()) } - override Class getBaseClass() { - result = getConversionClass(getExpr()) - } - - override Class getDerivedClass() { - result = getConversionClass(this) - } + override Class getDerivedClass() { result = getConversionClass(this) } } /** @@ -449,12 +422,12 @@ class DerivedClassConversion extends InheritanceConversion { * of an immediate base class. */ class PointerToMemberBaseClassConversion extends Cast { - PointerToMemberBaseClassConversion() { - conversionkinds(underlyingElement(this), 4) + PointerToMemberBaseClassConversion() { conversionkinds(underlyingElement(this), 4) } + + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "PointerToMemberBaseClassConversion" } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "PointerToMemberBaseClassConversion" } - override string getSemanticConversionString() { result = "pointer-to-member base class conversion" } @@ -465,11 +438,11 @@ class PointerToMemberBaseClassConversion extends Cast { * of an immediate derived class. */ class PointerToMemberDerivedClassConversion extends Cast { - PointerToMemberDerivedClassConversion() { - conversionkinds(underlyingElement(this), 5) - } + PointerToMemberDerivedClassConversion() { conversionkinds(underlyingElement(this), 5) } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "PointerToMemberDerivedClassConversion" } + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "PointerToMemberDerivedClassConversion" + } override string getSemanticConversionString() { result = "pointer-to-member derived class conversion" @@ -482,15 +455,13 @@ class PointerToMemberDerivedClassConversion extends Cast { * derived classes, see `BaseClassConversion` and `DerivedClassConversion`. */ class GlvalueConversion extends Cast { - GlvalueConversion() { - conversionkinds(underlyingElement(this), 6) + GlvalueConversion() { conversionkinds(underlyingElement(this), 6) } + + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "GlvalueConversion" } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "GlvalueConversion" } - - override string getSemanticConversionString() { - result = "glvalue conversion" - } + override string getSemanticConversionString() { result = "glvalue conversion" } } /** @@ -508,15 +479,13 @@ class GlvalueConversion extends Cast { * to the reference. */ class PrvalueAdjustmentConversion extends Cast { - PrvalueAdjustmentConversion() { - conversionkinds(underlyingElement(this), 7) + PrvalueAdjustmentConversion() { conversionkinds(underlyingElement(this), 7) } + + override string getCanonicalQLClass() { + not exists(qlCast(this)) and result = "PrvalueAdjustmentConversion" } - override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "PrvalueAdjustmentConversion" } - - override string getSemanticConversionString() { - result = "prvalue adjustment conversion" - } + override string getSemanticConversionString() { result = "prvalue adjustment conversion" } } /** @@ -529,9 +498,7 @@ class DynamicCast extends Cast, @dynamic_cast { override string getCanonicalQLClass() { result = "DynamicCast" } - override string getSemanticConversionString() { - result = "dynamic_cast" - } + override string getSemanticConversionString() { result = "dynamic_cast" } } /** @@ -540,18 +507,15 @@ class DynamicCast extends Cast, @dynamic_cast { */ class UuidofOperator extends Expr, @uuidof { override string toString() { - if exists(getTypeOperand()) then - result = "__uuidof(" + getTypeOperand().getName() + ")" - else - result = "__uuidof(0)" + if exists(getTypeOperand()) + then result = "__uuidof(" + getTypeOperand().getName() + ")" + else result = "__uuidof(0)" } override int getPrecedence() { result = 15 } /** Gets the contained type. */ - Type getTypeOperand() { - uuidof_bind(underlyingElement(this), unresolveElement(result)) - } + Type getTypeOperand() { uuidof_bind(underlyingElement(this), unresolveElement(result)) } } /** @@ -571,7 +535,7 @@ class TypeidOperator extends Expr, @type_id { * printf("the type of ptr is: %s\n", typeid(ptr).name); * ``` */ - Type getResultType() { typeid_bind(underlyingElement(this),unresolveElement(result)) } + Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) } /** * DEPRECATED: Use `getResultType()` instead. @@ -592,12 +556,9 @@ class TypeidOperator extends Expr, @type_id { override int getPrecedence() { result = 16 } - override predicate mayBeImpure() { - this.getExpr().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getExpr().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } } /** @@ -611,12 +572,9 @@ class SizeofPackOperator extends Expr, @sizeof_pack { override string getCanonicalQLClass() { result = "SizeofPackOperator" } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -633,7 +591,7 @@ class SizeofExprOperator extends SizeofOperator { SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) } override string getCanonicalQLClass() { result = "SizeofExprOperator" } - + /** Gets the contained expression. */ Expr getExprOperand() { result = this.getChild(0) } @@ -641,29 +599,26 @@ class SizeofExprOperator extends SizeofOperator { * DEPRECATED: Use `getExprOperand()` instead * * Gets the contained expression. - * */ + */ deprecated Expr getExpr() { result = this.getExprOperand() } override string toString() { result = "sizeof()" } - override predicate mayBeImpure() { - this.getExprOperand().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getExprOperand().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() } } /** * A C/C++ sizeof expression whose operand is a type name. */ class SizeofTypeOperator extends SizeofOperator { - SizeofTypeOperator() { sizeof_bind(underlyingElement(this),_) } + SizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) } override string getCanonicalQLClass() { result = "SizeofTypeOperator" } /** Gets the contained type. */ - Type getTypeOperand() { sizeof_bind(underlyingElement(this),unresolveElement(result)) } + Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } /** * DEPRECATED: Use `getTypeOperand()` instead @@ -674,12 +629,9 @@ class SizeofTypeOperator extends SizeofOperator { override string toString() { result = "sizeof(" + this.getTypeOperand().getName() + ")" } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -712,10 +664,10 @@ class AlignofExprOperator extends AlignofOperator { * A C++11 `alignof` expression whose operand is a type name. */ class AlignofTypeOperator extends AlignofOperator { - AlignofTypeOperator() { sizeof_bind(underlyingElement(this),_) } + AlignofTypeOperator() { sizeof_bind(underlyingElement(this), _) } /** Gets the contained type. */ - Type getTypeOperand() { sizeof_bind(underlyingElement(this),unresolveElement(result)) } + Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) } /** * DEPRECATED: Use `getTypeOperand()` instead. @@ -733,13 +685,10 @@ class ArrayToPointerConversion extends Conversion, @array_to_pointer { override string toString() { result = "array to pointer conversion" } override string getCanonicalQLClass() { result = "ArrayToPointerConversion" } - - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -747,10 +696,14 @@ class ArrayToPointerConversion extends Conversion, @array_to_pointer { */ string qlCast(Cast cast) { // NB: Take care and include only leaf QL classes - cast instanceof CStyleCast and result = "CStyleCast" or - cast instanceof StaticCast and result = "StaticCast" or - cast instanceof DynamicCast and result = "DynamicCast" or - cast instanceof ConstCast and result = "ConstCast" or + cast instanceof CStyleCast and result = "CStyleCast" + or + cast instanceof StaticCast and result = "StaticCast" + or + cast instanceof DynamicCast and result = "DynamicCast" + or + cast instanceof ConstCast and result = "ConstCast" + or cast instanceof ReinterpretCast and result = "ReinterpretCast" } @@ -759,22 +712,40 @@ string qlCast(Cast cast) { */ string qlConversion(Cast cast) { // NB: Take care and include only leaf QL classes - cast instanceof IntegralConversion and result = "IntegralConversion" or - cast instanceof FloatingPointConversion and result = "FloatingPointConversion" or - cast instanceof FloatingPointToIntegralConversion and result = "FloatingPointToIntegralConversion" or - cast instanceof IntegralToFloatingPointConversion and result = "IntegralToFloatingPointConversion" or - cast instanceof PointerConversion and result = "PointerConversion" or - cast instanceof PointerToMemberConversion and result = "PointerToMemberConversion" or - cast instanceof PointerToIntegralConversion and result = "PointerToIntegralConversion" or - cast instanceof IntegralToPointerConversion and result = "IntegralToPointerConversion" or - cast instanceof BoolConversion and result = "BoolConversion" or - cast instanceof VoidConversion and result = "VoidConversion" or - cast instanceof BaseClassConversion and result = "BaseClassConversion" or - cast instanceof DerivedClassConversion and result = "DerivedClassConversion" or - cast instanceof PointerToMemberBaseClassConversion and result = "PointerToMemberBaseClassConversion" or - cast instanceof PointerToMemberDerivedClassConversion and result = "PointerToMemberDerivedClassConversion" or - cast instanceof GlvalueConversion and result = "GlvalueConversion" or - cast instanceof PrvalueAdjustmentConversion and result = "PrvalueAdjustmentConversion" or + cast instanceof IntegralConversion and result = "IntegralConversion" + or + cast instanceof FloatingPointConversion and result = "FloatingPointConversion" + or + cast instanceof FloatingPointToIntegralConversion and result = "FloatingPointToIntegralConversion" + or + cast instanceof IntegralToFloatingPointConversion and result = "IntegralToFloatingPointConversion" + or + cast instanceof PointerConversion and result = "PointerConversion" + or + cast instanceof PointerToMemberConversion and result = "PointerToMemberConversion" + or + cast instanceof PointerToIntegralConversion and result = "PointerToIntegralConversion" + or + cast instanceof IntegralToPointerConversion and result = "IntegralToPointerConversion" + or + cast instanceof BoolConversion and result = "BoolConversion" + or + cast instanceof VoidConversion and result = "VoidConversion" + or + cast instanceof BaseClassConversion and result = "BaseClassConversion" + or + cast instanceof DerivedClassConversion and result = "DerivedClassConversion" + or + cast instanceof PointerToMemberBaseClassConversion and + result = "PointerToMemberBaseClassConversion" + or + cast instanceof PointerToMemberDerivedClassConversion and + result = "PointerToMemberDerivedClassConversion" + or + cast instanceof GlvalueConversion and result = "GlvalueConversion" + or + cast instanceof PrvalueAdjustmentConversion and result = "PrvalueAdjustmentConversion" + or // treat dynamic_cast<...>(...) as a conversion cast instanceof DynamicCast and result = "DynamicCast" } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/ComparisonOperation.qll b/cpp/ql/src/semmle/code/cpp/exprs/ComparisonOperation.qll index aae9007303c..c8f1e215656 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/ComparisonOperation.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/ComparisonOperation.qll @@ -3,8 +3,7 @@ import semmle.code.cpp.exprs.Expr /** * A C/C++ comparison operation, that is, either an equality operation or a relational operation. */ -abstract class ComparisonOperation extends BinaryOperation { -} +abstract class ComparisonOperation extends BinaryOperation { } /** * A C/C++ equality operation, that is, either "==" or "!=". @@ -40,18 +39,12 @@ abstract class RelationalOperation extends ComparisonOperation { /** * DEPRECATED: Use `getGreaterOperand()` instead. */ - deprecated - Expr getLarge() { - result = getGreaterOperand() - } + deprecated Expr getLarge() { result = getGreaterOperand() } /** * DEPRECATED: Use `getLesserOperand()` instead. */ - deprecated - Expr getSmall() { - result = getLesserOperand() - } + deprecated Expr getSmall() { result = getLesserOperand() } /** * Gets the operand on the "greater" (or "greater-or-equal") side @@ -77,8 +70,9 @@ class GTExpr extends RelationalOperation, @gtexpr { override string getCanonicalQLClass() { result = "GTExpr" } override string getOperator() { result = ">" } - + override Expr getGreaterOperand() { result = getLeftOperand() } + override Expr getLesserOperand() { result = getRightOperand() } } @@ -91,6 +85,7 @@ class LTExpr extends RelationalOperation, @ltexpr { override string getOperator() { result = "<" } override Expr getGreaterOperand() { result = getRightOperand() } + override Expr getLesserOperand() { result = getLeftOperand() } } @@ -103,6 +98,7 @@ class GEExpr extends RelationalOperation, @geexpr { override string getOperator() { result = ">=" } override Expr getGreaterOperand() { result = getLeftOperand() } + override Expr getLesserOperand() { result = getRightOperand() } } @@ -115,5 +111,6 @@ class LEExpr extends RelationalOperation, @leexpr { override string getOperator() { result = "<=" } override Expr getGreaterOperand() { result = getRightOperand() } + override Expr getLesserOperand() { result = getLeftOperand() } } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index 7e9546b5616..63141d9d4a1 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -1,4 +1,3 @@ - import semmle.code.cpp.Element private import semmle.code.cpp.Enclosing private import semmle.code.cpp.internal.ResolveClass @@ -9,7 +8,7 @@ private import semmle.code.cpp.internal.AddressConstantExpression */ class Expr extends StmtParent, @expr { /** Gets the nth child of this expression. */ - Expr getChild(int n) { exprparents(unresolveElement(result),n,underlyingElement(this)) } + Expr getChild(int n) { exprparents(unresolveElement(result), n, underlyingElement(this)) } /** Gets the number of direct children of this expression. */ int getNumChild() { result = count(this.getAChild()) } @@ -21,29 +20,37 @@ class Expr extends StmtParent, @expr { Function getEnclosingFunction() { result = exprEnclosingElement(this) } /** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */ - Block getEnclosingBlock() { - result = getEnclosingStmt().getEnclosingBlock() - } + Block getEnclosingBlock() { result = getEnclosingStmt().getEnclosingBlock() } override Stmt getEnclosingStmt() { - result = this.getParent().(Expr).getEnclosingStmt() or - result = this.getParent().(Stmt) or - exists(Expr other | result = other.getEnclosingStmt() and other.getConversion() = this) or - exists(DeclStmt d, LocalVariable v | d.getADeclaration() = v and v.getInitializer().getExpr() = this and result = d) or - exists(ConditionDeclExpr cde, LocalVariable v | cde.getVariable() = v and v.getInitializer().getExpr() = this and result = cde.getEnclosingStmt()) + result = this.getParent().(Expr).getEnclosingStmt() + or + result = this.getParent().(Stmt) + or + exists(Expr other | result = other.getEnclosingStmt() and other.getConversion() = this) + or + exists(DeclStmt d, LocalVariable v | + d.getADeclaration() = v and v.getInitializer().getExpr() = this and result = d + ) + or + exists(ConditionDeclExpr cde, LocalVariable v | + cde.getVariable() = v and + v.getInitializer().getExpr() = this and + result = cde.getEnclosingStmt() + ) } /** Gets the enclosing variable of this expression, if any. */ Variable getEnclosingVariable() { result = exprEnclosingElement(this) } /** Gets a child of this expression. */ - Expr getAChild() { exists (int n | result = this.getChild(n)) } + Expr getAChild() { exists(int n | result = this.getChild(n)) } /** Gets the parent of this expression, if any. */ - Element getParent() { exprparents(underlyingElement(this),_,unresolveElement(result)) } + Element getParent() { exprparents(underlyingElement(this), _, unresolveElement(result)) } /** Gets the location of this expression. */ - override Location getLocation() { exprs(underlyingElement(this),_,result) } + override Location getLocation() { exprs(underlyingElement(this), _, result) } /** Holds if this is an auxiliary expression generated by the compiler. */ predicate isCompilerGenerated() { @@ -57,7 +64,9 @@ class Expr extends StmtParent, @expr { * As the type of an expression can sometimes be a TypedefType, calling getUnderlyingType() * is often more useful than calling this predicate. */ - pragma[nomagic] cached Type getType() { expr_types(underlyingElement(this),unresolveElement(result),_) } + pragma[nomagic] + cached + Type getType() { expr_types(underlyingElement(this), unresolveElement(result), _) } /** * Gets the type of this expression after typedefs have been resolved. @@ -79,17 +88,19 @@ class Expr extends StmtParent, @expr { * * DEPRECATED: use the subclasses of `Expr` rather than relying on this predicate. */ - deprecated int getKind() { exprs(underlyingElement(this),result,_) } + deprecated int getKind() { exprs(underlyingElement(this), result, _) } /** Gets a textual representation of this expression. */ override string toString() { none() } /** Gets the value of this expression, if it is a constant. */ - string getValue() { exists(@value v | values(v,result) and valuebind(v,underlyingElement(this))) } + string getValue() { + exists(@value v | values(v, result) and valuebind(v, underlyingElement(this))) + } /** Gets the value text of this expression that's in the database. */ private string getDbValueText() { - exists(@value v | valuebind(v,underlyingElement(this)) and valuetext(v, result)) + exists(@value v | valuebind(v, underlyingElement(this)) and valuetext(v, result)) } /** @@ -99,10 +110,12 @@ class Expr extends StmtParent, @expr { private string getValueTextFollowingConversions() { if exists(this.getDbValueText()) then result = this.getDbValueText() - else exists(Expr e | - e = this.getConversion() and - e.getValue() = this.getValue() and - result = e.getValueTextFollowingConversions()) + else + exists(Expr e | + e = this.getConversion() and + e.getValue() = this.getValue() and + result = e.getValueTextFollowingConversions() + ) } /** Gets the source text for the value of this expression, if it is a constant. */ @@ -111,11 +124,11 @@ class Expr extends StmtParent, @expr { then result = this.getValueTextFollowingConversions() else result = this.getValue() } - + /** Holds if this expression has a value that can be determined at compile time. */ cached predicate isConstant() { - valuebind(_,underlyingElement(this)) + valuebind(_, underlyingElement(this)) or addressConstantExpression(this) } @@ -129,17 +142,13 @@ class Expr extends StmtParent, @expr { * the usual definition of a 'pure' function because reading * from global state is permitted, just not writing / output. */ - final predicate isPure() { - not this.mayBeImpure() - } + final predicate isPure() { not this.mayBeImpure() } /** * Holds if it is possible that the expression may be impure. If we are not * sure, then it holds. */ - predicate mayBeImpure() { - any() - } + predicate mayBeImpure() { any() } /** * Holds if it is possible that the expression may be impure. If we are not @@ -149,18 +158,14 @@ class Expr extends StmtParent, @expr { * as a whole will have no side-effects, even if it mutates its own fresh * stack variables. */ - predicate mayBeGloballyImpure() { - any() - } + predicate mayBeGloballyImpure() { any() } /** * Holds if this expression is an lvalue. An lvalue is an expression that * represents a location, rather than a value. * See [basic.lval] for more about lvalues. */ - predicate isLValueCategory() { - expr_types(underlyingElement(this), _, 3) - } + predicate isLValueCategory() { expr_types(underlyingElement(this), _, 3) } /** * Holds if this expression is an xvalue. An xvalue is a location whose @@ -168,35 +173,27 @@ class Expr extends StmtParent, @expr { * call). * See [basic.lval] for more about xvalues. */ - predicate isXValueCategory() { - expr_types(underlyingElement(this), _, 2) - } + predicate isXValueCategory() { expr_types(underlyingElement(this), _, 2) } /** * Holds if this expression is a prvalue. A prvalue is an expression that * represents a value, rather than a location. * See [basic.lval] for more about prvalues. */ - predicate isPRValueCategory() { - expr_types(underlyingElement(this), _, 1) - } + predicate isPRValueCategory() { expr_types(underlyingElement(this), _, 1) } /** * Holds if this expression is a glvalue. A glvalue is either an lvalue or an * xvalue. */ - predicate isGLValueCategory() { - isLValueCategory() or isXValueCategory() - } + predicate isGLValueCategory() { isLValueCategory() or isXValueCategory() } /** * Holds if this expression is an rvalue. An rvalue is either a prvalue or an * xvalue. */ - predicate isRValueCategory() { - isPRValueCategory() or isXValueCategory() - } - + predicate isRValueCategory() { isPRValueCategory() or isXValueCategory() } + /** * Gets a string representation of the value category of the expression. * This is intended only for debugging. The possible values are: @@ -210,19 +207,15 @@ class Expr extends StmtParent, @expr { * `hasLValueToRvalueConversion()` holds. */ string getValueCategoryString() { - ( - isLValueCategory() and - result = "lvalue" - ) or ( - isXValueCategory() and - result = "xvalue" - ) or ( + isLValueCategory() and + result = "lvalue" + or + isXValueCategory() and + result = "xvalue" + or + ( isPRValueCategory() and - if hasLValueToRValueConversion() then - result = "prvalue(load)" - else - result = "prvalue" - + if hasLValueToRValueConversion() then result = "prvalue(load)" else result = "prvalue" ) } @@ -230,30 +223,32 @@ class Expr extends StmtParent, @expr { * Gets the parent of this expression, if any, in an alternative syntax tree * that has `Conversion`s as part of the tree. */ - Element getParentWithConversions() { convparents(this,_,result) } - + Element getParentWithConversions() { convparents(this, _, result) } + /** * Holds if this expression will not be evaluated because of its context, * such as an expression inside a sizeof. */ predicate isUnevaluated() { - exists (Element e | - e = getParentWithConversions+() | - e instanceof SizeofOperator or - exists ( Expr e2 | + exists(Element e | e = getParentWithConversions+() | + e instanceof SizeofOperator + or + exists(Expr e2 | e.(TypeidOperator).getExpr() = e2 and ( not e2.getFullyConverted().getUnspecifiedType().(Class).isPolymorphic() or not e2.isGLValueCategory() ) - ) or - e instanceof NoExceptExpr or + ) + or + e instanceof NoExceptExpr + or e instanceof AlignofOperator - ) or exists (Decltype d | - d.getExpr() = getParentWithConversions*() ) + or + exists(Decltype d | d.getExpr() = getParentWithConversions*()) } - + /** * Holds if this expression has undergone an lvalue-to-rvalue conversion to * extract its value. @@ -268,9 +263,7 @@ class Expr extends StmtParent, @expr { * * See [conv.lval] for more about the lvalue-to-rvalue conversion */ - predicate hasLValueToRValueConversion() { - expr_isload(underlyingElement(this)) - } + predicate hasLValueToRValueConversion() { expr_isload(underlyingElement(this)) } /** * Holds if this expression is an LValue, in the sense of having an address. @@ -292,7 +285,7 @@ class Expr extends StmtParent, @expr { this.(ParenthesisExpr).getExpr().isLValue() or // C++ n3337 - 5.1.1 clauses 8 and 9, variables and data members - (this instanceof VariableAccess and not this instanceof FieldAccess) + this instanceof VariableAccess and not this instanceof FieldAccess or // C++ n3337 - 5.1.1 clauses 8 and 9, functions exists(FunctionAccess fa | fa = this | @@ -346,9 +339,7 @@ class Expr extends StmtParent, @expr { * Gets the precedence of the main operator of this expression; * higher precedence binds tighter. */ - int getPrecedence() { - none() - } + int getPrecedence() { none() } /** * Holds if this expression has a conversion. @@ -366,33 +357,47 @@ class Expr extends StmtParent, @expr { * and 1 has a bool conversion, while the bool conversion itself has * an int conversion. */ - predicate hasConversion() { exists(Expr e | exprconv(underlyingElement(this),unresolveElement(e))) } + predicate hasConversion() { + exists(Expr e | exprconv(underlyingElement(this), unresolveElement(e))) + } /** * Holds if this expression has an implicit conversion. - * + * * For example in `char *str = 0`, the `0` has an implicit conversion to type `char *`. */ - predicate hasImplicitConversion() { exists(Expr e | exprconv(underlyingElement(this),unresolveElement(e)) and e.(Cast).isImplicit()) } + predicate hasImplicitConversion() { + exists(Expr e | + exprconv(underlyingElement(this), unresolveElement(e)) and e.(Cast).isImplicit() + ) + } /** * Holds if this expression has an explicit conversion. - * + * * For example in `(MyClass *)ptr`, the `ptr` has an explicit * conversion to type `MyClass *`. */ - predicate hasExplicitConversion() { exists(Expr e | exprconv(underlyingElement(this),unresolveElement(e)) and not e.(Cast).isImplicit()) } + predicate hasExplicitConversion() { + exists(Expr e | + exprconv(underlyingElement(this), unresolveElement(e)) and not e.(Cast).isImplicit() + ) + } /** * Gets the conversion associated with this expression, if any. */ - Expr getConversion() { exprconv(underlyingElement(this),unresolveElement(result)) } + Expr getConversion() { exprconv(underlyingElement(this), unresolveElement(result)) } /** * Gets a string describing the conversion associated with this expression, * or "" if there is none. */ - string getConversionString() { (result = this.getConversion().toString() and this.hasConversion()) or (result = "" and not this.hasConversion()) } + string getConversionString() { + result = this.getConversion().toString() and this.hasConversion() + or + result = "" and not this.hasConversion() + } /** Gets the fully converted form of this expression, including all type casts and other conversions. */ cached @@ -428,12 +433,11 @@ class Expr extends StmtParent, @expr { * up to (but not including) the first explicit cast (if any). */ Expr getImplicitlyConverted() { - if this.hasImplicitConversion() then - result = this.getConversion().getImplicitlyConverted() - else - result = this + if this.hasImplicitConversion() + then result = this.getConversion().getImplicitlyConverted() + else result = this } - + /** * Gets the type of this expression, after any implicit conversions and explicit casts, and after resolving typedefs. * @@ -441,17 +445,13 @@ class Expr extends StmtParent, @expr { * contains three expressions: two CStyleCasts and one literal Zero. For all three expressions, the result of this * predicate will be `long long`. */ - Type getActualType() { - result = this.getFullyConverted().getType().getUnderlyingType() - } + Type getActualType() { result = this.getFullyConverted().getType().getUnderlyingType() } /** Holds if this expression is parenthesised. */ predicate isParenthesised() { this.getConversion() instanceof ParenthesisExpr } /** Gets the function containing this control-flow node. */ - override Function getControlFlowScope() { - result = this.getEnclosingFunction() - } + override Function getControlFlowScope() { result = this.getEnclosingFunction() } } /** @@ -462,9 +462,7 @@ abstract class Operation extends Expr { abstract string getOperator(); /** Gets an operand of this operation. */ - Expr getAnOperand() { - result = this.getAChild() - } + Expr getAnOperand() { result = this.getAChild() } } /** @@ -472,16 +470,13 @@ abstract class Operation extends Expr { */ abstract class UnaryOperation extends Operation { /** Gets the operand of this unary operation. */ - Expr getOperand() { this.hasChild(result,0) } + Expr getOperand() { this.hasChild(result, 0) } override string toString() { result = this.getOperator() + " ..." } - override predicate mayBeImpure() { - this.getOperand().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getOperand().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getOperand().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getOperand().mayBeGloballyImpure() } } /** @@ -489,10 +484,10 @@ abstract class UnaryOperation extends Operation { */ abstract class BinaryOperation extends Operation { /** Gets the left operand of this binary operation. */ - Expr getLeftOperand() { this.hasChild(result,0) } + Expr getLeftOperand() { this.hasChild(result, 0) } /** Gets the right operand of this binary operation. */ - Expr getRightOperand() { this.hasChild(result,1) } + Expr getRightOperand() { this.hasChild(result, 1) } override string toString() { result = "... " + this.getOperator() + " ..." } @@ -500,6 +495,7 @@ abstract class BinaryOperation extends Operation { this.getLeftOperand().mayBeImpure() or this.getRightOperand().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getLeftOperand().mayBeGloballyImpure() or this.getRightOperand().mayBeGloballyImpure() @@ -521,7 +517,7 @@ class ParenthesizedBracedInitializerList extends Expr, @braced_init_list { /** * A C/C++ parenthesis expression. -*/ + */ class ParenthesisExpr extends Conversion, @parexpr { override string toString() { result = "(...)" } @@ -549,17 +545,17 @@ class AssumeExpr extends Expr, @assume { */ class CommaExpr extends Expr, @commaexpr { override string getCanonicalQLClass() { result = "CommaExpr" } - + /** * Gets the left operand, which is the one whose value is discarded. */ - Expr getLeftOperand() { this.hasChild(result,0) } + Expr getLeftOperand() { this.hasChild(result, 0) } /** * Gets the right operand, which is the one whose value is equal to the value * of the comma expression itself. */ - Expr getRightOperand() { this.hasChild(result,1) } + Expr getRightOperand() { this.hasChild(result, 1) } override string toString() { result = "... , ..." } @@ -569,6 +565,7 @@ class CommaExpr extends Expr, @commaexpr { this.getLeftOperand().mayBeImpure() or this.getRightOperand().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getLeftOperand().mayBeGloballyImpure() or this.getRightOperand().mayBeGloballyImpure() @@ -580,24 +577,22 @@ class CommaExpr extends Expr, @commaexpr { */ class AddressOfExpr extends UnaryOperation, @address_of { override string getCanonicalQLClass() { result = "AddressOfExpr" } - + /** Gets the function or variable whose address is taken. */ Declaration getAddressable() { - result = this.getOperand().(Access).getTarget() - // this handles the case where we are taking the address of a reference variable - or result = this.getOperand().(ReferenceDereferenceExpr).getChild(0).(Access).getTarget() + result = this.getOperand().(Access).getTarget() + or + // this handles the case where we are taking the address of a reference variable + result = this.getOperand().(ReferenceDereferenceExpr).getChild(0).(Access).getTarget() } override string getOperator() { result = "&" } override int getPrecedence() { result = 15 } - override predicate mayBeImpure() { - this.getOperand().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getOperand().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getOperand().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getOperand().mayBeGloballyImpure() } } /** @@ -611,7 +606,7 @@ class ReferenceToExpr extends Conversion, @reference_to { override string toString() { result = "(reference to)" } override string getCanonicalQLClass() { result = "ReferenceToExpr" } - + override int getPrecedence() { result = 15 } } @@ -622,15 +617,13 @@ class ReferenceToExpr extends Conversion, @reference_to { */ class PointerDereferenceExpr extends UnaryOperation, @indirect { override string getCanonicalQLClass() { result = "PointerDereferenceExpr" } - + /** * DEPRECATED: Use getOperand() instead. * * Gets the expression that is being dereferenced. */ - deprecated Expr getExpr() { - result = getOperand() - } + deprecated Expr getExpr() { result = getOperand() } override string getOperator() { result = "*" } @@ -640,6 +633,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect { this.getChild(0).mayBeImpure() or this.getChild(0).getFullyConverted().getType().(DerivedType).getBaseType().isVolatile() } + override predicate mayBeGloballyImpure() { this.getChild(0).mayBeGloballyImpure() or this.getChild(0).getFullyConverted().getType().(DerivedType).getBaseType().isVolatile() @@ -668,17 +662,13 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { /** * Gets the `operator new` or `operator new[]` that allocates storage. */ - Function getAllocator() { - expr_allocator(underlyingElement(this), unresolveElement(result), _) - } + Function getAllocator() { expr_allocator(underlyingElement(this), unresolveElement(result), _) } /** * Holds if the allocation function is the version that expects an alignment * argument of type `std::align_val_t`. */ - predicate hasAlignedAllocation() { - expr_allocator(underlyingElement(this), _, 1) - } + predicate hasAlignedAllocation() { expr_allocator(underlyingElement(this), _, 1) } /** * Gets the alignment argument passed to the allocation function, if any. @@ -688,7 +678,8 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { ( // If we have an allocator call, the alignment is the second argument to // that call. - result = getAllocatorCall().getArgument(1) or + result = getAllocatorCall().getArgument(1) + or // Otherwise, the alignment winds up as child number 3 of the `new` // itself. result = getChild(3) @@ -721,7 +712,7 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { predicate hasSizedDeallocation() { exists(int form | expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(1) != 0 // Bit zero is the "size" bit + form.bitAnd(1) != 0 // Bit zero is the "size" bit ) } @@ -731,7 +722,7 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { predicate hasAlignedDeallocation() { exists(int form | expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(2) != 0 // Bit one is the "alignment" bit + form.bitAnd(2) != 0 // Bit one is the "alignment" bit ) } @@ -761,7 +752,7 @@ class NewExpr extends NewOrNewArrayExpr, @new_expr { override string toString() { result = "new" } override string getCanonicalQLClass() { result = "NewExpr" } - + /** * Gets the type that is being allocated. * @@ -787,7 +778,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr { override string toString() { result = "new[]" } override string getCanonicalQLClass() { result = "NewArrayExpr" } - + /** * Gets the type that is being allocated. * @@ -832,14 +823,19 @@ class DeleteExpr extends Expr, @delete_expr { override string toString() { result = "delete" } override string getCanonicalQLClass() { result = "DeleteExpr" } - + override int getPrecedence() { result = 15 } /** * Gets the compile-time type of the object being deleted. */ Type getDeletedObjectType() { - result = getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() + result = getExpr() + .getFullyConverted() + .getType() + .stripTopLevelSpecifiers() + .(PointerType) + .getBaseType() } /** @@ -868,7 +864,7 @@ class DeleteExpr extends Expr, @delete_expr { predicate hasSizedDeallocation() { exists(int form | expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(1) != 0 // Bit zero is the "size" bit + form.bitAnd(1) != 0 // Bit zero is the "size" bit ) } @@ -878,11 +874,11 @@ class DeleteExpr extends Expr, @delete_expr { predicate hasAlignedDeallocation() { exists(int form | expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(2) != 0 // Bit one is the "alignment" bit + form.bitAnd(2) != 0 // Bit one is the "alignment" bit ) } -/** + /** * Gets the call to a non-default `operator delete` that deallocates storage, if any. * * This will only be present when the type being deleted has a custom `operator delete`. @@ -902,14 +898,19 @@ class DeleteArrayExpr extends Expr, @delete_array_expr { override string toString() { result = "delete[]" } override string getCanonicalQLClass() { result = "DeleteArrayExpr" } - + override int getPrecedence() { result = 15 } /** * Gets the element type of the array being deleted. */ Type getDeletedElementType() { - result = getExpr().getFullyConverted().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() + result = getExpr() + .getFullyConverted() + .getType() + .stripTopLevelSpecifiers() + .(PointerType) + .getBaseType() } /** @@ -938,7 +939,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr { predicate hasSizedDeallocation() { exists(int form | expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(1) != 0 // Bit zero is the "size" bit + form.bitAnd(1) != 0 // Bit zero is the "size" bit ) } @@ -948,7 +949,7 @@ class DeleteArrayExpr extends Expr, @delete_array_expr { predicate hasAlignedDeallocation() { exists(int form | expr_deallocator(underlyingElement(this), _, form) and - form.bitAnd(2) != 0 // Bit one is the "alignment" bit + form.bitAnd(2) != 0 // Bit one is the "alignment" bit ) } @@ -986,9 +987,7 @@ class StmtExpr extends Expr, @expr_stmt { * x = ({ dosomething(); a+b; }); * ``` */ - Expr getResultExpr() { - result = getStmtResultExpr(getStmt()) - } + Expr getResultExpr() { result = getStmtResultExpr(getStmt()) } } /** Get the result expression of a statement. (Helper function for StmtExpr.) */ @@ -1004,13 +1003,10 @@ class ThisExpr extends Expr, @thisaccess { override string toString() { result = "this" } override string getCanonicalQLClass() { result = "ThisExpr" } - - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -1020,18 +1016,14 @@ class ThisExpr extends Expr, @thisaccess { * branch of GCC. */ class BlockExpr extends Literal { - BlockExpr() { - code_block(underlyingElement(this), _) - } + BlockExpr() { code_block(underlyingElement(this), _) } override string toString() { result = "^ { ... }" } /** * Gets the (anonymous) function associated with this code block expression. */ - Function getFunction() { - code_block(underlyingElement(this), unresolveElement(result)) - } + Function getFunction() { code_block(underlyingElement(this), unresolveElement(result)) } } /** @@ -1041,13 +1033,11 @@ class NoExceptExpr extends Expr, @noexceptexpr { override string toString() { result = "noexcept(...)" } override string getCanonicalQLClass() { result = "NoExceptExpr" } - + /** * Gets the expression inside this noexcept expression. */ - Expr getExpr() { - result = this.getChild(0) - } + Expr getExpr() { result = this.getChild(0) } } /** diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Lambda.qll b/cpp/ql/src/semmle/code/cpp/exprs/Lambda.qll index b2517b2eaf6..f634d9239b3 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Lambda.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Lambda.qll @@ -13,18 +13,14 @@ import semmle.code.cpp.Class * The type given by `getType()` will be an instance of `Closure`. */ class LambdaExpression extends Expr, @lambdaexpr { - override string toString() { - result = "[...](...){...}" - } + override string toString() { result = "[...](...){...}" } override string getCanonicalQLClass() { result = "LambdaExpression" } /** * Gets an implicitly or explicitly captured value of this lambda expression. */ - LambdaCapture getACapture() { - result = getCapture(_) - } + LambdaCapture getACapture() { result = getCapture(_) } /** * Gets the nth implicitly or explicitly captured value of this lambda expression. @@ -41,16 +37,12 @@ class LambdaExpression extends Expr, @lambdaexpr { * - "&" if capture-by-reference is the default for implicit captures. * - "=" if capture-by-value is the default for implicit captures. */ - string getDefaultCaptureMode() { - lambdas(underlyingElement(this), result, _) - } + string getDefaultCaptureMode() { lambdas(underlyingElement(this), result, _) } /** * Holds if the return type (of the call operator of the resulting object) was explicitly specified. */ - predicate returnTypeIsExplicit() { - lambdas(underlyingElement(this), _, true) - } + predicate returnTypeIsExplicit() { lambdas(underlyingElement(this), _, true) } /** * Gets the function which will be invoked when the resulting object is called. @@ -62,17 +54,13 @@ class LambdaExpression extends Expr, @lambdaexpr { * - The return type. * - The statements comprising the lambda body. */ - Operator getLambdaFunction() { - result = getType().(Closure).getLambdaFunction() - } + Operator getLambdaFunction() { result = getType().(Closure).getLambdaFunction() } /** * Gets the initializer that initializes the captured variables in the closure, if any. * A lambda that does not capture any variables will not have an initializer. */ - ClassAggregateLiteral getInitializer() { - result = getChild(0) - } + ClassAggregateLiteral getInitializer() { result = getChild(0) } } /** @@ -85,26 +73,20 @@ class LambdaExpression extends Expr, @lambdaexpr { * ``` */ class Closure extends Class { - Closure() { - exists(LambdaExpression e | this = e.getType()) - } + Closure() { exists(LambdaExpression e | this = e.getType()) } override string getCanonicalQLClass() { result = "Closure" } /** Gets the lambda expression of which this is the type. */ - LambdaExpression getLambdaExpression() { - result.getType() = this - } + LambdaExpression getLambdaExpression() { result.getType() = this } /** Gets the compiler-generated operator() of this closure type. */ Operator getLambdaFunction() { - result = this.getAMember() - and result.getName() = "operator()" + result = this.getAMember() and + result.getName() = "operator()" } - override string toString() { - result = "decltype([...](...){...})" - } + override string toString() { result = "decltype([...](...){...})" } } /** @@ -117,18 +99,14 @@ class Closure extends Class { * ``` */ class LambdaCapture extends Locatable, @lambdacapture { - override string toString() { - result = getField().toString() - } + override string toString() { result = getField().toString() } override string getCanonicalQLClass() { result = "LambdaCapture" } /** * Holds if this capture was made implicitly. */ - predicate isImplicit() { - lambda_capture(this, _, _, _, _, true, _) - } + predicate isImplicit() { lambda_capture(this, _, _, _, _, true, _) } /** * Holds if the variable was captured by reference. @@ -139,9 +117,7 @@ class LambdaCapture extends Locatable, @lambdacapture { * - The identifier is "this". [Said behaviour is dictated by the C++11 standard, but it * is actually "*this" being captured rather than "this".] */ - predicate isCapturedByReference() { - lambda_capture(this, _, _, _, true, _, _) - } + predicate isCapturedByReference() { lambda_capture(this, _, _, _, true, _, _) } /** * Gets the location of the declaration of this capture. @@ -151,16 +127,12 @@ class LambdaCapture extends Locatable, @lambdacapture { * For implicit captures, this is the first location within the "{...}" part of the lambda * expression which accesses the captured variable. */ - override Location getLocation() { - lambda_capture(this, _, _, _, _, _, result) - } + override Location getLocation() { lambda_capture(this, _, _, _, _, _, result) } /** * Gets the field of the lambda expression's closure type which is used to store this capture. */ - MemberVariable getField() { - lambda_capture(this, _, _, result, _, _, _) - } + MemberVariable getField() { lambda_capture(this, _, _, result, _, _, _) } /** * Gets the expression which yields the final captured value. diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Literal.qll b/cpp/ql/src/semmle/code/cpp/exprs/Literal.qll index 45435ab5b89..f8d2b56190d 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Literal.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Literal.qll @@ -6,47 +6,39 @@ import semmle.code.cpp.exprs.Expr class Literal extends Expr, @literal { /** Gets a textual representation of this literal. */ override string toString() { - result = this.getValue() or - ( - not exists(this.getValue()) and - result = "Unknown literal" - ) + result = this.getValue() + or + not exists(this.getValue()) and + result = "Unknown literal" } override string getCanonicalQLClass() { result = "Literal" } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** * A label literal, that is, a use of the '&&' operator to take the address of a * label for use in a computed goto statement. This is a non-standard C/C++ extension. - * + * * For example: * ``` * void *label_ptr = &&myLabel; // &&myLabel is a LabelLiteral - * + * * goto *label_ptr; // this is a ComputedGotoStmt - * + * * myLabel: // this is a LabelStmt * ``` */ class LabelLiteral extends Literal { - LabelLiteral() { - jumpinfo(underlyingElement(this),_,_) - } + LabelLiteral() { jumpinfo(underlyingElement(this), _, _) } override string getCanonicalQLClass() { result = "LabelLiteral" } /** Gets the corresponding label statement. */ - LabelStmt getLabel() { - jumpinfo(underlyingElement(this),_,unresolveElement(result)) - } + LabelStmt getLabel() { jumpinfo(underlyingElement(this), _, unresolveElement(result)) } } /** A character literal or a string literal. */ @@ -68,10 +60,9 @@ abstract class TextLiteral extends Literal { string getANonStandardEscapeSequence(int occurrence, int offset) { // Find all single character escape sequences (ignoring the start of octal escape sequences), // together with anything starting like a hex escape sequence but not followed by a hex digit. - result = getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) - + result = getValueText().regexpFind("\\\\[^x0-7\\s]|\\\\x[^0-9a-fA-F]", occurrence, offset) and // From these, exclude all standard escape sequences. - and not(result = getAStandardEscapeSequence(_,_)) + not result = getAStandardEscapeSequence(_, _) } /** Gets a simple escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */ @@ -81,43 +72,35 @@ abstract class TextLiteral extends Literal { /** Gets a standard escape sequence that appears in the char or string literal (see [lex.ccon] in the C++ Standard). */ string getAStandardEscapeSequence(int occurrence, int offset) { - result = getASimpleEscapeSequence(occurrence, offset) - or result = getAnOctalEscapeSequence(occurrence, offset) - or result = getAHexEscapeSequence(occurrence, offset) + result = getASimpleEscapeSequence(occurrence, offset) or + result = getAnOctalEscapeSequence(occurrence, offset) or + result = getAHexEscapeSequence(occurrence, offset) } /** * Gets the length of the string literal (including null) before escape sequences added by the extractor. */ - int getOriginalLength() - { - result = getValue().length() + 1 - } + int getOriginalLength() { result = getValue().length() + 1 } } /** * A character literal, for example `'a'` or `L'a'`. */ class CharLiteral extends TextLiteral { - CharLiteral() { - this.getValueText().regexpMatch("(?s)\\s*L?'.*") - } + CharLiteral() { this.getValueText().regexpMatch("(?s)\\s*L?'.*") } override string getCanonicalQLClass() { result = "CharLiteral" } /** * Gets the character of this literal. For example `L'a'` has character `"a"`. */ - string getCharacter() { - result = this.getValueText().regexpCapture("(?s)\\s*L?'(.*)'", 1) - } + string getCharacter() { result = this.getValueText().regexpCapture("(?s)\\s*L?'(.*)'", 1) } } /** * A string literal, for example `"abcdef"` or `L"123456"`. */ -class StringLiteral extends TextLiteral -{ +class StringLiteral extends TextLiteral { StringLiteral() { this.getType() instanceof ArrayType // Note that `AggregateLiteral`s can also have an array type, but they derive from @@ -125,16 +108,13 @@ class StringLiteral extends TextLiteral } override string getCanonicalQLClass() { result = "StringLiteral" } - } /** * An octal literal. */ class OctalLiteral extends Literal { - OctalLiteral() { - super.getValueText().regexpMatch("\\s*0[0-7]+[uUlL]*\\s*") - } + OctalLiteral() { super.getValueText().regexpMatch("\\s*0[0-7]+[uUlL]*\\s*") } override string getCanonicalQLClass() { result = "OctalLiteral" } } @@ -143,19 +123,16 @@ class OctalLiteral extends Literal { * A hexadecimal literal. */ class HexLiteral extends Literal { - HexLiteral() { - super.getValueText().regexpMatch("\\s*0[xX][0-9a-fA-F]+[uUlL]*\\s*") - } + HexLiteral() { super.getValueText().regexpMatch("\\s*0[xX][0-9a-fA-F]+[uUlL]*\\s*") } override string getCanonicalQLClass() { result = "HexLiteral" } } /** * A C/C++ aggregate literal. -*/ + */ class AggregateLiteral extends Expr, @aggregateliteral { // if this is turned into a Literal we need to change mayBeImpure - override string getCanonicalQLClass() { result = "AggregateLiteral" } /** @@ -178,9 +155,7 @@ class AggregateLiteral extends Expr, @aggregateliteral { class ClassAggregateLiteral extends AggregateLiteral { Class classType; - ClassAggregateLiteral() { - classType = this.getUnspecifiedType() - } + ClassAggregateLiteral() { classType = this.getUnspecifiedType() } override string getCanonicalQLClass() { result = "ClassAggregateLiteral" } @@ -190,8 +165,7 @@ class ClassAggregateLiteral extends AggregateLiteral { */ Expr getFieldExpr(Field field) { field = classType.getAField() and - aggregate_field_init(underlyingElement(this), unresolveElement(result), - unresolveElement(field)) + aggregate_field_init(underlyingElement(this), unresolveElement(result), unresolveElement(field)) } /** @@ -205,16 +179,16 @@ class ClassAggregateLiteral extends AggregateLiteral { ( // If the field has an explicit initializer expression, then the field is // initialized. - exists(getFieldExpr(field)) or + exists(getFieldExpr(field)) + or // If the type is not a union, all fields without initializers are value // initialized. - not classType instanceof Union or + not classType instanceof Union + or // If the type is a union, and there are no explicit initializers, then // the first declared field is value initialized. - ( - not exists(getAChild()) and - field.getInitializationOrder() = 0 - ) + not exists(getAChild()) and + field.getInitializationOrder() = 0 ) } @@ -251,24 +225,19 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral { * Gets the number of elements initialized by this initializer list, either explicitly with an * expression, or by implicit value initialization. */ - int getArraySize() { - none() - } + int getArraySize() { none() } /** * Gets the type of the elements in the initializer list. */ - Type getElementType() { - none() - } + Type getElementType() { none() } /** * Gets the expression within the aggregate literal that is used to initialize * element `elementIndex`, if present. */ Expr getElementExpr(int elementIndex) { - aggregate_array_init(underlyingElement(this), unresolveElement(result), - elementIndex) + aggregate_array_init(underlyingElement(this), unresolveElement(result), elementIndex) } /** @@ -303,19 +272,13 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral { class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral { ArrayType arrayType; - ArrayAggregateLiteral() { - arrayType = this.getUnspecifiedType() - } + ArrayAggregateLiteral() { arrayType = this.getUnspecifiedType() } override string getCanonicalQLClass() { result = "ArrayAggregateLiteral" } - override int getArraySize() { - result = arrayType.getArraySize() - } + override int getArraySize() { result = arrayType.getArraySize() } - override Type getElementType() { - result = arrayType.getBaseType() - } + override Type getElementType() { result = arrayType.getBaseType() } } /** @@ -324,17 +287,11 @@ class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral { class VectorAggregateLiteral extends ArrayOrVectorAggregateLiteral { GNUVectorType vectorType; - VectorAggregateLiteral() { - vectorType = this.getUnspecifiedType() - } + VectorAggregateLiteral() { vectorType = this.getUnspecifiedType() } override string getCanonicalQLClass() { result = "VectorAggregateLiteral" } - override int getArraySize() { - result = vectorType.getNumElements() - } + override int getArraySize() { result = vectorType.getNumElements() } - override Type getElementType() { - result = vectorType.getBaseType() - } + override Type getElementType() { result = vectorType.getBaseType() } } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/LogicalOperation.qll b/cpp/ql/src/semmle/code/cpp/exprs/LogicalOperation.qll index 66caabaa4c4..902aab6358a 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/LogicalOperation.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/LogicalOperation.qll @@ -3,8 +3,7 @@ import semmle.code.cpp.exprs.Expr /** * A C/C++ unary logical operation. */ -abstract class UnaryLogicalOperation extends UnaryOperation { -} +abstract class UnaryLogicalOperation extends UnaryOperation { } /** * A C/C++ logical not expression. @@ -13,7 +12,7 @@ class NotExpr extends UnaryLogicalOperation, @notexpr { override string getOperator() { result = "!" } override string getCanonicalQLClass() { result = "NotExpr" } - + override int getPrecedence() { result = 15 } } @@ -30,7 +29,8 @@ abstract class BinaryLogicalOperation extends BinaryOperation { * x && y * ``` * is true, `x` and `y` must also be true, so `impliesValue(x, true, true)` and - * `impliesValue(y, true, true)` hold. */ + * `impliesValue(y, true, true)` hold. + */ abstract predicate impliesValue(Expr part, boolean partIsTrue, boolean wholeIsTrue); } @@ -41,13 +41,14 @@ class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr { override string getOperator() { result = "&&" } override string getCanonicalQLClass() { result = "LogicalAndExpr" } - + override int getPrecedence() { result = 5 } override predicate impliesValue(Expr part, boolean partIsTrue, boolean wholeIsTrue) { wholeIsTrue = true and partIsTrue = true and part = this.getAnOperand() or - wholeIsTrue = true and this.getAnOperand().(BinaryLogicalOperation).impliesValue(part, partIsTrue, true) + wholeIsTrue = true and + this.getAnOperand().(BinaryLogicalOperation).impliesValue(part, partIsTrue, true) } } @@ -58,13 +59,14 @@ class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr { override string getOperator() { result = "||" } override string getCanonicalQLClass() { result = "LogicalOrExpr" } - + override int getPrecedence() { result = 4 } override predicate impliesValue(Expr part, boolean partIsTrue, boolean wholeIsTrue) { wholeIsTrue = false and partIsTrue = false and part = this.getAnOperand() or - wholeIsTrue = false and this.getAnOperand().(BinaryLogicalOperation).impliesValue(part, partIsTrue, false) + wholeIsTrue = false and + this.getAnOperand().(BinaryLogicalOperation).impliesValue(part, partIsTrue, false) } } @@ -73,12 +75,10 @@ class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr { */ class ConditionalExpr extends Operation, @conditionalexpr { /** Gets the condition of this conditional expression. */ - Expr getCondition() { - expr_cond_guard(underlyingElement(this), unresolveElement(result)) - } + Expr getCondition() { expr_cond_guard(underlyingElement(this), unresolveElement(result)) } override string getCanonicalQLClass() { result = "ConditionalExpr" } - + /** Gets the 'then' expression of this conditional expression. */ Expr getThen() { if this.isTwoOperand() @@ -87,20 +87,16 @@ class ConditionalExpr extends Operation, @conditionalexpr { } /** Gets the 'else' expression of this conditional expression. */ - Expr getElse() { - expr_cond_false(underlyingElement(this), unresolveElement(result)) - } + Expr getElse() { expr_cond_false(underlyingElement(this), unresolveElement(result)) } /** * Holds if this expression used the two operand form `guard ? : false`. */ - predicate isTwoOperand() { - expr_cond_two_operand(underlyingElement(this)) - } + predicate isTwoOperand() { expr_cond_two_operand(underlyingElement(this)) } override string getOperator() { result = "?" } - override string toString() { result = "... ? ... : ..." } + override string toString() { result = "... ? ... : ..." } override int getPrecedence() { result = 3 } @@ -109,6 +105,7 @@ class ConditionalExpr extends Operation, @conditionalexpr { this.getThen().mayBeImpure() or this.getElse().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getCondition().mayBeGloballyImpure() or this.getThen().mayBeGloballyImpure() or diff --git a/cpp/ql/src/semmle/code/cpp/exprs/ObjectiveC.qll b/cpp/ql/src/semmle/code/cpp/exprs/ObjectiveC.qll index a64d1815fba..61699023f8f 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/ObjectiveC.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/ObjectiveC.qll @@ -10,9 +10,7 @@ private import semmle.code.cpp.internal.ResolveClass deprecated class MessageExpr extends Expr, Call { MessageExpr() { none() } - override string toString() { - none() - } + override string toString() { none() } /** * Gets the selector of this message expression, for example `-changeColorToRed:green:blue:`. @@ -29,16 +27,12 @@ deprecated class MessageExpr extends Expr, Call { * In all cases, actual function dispatch isn't performed until runtime, but the * lack of a static target is often cause for concern. */ - MemberFunction getStaticTarget() { - none() - } + MemberFunction getStaticTarget() { none() } /** * Provided for compatibility with Call. It is the same as the static target. */ - override MemberFunction getTarget() { - none() - } + override MemberFunction getTarget() { none() } /** * Holds if the compiler could infer a function as the target of this message. @@ -46,9 +40,7 @@ deprecated class MessageExpr extends Expr, Call { * In all cases, actual function dispatch isn't performed until runtime, but the * lack of a static target is often cause for concern. */ - predicate hasStaticTarget() { - none() - } + predicate hasStaticTarget() { none() } /** * Gets the number of arguments passed by this message expression. @@ -61,18 +53,14 @@ deprecated class MessageExpr extends Expr, Call { /** * Gets an argument passed by this message expression. */ - override Expr getAnArgument() { - none() - } + override Expr getAnArgument() { none() } /** * Gets the nth argument passed by this message expression. * * The range of `n` is [`0` .. `getNumberOfArguments()`]. */ - override Expr getArgument(int n) { - none() - } + override Expr getArgument(int n) { none() } override int getPrecedence() { none() } } @@ -111,9 +99,7 @@ deprecated class ExprMessageExpr extends MessageExpr { /** * Gets the expression which gives the receiver of this message. */ - Expr getReceiver() { - none() - } + Expr getReceiver() { none() } /** * Gets the Objective C class of which the receiving expression is an instance. @@ -122,9 +108,7 @@ deprecated class ExprMessageExpr extends MessageExpr { * then there will be no result. If the receiving expression has type `C*` or type * `C

*` for some protocol `P`, then the result will be the type `C`. */ - ObjectiveClass getReceiverClass() { - none() - } + ObjectiveClass getReceiverClass() { none() } /** * Gets the Objective C classes and/or protocols which are statically implemented @@ -135,9 +119,7 @@ deprecated class ExprMessageExpr extends MessageExpr { * If the receiving expression has type `C*`, then `C` will be the sole result. * If the receiving expression has type `C

*`, then `C` and `P` will both be results. */ - Class getAReceiverClassOrProtocol() { - none() - } + Class getAReceiverClassOrProtocol() { none() } } /** @@ -152,9 +134,7 @@ deprecated class PropertyAccess extends ExprMessageExpr { /** * Gets the property being accessed by this expression. */ - Property getProperty() { - none() - } + Property getProperty() { none() } } /** @@ -164,9 +144,7 @@ deprecated class PropertyAccess extends ExprMessageExpr { deprecated class AtSelectorExpr extends Expr { AtSelectorExpr() { none() } - override string toString() { - none() - } + override string toString() { none() } /** * Gets the selector of this `@selector` expression, for example `driveForDistance:`. @@ -181,9 +159,7 @@ deprecated class AtSelectorExpr extends Expr { deprecated class AtProtocolExpr extends Expr { AtProtocolExpr() { none() } - override string toString() { - none() - } + override string toString() { none() } /** * Gets the protocol of this `@protocol` expression, for example `SomeProtocol`. @@ -198,9 +174,7 @@ deprecated class AtProtocolExpr extends Expr { deprecated class AtEncodeExpr extends Expr { AtEncodeExpr() { none() } - override string toString() { - none() - } + override string toString() { none() } /** * Gets the type this `@encode` expression encodes, for example `int *`. @@ -313,10 +287,7 @@ deprecated class CmdExpr extends Expr { override string toString() { none() } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } diff --git a/cpp/ql/src/semmle/code/cpp/headers/MultipleInclusion.qll b/cpp/ql/src/semmle/code/cpp/headers/MultipleInclusion.qll index 299998647c1..1b8418c38b1 100644 --- a/cpp/ql/src/semmle/code/cpp/headers/MultipleInclusion.qll +++ b/cpp/ql/src/semmle/code/cpp/headers/MultipleInclusion.qll @@ -8,19 +8,15 @@ import cpp /** * A header file with an include guard. */ -abstract class IncludeGuardedHeader extends HeaderFile { - -} +abstract class IncludeGuardedHeader extends HeaderFile { } /** * A header file that uses a non-portable mechanism to prevent multiple * inclusion. */ abstract class BadIncludeGuard extends IncludeGuardedHeader { - /** Gets the element to blame for this bad include guard pattern. */ abstract Element blame(); - } /** @@ -28,8 +24,7 @@ abstract class BadIncludeGuard extends IncludeGuardedHeader { * `#define`, and `#endif`. */ class CorrectIncludeGuard extends IncludeGuardedHeader { - - CorrectIncludeGuard() { correctIncludeGuard(this,_,_,_,_) } + CorrectIncludeGuard() { correctIncludeGuard(this, _, _, _, _) } /** Gets the name of the preprocessor define used to prevent multiple inclusion of this file. */ string getIncludeGuardName() { correctIncludeGuard(this, _, _, _, result) } @@ -42,17 +37,13 @@ class CorrectIncludeGuard extends IncludeGuardedHeader { /** Gets the `#endif` directive closing this file. */ PreprocessorEndif getEndif() { correctIncludeGuard(this, _, _, result, _) } - } /** * DEPRECATED: no longer useful. */ -deprecated -class NotIncludedGuard extends IncludeGuardedHeader { - NotIncludedGuard() { - none() - } +deprecated class NotIncludedGuard extends IncludeGuardedHeader { + NotIncludedGuard() { none() } /** Gets the `#ifndef` directive used to prevent multiple inclusion of this file. */ PreprocessorIfndef getIfndef() { result.getFile() = this } @@ -65,9 +56,7 @@ class NotIncludedGuard extends IncludeGuardedHeader { * A file with no code in it. */ class EmptyFile extends IncludeGuardedHeader { - EmptyFile() { - this.(MetricFile).getNumberOfLinesOfCode() = 0 - } + EmptyFile() { this.(MetricFile).getNumberOfLinesOfCode() = 0 } } private predicate hasMacro(HeaderFile hf, string name, Macro define) { @@ -78,7 +67,9 @@ private predicate hasMacro(HeaderFile hf, string name, Macro define) { * Holds if `hf` begins with an `#ifndef` or `#if` directive `ifndef`, to test * the macro named `includeGuard`, and ends with the matching `endif`. */ -predicate hasIncludeGuard(HeaderFile hf, PreprocessorDirective ifndef, PreprocessorEndif endif, string includeGuard) { +predicate hasIncludeGuard( + HeaderFile hf, PreprocessorDirective ifndef, PreprocessorEndif endif, string includeGuard +) { startsWithIfndef(hf, ifndef, includeGuard) and endsWithEndif(hf, endif) and endif.getIf() = ifndef @@ -90,17 +81,21 @@ predicate hasIncludeGuard(HeaderFile hf, PreprocessorDirective ifndef, Preproces * analysis is also exposed in an object-oriented style through the class * `CorrectIncludeGuard`. */ -pragma[noopt] predicate correctIncludeGuard(HeaderFile hf, PreprocessorDirective ifndef, Macro define, PreprocessorEndif endif, string includeGuard) { +pragma[noopt] +predicate correctIncludeGuard( + HeaderFile hf, PreprocessorDirective ifndef, Macro define, PreprocessorEndif endif, + string includeGuard +) { hasIncludeGuard(hf, ifndef, endif, includeGuard) and hasMacro(hf, includeGuard, define) and // we already know the ifndef is first and the endif last, so we just need // to check there is nothing before the define that isn't the ifndef. - not exists(int relevant, - Location ifndefLocation, int ifndefLine, - Location defineLocation, int defineLine | + not exists( + int relevant, Location ifndefLocation, int ifndefLine, Location defineLocation, int defineLine + | includeGuardRelevantLine(hf, relevant) and - ifndefLocation = ifndef.getLocation() and - ifndefLine = ifndefLocation.getStartLine() and + ifndefLocation = ifndef.getLocation() and + ifndefLine = ifndefLocation.getStartLine() and relevant != ifndefLine and defineLocation = define.getLocation() and defineLine = defineLocation.getStartLine() and @@ -122,8 +117,8 @@ predicate startsWithIfndef(HeaderFile hf, PreprocessorDirective ifndef, string m } private predicate endifLocation(PreprocessorEndif endif, File f, int line) { - endif.getFile() = f and - endif.getLocation().getStartLine() = line + endif.getFile() = f and + endif.getLocation().getStartLine() = line } private predicate lastEndifLocation(PreprocessorEndif endif, File f, int line) { @@ -143,12 +138,11 @@ predicate endsWithEndif(HeaderFile hf, PreprocessorEndif endif) { private predicate includeGuardRelevantLine(HeaderFile hf, int line) { exists(Location l | l.getFile() = hf and line = l.getStartLine() | // any declaration - exists(Declaration d | l = d.getADeclarationLocation()) or - + exists(Declaration d | l = d.getADeclarationLocation()) + or // most preprocessor directives exists(PreprocessorDirective p | l = p.getLocation() and - // included files may be outside the include guards, as they // should contain an include guarding mechanism of their own. not p instanceof Include @@ -161,19 +155,28 @@ private predicate includeGuardRelevantLine(HeaderFile hf, int line) { * This includes `#if !defined(macro)`. */ predicate ifndefDirective(PreprocessorDirective ppd, string macro) { - (ppd instanceof PreprocessorIfndef and macro = ppd.getHead()) + ppd instanceof PreprocessorIfndef and macro = ppd.getHead() or - (ppd instanceof PreprocessorIf and - exists(string head | head = ppd.getHead() | - macro = head.replaceAll("(", " ").replaceAll(")", "").replaceAll("\t", " ").regexpCapture("[ ]*![ ]*defined[ ]+([^ ]*)[ ]*", 1).trim() - )) + ppd instanceof PreprocessorIf and + exists(string head | head = ppd.getHead() | + macro = head + .replaceAll("(", " ") + .replaceAll(")", "") + .replaceAll("\t", " ") + .regexpCapture("[ ]*![ ]*defined[ ]+([^ ]*)[ ]*", 1) + .trim() + ) } /** * A header file with the `#pragma once` include guard. */ class PragmaOnceIncludeGuard extends BadIncludeGuard { - PragmaOnceIncludeGuard() { exists(PreprocessorPragma p | p.getFile() = this and p.getHead() = "once") } + PragmaOnceIncludeGuard() { + exists(PreprocessorPragma p | p.getFile() = this and p.getHead() = "once") + } - override Element blame() { exists(PreprocessorPragma p | p.getFile() = this and p = result and p.getHead() = "once") } + override Element blame() { + exists(PreprocessorPragma p | p.getFile() = this and p = result and p.getHead() = "once") + } } diff --git a/cpp/ql/src/semmle/code/cpp/internal/QualifiedName.qll b/cpp/ql/src/semmle/code/cpp/internal/QualifiedName.qll index f9fe593946e..2813d194b56 100644 --- a/cpp/ql/src/semmle/code/cpp/internal/QualifiedName.qll +++ b/cpp/ql/src/semmle/code/cpp/internal/QualifiedName.qll @@ -41,9 +41,7 @@ class Namespace extends @namespace { string getAQualifierForMembers() { if namespacembrs(_, this) then - exists(Namespace ns | - namespacembrs(ns, this) - | + exists(Namespace ns | namespacembrs(ns, this) | result = ns.getAQualifierForMembers() + "::" + this.getName() or // If this is an inline namespace, its members are also visible in any @@ -108,15 +106,11 @@ abstract class Declaration extends @declaration { this.canHaveQualifiedName() | exists(string t | t = this.getTypeQualifierWithArgs() | - if ns != "" - then result = ns + "::" + t + "::" + name - else result = t + "::" + name + if ns != "" then result = ns + "::" + t + "::" + name else result = t + "::" + name ) or not hasTypeQualifier(this) and - if ns != "" - then result = ns + "::" + name - else result = name + if ns != "" then result = ns + "::" + name else result = name ) } @@ -171,8 +165,7 @@ class TemplateVariable extends Variable { class LocalScopeVariable extends Variable, @localscopevariable { } -class LocalVariable extends LocalScopeVariable, @localvariable { -} +class LocalVariable extends LocalScopeVariable, @localvariable { } /** * A particular declaration or definition of a C/C++ variable. @@ -194,14 +187,12 @@ class VariableDeclarationEntry extends @var_decl { class Parameter extends LocalScopeVariable, @parameter { @functionorblock function; - int index; Parameter() { params(this, function, index, _) } } -class GlobalOrNamespaceVariable extends Variable, @globalvariable { -} +class GlobalOrNamespaceVariable extends Variable, @globalvariable { } // Unlike the usual `EnumConstant`, this one doesn't have a // `getDeclaringType()`. This simplifies the recursive computation of type diff --git a/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll b/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll index 73d3cb6772e..7e5d19d3f9f 100644 --- a/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll +++ b/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll @@ -95,30 +95,42 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) { } import Cached -cached private module Cached { + +cached +private module Cached { /** * 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) { + cached + @usertype resolveClass(@usertype c) { hasCompleteTwin(c, result) or oldHasCompleteTwin(c, result) or - (not hasCompleteTwin(c, _) and - not oldHasCompleteTwin(c, _) and - result = c) + not hasCompleteTwin(c, _) and + not oldHasCompleteTwin(c, _) and + result = c } /** * Holds if `t` is a struct, class, union, or template. */ - cached predicate isClass(@usertype t) { - (usertypes(t,_,1) or usertypes(t,_,2) or usertypes(t,_,3) or usertypes(t,_,6) - or usertypes(t,_,10) or usertypes(t,_,11) or usertypes(t,_,12)) + cached + predicate isClass(@usertype t) { + ( + usertypes(t, _, 1) or + usertypes(t, _, 2) or + usertypes(t, _, 3) or + usertypes(t, _, 6) or + usertypes(t, _, 10) or + usertypes(t, _, 11) or + usertypes(t, _, 12) + ) } - cached predicate isType(@type t) { + cached + predicate isType(@type t) { not isClass(t) or t = resolveClass(_) diff --git a/cpp/ql/src/semmle/code/cpp/ir/IRSanity.ql b/cpp/ql/src/semmle/code/cpp/ir/IRSanity.ql index c5f73c15a70..2c2c6e348a1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/IRSanity.ql +++ b/cpp/ql/src/semmle/code/cpp/ir/IRSanity.ql @@ -1,6 +1,6 @@ /** * @name IR Sanity Check - * @description Performs sanity checks on the Intermediate Representation. This query should have no results. + * @description Performs sanity checks on the Intermediate Representation. This query should have no results. * @kind table * @id cpp/ir-sanity-check */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow.qll index 3d5a077b0d1..9315830fc49 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow.qll @@ -16,6 +16,7 @@ * (intraprocedural) data flow, invoke `DataFlow::localFlow` or * `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`. */ + import cpp module DataFlow { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow2.qll index 0e24e2949f0..11caa963182 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow2.qll @@ -8,6 +8,7 @@ * * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. */ + import cpp module DataFlow2 { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow3.qll index 9ea19b45a37..479971baadd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow3.qll @@ -8,6 +8,7 @@ * * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. */ + import cpp module DataFlow3 { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow4.qll index cd9bb5869c1..8264178b6b3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow4.qll @@ -8,6 +8,7 @@ * * See `semmle.code.cpp.dataflow.DataFlow` for the full documentation. */ + import cpp module DataFlow4 { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index b517728d770..d0325a28d3e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -59,7 +59,9 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam * Holds if the call context `ctx` reduces the set of viable dispatch * targets of `ma` in `c`. */ -predicate reducedViableImplInCallContext(CallInstruction call, Function f, CallInstruction ctx) { none() } +predicate reducedViableImplInCallContext(CallInstruction call, Function f, CallInstruction ctx) { + none() +} /** * Gets a viable dispatch target of `ma` in the context `ctx`. This is diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 1db97a49c03..43853f03ad9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -155,9 +155,7 @@ UninitializedNode uninitializedNode(LocalVariable v) { result.getLocalVariable() * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local * (intra-procedural) step. */ -predicate localFlowStep(Node nodeFrom, Node nodeTo) { - simpleLocalFlowStep(nodeFrom, nodeTo) -} +predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } /** * INTERNAL: do not use. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRConfiguration.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRConfiguration.qll index e4a1f1cecf1..c7133c21798 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRConfiguration.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRConfiguration.qll @@ -6,14 +6,10 @@ private newtype TIRConfiguration = MkIRConfiguration() * The query can extend this class to control which functions have IR generated for them. */ class IRConfiguration extends TIRConfiguration { - string toString() { - result = "IRConfiguration" - } + string toString() { result = "IRConfiguration" } /** * Holds if IR should be created for function `func`. By default, holds for all functions. */ - predicate shouldCreateIRForFunction(Language::Function func) { - any() - } + predicate shouldCreateIRForFunction(Language::Function func) { any() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.ql b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.ql index edbf47d3339..b5d3ae4633e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.ql +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.ql @@ -1,6 +1,6 @@ /** * @name Aliased SSA IR Sanity Check - * @description Performs sanity checks on the Intermediate Representation. This query should have no results. + * @description Performs sanity checks on the Intermediate Representation. This query should have no results. * @kind table * @id cpp/aliased-ssa-ir-sanity-check */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/constant/ConstantAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/constant/ConstantAnalysis.qll index 01adf74efa8..40076b817a1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/constant/ConstantAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/constant/ConstantAnalysis.qll @@ -4,10 +4,14 @@ private import IR language[monotonicAggregates] int getConstantValue(Instruction instr) { - result = instr.(IntegerConstantInstruction).getValue().toInt() or - result = getBinaryInstructionValue(instr) or - result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) or - result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or + result = instr.(IntegerConstantInstruction).getValue().toInt() + or + result = getBinaryInstructionValue(instr) + or + result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) + or + result = getConstantValue(instr.(CopyInstruction).getSourceValue()) + or exists(PhiInstruction phi | phi = instr and result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and @@ -26,15 +30,24 @@ private int getBinaryInstructionValue(BinaryInstruction instr) { exists(int left, int right | binaryInstructionOperands(instr, left, right) and ( - instr instanceof AddInstruction and result = add(left, right) or - instr instanceof SubInstruction and result = sub(left, right) or - instr instanceof MulInstruction and result = mul(left, right) or - instr instanceof DivInstruction and result = div(left, right) or - instr instanceof CompareEQInstruction and result = compareEQ(left, right) or - instr instanceof CompareNEInstruction and result = compareNE(left, right) or - instr instanceof CompareLTInstruction and result = compareLT(left, right) or - instr instanceof CompareGTInstruction and result = compareGT(left, right) or - instr instanceof CompareLEInstruction and result = compareLE(left, right) or + instr instanceof AddInstruction and result = add(left, right) + or + instr instanceof SubInstruction and result = sub(left, right) + or + instr instanceof MulInstruction and result = mul(left, right) + or + instr instanceof DivInstruction and result = div(left, right) + or + instr instanceof CompareEQInstruction and result = compareEQ(left, right) + or + instr instanceof CompareNEInstruction and result = compareNE(left, right) + or + instr instanceof CompareLTInstruction and result = compareLT(left, right) + or + instr instanceof CompareGTInstruction and result = compareGT(left, right) + or + instr instanceof CompareLEInstruction and result = compareLE(left, right) + or instr instanceof CompareGEInstruction and result = compareGE(left, right) ) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll index 9488e708f59..e3e52df8931 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll @@ -10,10 +10,7 @@ class ValueNumberPropertyProvider extends IRPropertyProvider { exists(ValueNumber vn | vn = valueNumber(instr) and key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 then - result = vn.toString() - else - result = "unique" + if strictcount(vn.getAnInstruction()) > 1 then result = vn.toString() else result = "unique" ) } } @@ -25,9 +22,7 @@ newtype TValueNumber = TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) { initializeParameterValueNumber(_, irFunc, var) } or - TInitializeThisValueNumber(IRFunction irFunc) { - initializeThisValueNumber(_, irFunc) - } or + TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or TConstantValueNumber(IRFunction irFunc, Type type, string value) { constantValueNumber(_, irFunc, type, value) } or @@ -37,44 +32,40 @@ newtype TValueNumber = TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) { fieldAddressValueNumber(_, irFunc, field, objectAddress) } or - TBinaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, - ValueNumber rightOperand) { + TBinaryValueNumber( + IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand + ) { binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand) } or - TPointerArithmeticValueNumber(IRFunction irFunc, Opcode opcode, Type type, int elementSize, - ValueNumber leftOperand, ValueNumber rightOperand) { + TPointerArithmeticValueNumber( + IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, + ValueNumber rightOperand + ) { pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand) } or TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) { unaryValueNumber(_, irFunc, opcode, type, operand) } or - TInheritanceConversionValueNumber(IRFunction irFunc, Opcode opcode, Class baseClass, - Class derivedClass, ValueNumber operand) { + TInheritanceConversionValueNumber( + IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand + ) { inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand) } or - TUniqueValueNumber(IRFunction irFunc, Instruction instr) { - uniqueValueNumber(instr, irFunc) - } + TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } /** * The value number assigned to a particular set of instructions that produce equivalent results. */ class ValueNumber extends TValueNumber { - final string toString() { - result = getExampleInstruction().getResultId() - } + final string toString() { result = getExampleInstruction().getResultId() } - final Location getLocation() { - result = getExampleInstruction().getLocation() - } + final Location getLocation() { result = getExampleInstruction().getLocation() } /** * Gets the instructions that have been assigned this value number. This will always produce at * least one result. */ - final Instruction getAnInstruction() { - this = valueNumber(result) - } + final Instruction getAnInstruction() { this = valueNumber(result) } /** * Gets one of the instructions that was assigned this value number. The chosen instuction is @@ -82,17 +73,16 @@ class ValueNumber extends TValueNumber { */ final Instruction getExampleInstruction() { result = min(Instruction instr | - instr = getAnInstruction() | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + instr = getAnInstruction() + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) } /** * Gets an `Operand` whose definition is exact and has this value number. */ - final Operand getAUse() { - this = valueNumber(result.getDef()) - } + final Operand getAUse() { this = valueNumber(result.getDef()) } } /** @@ -120,26 +110,37 @@ private class CongruentCopyInstruction extends CopyInstruction { * a `unique` value number that is never shared by multiple instructions. */ private predicate numberableInstruction(Instruction instr) { - instr instanceof VariableAddressInstruction or - instr instanceof InitializeParameterInstruction or - instr instanceof InitializeThisInstruction or - instr instanceof ConstantInstruction or - instr instanceof StringConstantInstruction or - instr instanceof FieldAddressInstruction or - instr instanceof BinaryInstruction or - (instr instanceof UnaryInstruction and not instr instanceof CopyInstruction) or - instr instanceof PointerArithmeticInstruction or + instr instanceof VariableAddressInstruction + or + instr instanceof InitializeParameterInstruction + or + instr instanceof InitializeThisInstruction + or + instr instanceof ConstantInstruction + or + instr instanceof StringConstantInstruction + or + instr instanceof FieldAddressInstruction + or + instr instanceof BinaryInstruction + or + instr instanceof UnaryInstruction and not instr instanceof CopyInstruction + or + instr instanceof PointerArithmeticInstruction + or instr instanceof CongruentCopyInstruction } -private predicate variableAddressValueNumber(VariableAddressInstruction instr, IRFunction irFunc, - IRVariable var) { +private predicate variableAddressValueNumber( + VariableAddressInstruction instr, IRFunction irFunc, IRVariable var +) { instr.getEnclosingIRFunction() = irFunc and instr.getVariable() = var } -private predicate initializeParameterValueNumber(InitializeParameterInstruction instr, - IRFunction irFunc, IRVariable var) { +private predicate initializeParameterValueNumber( + InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var +) { instr.getEnclosingIRFunction() = irFunc and instr.getVariable() = var } @@ -148,40 +149,46 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF instr.getEnclosingIRFunction() = irFunc } -private predicate constantValueNumber(ConstantInstruction instr, IRFunction irFunc, Type type, - string value) { +private predicate constantValueNumber( + ConstantInstruction instr, IRFunction irFunc, Type type, string value +) { instr.getEnclosingIRFunction() = irFunc and instr.getResultType() = type and instr.getValue() = value } -private predicate stringConstantValueNumber(StringConstantInstruction instr, IRFunction irFunc, Type type, - string value) { +private predicate stringConstantValueNumber( + StringConstantInstruction instr, IRFunction irFunc, Type type, string value +) { instr.getEnclosingIRFunction() = irFunc and instr.getResultType() = type and instr.getValue().getValue() = value } -private predicate fieldAddressValueNumber(FieldAddressInstruction instr, IRFunction irFunc, - Field field, ValueNumber objectAddress) { +private predicate fieldAddressValueNumber( + FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress +) { instr.getEnclosingIRFunction() = irFunc and instr.getField() = field and valueNumber(instr.getObjectAddress()) = objectAddress } -private predicate binaryValueNumber(BinaryInstruction instr, IRFunction irFunc, Opcode opcode, - Type type, ValueNumber leftOperand, ValueNumber rightOperand) { +private predicate binaryValueNumber( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, + ValueNumber rightOperand +) { instr.getEnclosingIRFunction() = irFunc and - (not instr instanceof PointerArithmeticInstruction) and + not instr instanceof PointerArithmeticInstruction and instr.getOpcode() = opcode and instr.getResultType() = type and valueNumber(instr.getLeft()) = leftOperand and valueNumber(instr.getRight()) = rightOperand } -private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr, - IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, - ValueNumber rightOperand) { +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize, + ValueNumber leftOperand, ValueNumber rightOperand +) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getResultType() = type and @@ -190,18 +197,21 @@ private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction inst valueNumber(instr.getRight()) = rightOperand } -private predicate unaryValueNumber(UnaryInstruction instr, IRFunction irFunc, Opcode opcode, - Type type, ValueNumber operand) { +private predicate unaryValueNumber( + UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand +) { instr.getEnclosingIRFunction() = irFunc and - (not instr instanceof InheritanceConversionInstruction) and - (not instr instanceof CopyInstruction) and + not instr instanceof InheritanceConversionInstruction and + not instr instanceof CopyInstruction and instr.getOpcode() = opcode and instr.getResultType() = type and valueNumber(instr.getUnary()) = operand } -private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr, - IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) { +private predicate inheritanceConversionValueNumber( + InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass, + Class derivedClass, ValueNumber operand +) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getBaseClass() = baseClass and @@ -215,15 +225,17 @@ private predicate inheritanceConversionValueNumber(InheritanceConversionInstruct */ private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) { instr.getEnclosingIRFunction() = irFunc and - (not instr.getResultType() instanceof VoidType) and + not instr.getResultType() instanceof VoidType and not numberableInstruction(instr) } /** * Gets the value number assigned to `instr`, if any. Returns at most one result. */ -cached ValueNumber valueNumber(Instruction instr) { - result = nonUniqueValueNumber(instr) or +cached +ValueNumber valueNumber(Instruction instr) { + result = nonUniqueValueNumber(instr) + or exists(IRFunction irFunc | uniqueValueNumber(instr, irFunc) and result = TUniqueValueNumber(irFunc, instr) @@ -234,9 +246,7 @@ cached ValueNumber valueNumber(Instruction instr) { * Gets the value number assigned to the exact definition of `op`, if any. * Returns at most one result. */ -ValueNumber valueNumberOfOperand(Operand op) { - result = valueNumber(op.getDef()) -} +ValueNumber valueNumberOfOperand(Operand op) { result = valueNumber(op.getDef()) } /** * Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique @@ -249,47 +259,55 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) { exists(IRVariable var | variableAddressValueNumber(instr, irFunc, var) and result = TVariableAddressValueNumber(irFunc, var) - ) or + ) + or exists(IRVariable var | initializeParameterValueNumber(instr, irFunc, var) and result = TInitializeParameterValueNumber(irFunc, var) - ) or - ( - initializeThisValueNumber(instr, irFunc) and - result = TInitializeThisValueNumber(irFunc) - ) or + ) + or + initializeThisValueNumber(instr, irFunc) and + result = TInitializeThisValueNumber(irFunc) + or exists(Type type, string value | constantValueNumber(instr, irFunc, type, value) and result = TConstantValueNumber(irFunc, type, value) - ) or + ) + or exists(Type type, string value | stringConstantValueNumber(instr, irFunc, type, value) and result = TStringConstantValueNumber(irFunc, type, value) - ) or + ) + or exists(Field field, ValueNumber objectAddress | fieldAddressValueNumber(instr, irFunc, field, objectAddress) and result = TFieldAddressValueNumber(irFunc, field, objectAddress) - ) or + ) + or exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand | binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand) - ) or + ) + or exists(Opcode opcode, Type type, ValueNumber operand | unaryValueNumber(instr, irFunc, opcode, type, operand) and result = TUnaryValueNumber(irFunc, opcode, type, operand) - ) or + ) + or exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand | - inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, - operand) and + inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand) - ) or - exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, - ValueNumber rightOperand | + ) + or + exists( + Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand + | pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand, - rightOperand) and + rightOperand) and result = TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand) - ) or + ) + or // The value number of a copy is just the value number of its source value. result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue()) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 3c50cea6206..dc50ef01354 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -2,7 +2,6 @@ private import AliasAnalysisInternal private import cpp private import InputIR private import semmle.code.cpp.ir.internal.IntegerConstant as Ints - private import semmle.code.cpp.models.interfaces.Alias private class IntValue = Ints::IntValue; @@ -12,35 +11,28 @@ private class IntValue = Ints::IntValue; * bytes:bits. */ bindingset[bits] -string bitsToBytesAndBits(int bits) { - result = (bits / 8).toString() + ":" + (bits % 8).toString() -} +string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() } /** * Gets a printable string for a bit offset with possibly unknown value. */ bindingset[bitOffset] string getBitOffsetString(IntValue bitOffset) { - if Ints::hasValue(bitOffset) then - if bitOffset >= 0 then - result = "+" + bitsToBytesAndBits(bitOffset) - else - result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) - else - result = "+?" + if Ints::hasValue(bitOffset) + then + if bitOffset >= 0 + then result = "+" + bitsToBytesAndBits(bitOffset) + else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) + else result = "+?" } /** * Gets the offset of field `field` in bits. */ private IntValue getFieldBitOffset(Field field) { - if (field instanceof BitField) then ( - result = Ints::add(Ints::mul(field.getByteOffset(), 8), - field.(BitField).getBitOffset()) - ) - else ( - result = Ints::mul(field.getByteOffset(), 8) - ) + if field instanceof BitField + then result = Ints::add(Ints::mul(field.getByteOffset(), 8), field.(BitField).getBitOffset()) + else result = Ints::mul(field.getByteOffset(), 8) } /** @@ -51,18 +43,22 @@ private IntValue getFieldBitOffset(Field field) { private predicate operandIsConsumedWithoutEscaping(Operand operand) { // The source/destination address of a Load/Store does not escape (but the // loaded/stored value could). - operand instanceof AddressOperand or - exists (Instruction instr | + operand instanceof AddressOperand + or + exists(Instruction instr | instr = operand.getUse() and ( // Neither operand of a Compare escapes. - instr instanceof CompareInstruction or + instr instanceof CompareInstruction + or // Neither operand of a PointerDiff escapes. - instr instanceof PointerDiffInstruction or + instr instanceof PointerDiffInstruction + or // Converting an address to a `bool` does not escape the address. instr.(ConvertInstruction).getResultType() instanceof BoolType ) - ) or + ) + or // Some standard function arguments never escape isNeverEscapesArgument(operand) } @@ -81,10 +77,9 @@ private predicate operandEscapesDomain(Operand operand) { * value of that constant. Otherwise, returns unknown. */ IntValue getConstantValue(Instruction instr) { - if instr instanceof IntegerConstantInstruction then - result = instr.(IntegerConstantInstruction).getValue().toInt() - else - result = Ints::unknown() + if instr instanceof IntegerConstantInstruction + then result = instr.(IntegerConstantInstruction).getValue().toInt() + else result = Ints::unknown() } /** @@ -94,12 +89,10 @@ IntValue getConstantValue(Instruction instr) { */ IntValue getPointerBitOffset(PointerOffsetInstruction instr) { exists(IntValue bitOffset | + bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRight()), instr.getElementSize()), 8) and ( - bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRight()), - instr.getElementSize()), 8) - ) and - ( - instr instanceof PointerAddInstruction and result = bitOffset or + instr instanceof PointerAddInstruction and result = bitOffset + or instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) ) ) @@ -119,35 +112,40 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { exists(ConvertToBaseInstruction convert | convert = instr and bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) - ) or + ) + or // Converting to a derived class subtracts the offset of the base class. exists(ConvertToDerivedInstruction convert | convert = instr and bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) - ) or + ) + or // Converting to a virtual base class adds an unknown offset. - ( - instr instanceof ConvertToVirtualBaseInstruction and - bitOffset = Ints::unknown() - ) or + instr instanceof ConvertToVirtualBaseInstruction and + bitOffset = Ints::unknown() + or // Conversion to another pointer type propagates the source address. exists(ConvertInstruction convert, Type resultType | convert = instr and resultType = convert.getResultType() and ( resultType instanceof PointerType or - resultType instanceof Class //REVIEW: Remove when all glvalues are pointers + resultType instanceof Class //REVIEW: Remove when all glvalues are pointers ) and bitOffset = 0 - ) or + ) + or // Adding an integer to or subtracting an integer from a pointer propagates // the address with an offset. - bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or + bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) + or // Computing a field address from a pointer propagates the address plus the // offset of the field. - bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or + bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) + or // A copy propagates the source value. - operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 or + operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 + or // Some functions are known to propagate an argument isAlwaysReturnedArgument(operand) and bitOffset = 0 ) @@ -212,14 +210,14 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) { resultReturned(init, bitOffset1) and resultReturned(ci, bitOffset2) and bitOffset = Ints::add(bitOffset1, bitOffset2) - ) or // The address is returned operand.getUse() instanceof ReturnValueInstruction and bitOffset = 0 or - isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUse(), _) and + isOnlyEscapesViaReturnArgument(operand) and + resultReturned(operand.getUse(), _) and bitOffset = Ints::unknown() } @@ -228,7 +226,8 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In ci = operand.getUse() and f = ci.getStaticCallTarget() and ( - init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex()) + init.(InitializeParameterInstruction).getParameter() = f + .getParameter(operand.(PositionalArgumentOperand).getIndex()) or init instanceof InitializeThisInstruction and init.getEnclosingFunction() = f and @@ -264,9 +263,7 @@ private predicate resultReturned(Instruction instr, IntValue bitOffset) { operandReturned(instr.getAUse(), bitOffset) } -private predicate resultMayReachReturn(Instruction instr) { - operandMayReachReturn(instr.getAUse()) -} +private predicate resultMayReachReturn(Instruction instr) { operandMayReachReturn(instr.getAUse()) } /** * Holds if any address held in the result of instruction `instr` escapes @@ -295,7 +292,8 @@ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { * analysis. */ predicate variableAddressEscapes(IRVariable var) { - automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or + automaticVariableAddressEscapes(var.(IRAutomaticVariable)) + or // All variables with static storage duration have their address escape. not var instanceof IRAutomaticVariable } @@ -306,11 +304,10 @@ predicate variableAddressEscapes(IRVariable var) { * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. */ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { - ( - // The address of a variable points to that variable, at offset 0. - instr.(VariableAddressInstruction).getVariable() = var and - bitOffset = 0 - ) or + // The address of a variable points to that variable, at offset 0. + instr.(VariableAddressInstruction).getVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.ql b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.ql index fdbe07f6cf2..a9d6b7943fe 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.ql +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.ql @@ -1,6 +1,6 @@ /** * @name Raw IR Sanity Check - * @description Performs sanity checks on the Intermediate Representation. This query should have no results. + * @description Performs sanity checks on the Intermediate Representation. This query should have no results. * @kind table * @id cpp/raw-ir-sanity-check */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll index 01adf74efa8..40076b817a1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll @@ -4,10 +4,14 @@ private import IR language[monotonicAggregates] int getConstantValue(Instruction instr) { - result = instr.(IntegerConstantInstruction).getValue().toInt() or - result = getBinaryInstructionValue(instr) or - result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) or - result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or + result = instr.(IntegerConstantInstruction).getValue().toInt() + or + result = getBinaryInstructionValue(instr) + or + result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) + or + result = getConstantValue(instr.(CopyInstruction).getSourceValue()) + or exists(PhiInstruction phi | phi = instr and result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and @@ -26,15 +30,24 @@ private int getBinaryInstructionValue(BinaryInstruction instr) { exists(int left, int right | binaryInstructionOperands(instr, left, right) and ( - instr instanceof AddInstruction and result = add(left, right) or - instr instanceof SubInstruction and result = sub(left, right) or - instr instanceof MulInstruction and result = mul(left, right) or - instr instanceof DivInstruction and result = div(left, right) or - instr instanceof CompareEQInstruction and result = compareEQ(left, right) or - instr instanceof CompareNEInstruction and result = compareNE(left, right) or - instr instanceof CompareLTInstruction and result = compareLT(left, right) or - instr instanceof CompareGTInstruction and result = compareGT(left, right) or - instr instanceof CompareLEInstruction and result = compareLE(left, right) or + instr instanceof AddInstruction and result = add(left, right) + or + instr instanceof SubInstruction and result = sub(left, right) + or + instr instanceof MulInstruction and result = mul(left, right) + or + instr instanceof DivInstruction and result = div(left, right) + or + instr instanceof CompareEQInstruction and result = compareEQ(left, right) + or + instr instanceof CompareNEInstruction and result = compareNE(left, right) + or + instr instanceof CompareLTInstruction and result = compareLT(left, right) + or + instr instanceof CompareGTInstruction and result = compareGT(left, right) + or + instr instanceof CompareLEInstruction and result = compareLE(left, right) + or instr instanceof CompareGEInstruction and result = compareGE(left, right) ) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll index 9488e708f59..e3e52df8931 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll @@ -10,10 +10,7 @@ class ValueNumberPropertyProvider extends IRPropertyProvider { exists(ValueNumber vn | vn = valueNumber(instr) and key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 then - result = vn.toString() - else - result = "unique" + if strictcount(vn.getAnInstruction()) > 1 then result = vn.toString() else result = "unique" ) } } @@ -25,9 +22,7 @@ newtype TValueNumber = TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) { initializeParameterValueNumber(_, irFunc, var) } or - TInitializeThisValueNumber(IRFunction irFunc) { - initializeThisValueNumber(_, irFunc) - } or + TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or TConstantValueNumber(IRFunction irFunc, Type type, string value) { constantValueNumber(_, irFunc, type, value) } or @@ -37,44 +32,40 @@ newtype TValueNumber = TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) { fieldAddressValueNumber(_, irFunc, field, objectAddress) } or - TBinaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, - ValueNumber rightOperand) { + TBinaryValueNumber( + IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand + ) { binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand) } or - TPointerArithmeticValueNumber(IRFunction irFunc, Opcode opcode, Type type, int elementSize, - ValueNumber leftOperand, ValueNumber rightOperand) { + TPointerArithmeticValueNumber( + IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, + ValueNumber rightOperand + ) { pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand) } or TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) { unaryValueNumber(_, irFunc, opcode, type, operand) } or - TInheritanceConversionValueNumber(IRFunction irFunc, Opcode opcode, Class baseClass, - Class derivedClass, ValueNumber operand) { + TInheritanceConversionValueNumber( + IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand + ) { inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand) } or - TUniqueValueNumber(IRFunction irFunc, Instruction instr) { - uniqueValueNumber(instr, irFunc) - } + TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } /** * The value number assigned to a particular set of instructions that produce equivalent results. */ class ValueNumber extends TValueNumber { - final string toString() { - result = getExampleInstruction().getResultId() - } + final string toString() { result = getExampleInstruction().getResultId() } - final Location getLocation() { - result = getExampleInstruction().getLocation() - } + final Location getLocation() { result = getExampleInstruction().getLocation() } /** * Gets the instructions that have been assigned this value number. This will always produce at * least one result. */ - final Instruction getAnInstruction() { - this = valueNumber(result) - } + final Instruction getAnInstruction() { this = valueNumber(result) } /** * Gets one of the instructions that was assigned this value number. The chosen instuction is @@ -82,17 +73,16 @@ class ValueNumber extends TValueNumber { */ final Instruction getExampleInstruction() { result = min(Instruction instr | - instr = getAnInstruction() | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + instr = getAnInstruction() + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) } /** * Gets an `Operand` whose definition is exact and has this value number. */ - final Operand getAUse() { - this = valueNumber(result.getDef()) - } + final Operand getAUse() { this = valueNumber(result.getDef()) } } /** @@ -120,26 +110,37 @@ private class CongruentCopyInstruction extends CopyInstruction { * a `unique` value number that is never shared by multiple instructions. */ private predicate numberableInstruction(Instruction instr) { - instr instanceof VariableAddressInstruction or - instr instanceof InitializeParameterInstruction or - instr instanceof InitializeThisInstruction or - instr instanceof ConstantInstruction or - instr instanceof StringConstantInstruction or - instr instanceof FieldAddressInstruction or - instr instanceof BinaryInstruction or - (instr instanceof UnaryInstruction and not instr instanceof CopyInstruction) or - instr instanceof PointerArithmeticInstruction or + instr instanceof VariableAddressInstruction + or + instr instanceof InitializeParameterInstruction + or + instr instanceof InitializeThisInstruction + or + instr instanceof ConstantInstruction + or + instr instanceof StringConstantInstruction + or + instr instanceof FieldAddressInstruction + or + instr instanceof BinaryInstruction + or + instr instanceof UnaryInstruction and not instr instanceof CopyInstruction + or + instr instanceof PointerArithmeticInstruction + or instr instanceof CongruentCopyInstruction } -private predicate variableAddressValueNumber(VariableAddressInstruction instr, IRFunction irFunc, - IRVariable var) { +private predicate variableAddressValueNumber( + VariableAddressInstruction instr, IRFunction irFunc, IRVariable var +) { instr.getEnclosingIRFunction() = irFunc and instr.getVariable() = var } -private predicate initializeParameterValueNumber(InitializeParameterInstruction instr, - IRFunction irFunc, IRVariable var) { +private predicate initializeParameterValueNumber( + InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var +) { instr.getEnclosingIRFunction() = irFunc and instr.getVariable() = var } @@ -148,40 +149,46 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF instr.getEnclosingIRFunction() = irFunc } -private predicate constantValueNumber(ConstantInstruction instr, IRFunction irFunc, Type type, - string value) { +private predicate constantValueNumber( + ConstantInstruction instr, IRFunction irFunc, Type type, string value +) { instr.getEnclosingIRFunction() = irFunc and instr.getResultType() = type and instr.getValue() = value } -private predicate stringConstantValueNumber(StringConstantInstruction instr, IRFunction irFunc, Type type, - string value) { +private predicate stringConstantValueNumber( + StringConstantInstruction instr, IRFunction irFunc, Type type, string value +) { instr.getEnclosingIRFunction() = irFunc and instr.getResultType() = type and instr.getValue().getValue() = value } -private predicate fieldAddressValueNumber(FieldAddressInstruction instr, IRFunction irFunc, - Field field, ValueNumber objectAddress) { +private predicate fieldAddressValueNumber( + FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress +) { instr.getEnclosingIRFunction() = irFunc and instr.getField() = field and valueNumber(instr.getObjectAddress()) = objectAddress } -private predicate binaryValueNumber(BinaryInstruction instr, IRFunction irFunc, Opcode opcode, - Type type, ValueNumber leftOperand, ValueNumber rightOperand) { +private predicate binaryValueNumber( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, + ValueNumber rightOperand +) { instr.getEnclosingIRFunction() = irFunc and - (not instr instanceof PointerArithmeticInstruction) and + not instr instanceof PointerArithmeticInstruction and instr.getOpcode() = opcode and instr.getResultType() = type and valueNumber(instr.getLeft()) = leftOperand and valueNumber(instr.getRight()) = rightOperand } -private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr, - IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, - ValueNumber rightOperand) { +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize, + ValueNumber leftOperand, ValueNumber rightOperand +) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getResultType() = type and @@ -190,18 +197,21 @@ private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction inst valueNumber(instr.getRight()) = rightOperand } -private predicate unaryValueNumber(UnaryInstruction instr, IRFunction irFunc, Opcode opcode, - Type type, ValueNumber operand) { +private predicate unaryValueNumber( + UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand +) { instr.getEnclosingIRFunction() = irFunc and - (not instr instanceof InheritanceConversionInstruction) and - (not instr instanceof CopyInstruction) and + not instr instanceof InheritanceConversionInstruction and + not instr instanceof CopyInstruction and instr.getOpcode() = opcode and instr.getResultType() = type and valueNumber(instr.getUnary()) = operand } -private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr, - IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) { +private predicate inheritanceConversionValueNumber( + InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass, + Class derivedClass, ValueNumber operand +) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getBaseClass() = baseClass and @@ -215,15 +225,17 @@ private predicate inheritanceConversionValueNumber(InheritanceConversionInstruct */ private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) { instr.getEnclosingIRFunction() = irFunc and - (not instr.getResultType() instanceof VoidType) and + not instr.getResultType() instanceof VoidType and not numberableInstruction(instr) } /** * Gets the value number assigned to `instr`, if any. Returns at most one result. */ -cached ValueNumber valueNumber(Instruction instr) { - result = nonUniqueValueNumber(instr) or +cached +ValueNumber valueNumber(Instruction instr) { + result = nonUniqueValueNumber(instr) + or exists(IRFunction irFunc | uniqueValueNumber(instr, irFunc) and result = TUniqueValueNumber(irFunc, instr) @@ -234,9 +246,7 @@ cached ValueNumber valueNumber(Instruction instr) { * Gets the value number assigned to the exact definition of `op`, if any. * Returns at most one result. */ -ValueNumber valueNumberOfOperand(Operand op) { - result = valueNumber(op.getDef()) -} +ValueNumber valueNumberOfOperand(Operand op) { result = valueNumber(op.getDef()) } /** * Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique @@ -249,47 +259,55 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) { exists(IRVariable var | variableAddressValueNumber(instr, irFunc, var) and result = TVariableAddressValueNumber(irFunc, var) - ) or + ) + or exists(IRVariable var | initializeParameterValueNumber(instr, irFunc, var) and result = TInitializeParameterValueNumber(irFunc, var) - ) or - ( - initializeThisValueNumber(instr, irFunc) and - result = TInitializeThisValueNumber(irFunc) - ) or + ) + or + initializeThisValueNumber(instr, irFunc) and + result = TInitializeThisValueNumber(irFunc) + or exists(Type type, string value | constantValueNumber(instr, irFunc, type, value) and result = TConstantValueNumber(irFunc, type, value) - ) or + ) + or exists(Type type, string value | stringConstantValueNumber(instr, irFunc, type, value) and result = TStringConstantValueNumber(irFunc, type, value) - ) or + ) + or exists(Field field, ValueNumber objectAddress | fieldAddressValueNumber(instr, irFunc, field, objectAddress) and result = TFieldAddressValueNumber(irFunc, field, objectAddress) - ) or + ) + or exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand | binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand) - ) or + ) + or exists(Opcode opcode, Type type, ValueNumber operand | unaryValueNumber(instr, irFunc, opcode, type, operand) and result = TUnaryValueNumber(irFunc, opcode, type, operand) - ) or + ) + or exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand | - inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, - operand) and + inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand) - ) or - exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, - ValueNumber rightOperand | + ) + or + exists( + Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand + | pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand, - rightOperand) and + rightOperand) and result = TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand) - ) or + ) + or // The value number of a copy is just the value number of its source value. result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue()) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 36c528bdb6c..43283db2bc1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -13,27 +13,28 @@ TranslatedElement getInstructionTranslatedElement(Instruction instruction) { instruction = MkInstruction(result, _) } -InstructionTag getInstructionTag(Instruction instruction) { - instruction = MkInstruction(_, result) -} +InstructionTag getInstructionTag(Instruction instruction) { instruction = MkInstruction(_, result) } import Cached -cached private module Cached { - cached predicate functionHasIR(Function func) { - exists(getTranslatedFunction(func)) - } - cached newtype TInstruction = +cached +private module Cached { + cached + predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) } + + cached + newtype TInstruction = MkInstruction(TranslatedElement element, InstructionTag tag) { element.hasInstruction(_, tag, _, _) } - cached predicate hasUserVariable(Function func, Variable var, Type type) { + cached + predicate hasUserVariable(Function func, Variable var, Type type) { getTranslatedFunction(func).hasUserVariable(var, type) } - - cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, - Type type) { + + cached + predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) { exists(TranslatedElement element | element.getAST() = ast and func = element.getFunction() and @@ -41,67 +42,76 @@ cached private module Cached { ) } - cached predicate hasModeledMemoryResult(Instruction instruction) { - none() - } + cached + predicate hasModeledMemoryResult(Instruction instruction) { none() } - cached Expr getInstructionConvertedResultExpression(Instruction instruction) { + cached + Expr getInstructionConvertedResultExpression(Instruction instruction) { exists(TranslatedExpr translatedExpr | translatedExpr = getTranslatedExpr(result) and instruction = translatedExpr.getResult() ) } - cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) { + cached + Expr getInstructionUnconvertedResultExpression(Instruction instruction) { exists(Expr converted, TranslatedExpr translatedExpr | result = converted.(Conversion).getExpr+() or result = converted - | + | not result instanceof Conversion and translatedExpr = getTranslatedExpr(converted) and instruction = translatedExpr.getResult() ) } - - cached Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) { - result = getInstructionTranslatedElement(instruction).getInstructionOperand( - getInstructionTag(instruction), tag) + + cached + Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) { + result = getInstructionTranslatedElement(instruction) + .getInstructionOperand(getInstructionTag(instruction), tag) } - cached Instruction getMemoryOperandDefinition(Instruction instruction, MemoryOperandTag tag, Overlap overlap) { - result = getInstructionTranslatedElement(instruction).getInstructionOperand( - getInstructionTag(instruction), tag) and + cached + Instruction getMemoryOperandDefinition( + Instruction instruction, MemoryOperandTag tag, Overlap overlap + ) { + result = getInstructionTranslatedElement(instruction) + .getInstructionOperand(getInstructionTag(instruction), tag) and overlap instanceof MustTotallyOverlap } - cached Type getInstructionOperandType(Instruction instruction, TypedOperandTag tag) { + cached + Type getInstructionOperandType(Instruction instruction, TypedOperandTag tag) { // For all `LoadInstruction`s, the operand type of the `LoadOperand` is the same as // the result type of the load. - result = instruction.(LoadInstruction).getResultType() or - ( - not instruction instanceof LoadInstruction and - result = getInstructionTranslatedElement(instruction).getInstructionOperandType( - getInstructionTag(instruction), tag) - ) + result = instruction.(LoadInstruction).getResultType() + or + not instruction instanceof LoadInstruction and + result = getInstructionTranslatedElement(instruction) + .getInstructionOperandType(getInstructionTag(instruction), tag) } - cached int getInstructionOperandSize(Instruction instruction, SideEffectOperandTag tag) { - result = getInstructionTranslatedElement(instruction).getInstructionOperandSize( - getInstructionTag(instruction), tag) + cached + int getInstructionOperandSize(Instruction instruction, SideEffectOperandTag tag) { + result = getInstructionTranslatedElement(instruction) + .getInstructionOperandSize(getInstructionTag(instruction), tag) } - - cached Instruction getPhiOperandDefinition(PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap) { + + cached + Instruction getPhiOperandDefinition( + PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap + ) { none() } - cached Instruction getPhiInstructionBlockStart(PhiInstruction instr) { - none() - } + cached + Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() } - cached Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { - result = getInstructionTranslatedElement(instruction).getInstructionSuccessor( - getInstructionTag(instruction), kind) + cached + Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) { + result = getInstructionTranslatedElement(instruction) + .getInstructionSuccessor(getInstructionTag(instruction), kind) } // This predicate has pragma[noopt] because otherwise the `getAChild*` calls @@ -110,7 +120,8 @@ cached private module Cached { // - Find all edges into the start of the loop (x 2). // - Restrict to edges that originate within the loop (/ 2). pragma[noopt] - cached Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) { + cached + Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) { // While loop: // Any edge from within the body of the loop to the condition of the loop // is a back edge. This includes edges from `continue` and the fall-through @@ -173,10 +184,7 @@ cached private module Cached { result = condition.getFirstInstruction() and exists(TranslatedElement inUpdate, InstructionTag tag | result = inUpdate.getInstructionSuccessor(tag, kind) and - exists(TranslatedElement update | - update = s.getUpdate() | - inUpdate = update.getAChild*() - ) and + exists(TranslatedElement update | update = s.getUpdate() | inUpdate = update.getAChild*()) and instruction = inUpdate.getInstruction(tag) ) ) @@ -203,93 +211,104 @@ cached private module Cached { goto.getLocation().isBefore(goto.getTarget().getLocation()) } - cached Locatable getInstructionAST(Instruction instruction) { + cached + Locatable getInstructionAST(Instruction instruction) { result = getInstructionTranslatedElement(instruction).getAST() } - cached predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) { + cached + predicate instructionHasType(Instruction instruction, Type type, boolean isGLValue) { getInstructionTranslatedElement(instruction) - .hasInstruction(_, getInstructionTag(instruction), type, isGLValue) + .hasInstruction(_, getInstructionTag(instruction), type, isGLValue) } - cached Opcode getInstructionOpcode(Instruction instruction) { + cached + Opcode getInstructionOpcode(Instruction instruction) { getInstructionTranslatedElement(instruction) - .hasInstruction(result, getInstructionTag(instruction), _, _) + .hasInstruction(result, getInstructionTag(instruction), _, _) } - cached IRFunction getInstructionEnclosingIRFunction(Instruction instruction) { + cached + IRFunction getInstructionEnclosingIRFunction(Instruction instruction) { result.getFunction() = getInstructionTranslatedElement(instruction).getFunction() } - cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction).getInstructionVariable( - getInstructionTag(instruction)) + cached + IRVariable getInstructionVariable(Instruction instruction) { + result = getInstructionTranslatedElement(instruction) + .getInstructionVariable(getInstructionTag(instruction)) } - cached Field getInstructionField(Instruction instruction) { + cached + Field getInstructionField(Instruction instruction) { exists(TranslatedElement element, InstructionTag tag | instructionOrigin(instruction, element, tag) and result = element.getInstructionField(tag) ) } - cached Function getInstructionFunction(Instruction instruction) { + cached + Function getInstructionFunction(Instruction instruction) { result = getInstructionTranslatedElement(instruction) - .getInstructionFunction(getInstructionTag(instruction)) + .getInstructionFunction(getInstructionTag(instruction)) } - cached string getInstructionConstantValue(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionConstantValue( - getInstructionTag(instruction)) + cached + string getInstructionConstantValue(Instruction instruction) { + result = getInstructionTranslatedElement(instruction) + .getInstructionConstantValue(getInstructionTag(instruction)) } - cached StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionStringLiteral( - getInstructionTag(instruction)) + cached + StringLiteral getInstructionStringLiteral(Instruction instruction) { + result = getInstructionTranslatedElement(instruction) + .getInstructionStringLiteral(getInstructionTag(instruction)) } - cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionBuiltInOperation( - getInstructionTag(instruction)) + cached + BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { + result = getInstructionTranslatedElement(instruction) + .getInstructionBuiltInOperation(getInstructionTag(instruction)) } - cached Type getInstructionExceptionType(Instruction instruction) { - result = - getInstructionTranslatedElement(instruction).getInstructionExceptionType( - getInstructionTag(instruction)) + cached + Type getInstructionExceptionType(Instruction instruction) { + result = getInstructionTranslatedElement(instruction) + .getInstructionExceptionType(getInstructionTag(instruction)) } - cached predicate getInstructionInheritance(Instruction instruction, - Class baseClass, Class derivedClass) { - getInstructionTranslatedElement(instruction).getInstructionInheritance( - getInstructionTag(instruction), baseClass, derivedClass) + cached + predicate getInstructionInheritance(Instruction instruction, Class baseClass, Class derivedClass) { + getInstructionTranslatedElement(instruction) + .getInstructionInheritance(getInstructionTag(instruction), baseClass, derivedClass) } pragma[noinline] - private predicate instructionOrigin(Instruction instruction, - TranslatedElement element, InstructionTag tag) { + private predicate instructionOrigin( + Instruction instruction, TranslatedElement element, InstructionTag tag + ) { element = getInstructionTranslatedElement(instruction) and tag = getInstructionTag(instruction) } - cached int getInstructionElementSize(Instruction instruction) { + cached + int getInstructionElementSize(Instruction instruction) { exists(TranslatedElement element, InstructionTag tag | instructionOrigin(instruction, element, tag) and result = element.getInstructionElementSize(tag) ) } - cached int getInstructionResultSize(Instruction instruction) { + cached + int getInstructionResultSize(Instruction instruction) { exists(TranslatedElement element, InstructionTag tag | instructionOrigin(instruction, element, tag) and result = element.getInstructionResultSize(tag) ) } - cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) { + cached + Instruction getPrimaryInstructionForSideEffect(Instruction instruction) { exists(TranslatedElement element, InstructionTag tag | instructionOrigin(instruction, element, tag) and result = element.getPrimaryInstructionForSideEffect(tag) @@ -298,16 +317,20 @@ cached private module Cached { } import CachedForDebugging -cached private module CachedForDebugging { - cached string getTempVariableUniqueId(IRTempVariable var) { + +cached +private module CachedForDebugging { + cached + string getTempVariableUniqueId(IRTempVariable var) { exists(TranslatedElement element | var = element.getTempVariable(_) and result = element.getId() + ":" + getTempVariableTagId(var.getTag()) ) } - cached string getInstructionUniqueId(Instruction instruction) { + cached + string getInstructionUniqueId(Instruction instruction) { result = getInstructionTranslatedElement(instruction).getId() + ":" + - getInstructionTagId(getInstructionTag(instruction)) + getInstructionTagId(getInstructionTag(instruction)) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index c60c726a0c0..ddac5692cdf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -1,7 +1,7 @@ private import cpp newtype TInstructionTag = - OnlyInstructionTag() or // Single instruction (not including implicit Load) + OnlyInstructionTag() or // Single instruction (not including implicit Load) InitializeThisTag() or InitializerVariableAddressTag() or InitializerLoadStringTag() or @@ -44,7 +44,7 @@ newtype TInstructionTag = ConditionValueResultLoadTag() or BoolConversionConstantTag() or BoolConversionCompareTag() or - LoadTag() or // Implicit load due to lvalue-to-rvalue conversion + LoadTag() or // Implicit load due to lvalue-to-rvalue conversion CatchTag() or ThrowTag() or UnwindTag() or @@ -57,16 +57,10 @@ newtype TInstructionTag = InitializerElementDefaultValueTag() or InitializerElementDefaultValueStoreTag() or AsmTag() or - AsmInputTag(int elementIndex) { - exists(AsmStmt asm | - exists(asm.getChild(elementIndex)) - ) - } + AsmInputTag(int elementIndex) { exists(AsmStmt asm | exists(asm.getChild(elementIndex))) } class InstructionTag extends TInstructionTag { - final string toString() { - result = "Tag" - } + final string toString() { result = "Tag" } } /** @@ -74,62 +68,115 @@ class InstructionTag extends TInstructionTag { * instruction IDs to ensure stable IR dumps. */ string getInstructionTagId(TInstructionTag tag) { - tag = OnlyInstructionTag() and result = "Only" or // Single instruction (not including implicit Load) - tag = InitializerVariableAddressTag() and result = "InitVarAddr" or - tag = InitializerLoadStringTag() and result = "InitLoadStr" or - tag = InitializerStoreTag() and result = "InitStore" or - tag = InitializerUninitializedTag() and result = "InitUninit" or - tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or - tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" or - tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" or - tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" or - tag = AssignOperationLoadTag() and result = "AssignOpLoad" or - tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" or - tag = AssignOperationOpTag() and result = "AssignOpOp" or - tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" or - tag = AssignmentStoreTag() and result = "AssignStore" or - tag = CrementLoadTag() and result = "CrementLoad" or - tag = CrementConstantTag() and result = "CrementConst" or - tag = CrementOpTag() and result = "CrementOp" or - tag = CrementStoreTag() and result = "CrementStore" or - tag = EnterFunctionTag() and result = "EnterFunc" or - tag = ReturnValueAddressTag() and result = "RetValAddr" or - tag = ReturnTag() and result = "Ret" or - tag = ExitFunctionTag() and result = "ExitFunc" or - tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" or - tag = UnmodeledUseTag() and result = "UnmodeledUse" or - tag = AliasedDefinitionTag() and result = "AliasedDef" or - tag = SwitchBranchTag() and result = "SwitchBranch" or - tag = CallTargetTag() and result = "CallTarget" or - tag = CallTag() and result = "Call" or - tag = CallSideEffectTag() and result = "CallSideEffect" or - tag = AllocationSizeTag() and result = "AllocSize" or - tag = AllocationElementSizeTag() and result = "AllocElemSize" or - tag = AllocationExtentConvertTag() and result = "AllocExtConv" or - tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" or - tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" or - tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" or - tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" or - tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" or - tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" or - tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" or - tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" or - tag = ConditionValueResultLoadTag() and result = "CondValResLoad" or - tag = BoolConversionConstantTag() and result = "BoolConvConst" or - tag = BoolConversionCompareTag() and result = "BoolConvComp" or - tag = LoadTag() and result = "Load" or // Implicit load due to lvalue-to-rvalue conversion - tag = CatchTag() and result = "Catch" or - tag = ThrowTag() and result = "Throw" or - tag = UnwindTag() and result = "Unwind" or - tag = InitializerFieldAddressTag() and result = "InitFieldAddr" or - tag = InitializerFieldDefaultValueTag() and result = "InitFieldDefVal" or - tag = InitializerFieldDefaultValueStoreTag() and result = "InitFieldDefValStore" or - tag = InitializerElementIndexTag() and result = "InitElemIndex" or - tag = InitializerElementAddressTag() and result = "InitElemAddr" or - tag = InitializerElementDefaultValueTag() and result = "InitElemDefVal" or - tag = InitializerElementDefaultValueStoreTag() and result = "InitElemDefValStore" or - tag = AsmTag() and result = "Asm" or - exists(int index | - tag = AsmInputTag(index) and result = "AsmInputTag(" + index + ")" - ) + tag = OnlyInstructionTag() and result = "Only" // Single instruction (not including implicit Load) + or + tag = InitializerVariableAddressTag() and result = "InitVarAddr" + or + tag = InitializerLoadStringTag() and result = "InitLoadStr" + or + tag = InitializerStoreTag() and result = "InitStore" + or + tag = InitializerUninitializedTag() and result = "InitUninit" + or + tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" + or + tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" + or + tag = ZeroPadStringElementAddressTag() and result = "ZeroPadElemAddr" + or + tag = ZeroPadStringStoreTag() and result = "ZeroPadStore" + or + tag = AssignOperationLoadTag() and result = "AssignOpLoad" + or + tag = AssignOperationConvertLeftTag() and result = "AssignOpConvLeft" + or + tag = AssignOperationOpTag() and result = "AssignOpOp" + or + tag = AssignOperationConvertResultTag() and result = "AssignOpConvRes" + or + tag = AssignmentStoreTag() and result = "AssignStore" + or + tag = CrementLoadTag() and result = "CrementLoad" + or + tag = CrementConstantTag() and result = "CrementConst" + or + tag = CrementOpTag() and result = "CrementOp" + or + tag = CrementStoreTag() and result = "CrementStore" + or + tag = EnterFunctionTag() and result = "EnterFunc" + or + tag = ReturnValueAddressTag() and result = "RetValAddr" + or + tag = ReturnTag() and result = "Ret" + or + tag = ExitFunctionTag() and result = "ExitFunc" + or + tag = UnmodeledDefinitionTag() and result = "UnmodeledDef" + or + tag = UnmodeledUseTag() and result = "UnmodeledUse" + or + tag = AliasedDefinitionTag() and result = "AliasedDef" + or + tag = SwitchBranchTag() and result = "SwitchBranch" + or + tag = CallTargetTag() and result = "CallTarget" + or + tag = CallTag() and result = "Call" + or + tag = CallSideEffectTag() and result = "CallSideEffect" + or + tag = AllocationSizeTag() and result = "AllocSize" + or + tag = AllocationElementSizeTag() and result = "AllocElemSize" + or + tag = AllocationExtentConvertTag() and result = "AllocExtConv" + or + tag = ValueConditionConditionalBranchTag() and result = "ValCondCondBranch" + or + tag = ConditionValueTrueTempAddressTag() and result = "CondValTrueTempAddr" + or + tag = ConditionValueTrueConstantTag() and result = "CondValTrueConst" + or + tag = ConditionValueTrueStoreTag() and result = "CondValTrueStore" + or + tag = ConditionValueFalseTempAddressTag() and result = "CondValFalseTempAddr" + or + tag = ConditionValueFalseConstantTag() and result = "CondValFalseConst" + or + tag = ConditionValueFalseStoreTag() and result = "CondValFalseStore" + or + tag = ConditionValueResultTempAddressTag() and result = "CondValResTempAddr" + or + tag = ConditionValueResultLoadTag() and result = "CondValResLoad" + or + tag = BoolConversionConstantTag() and result = "BoolConvConst" + or + tag = BoolConversionCompareTag() and result = "BoolConvComp" + or + tag = LoadTag() and result = "Load" // Implicit load due to lvalue-to-rvalue conversion + or + tag = CatchTag() and result = "Catch" + or + tag = ThrowTag() and result = "Throw" + or + tag = UnwindTag() and result = "Unwind" + or + tag = InitializerFieldAddressTag() and result = "InitFieldAddr" + or + tag = InitializerFieldDefaultValueTag() and result = "InitFieldDefVal" + or + tag = InitializerFieldDefaultValueStoreTag() and result = "InitFieldDefValStore" + or + tag = InitializerElementIndexTag() and result = "InitElemIndex" + or + tag = InitializerElementAddressTag() and result = "InitElemAddr" + or + tag = InitializerElementDefaultValueTag() and result = "InitElemDefVal" + or + tag = InitializerElementDefaultValueStoreTag() and result = "InitElemDefValStore" + or + tag = AsmTag() and result = "Asm" + or + exists(int index | tag = AsmInputTag(index) and result = "AsmInputTag(" + index + ")") } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 6058e2e379f..14168217d9b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -12,123 +12,107 @@ private import TranslatedExpr * of a higher-level constructor (e.g. the allocator call in a `NewExpr`). */ abstract class TranslatedCall extends TranslatedExpr { - override final TranslatedElement getChild(int id) { + final override TranslatedElement getChild(int id) { // We choose the child's id in the order of evaluation. // The qualifier is evaluated before the call target, because the value of // the call target may depend on the value of the qualifier for virtual // calls. - id = -2 and result = getQualifier() or - id = -1 and result = getCallTarget() or + id = -2 and result = getQualifier() + or + id = -1 and result = getCallTarget() + or result = getArgument(id) } - override final Instruction getFirstInstruction() { - if exists(getQualifier()) then - result = getQualifier().getFirstInstruction() - else - result = getFirstCallTargetInstruction() + final override Instruction getFirstInstruction() { + if exists(getQualifier()) + then result = getQualifier().getFirstInstruction() + else result = getFirstCallTargetInstruction() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = CallTag() and + opcode instanceof Opcode::Call and + resultType = getCallResultType() and + isGLValue = false + or + hasSideEffect() and + tag = CallSideEffectTag() and ( - tag = CallTag() and - opcode instanceof Opcode::Call and - resultType = getCallResultType() and - isGLValue = false - ) or - ( - hasSideEffect() and - tag = CallSideEffectTag() and - ( - if hasWriteSideEffect() then ( - opcode instanceof Opcode::CallSideEffect and - resultType instanceof UnknownType - ) - else ( - opcode instanceof Opcode::CallReadSideEffect and - resultType instanceof VoidType - ) - ) and - isGLValue = false - ) + if hasWriteSideEffect() + then ( + opcode instanceof Opcode::CallSideEffect and + resultType instanceof UnknownType + ) else ( + opcode instanceof Opcode::CallReadSideEffect and + resultType instanceof VoidType + ) + ) and + isGLValue = false } - + override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getQualifier() and - result = getFirstCallTargetInstruction() - ) or - ( - child = getCallTarget() and - result = getFirstArgumentOrCallInstruction() - ) or + child = getQualifier() and + result = getFirstCallTargetInstruction() + or + child = getCallTarget() and + result = getFirstArgumentOrCallInstruction() + or exists(int argIndex | child = getArgument(argIndex) and - if exists(getArgument(argIndex + 1)) then - result = getArgument(argIndex + 1).getFirstInstruction() - else - result = getInstruction(CallTag()) + if exists(getArgument(argIndex + 1)) + then result = getArgument(argIndex + 1).getFirstInstruction() + else result = getInstruction(CallTag()) ) } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( ( tag = CallTag() and - if hasSideEffect() then - result = getInstruction(CallSideEffectTag()) - else - result = getParent().getChildSuccessor(this) - ) or - ( - hasSideEffect() and - tag = CallSideEffectTag() and - result = getParent().getChildSuccessor(this) + if hasSideEffect() + then result = getInstruction(CallSideEffectTag()) + else result = getParent().getChildSuccessor(this) ) - ) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - ( - tag = CallTag() and - ( - ( - operandTag instanceof CallTargetOperandTag and - result = getCallTargetResult() - ) or - ( - operandTag instanceof ThisArgumentOperandTag and - result = getQualifierResult() - ) or - exists(PositionalArgumentOperandTag argTag | - argTag = operandTag and - result = getArgument(argTag.getArgIndex()).getResult() - ) - ) - ) or - ( - tag = CallSideEffectTag() and + or hasSideEffect() and - operandTag instanceof SideEffectOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() + tag = CallSideEffectTag() and + result = getParent().getChildSuccessor(this) ) } - override final Type getInstructionOperandType(InstructionTag tag, - TypedOperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = CallTag() and + ( + operandTag instanceof CallTargetOperandTag and + result = getCallTargetResult() + or + operandTag instanceof ThisArgumentOperandTag and + result = getQualifierResult() + or + exists(PositionalArgumentOperandTag argTag | + argTag = operandTag and + result = getArgument(argTag.getArgIndex()).getResult() + ) + ) + or + tag = CallSideEffectTag() and + hasSideEffect() and + operandTag instanceof SideEffectOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() + } + + final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { tag = CallSideEffectTag() and hasSideEffect() and operandTag instanceof SideEffectOperandTag and result instanceof UnknownType } - override final Instruction getResult() { - result = getInstruction(CallTag()) - } + final override Instruction getResult() { result = getInstruction(CallTag()) } /** * Gets the result type of the call. @@ -138,16 +122,12 @@ abstract class TranslatedCall extends TranslatedExpr { /** * Holds if the call has a `this` argument. */ - predicate hasQualifier() { - exists(getQualifier()) - } + predicate hasQualifier() { exists(getQualifier()) } /** * Gets the `TranslatedExpr` for the indirect target of the call, if any. */ - TranslatedExpr getCallTarget() { - none() - } + TranslatedExpr getCallTarget() { none() } /** * Gets the first instruction of the sequence to evaluate the call target. @@ -155,9 +135,7 @@ abstract class TranslatedCall extends TranslatedExpr { * it can be overridden by a subclass for cases where there is a call target * that is not computed from an expression (e.g. a direct call). */ - Instruction getFirstCallTargetInstruction() { - result = getCallTarget().getFirstInstruction() - } + Instruction getFirstCallTargetInstruction() { result = getCallTarget().getFirstInstruction() } /** * Gets the instruction whose result value is the target of the call. By @@ -165,9 +143,7 @@ abstract class TranslatedCall extends TranslatedExpr { * overridden by a subclass for cases where there is a call target that is not * computed from an expression (e.g. a direct call). */ - Instruction getCallTargetResult() { - result = getCallTarget().getResult() - } + Instruction getCallTargetResult() { result = getCallTarget().getResult() } /** * Gets the `TranslatedExpr` for the qualifier of the call (i.e. the value @@ -181,9 +157,7 @@ abstract class TranslatedCall extends TranslatedExpr { * overridden by a subclass for cases where there is a `this` argument that is * not computed from a child expression (e.g. a constructor call). */ - Instruction getQualifierResult() { - result = getQualifier().getResult() - } + Instruction getQualifierResult() { result = getQualifier().getResult() } /** * Gets the argument with the specified `index`. Does not include the `this` @@ -196,10 +170,9 @@ abstract class TranslatedCall extends TranslatedExpr { * argument. Otherwise, returns the call instruction. */ final Instruction getFirstArgumentOrCallInstruction() { - if hasArguments() then - result = getArgument(0).getFirstInstruction() - else - result = getInstruction(CallTag()) + if hasArguments() + then result = getArgument(0).getFirstInstruction() + else result = getInstruction(CallTag()) } /** @@ -207,22 +180,16 @@ abstract class TranslatedCall extends TranslatedExpr { */ abstract predicate hasArguments(); - predicate hasReadSideEffect() { - any() - } + predicate hasReadSideEffect() { any() } - predicate hasWriteSideEffect() { - any() - } + predicate hasWriteSideEffect() { any() } - private predicate hasSideEffect() { - hasReadSideEffect() or hasWriteSideEffect() - } + private predicate hasSideEffect() { hasReadSideEffect() or hasWriteSideEffect() } override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { - hasSideEffect() and - tag = CallSideEffectTag() and - result = getResult() + hasSideEffect() and + tag = CallSideEffectTag() and + result = getResult() } } @@ -232,59 +199,50 @@ abstract class TranslatedCall extends TranslatedExpr { * (`TranslatedAllocatorCall`). */ abstract class TranslatedDirectCall extends TranslatedCall { - override final Instruction getFirstCallTargetInstruction() { + final override Instruction getFirstCallTargetInstruction() { result = getInstruction(CallTargetTag()) } - override final Instruction getCallTargetResult() { - result = getInstruction(CallTargetTag()) + final override Instruction getCallTargetResult() { result = getInstruction(CallTargetTag()) } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + TranslatedCall.super.hasInstruction(opcode, tag, resultType, isGLValue) + or + tag = CallTargetTag() and + opcode instanceof Opcode::FunctionAddress and + // The database does not contain a `FunctionType` for a function unless + // its address was taken, so we'll just use glval instead of + // glval. + resultType instanceof UnknownType and + isGLValue = true } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - TranslatedCall.super.hasInstruction(opcode, tag, resultType, isGLValue) or - ( - tag = CallTargetTag() and - opcode instanceof Opcode::FunctionAddress and - // The database does not contain a `FunctionType` for a function unless - // its address was taken, so we'll just use glval instead of - // glval. - resultType instanceof UnknownType and - isGLValue = true - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - result = TranslatedCall.super.getInstructionSuccessor(tag, kind) or - ( - tag = CallTargetTag() and - kind instanceof GotoEdge and - result = getFirstArgumentOrCallInstruction() - ) + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + result = TranslatedCall.super.getInstructionSuccessor(tag, kind) + or + tag = CallTargetTag() and + kind instanceof GotoEdge and + result = getFirstArgumentOrCallInstruction() } } /** * The IR translation of a call to a function. */ -abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, - TranslatedCall { +abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedCall { override Call expr; - override final Type getCallResultType() { - result = getResultType() - } + final override Type getCallResultType() { result = getResultType() } - override final predicate hasArguments() { - exists(expr.getArgument(0)) - } + final override predicate hasArguments() { exists(expr.getArgument(0)) } - override final TranslatedExpr getQualifier() { + final override TranslatedExpr getQualifier() { result = getTranslatedExpr(expr.getQualifier().getFullyConverted()) } - override final TranslatedExpr getArgument(int index) { + final override TranslatedExpr getArgument(int index) { result = getTranslatedExpr(expr.getArgument(index).getFullyConverted()) } } @@ -295,7 +253,6 @@ abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, class TranslatedExprCall extends TranslatedCallExpr { override ExprCall expr; - override TranslatedExpr getCallTarget() { result = getTranslatedExpr(expr.getExpr().getFullyConverted()) } @@ -336,7 +293,5 @@ class TranslatedStructorCall extends TranslatedFunctionCall { ) } - override predicate hasQualifier() { - any() - } + override predicate hasQualifier() { any() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll index 44ac77cc3d8..6c501ef4284 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll @@ -11,65 +11,41 @@ abstract class ConditionContext extends TranslatedElement { abstract Instruction getChildFalseSuccessor(TranslatedCondition child); } -TranslatedCondition getTranslatedCondition(Expr expr) { - result.getExpr() = expr -} +TranslatedCondition getTranslatedCondition(Expr expr) { result.getExpr() = expr } abstract class TranslatedCondition extends TranslatedElement { Expr expr; - override final string toString() { - result = expr.toString() - } + final override string toString() { result = expr.toString() } - override final Locatable getAST() { - result = expr - } + final override Locatable getAST() { result = expr } - final ConditionContext getConditionContext() { - result = getParent() - } + final ConditionContext getConditionContext() { result = getParent() } - final Expr getExpr() { - result = expr - } + final Expr getExpr() { result = expr } - override final Function getFunction() { - result = expr.getEnclosingFunction() - } + final override Function getFunction() { result = expr.getEnclosingFunction() } - final Type getResultType() { - result = expr.getUnspecifiedType() - } + final Type getResultType() { result = expr.getUnspecifiedType() } } -abstract class TranslatedFlexibleCondition extends TranslatedCondition, - ConditionContext, TTranslatedFlexibleCondition { - TranslatedFlexibleCondition() { - this = TTranslatedFlexibleCondition(expr) - } +abstract class TranslatedFlexibleCondition extends TranslatedCondition, ConditionContext, + TTranslatedFlexibleCondition { + TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) } - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } + final override Instruction getChildSuccessor(TranslatedElement child) { none() } abstract TranslatedCondition getOperand(); } @@ -104,45 +80,38 @@ class TranslatedNotCondition extends TranslatedFlexibleCondition { child = getOperand() and result = getConditionContext().getChildTrueSuccessor(this) } - + override TranslatedCondition getOperand() { result = getTranslatedCondition(expr.getOperand().getFullyConverted()) } } -abstract class TranslatedNativeCondition extends TranslatedCondition, - TTranslatedNativeCondition { - TranslatedNativeCondition() { - this = TTranslatedNativeCondition(expr) - } +abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition { + TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) } - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } + final override Instruction getChildSuccessor(TranslatedElement child) { none() } } -abstract class TranslatedBinaryLogicalOperation extends - TranslatedNativeCondition, ConditionContext { +abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeCondition, ConditionContext { override BinaryLogicalOperation expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getLeftOperand() + or id = 1 and result = getRightOperand() } - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { result = getLeftOperand().getFirstInstruction() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } final TranslatedCondition getLeftOperand() { result = getTranslatedCondition(expr.getLeftOperand().getFullyConverted()) @@ -154,19 +123,14 @@ abstract class TranslatedBinaryLogicalOperation extends } class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation { - TranslatedLogicalAndExpr() { - expr instanceof LogicalAndExpr - } + TranslatedLogicalAndExpr() { expr instanceof LogicalAndExpr } override Instruction getChildTrueSuccessor(TranslatedCondition child) { - ( - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() - ) or - ( - child = getRightOperand() and - result = getConditionContext().getChildTrueSuccessor(this) - ) + child = getLeftOperand() and + result = getRightOperand().getFirstInstruction() + or + child = getRightOperand() and + result = getConditionContext().getChildTrueSuccessor(this) } override Instruction getChildFalseSuccessor(TranslatedCondition child) { @@ -184,33 +148,24 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { } override Instruction getChildFalseSuccessor(TranslatedCondition child) { - ( - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() - ) or - ( - child = getRightOperand() and - result = getConditionContext().getChildFalseSuccessor(this) - ) + child = getLeftOperand() and + result = getRightOperand().getFirstInstruction() + or + child = getRightOperand() and + result = getConditionContext().getChildFalseSuccessor(this) } } -class TranslatedValueCondition extends TranslatedCondition, - TTranslatedValueCondition { - TranslatedValueCondition() { - this = TTranslatedValueCondition(expr) - } +class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCondition { + TranslatedValueCondition() { this = TTranslatedValueCondition(expr) } - override TranslatedElement getChild(int id) { - id = 0 and result = getValueExpr() - } + override TranslatedElement getChild(int id) { id = 0 and result = getValueExpr() } - override Instruction getFirstInstruction() { - result = getValueExpr().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getValueExpr().getFirstInstruction() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = ValueConditionConditionalBranchTag() and opcode instanceof Opcode::ConditionalBranch and resultType instanceof VoidType and @@ -222,29 +177,22 @@ class TranslatedValueCondition extends TranslatedCondition, result = getInstruction(ValueConditionConditionalBranchTag()) } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = ValueConditionConditionalBranchTag() and ( - ( - kind instanceof TrueEdge and - result = getConditionContext().getChildTrueSuccessor(this) - ) or - ( - kind instanceof FalseEdge and - result = getConditionContext().getChildFalseSuccessor(this) - ) + kind instanceof TrueEdge and + result = getConditionContext().getChildTrueSuccessor(this) + or + kind instanceof FalseEdge and + result = getConditionContext().getChildFalseSuccessor(this) ) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = ValueConditionConditionalBranchTag() and operandTag instanceof ConditionOperandTag and result = getValueExpr().getResult() } - private TranslatedExpr getValueExpr() { - result = getTranslatedExpr(expr) - } + private TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 5feff1c4fc3..1efe8cf9f78 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -24,24 +24,18 @@ TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslatedDeclarationEntry { DeclarationEntry entry; - TranslatedDeclarationEntry() { - this = TTranslatedDeclarationEntry(entry) - } + TranslatedDeclarationEntry() { this = TTranslatedDeclarationEntry(entry) } - override final Function getFunction() { + final override Function getFunction() { exists(DeclStmt stmt | stmt.getADeclarationEntry() = entry and result = stmt.getEnclosingFunction() ) } - override final string toString() { - result = entry.toString() - } + final override string toString() { result = entry.toString() } - override final Locatable getAST() { - result = entry - } + final override Locatable getAST() { result = entry } } /** @@ -54,49 +48,43 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali */ abstract LocalVariable getVariable(); - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } + override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } override Instruction getFirstInstruction() { result = getInstruction(InitializerVariableAddressTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = getVariableType(getVariable()) and - isGLValue = true - ) or - ( - hasUninitializedInstruction() and - tag = InitializerStoreTag() and - opcode instanceof Opcode::Uninitialized and - resultType = getVariableType(getVariable()) and - isGLValue = false - ) + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getVariableType(getVariable()) and + isGLValue = true + or + hasUninitializedInstruction() and + tag = InitializerStoreTag() and + opcode instanceof Opcode::Uninitialized and + resultType = getVariableType(getVariable()) and + isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { ( tag = InitializerVariableAddressTag() and kind instanceof GotoEdge and - if hasUninitializedInstruction() then - result = getInstruction(InitializerStoreTag()) - else - result = getInitialization().getFirstInstruction() - ) or + if hasUninitializedInstruction() + then result = getInstruction(InitializerStoreTag()) + else result = getInitialization().getFirstInstruction() + ) + or + hasUninitializedInstruction() and + kind instanceof GotoEdge and + tag = InitializerStoreTag() and ( - hasUninitializedInstruction() and - kind instanceof GotoEdge and - tag = InitializerStoreTag() and - ( - result = getInitialization().getFirstInstruction() or - not exists(getInitialization()) and result = getParent().getChildSuccessor(this) - ) + result = getInitialization().getFirstInstruction() + or + not exists(getInitialization()) and result = getParent().getChildSuccessor(this) ) } @@ -106,7 +94,8 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali override IRVariable getInstructionVariable(InstructionTag tag) { ( - tag = InitializerVariableAddressTag() or + tag = InitializerVariableAddressTag() + or hasUninitializedInstruction() and tag = InitializerStoreTag() ) and result = getIRUserVariable(getFunction(), getVariable()) @@ -123,12 +112,13 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali result = getInstruction(InitializerVariableAddressTag()) } - override Type getTargetType() { - result = getVariableType(getVariable()) - } + override Type getTargetType() { result = getVariableType(getVariable()) } private TranslatedInitialization getInitialization() { - result = getTranslatedInitialization(getVariable().getInitializer().getExpr().getFullyConverted()) + result = getTranslatedInitialization(getVariable() + .getInitializer() + .getExpr() + .getFullyConverted()) } private predicate hasUninitializedInstruction() { @@ -141,16 +131,12 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali * Represents the IR translation of a local variable declaration within a declaration statement. */ class TranslatedVariableDeclarationEntry extends TranslatedVariableDeclaration, - TranslatedDeclarationEntry { + TranslatedDeclarationEntry { LocalVariable var; - TranslatedVariableDeclarationEntry() { - var = entry.getDeclaration() - } + TranslatedVariableDeclarationEntry() { var = entry.getDeclaration() } - override LocalVariable getVariable() { - result = var - } + override LocalVariable getVariable() { result = var } } /** @@ -158,7 +144,8 @@ class TranslatedVariableDeclarationEntry extends TranslatedVariableDeclaration, * `var`. */ TranslatedRangeBasedForVariableDeclaration getTranslatedRangeBasedForVariableDeclaration( - LocalVariable var) { + LocalVariable var +) { result.getVariable() = var } @@ -166,7 +153,7 @@ TranslatedRangeBasedForVariableDeclaration getTranslatedRangeBasedForVariableDec * Represents the IR translation of a compiler-generated variable in a range-based `for` loop. */ class TranslatedRangeBasedForVariableDeclaration extends TranslatedVariableDeclaration, - TTranslatedRangeBasedForVariableDeclaration { + TTranslatedRangeBasedForVariableDeclaration { RangeBasedForStmt forStmt; LocalVariable var; @@ -174,21 +161,13 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedVariableDecla this = TTranslatedRangeBasedForVariableDeclaration(forStmt, var) } - override string toString() { - result = var.toString() - } + override string toString() { result = var.toString() } - override Locatable getAST() { - result = var - } + override Locatable getAST() { result = var } - override Function getFunction() { - result = forStmt.getEnclosingFunction() - } + override Function getFunction() { result = forStmt.getEnclosingFunction() } - override LocalVariable getVariable() { - result = var - } + override LocalVariable getVariable() { result = var } } TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) { @@ -206,23 +185,13 @@ TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) { class TranslatedConditionDecl extends TranslatedVariableDeclaration, TTranslatedConditionDecl { ConditionDeclExpr conditionDeclExpr; - TranslatedConditionDecl() { - this = TTranslatedConditionDecl(conditionDeclExpr) - } + TranslatedConditionDecl() { this = TTranslatedConditionDecl(conditionDeclExpr) } - override string toString() { - result = "decl: " + conditionDeclExpr.toString() - } + override string toString() { result = "decl: " + conditionDeclExpr.toString() } - override Locatable getAST() { - result = conditionDeclExpr - } + override Locatable getAST() { result = conditionDeclExpr } - override Function getFunction() { - result = conditionDeclExpr.getEnclosingFunction() - } + override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() } - override LocalVariable getVariable() { - result = conditionDeclExpr.getVariable() - } + override LocalVariable getVariable() { result = conditionDeclExpr.getVariable() } } 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 4fe1f4addcc..23d3036ca15 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 @@ -13,9 +13,7 @@ private import IRConstruction /** * Gets the built-in `int` type. */ -Type getIntType() { - result.(IntType).isImplicitlySigned() -} +Type getIntType() { result.(IntType).isImplicitlySigned() } /** * Gets the "real" parent of `expr`. This predicate treats conversions as if @@ -36,9 +34,7 @@ private Element getRealParent(Expr expr) { predicate isIRConstant(Expr expr) { exists(expr.getValue()) } // Pulled out to work around QL-796 -private predicate isOrphan(Expr expr) { - not exists(getRealParent(expr)) -} +private predicate isOrphan(Expr expr) { not exists(getRealParent(expr)) } /** * Holds if `expr` should be ignored for the purposes of IR generation due to @@ -46,29 +42,35 @@ private predicate isOrphan(Expr expr) { */ private predicate ignoreExprAndDescendants(Expr expr) { // Ignore parentless expressions - isOrphan(expr) or + isOrphan(expr) + or // Ignore the constants in SwitchCase, since their values are embedded in the // CaseEdge. - getRealParent(expr) instanceof SwitchCase or + getRealParent(expr) instanceof SwitchCase + or // Ignore descendants of constant expressions, since we'll just substitute the // constant value. - isIRConstant(getRealParent(expr)) or + isIRConstant(getRealParent(expr)) + or // The `DestructorCall` node for a `DestructorFieldDestruction` has a `FieldAccess` // node as its qualifier, but that `FieldAccess` does not have a child of its own. // We'll ignore that `FieldAccess`, and supply the receiver as part of the calling // context, much like we do with constructor calls. - expr.getParent().(DestructorCall).getParent() instanceof DestructorFieldDestruction or + expr.getParent().(DestructorCall).getParent() instanceof DestructorFieldDestruction + or exists(NewArrayExpr newExpr | // REVIEW: Ignore initializers for `NewArrayExpr` until we determine how to // represent them. newExpr.getInitializer().getFullyConverted() = expr - ) or + ) + or // Do not translate input/output variables in GNU asm statements - getRealParent(expr) instanceof AsmStmt or + getRealParent(expr) instanceof AsmStmt + or ignoreExprAndDescendants(getRealParent(expr)) // recursive case + or // We do not yet translate destructors properly, so for now we ignore any // custom deallocator call, if present. - or exists(DeleteExpr deleteExpr | deleteExpr.getAllocatorCall() = expr) or exists(DeleteArrayExpr deleteArrayExpr | deleteArrayExpr.getAllocatorCall() = expr) @@ -118,13 +120,15 @@ private predicate isInvalidFunction(Function func) { // that is a `Literal` with no value. literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and not exists(literal.getValue()) - ) or + ) + or exists(ThisExpr thisExpr | // An instantiation of a member function template is not treated as a `MemberFunction` if it has // only non-type template arguments. thisExpr.getEnclosingFunction() = func and not func instanceof MemberFunction - ) or + ) + or exists(Expr expr | // Expression missing a type. expr.getEnclosingFunction() = func and @@ -139,17 +143,13 @@ private predicate translateFunction(Function func) { not func.isFromUninstantiatedTemplate(_) and func.hasEntryPoint() and not isInvalidFunction(func) and - exists(IRConfiguration config | - config.shouldCreateIRForFunction(func) - ) + exists(IRConfiguration config | config.shouldCreateIRForFunction(func)) } /** * Holds if `stmt` should be translated to IR. */ -private predicate translateStmt(Stmt stmt) { - translateFunction(stmt.getEnclosingFunction()) -} +private predicate translateStmt(Stmt stmt) { translateFunction(stmt.getEnclosingFunction()) } /** * Holds if `expr` is most naturally evaluated as control flow, rather than as @@ -181,20 +181,19 @@ private predicate usedAsCondition(Expr expr) { exists(BinaryLogicalOperation op | op.getLeftOperand().getFullyConverted() = expr or op.getRightOperand().getFullyConverted() = expr - ) or - exists(Loop loop | - loop.getCondition().getFullyConverted() = expr - ) or - exists(IfStmt ifStmt | - ifStmt.getCondition().getFullyConverted() = expr - ) or - exists(ConditionalExpr condExpr | - condExpr.getCondition().getFullyConverted() = expr - ) or + ) + or + exists(Loop loop | loop.getCondition().getFullyConverted() = expr) + or + exists(IfStmt ifStmt | ifStmt.getCondition().getFullyConverted() = expr) + or + exists(ConditionalExpr condExpr | condExpr.getCondition().getFullyConverted() = expr) + or exists(NotExpr notExpr | notExpr.getOperand().getFullyConverted() = expr and usedAsCondition(notExpr) - ) or + ) + or exists(ParenthesisExpr paren | paren.getExpr() = expr and usedAsCondition(paren) @@ -213,10 +212,10 @@ predicate ignoreLoad(Expr expr) { ( expr instanceof ThisExpr or expr instanceof FunctionAccess or - expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType(). - getUnspecifiedType() instanceof FunctionPointerType or - expr.(ReferenceDereferenceExpr).getExpr().getType(). - getUnspecifiedType() instanceof FunctionReferenceType + expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType() + instanceof FunctionPointerType or + expr.(ReferenceDereferenceExpr).getExpr().getType().getUnspecifiedType() instanceof + FunctionReferenceType ) } @@ -268,40 +267,26 @@ newtype TTranslatedElement = TTranslatedInitialization(Expr expr) { not ignoreExpr(expr) and ( - exists(Initializer init | - init.getExpr().getFullyConverted() = expr - ) or - exists(ClassAggregateLiteral initList | - initList.getFieldExpr(_).getFullyConverted() = expr - ) or + exists(Initializer init | init.getExpr().getFullyConverted() = expr) or + exists(ClassAggregateLiteral initList | initList.getFieldExpr(_).getFullyConverted() = expr) or exists(ArrayOrVectorAggregateLiteral initList | initList.getElementExpr(_).getFullyConverted() = expr ) or - exists(ReturnStmt returnStmt | - returnStmt.getExpr().getFullyConverted() = expr - ) or - exists(ConstructorFieldInit fieldInit | - fieldInit.getExpr().getFullyConverted() = expr - ) or - exists(NewExpr newExpr | - newExpr.getInitializer().getFullyConverted() = expr - ) or - exists(ThrowExpr throw | - throw.getExpr().getFullyConverted() = expr - ) or - exists(LambdaExpression lambda | - lambda.getInitializer().getFullyConverted() = expr - ) + exists(ReturnStmt returnStmt | returnStmt.getExpr().getFullyConverted() = expr) or + exists(ConstructorFieldInit fieldInit | fieldInit.getExpr().getFullyConverted() = expr) or + exists(NewExpr newExpr | newExpr.getInitializer().getFullyConverted() = expr) or + exists(ThrowExpr throw | throw.getExpr().getFullyConverted() = expr) or + exists(LambdaExpression lambda | lambda.getInitializer().getFullyConverted() = expr) ) } or // The initialization of a field via a member of an initializer list. - TTranslatedExplicitFieldInitialization(Expr ast, Field field, - Expr expr) { + TTranslatedExplicitFieldInitialization(Expr ast, Field field, Expr expr) { exists(ClassAggregateLiteral initList | not ignoreExpr(initList) and ast = initList and expr = initList.getFieldExpr(field).getFullyConverted() - ) or + ) + or exists(ConstructorFieldInit init | not ignoreExpr(init) and ast = init and @@ -319,25 +304,21 @@ newtype TTranslatedElement = ) } or // The initialization of an array element via a member of an initializer list. - TTranslatedExplicitElementInitialization( - ArrayOrVectorAggregateLiteral initList, int elementIndex) { + TTranslatedExplicitElementInitialization(ArrayOrVectorAggregateLiteral initList, int elementIndex) { not ignoreExpr(initList) and exists(initList.getElementExpr(elementIndex)) } or // The value initialization of a range of array elements that were omitted // from an initializer list. - TTranslatedElementValueInitialization(ArrayOrVectorAggregateLiteral initList, - int elementIndex, int elementCount) { + TTranslatedElementValueInitialization( + ArrayOrVectorAggregateLiteral initList, int elementIndex, int elementCount + ) { not ignoreExpr(initList) and isFirstValueInitializedElementInRange(initList, elementIndex) and - elementCount = - getEndOfValueInitializedRange(initList, elementIndex) - - elementIndex + elementCount = getEndOfValueInitializedRange(initList, elementIndex) - elementIndex } or // The initialization of a base class from within a constructor. - TTranslatedConstructorBaseInit(ConstructorBaseInit init) { - not ignoreExpr(init) - } or + TTranslatedConstructorBaseInit(ConstructorBaseInit init) { not ignoreExpr(init) } or // The destruction of a base class from within a destructor. TTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) { not ignoreExpr(destruction) @@ -347,21 +328,13 @@ newtype TTranslatedElement = not ignoreExpr(destruction) } or // A statement - TTranslatedStmt(Stmt stmt) { - translateStmt(stmt) - } or + TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or // A function - TTranslatedFunction(Function func) { - translateFunction(func) - } or + TTranslatedFunction(Function func) { translateFunction(func) } or // A constructor init list - TTranslatedConstructorInitList(Function func) { - translateFunction(func) - } or + TTranslatedConstructorInitList(Function func) { translateFunction(func) } or // A destructor destruction list - TTranslatedDestructorDestructionList(Function func) { - translateFunction(func) - } or + TTranslatedDestructorDestructionList(Function func) { translateFunction(func) } or // A function parameter TTranslatedParameter(Parameter param) { exists(Function func | @@ -386,23 +359,17 @@ newtype TTranslatedElement = TTranslatedRangeBasedForVariableDeclaration(RangeBasedForStmt forStmt, LocalVariable var) { translateStmt(forStmt) and ( - var = forStmt.getRangeVariable() or + var = forStmt.getRangeVariable() or var = forStmt.getBeginEndDeclaration().getADeclaration() or var = forStmt.getVariable() ) } or // An allocator call in a `new` or `new[]` expression - TTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { - not ignoreExpr(newExpr) - } or + TTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { not ignoreExpr(newExpr) } or // An allocation size for a `new` or `new[]` expression - TTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { - not ignoreExpr(newExpr) - } or + TTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { not ignoreExpr(newExpr) } or // The declaration/initialization part of a `ConditionDeclExpr` - TTranslatedConditionDecl(ConditionDeclExpr expr) { - not ignoreExpr(expr) - } + TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } /** * Gets the index of the first explicitly initialized element in `initList` @@ -412,8 +379,9 @@ newtype TTranslatedElement = * `initList`, the result is the total number of elements in the array being * initialized. */ -private int getEndOfValueInitializedRange(ArrayOrVectorAggregateLiteral initList, - int afterElementIndex) { +private int getEndOfValueInitializedRange( + ArrayOrVectorAggregateLiteral initList, int afterElementIndex +) { result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex) or isFirstValueInitializedElementInRange(initList, afterElementIndex) and @@ -428,7 +396,8 @@ private int getEndOfValueInitializedRange(ArrayOrVectorAggregateLiteral initList * `initList`. */ private int getNextExplicitlyInitializedElementAfter( - ArrayOrVectorAggregateLiteral initList, int afterElementIndex) { + ArrayOrVectorAggregateLiteral initList, int afterElementIndex +) { isFirstValueInitializedElementInRange(initList, afterElementIndex) and result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex) } @@ -438,7 +407,8 @@ private int getNextExplicitlyInitializedElementAfter( * range of one or more consecutive value-initialized elements in `initList`. */ private predicate isFirstValueInitializedElementInRange( - ArrayOrVectorAggregateLiteral initList, int elementIndex) { + ArrayOrVectorAggregateLiteral initList, int elementIndex +) { initList.isValueInitialized(elementIndex) and ( elementIndex = 0 or @@ -470,9 +440,7 @@ abstract class TranslatedElement extends TTranslatedElement { /** * Get the immediate child elements of this element. */ - final TranslatedElement getAChild() { - result = getChild(_) - } + final TranslatedElement getAChild() { result = getChild(_) } /** * Gets the immediate child element of this element. The `id` is unique @@ -485,39 +453,35 @@ abstract class TranslatedElement extends TTranslatedElement { * Gets the an identifier string for the element. This string is unique within * the scope of the element's function. */ - final string getId() { - result = getUniqueId().toString() - } + final string getId() { result = getUniqueId().toString() } private TranslatedElement getChildByRank(int rankIndex) { result = rank[rankIndex + 1](TranslatedElement child, int id | - child = getChild(id) | - child order by id - ) + child = getChild(id) + | + child order by id + ) } language[monotonicAggregates] private int getDescendantCount() { - result = 1 + sum(TranslatedElement child | - child = getChildByRank(_) | - child.getDescendantCount() - ) + result = 1 + + sum(TranslatedElement child | child = getChildByRank(_) | child.getDescendantCount()) } private int getUniqueId() { - if not exists(getParent()) then - result = 0 + if not exists(getParent()) + then result = 0 else exists(TranslatedElement parent | parent = getParent() and - if this = parent.getChildByRank(0) then - result = 1 + parent.getUniqueId() + if this = parent.getChildByRank(0) + then result = 1 + parent.getUniqueId() else exists(int childIndex, TranslatedElement previousChild | this = parent.getChildByRank(childIndex) and previousChild = parent.getChildByRank(childIndex - 1) and - result = previousChild.getUniqueId() + - previousChild.getDescendantCount() + result = previousChild.getUniqueId() + previousChild.getDescendantCount() ) ) } @@ -530,8 +494,9 @@ abstract class TranslatedElement extends TTranslatedElement { * If the instruction does not return a result, `resultType` should be * `VoidType`. */ - abstract predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue); + abstract predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ); /** * Gets the `Function` that contains this element. @@ -542,8 +507,7 @@ abstract class TranslatedElement extends TTranslatedElement { * Gets the successor instruction of the instruction that was generated by * this element for tag `tag`. The successor edge kind is specified by `kind`. */ - abstract Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind); + abstract Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind); /** * Gets the successor instruction to which control should flow after the @@ -565,97 +529,74 @@ abstract class TranslatedElement extends TTranslatedElement { * Gets the primary instruction for the side effect instruction that was * generated by this element for tag `tag`. */ - Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { - none() - } + Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { none() } /** * Holds if this element generates a temporary variable with type `type`. * `tag` must be unique for each variable generated from the same AST node * (not just from the same `TranslatedElement`). */ - predicate hasTempVariable(TempVariableTag tag, Type type) { - none() - } + predicate hasTempVariable(TempVariableTag tag, Type type) { none() } /** * If the instruction specified by `tag` is a `FunctionInstruction`, gets the * `Function` for that instruction. */ - Function getInstructionFunction(InstructionTag tag) { - none() - } + Function getInstructionFunction(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `VariableInstruction`, gets the * `IRVariable` for that instruction. */ - IRVariable getInstructionVariable(InstructionTag tag) { - none() - } + IRVariable getInstructionVariable(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `FieldInstruction`, gets the * `Field` for that instruction. */ - Field getInstructionField(InstructionTag tag) { - none() - } - + Field getInstructionField(InstructionTag tag) { none() } + /** * If the instruction specified by `tag` is a `ConstantValueInstruction`, gets * the constant value for that instruction. */ - string getInstructionConstantValue(InstructionTag tag) { - none() - } + string getInstructionConstantValue(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `PointerArithmeticInstruction`, * gets the size of the type pointed to by the pointer. */ - int getInstructionElementSize(InstructionTag tag) { - none() - } + int getInstructionElementSize(InstructionTag tag) { none() } /** * If the instruction specified by `tag` has a result of type `UnknownType`, * gets the size of the result in bytes. If the result does not have a knonwn * constant size, this predicate does not hold. */ - int getInstructionResultSize(InstructionTag tag) { - none() - } + int getInstructionResultSize(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `StringConstantInstruction`, * gets the `StringLiteral` for that instruction. */ - StringLiteral getInstructionStringLiteral(InstructionTag tag) { - none() - } + StringLiteral getInstructionStringLiteral(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `BuiltInInstruction`, gets the built-in operation. */ - BuiltInOperation getInstructionBuiltInOperation(InstructionTag tag) { - none() - } + BuiltInOperation getInstructionBuiltInOperation(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `CatchByTypeInstruction`, * gets the type of the exception to be caught. */ - Type getInstructionExceptionType(InstructionTag tag) { - none() - } + Type getInstructionExceptionType(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is an `InheritanceConversionInstruction`, * gets the inheritance relationship for that instruction. */ - predicate getInstructionInheritance(InstructionTag tag, Class baseClass, - Class derivedClass) { + predicate getInstructionInheritance(InstructionTag tag, Class baseClass, Class derivedClass) { none() } @@ -663,24 +604,18 @@ abstract class TranslatedElement extends TTranslatedElement { * Gets the instruction whose result is consumed as an operand of the * instruction specified by `tag`, with the operand specified by `operandTag`. */ - Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { - none() - } + Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } /** * Gets the type of the memory operand specified by `operandTag` on the the instruction specified by `tag`. */ - Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { - none() - } + Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { none() } /** * Gets the size of the memory operand specified by `operandTag` on the the instruction specified by `tag`. * Only holds for operands whose type is `UnknownType`. */ - int getInstructionOperandSize(InstructionTag tag, SideEffectOperandTag operandTag) { - none() - } + int getInstructionOperandSize(InstructionTag tag, SideEffectOperandTag operandTag) { none() } /** * Gets the instruction generated by this element with tag `tag`. @@ -702,7 +637,5 @@ abstract class TranslatedElement extends TTranslatedElement { /** * Gets the parent element of this element. */ - final TranslatedElement getParent() { - result.getAChild() = this - } + final TranslatedElement getParent() { result.getAChild() = this } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index 37489379515..fa8eeb36adb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -22,7 +22,7 @@ TranslatedExpr getTranslatedExpr(Expr expr) { } /** - * The IR translation of some part of an expression. + * The IR translation of some part of an expression. * A single `Expr` may consist of multiple `TranslatedExpr` objects. Every * `Expr` has a single `TranslatedCoreExpr`, which produces the result of the * expression before any implicit lvalue-to-rvalue conversion. Any expression @@ -54,24 +54,16 @@ abstract class TranslatedExpr extends TranslatedElement { /** * Gets the type of the result produced by this expression. */ - final Type getResultType() { - result = expr.getUnspecifiedType() - } + final Type getResultType() { result = expr.getUnspecifiedType() } - override final Locatable getAST() { - result = expr - } + final override Locatable getAST() { result = expr } - override final Function getFunction() { - result = expr.getEnclosingFunction() - } + final override Function getFunction() { result = expr.getEnclosingFunction() } /** * Gets the expression from which this `TranslatedExpr` is generated. */ - final Expr getExpr() { - result = expr - } + final Expr getExpr() { result = expr } /** * Gets the `TranslatedFunction` containing this expression. @@ -88,14 +80,13 @@ abstract class TranslatedExpr extends TranslatedElement { * `TranslatedCoreExpr`. */ abstract class TranslatedCoreExpr extends TranslatedExpr { - override final string toString() { - result = expr.toString() - } + final override string toString() { result = expr.toString() } - override final predicate producesExprResult() { + final override predicate producesExprResult() { // If there's no load, then this is the only TranslatedExpr for this // expression. - not expr.hasLValueToRValueConversion() or + not expr.hasLValueToRValueConversion() + or // If we're supposed to ignore the load on this expression, then this // is the only TranslatedExpr. ignoreLoad(expr) @@ -110,149 +101,114 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { * `boolean` value. */ final boolean isResultGLValue() { - if( - expr.isGLValueCategory() or + if + expr.isGLValueCategory() + or // If this TranslatedExpr doesn't produce the result, then it must represent // a glvalue that is then loaded by a TranslatedLoad. not producesExprResult() - ) then - result = true - else - result = false + then result = true + else result = false } } class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, TTranslatedConditionValue { - TranslatedConditionValue() { - this = TTranslatedConditionValue(expr) + TranslatedConditionValue() { this = TTranslatedConditionValue(expr) } + + override TranslatedElement getChild(int id) { id = 0 and result = getCondition() } + + override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + ( + tag = ConditionValueTrueTempAddressTag() or + tag = ConditionValueFalseTempAddressTag() or + tag = ConditionValueResultTempAddressTag() + ) and + opcode instanceof Opcode::VariableAddress and + resultType = getResultType() and + isGLValue = true + or + ( + tag = ConditionValueTrueConstantTag() or + tag = ConditionValueFalseConstantTag() + ) and + opcode instanceof Opcode::Constant and + resultType = getResultType() and + isGLValue = isResultGLValue() + or + ( + tag = ConditionValueTrueStoreTag() or + tag = ConditionValueFalseStoreTag() + ) and + opcode instanceof Opcode::Store and + resultType = getResultType() and + isGLValue = isResultGLValue() + or + tag = ConditionValueResultLoadTag() and + opcode instanceof Opcode::Load and + resultType = getResultType() and + isGLValue = isResultGLValue() } - override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() - } - - override Instruction getFirstInstruction() { - result = getCondition().getFirstInstruction() - } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - ( - ( - tag = ConditionValueTrueTempAddressTag() or - tag = ConditionValueFalseTempAddressTag() or - tag = ConditionValueResultTempAddressTag() - ) and - opcode instanceof Opcode::VariableAddress and - resultType = getResultType() and - isGLValue = true - ) or - ( - ( - tag = ConditionValueTrueConstantTag() or - tag = ConditionValueFalseConstantTag() - ) and - opcode instanceof Opcode::Constant and - resultType = getResultType() and - isGLValue = isResultGLValue() - ) or - ( - ( - tag = ConditionValueTrueStoreTag() or - tag = ConditionValueFalseStoreTag() - ) and - opcode instanceof Opcode::Store and - resultType = getResultType() and - isGLValue = isResultGLValue() - ) or - ( - tag = ConditionValueResultLoadTag() and - opcode instanceof Opcode::Load and - resultType = getResultType() and - isGLValue = isResultGLValue() - ) - } - - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = ConditionValueTrueTempAddressTag() and - result = getInstruction(ConditionValueTrueConstantTag()) - ) or - ( - tag = ConditionValueTrueConstantTag() and - result = getInstruction(ConditionValueTrueStoreTag()) - ) or - ( - tag = ConditionValueTrueStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) - ) or - ( - tag = ConditionValueFalseTempAddressTag() and - result = getInstruction(ConditionValueFalseConstantTag()) - ) or - ( - tag = ConditionValueFalseConstantTag() and - result = getInstruction(ConditionValueFalseStoreTag()) - ) or - ( - tag = ConditionValueFalseStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) - ) or - ( - tag = ConditionValueResultTempAddressTag() and - result = getInstruction(ConditionValueResultLoadTag()) - ) or - ( - tag = ConditionValueResultLoadTag() and - result = getParent().getChildSuccessor(this) - ) + tag = ConditionValueTrueTempAddressTag() and + result = getInstruction(ConditionValueTrueConstantTag()) + or + tag = ConditionValueTrueConstantTag() and + result = getInstruction(ConditionValueTrueStoreTag()) + or + tag = ConditionValueTrueStoreTag() and + result = getInstruction(ConditionValueResultTempAddressTag()) + or + tag = ConditionValueFalseTempAddressTag() and + result = getInstruction(ConditionValueFalseConstantTag()) + or + tag = ConditionValueFalseConstantTag() and + result = getInstruction(ConditionValueFalseStoreTag()) + or + tag = ConditionValueFalseStoreTag() and + result = getInstruction(ConditionValueResultTempAddressTag()) + or + tag = ConditionValueResultTempAddressTag() and + result = getInstruction(ConditionValueResultLoadTag()) + or + tag = ConditionValueResultLoadTag() and + result = getParent().getChildSuccessor(this) ) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = ConditionValueTrueStoreTag() and ( - tag = ConditionValueTrueStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueTrueTempAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(ConditionValueTrueConstantTag()) - ) - ) - ) or + operandTag instanceof AddressOperandTag and + result = getInstruction(ConditionValueTrueTempAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(ConditionValueTrueConstantTag()) + ) + or + tag = ConditionValueFalseStoreTag() and ( - tag = ConditionValueFalseStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueFalseTempAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(ConditionValueFalseConstantTag()) - ) - ) - ) or + operandTag instanceof AddressOperandTag and + result = getInstruction(ConditionValueFalseTempAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(ConditionValueFalseConstantTag()) + ) + or + tag = ConditionValueResultLoadTag() and ( - tag = ConditionValueResultLoadTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueResultTempAddressTag()) - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(ConditionValueResultTempAddressTag()) + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) } @@ -271,17 +227,14 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, } override string getInstructionConstantValue(InstructionTag tag) { - tag = ConditionValueTrueConstantTag() and result = "1" or + tag = ConditionValueTrueConstantTag() and result = "1" + or tag = ConditionValueFalseConstantTag() and result = "0" } - override Instruction getResult() { - result = getInstruction(ConditionValueResultLoadTag()) - } + override Instruction getResult() { result = getInstruction(ConditionValueResultLoadTag()) } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } override Instruction getChildTrueSuccessor(TranslatedCondition child) { child = getCondition() and @@ -292,10 +245,8 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, child = getCondition() and result = getInstruction(ConditionValueFalseTempAddressTag()) } - - private TranslatedCondition getCondition() { - result = getTranslatedCondition(expr) - } + + private TranslatedCondition getCondition() { result = getTranslatedCondition(expr) } } /** @@ -303,35 +254,24 @@ class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, * an expression. */ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { - TranslatedLoad() { - this = TTranslatedLoad(expr) - } + TranslatedLoad() { this = TTranslatedLoad(expr) } - override string toString() { - result = "Load of " + expr.toString() - } + override string toString() { result = "Load of " + expr.toString() } - override Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = LoadTag() and opcode instanceof Opcode::Load and resultType = expr.getUnspecifiedType() and - if expr.isGLValueCategory() then - isGLValue = true - else - isGLValue = false + if expr.isGLValueCategory() then isGLValue = true else isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = LoadTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge @@ -341,73 +281,56 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { child = getOperand() and result = getInstruction(LoadTag()) } - override Instruction getResult() { - result = getInstruction(LoadTag()) - } + override Instruction getResult() { result = getInstruction(LoadTag()) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = LoadTag() and ( - ( - operandTag instanceof AddressOperandTag and - result = getOperand().getResult() - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) + operandTag instanceof AddressOperandTag and + result = getOperand().getResult() + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) } - override final predicate producesExprResult() { + final override predicate producesExprResult() { // A load always produces the result of the expression. any() } - private TranslatedCoreExpr getOperand() { - result.getExpr() = expr - } + private TranslatedCoreExpr getOperand() { result.getExpr() = expr } } class TranslatedCommaExpr extends TranslatedNonConstantExpr { override CommaExpr expr; - override Instruction getFirstInstruction() { - result = getLeftOperand().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getLeftOperand().getFirstInstruction() } override TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() or + id = 0 and result = getLeftOperand() + or id = 1 and result = getRightOperand() } - override Instruction getResult() { - result = getRightOperand().getResult() - } + override Instruction getResult() { result = getRightOperand().getResult() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() - ) or + child = getLeftOperand() and + result = getRightOperand().getFirstInstruction() + or child = getRightOperand() and result = getParent().getChildSuccessor(this) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - none() - } + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } private TranslatedExpr getLeftOperand() { result = getTranslatedExpr(expr.getLeftOperand().getFullyConverted()) @@ -421,17 +344,17 @@ class TranslatedCommaExpr extends TranslatedNonConstantExpr { abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { override CrementOperation expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override final string getInstructionConstantValue(InstructionTag tag) { + final override string getInstructionConstantValue(InstructionTag tag) { tag = CrementConstantTag() and exists(Type resultType | resultType = getResultType() and ( - resultType instanceof IntegralType and result = "1" or - resultType instanceof FloatingPointType and result = "1.0" or + resultType instanceof IntegralType and result = "1" + or + resultType instanceof FloatingPointType and result = "1.0" + or resultType instanceof PointerType and result = "1" ) ) @@ -441,114 +364,89 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { exists(Type resultType | resultType = getResultType() and ( - resultType instanceof ArithmeticType and result = resultType or + resultType instanceof ArithmeticType and result = resultType + or resultType instanceof PointerType and result = getIntType() ) ) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { isGLValue = false and - ( - ( - tag = CrementLoadTag() and - opcode instanceof Opcode::Load and - resultType = getResultType() - ) or - ( - tag = CrementConstantTag() and - opcode instanceof Opcode::Constant and - resultType = getConstantType() - ) or - ( - tag = CrementOpTag() and - opcode = getOpcode() and - resultType = getResultType() - ) or - ( - tag = CrementStoreTag() and - opcode instanceof Opcode::Store and - resultType = getResultType() - ) - ) - } - - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { ( tag = CrementLoadTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getOperand().getResult() - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) - ) - ) or - ( + opcode instanceof Opcode::Load and + resultType = getResultType() + or + tag = CrementConstantTag() and + opcode instanceof Opcode::Constant and + resultType = getConstantType() + or tag = CrementOpTag() and - ( - ( - operandTag instanceof LeftOperandTag and - result = getInstruction(CrementLoadTag()) - ) or - ( - operandTag instanceof RightOperandTag and - result = getInstruction(CrementConstantTag()) - ) - ) - ) or - ( + opcode = getOpcode() and + resultType = getResultType() + or tag = CrementStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getOperand().getResult() - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(CrementOpTag()) - ) - ) + opcode instanceof Opcode::Store and + resultType = getResultType() ) } - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = CrementLoadTag() and + ( + operandTag instanceof AddressOperandTag and + result = getOperand().getResult() + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() + ) + or + tag = CrementOpTag() and + ( + operandTag instanceof LeftOperandTag and + result = getInstruction(CrementLoadTag()) + or + operandTag instanceof RightOperandTag and + result = getInstruction(CrementConstantTag()) + ) + or + tag = CrementStoreTag() and + ( + operandTag instanceof AddressOperandTag and + result = getOperand().getResult() + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(CrementOpTag()) + ) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = CrementLoadTag() and - result = getInstruction(CrementConstantTag()) - ) or - ( - tag = CrementConstantTag() and - result = getInstruction(CrementOpTag()) - ) or - ( - tag = CrementOpTag() and - result = getInstruction(CrementStoreTag()) - ) or - ( - tag = CrementStoreTag() and - result = getParent().getChildSuccessor(this) - ) + tag = CrementLoadTag() and + result = getInstruction(CrementConstantTag()) + or + tag = CrementConstantTag() and + result = getInstruction(CrementOpTag()) + or + tag = CrementOpTag() and + result = getInstruction(CrementStoreTag()) + or + tag = CrementStoreTag() and + result = getParent().getChildSuccessor(this) ) } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getOperand() and result = getInstruction(CrementLoadTag()) } - override final int getInstructionElementSize(InstructionTag tag) { + final override int getInstructionElementSize(InstructionTag tag) { tag = CrementOpTag() and ( getOpcode() instanceof Opcode::PointerAdd or @@ -567,17 +465,16 @@ abstract class TranslatedCrementOperation extends TranslatedNonConstantExpr { ( ( expr instanceof IncrementOperation and - if resultType instanceof PointerType then - result instanceof Opcode::PointerAdd - else - result instanceof Opcode::Add - ) or + if resultType instanceof PointerType + then result instanceof Opcode::PointerAdd + else result instanceof Opcode::Add + ) + or ( expr instanceof DecrementOperation and - if resultType instanceof PointerType then - result instanceof Opcode::PointerSub - else - result instanceof Opcode::Sub + if resultType instanceof PointerType + then result instanceof Opcode::PointerSub + else result instanceof Opcode::Sub ) ) ) @@ -588,18 +485,17 @@ class TranslatedPrefixCrementOperation extends TranslatedCrementOperation { override PrefixCrementOperation expr; override Instruction getResult() { - if expr.isPRValueCategory() then ( + if expr.isPRValueCategory() + then // If this is C, then the result of a prefix crement is a prvalue for the // new value assigned to the operand. If this is C++, then the result is // an lvalue, but that lvalue is being loaded as part of this expression. // EDG doesn't mark this as a load. result = getInstruction(CrementOpTag()) - ) - else ( + else // This is C++, where the result is an lvalue for the operand, and that // lvalue is not being loaded as part of this expression. result = getOperand().getResult() - ) } } @@ -620,57 +516,49 @@ class TranslatedPostfixCrementOperation extends TranslatedCrementOperation { class TranslatedArrayExpr extends TranslatedNonConstantExpr { override ArrayExpr expr; - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { result = getBaseOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getBaseOperand() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getBaseOperand() + or id = 1 and result = getOffsetOperand() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getBaseOperand() and - result = getOffsetOperand().getFirstInstruction() - ) or - ( - child = getOffsetOperand() and - result = getInstruction(OnlyInstructionTag()) - ) - } - - override Instruction getResult() { + child = getBaseOperand() and + result = getOffsetOperand().getFirstInstruction() + or + child = getOffsetOperand() and result = getInstruction(OnlyInstructionTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::PointerAdd and resultType = getResultType() and isGLValue = true } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and ( - ( - operandTag instanceof LeftOperandTag and - result = getBaseOperand().getResult() - ) or - ( - operandTag instanceof RightOperandTag and - result = getOffsetOperand().getResult() - ) + operandTag instanceof LeftOperandTag and + result = getBaseOperand().getResult() + or + operandTag instanceof RightOperandTag and + result = getOffsetOperand().getResult() ) } @@ -689,34 +577,25 @@ class TranslatedArrayExpr extends TranslatedNonConstantExpr { } abstract class TranslatedTransparentExpr extends TranslatedNonConstantExpr { - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getOperand() and result = getParent().getChildSuccessor(this) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override final Instruction getResult() { - result = getOperand().getResult() - } + final override Instruction getResult() { result = getOperand().getResult() } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } @@ -753,47 +632,36 @@ class TranslatedTransparentConversion extends TranslatedTransparentExpr { ) } - override TranslatedExpr getOperand() { - result = getTranslatedExpr(expr.getExpr()) - } + override TranslatedExpr getOperand() { result = getTranslatedExpr(expr.getExpr()) } } class TranslatedThisExpr extends TranslatedNonConstantExpr { override ThisExpr expr; - override final TranslatedElement getChild(int id) { - none() - } + final override TranslatedElement getChild(int id) { none() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::CopyValue and resultType = expr.getUnspecifiedType() and isGLValue = false } - override final Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) } - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } + final override Instruction getChildSuccessor(TranslatedElement child) { none() } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and result = getInitializeThisInstruction() @@ -807,49 +675,41 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr { abstract class TranslatedVariableAccess extends TranslatedNonConstantExpr { override VariableAccess expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getQualifier() // Might not exist + final override TranslatedElement getChild(int id) { + id = 0 and result = getQualifier() // Might not exist } final TranslatedExpr getQualifier() { result = getTranslatedExpr(expr.getQualifier().getFullyConverted()) } - override Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getQualifier() and result = getInstruction(OnlyInstructionTag()) } } class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess { - TranslatedNonFieldVariableAccess() { - not expr instanceof FieldAccess - } + TranslatedNonFieldVariableAccess() { not expr instanceof FieldAccess } override Instruction getFirstInstruction() { - if exists(getQualifier()) then - result = getQualifier().getFirstInstruction() - else - result = getInstruction(OnlyInstructionTag()) + if exists(getQualifier()) + then result = getQualifier().getFirstInstruction() + else result = getInstruction(OnlyInstructionTag()) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - none() - } + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::VariableAddress and resultType = getResultType() and @@ -858,27 +718,24 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess { override IRVariable getInstructionVariable(InstructionTag tag) { tag = OnlyInstructionTag() and - result = getIRUserVariable(expr.getEnclosingFunction(), - expr.getTarget()) + result = getIRUserVariable(expr.getEnclosingFunction(), expr.getTarget()) } } class TranslatedFieldAccess extends TranslatedVariableAccess { override FieldAccess expr; - override Instruction getFirstInstruction() { - result = getQualifier().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getQualifier().getFirstInstruction() } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and result = getQualifier().getResult() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::FieldAddress and resultType = getResultType() and @@ -894,27 +751,21 @@ class TranslatedFieldAccess extends TranslatedVariableAccess { class TranslatedFunctionAccess extends TranslatedNonConstantExpr { override FunctionAccess expr; - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::FunctionAddress and resultType = expr.getUnspecifiedType() and @@ -926,9 +777,7 @@ class TranslatedFunctionAccess extends TranslatedNonConstantExpr { result = expr.getTarget() } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } } /** @@ -952,61 +801,47 @@ abstract class TranslatedConstantExpr extends TranslatedCoreExpr, TTranslatedVal isIRConstant(expr) } - override final Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override final TranslatedElement getChild(int id) { + final override TranslatedElement getChild(int id) { none() } + + final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } - override final Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } - - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { - none() - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode = getOpcode() and resultType = getResultType() and - if(expr.isGLValueCategory() or expr.hasLValueToRValueConversion()) then - isGLValue = true - else - isGLValue = false + if expr.isGLValueCategory() or expr.hasLValueToRValueConversion() + then isGLValue = true + else isGLValue = false } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } + final override Instruction getChildSuccessor(TranslatedElement child) { none() } abstract Opcode getOpcode(); } class TranslatedArithmeticLiteral extends TranslatedConstantExpr { - TranslatedArithmeticLiteral() { - not expr instanceof StringLiteral - } + TranslatedArithmeticLiteral() { not expr instanceof StringLiteral } override string getInstructionConstantValue(InstructionTag tag) { tag = OnlyInstructionTag() and result = expr.getValue() } - override Opcode getOpcode() { - result instanceof Opcode::Constant - } + override Opcode getOpcode() { result instanceof Opcode::Constant } } class TranslatedStringLiteral extends TranslatedConstantExpr { @@ -1017,33 +852,29 @@ class TranslatedStringLiteral extends TranslatedConstantExpr { result = expr } - override Opcode getOpcode() { - result instanceof Opcode::StringConstant - } + override Opcode getOpcode() { result instanceof Opcode::StringConstant } } /** * IR translation of an expression that performs a single operation on its * operands and returns the result. */ -abstract class TranslatedSingleInstructionExpr extends - TranslatedNonConstantExpr { +abstract class TranslatedSingleInstructionExpr extends TranslatedNonConstantExpr { /** * Gets the `Opcode` of the operation to be performed. */ abstract Opcode getOpcode(); - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { opcode = getOpcode() and tag = OnlyInstructionTag() and resultType = getResultType() and isGLValue = isResultGLValue() } - override final Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } } class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr { @@ -1054,60 +885,49 @@ class TranslatedUnaryExpr extends TranslatedSingleInstructionExpr { expr instanceof UnaryMinusExpr } - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getOperand() and result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and result = getOperand().getResult() and operandTag instanceof UnaryOperandTag } - override final Opcode getOpcode() { - expr instanceof NotExpr and result instanceof Opcode::LogicalNot or - expr instanceof ComplementExpr and result instanceof Opcode::BitComplement or - expr instanceof UnaryPlusExpr and result instanceof Opcode::CopyValue or + final override Opcode getOpcode() { + expr instanceof NotExpr and result instanceof Opcode::LogicalNot + or + expr instanceof ComplementExpr and result instanceof Opcode::BitComplement + or + expr instanceof UnaryPlusExpr and result instanceof Opcode::CopyValue + or expr instanceof UnaryMinusExpr and result instanceof Opcode::Negate } private TranslatedExpr getOperand() { - result = getTranslatedExpr( - expr.(UnaryOperation).getOperand().getFullyConverted() - ) + result = getTranslatedExpr(expr.(UnaryOperation).getOperand().getFullyConverted()) } } abstract class TranslatedConversion extends TranslatedNonConstantExpr { override Conversion expr; - override Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - final TranslatedExpr getOperand() { - result = getTranslatedExpr(expr.(Conversion).getExpr()) - } + final TranslatedExpr getOperand() { result = getTranslatedExpr(expr.(Conversion).getExpr()) } } /** @@ -1115,8 +935,7 @@ abstract class TranslatedConversion extends TranslatedNonConstantExpr { * single instruction. */ abstract class TranslatedSingleInstructionConversion extends TranslatedConversion { - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge @@ -1126,20 +945,18 @@ abstract class TranslatedSingleInstructionConversion extends TranslatedConversio child = getOperand() and result = getInstruction(OnlyInstructionTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode = getOpcode() and resultType = getResultType() and isGLValue = isResultGLValue() } - override Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and result = getOperand().getResult() @@ -1168,30 +985,24 @@ class TranslatedSimpleConversion extends TranslatedSingleInstructionConversion { expr instanceof VoidConversion } - override Opcode getOpcode() { - result instanceof Opcode::Convert - } + override Opcode getOpcode() { result instanceof Opcode::Convert } } /** * Represents the translation of a dynamic_cast expression. */ class TranslatedDynamicCast extends TranslatedSingleInstructionConversion { - TranslatedDynamicCast() { - expr instanceof DynamicCast - } + TranslatedDynamicCast() { expr instanceof DynamicCast } override Opcode getOpcode() { exists(Type resultType | resultType = getResultType() and - if resultType instanceof PointerType then ( - if resultType.(PointerType).getBaseType() instanceof VoidType then - result instanceof Opcode::DynamicCastToVoid - else - result instanceof Opcode::CheckedConvertOrNull - ) - else - result instanceof Opcode::CheckedConvertOrThrow + if resultType instanceof PointerType + then + if resultType.(PointerType).getBaseType() instanceof VoidType + then result instanceof Opcode::DynamicCastToVoid + else result instanceof Opcode::CheckedConvertOrNull + else result instanceof Opcode::CheckedConvertOrThrow ) } } @@ -1203,23 +1014,21 @@ class TranslatedDynamicCast extends TranslatedSingleInstructionConversion { class TranslatedInheritanceConversion extends TranslatedSingleInstructionConversion { override InheritanceConversion expr; - - override predicate getInstructionInheritance(InstructionTag tag, Class baseClass, - Class derivedClass) { + override predicate getInstructionInheritance( + InstructionTag tag, Class baseClass, Class derivedClass + ) { tag = OnlyInstructionTag() and baseClass = expr.getBaseClass() and derivedClass = expr.getDerivedClass() } override Opcode getOpcode() { - if expr instanceof BaseClassConversion then ( - if expr.(BaseClassConversion).isVirtual() then - result instanceof Opcode::ConvertToVirtualBase - else - result instanceof Opcode::ConvertToBase - ) - else - result instanceof Opcode::ConvertToDerived + if expr instanceof BaseClassConversion + then + if expr.(BaseClassConversion).isVirtual() + then result instanceof Opcode::ConvertToVirtualBase + else result instanceof Opcode::ConvertToBase + else result instanceof Opcode::ConvertToDerived } } @@ -1230,18 +1039,14 @@ class TranslatedInheritanceConversion extends TranslatedSingleInstructionConvers class TranslatedBoolConversion extends TranslatedConversion { override BoolConversion expr; - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = BoolConversionConstantTag() and - result = getInstruction(BoolConversionCompareTag()) - ) or - ( - tag = BoolConversionCompareTag() and - result = getParent().getChildSuccessor(this) - ) + tag = BoolConversionConstantTag() and + result = getInstruction(BoolConversionCompareTag()) + or + tag = BoolConversionCompareTag() and + result = getParent().getChildSuccessor(this) ) } @@ -1249,39 +1054,31 @@ class TranslatedBoolConversion extends TranslatedConversion { child = getOperand() and result = getInstruction(BoolConversionConstantTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { isGLValue = false and ( - ( - tag = BoolConversionConstantTag() and - opcode instanceof Opcode::Constant and - resultType = getOperand().getResultType() - ) or - ( - tag = BoolConversionCompareTag() and - opcode instanceof Opcode::CompareNE and - resultType instanceof BoolType - ) + tag = BoolConversionConstantTag() and + opcode instanceof Opcode::Constant and + resultType = getOperand().getResultType() + or + tag = BoolConversionCompareTag() and + opcode instanceof Opcode::CompareNE and + resultType instanceof BoolType ) } - override Instruction getResult() { - result = getInstruction(BoolConversionCompareTag()) - } + override Instruction getResult() { result = getInstruction(BoolConversionCompareTag()) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = BoolConversionCompareTag() and ( - ( - operandTag instanceof LeftOperandTag and - result = getOperand().getResult() - ) or - ( - operandTag instanceof RightOperandTag and - result = getInstruction(BoolConversionConstantTag()) - ) + operandTag instanceof LeftOperandTag and + result = getOperand().getResult() + or + operandTag instanceof RightOperandTag and + result = getInstruction(BoolConversionConstantTag()) ) } @@ -1292,30 +1089,46 @@ class TranslatedBoolConversion extends TranslatedConversion { } private Opcode binaryBitwiseOpcode(BinaryBitwiseOperation expr) { - expr instanceof LShiftExpr and result instanceof Opcode::ShiftLeft or - expr instanceof RShiftExpr and result instanceof Opcode::ShiftRight or - expr instanceof BitwiseAndExpr and result instanceof Opcode::BitAnd or - expr instanceof BitwiseOrExpr and result instanceof Opcode::BitOr or + expr instanceof LShiftExpr and result instanceof Opcode::ShiftLeft + or + expr instanceof RShiftExpr and result instanceof Opcode::ShiftRight + or + expr instanceof BitwiseAndExpr and result instanceof Opcode::BitAnd + or + expr instanceof BitwiseOrExpr and result instanceof Opcode::BitOr + or expr instanceof BitwiseXorExpr and result instanceof Opcode::BitXor } private Opcode binaryArithmeticOpcode(BinaryArithmeticOperation expr) { - expr instanceof AddExpr and result instanceof Opcode::Add or - expr instanceof SubExpr and result instanceof Opcode::Sub or - expr instanceof MulExpr and result instanceof Opcode::Mul or - expr instanceof DivExpr and result instanceof Opcode::Div or - expr instanceof RemExpr and result instanceof Opcode::Rem or - expr instanceof PointerAddExpr and result instanceof Opcode::PointerAdd or - expr instanceof PointerSubExpr and result instanceof Opcode::PointerSub or + expr instanceof AddExpr and result instanceof Opcode::Add + or + expr instanceof SubExpr and result instanceof Opcode::Sub + or + expr instanceof MulExpr and result instanceof Opcode::Mul + or + expr instanceof DivExpr and result instanceof Opcode::Div + or + expr instanceof RemExpr and result instanceof Opcode::Rem + or + expr instanceof PointerAddExpr and result instanceof Opcode::PointerAdd + or + expr instanceof PointerSubExpr and result instanceof Opcode::PointerSub + or expr instanceof PointerDiffExpr and result instanceof Opcode::PointerDiff } private Opcode comparisonOpcode(ComparisonOperation expr) { - expr instanceof EQExpr and result instanceof Opcode::CompareEQ or - expr instanceof NEExpr and result instanceof Opcode::CompareNE or - expr instanceof LTExpr and result instanceof Opcode::CompareLT or - expr instanceof GTExpr and result instanceof Opcode::CompareGT or - expr instanceof LEExpr and result instanceof Opcode::CompareLE or + expr instanceof EQExpr and result instanceof Opcode::CompareEQ + or + expr instanceof NEExpr and result instanceof Opcode::CompareNE + or + expr instanceof LTExpr and result instanceof Opcode::CompareLT + or + expr instanceof GTExpr and result instanceof Opcode::CompareGT + or + expr instanceof LEExpr and result instanceof Opcode::CompareLE + or expr instanceof GEExpr and result instanceof Opcode::CompareGE } @@ -1329,56 +1142,44 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { expr instanceof ComparisonOperation } - override Instruction getFirstInstruction() { - result = getLeftOperand().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getLeftOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getLeftOperand() + or id = 1 and result = getRightOperand() } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and - if swapOperandsOnOp() then ( - ( - operandTag instanceof RightOperandTag and - result = getLeftOperand().getResult() - ) or - ( - operandTag instanceof LeftOperandTag and - result = getRightOperand().getResult() - ) - ) - else ( - ( - operandTag instanceof LeftOperandTag and - result = getLeftOperand().getResult() - ) or - ( - operandTag instanceof RightOperandTag and - result = getRightOperand().getResult() - ) + if swapOperandsOnOp() + then ( + operandTag instanceof RightOperandTag and + result = getLeftOperand().getResult() + or + operandTag instanceof LeftOperandTag and + result = getRightOperand().getResult() + ) else ( + operandTag instanceof LeftOperandTag and + result = getLeftOperand().getResult() + or + operandTag instanceof RightOperandTag and + result = getRightOperand().getResult() ) } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - + override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getLeftOperand() and - result = getRightOperand().getFirstInstruction() - ) or - ( - child = getRightOperand() and - result = getInstruction(OnlyInstructionTag()) - ) + child = getLeftOperand() and + result = getRightOperand().getFirstInstruction() + or + child = getRightOperand() and + result = getInstruction(OnlyInstructionTag()) } override Opcode getOpcode() { @@ -1392,17 +1193,16 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { exists(Opcode opcode | opcode = getOpcode() and ( - opcode instanceof Opcode::PointerAdd or opcode instanceof Opcode::PointerSub or opcode instanceof Opcode::PointerDiff + opcode instanceof Opcode::PointerAdd or + opcode instanceof Opcode::PointerSub or + opcode instanceof Opcode::PointerDiff ) and result = max(getPointerOperand().getResultType().(PointerType).getBaseType().getSize()) ) } private TranslatedExpr getPointerOperand() { - if swapOperandsOnOp() then - result = getRightOperand() - else - result = getLeftOperand() + if swapOperandsOnOp() then result = getRightOperand() else result = getLeftOperand() } private predicate swapOperandsOnOp() { @@ -1417,68 +1217,57 @@ class TranslatedBinaryOperation extends TranslatedSingleInstructionExpr { } private TranslatedExpr getLeftOperand() { - result = getTranslatedExpr( - expr.(BinaryOperation).getLeftOperand().getFullyConverted() - ) + result = getTranslatedExpr(expr.(BinaryOperation).getLeftOperand().getFullyConverted()) } private TranslatedExpr getRightOperand() { - result = getTranslatedExpr( - expr.(BinaryOperation).getRightOperand().getFullyConverted() - ) + result = getTranslatedExpr(expr.(BinaryOperation).getRightOperand().getFullyConverted()) } } abstract class TranslatedAssignment extends TranslatedNonConstantExpr { override Assignment expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getLeftOperand() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getLeftOperand() + or id = 1 and result = getRightOperand() } - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { // Evaluation is right-to-left result = getRightOperand().getFirstInstruction() } - override final Instruction getResult() { - if expr.isPRValueCategory() then ( + final override Instruction getResult() { + if expr.isPRValueCategory() + then // If this is C, then the result of an assignment is a prvalue for the new // value assigned to the left operand. If this is C++, then the result is // an lvalue, but that lvalue is being loaded as part of this expression. // EDG doesn't mark this as a load. result = getStoredValue() - ) - else ( + else // This is C++, where the result is an lvalue for the left operand, // and that lvalue is not being loaded as part of this expression. result = getLeftOperand().getResult() - ) } abstract Instruction getStoredValue(); final TranslatedExpr getLeftOperand() { - result = getTranslatedExpr( - expr.getLValue().getFullyConverted() - ) + result = getTranslatedExpr(expr.getLValue().getFullyConverted()) } final TranslatedExpr getRightOperand() { - result = getTranslatedExpr( - expr.getRValue().getFullyConverted() - ) + result = getTranslatedExpr(expr.getRValue().getFullyConverted()) } } class TranslatedAssignExpr extends TranslatedAssignment { - TranslatedAssignExpr() { - expr instanceof AssignExpr - } + TranslatedAssignExpr() { expr instanceof AssignExpr } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = AssignmentStoreTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge @@ -1486,104 +1275,89 @@ class TranslatedAssignExpr extends TranslatedAssignment { override Instruction getChildSuccessor(TranslatedElement child) { // Operands are evaluated right-to-left. - ( - child = getRightOperand() and - result = getLeftOperand().getFirstInstruction() - ) or - ( - child = getLeftOperand() and - result = getInstruction(AssignmentStoreTag()) - ) + child = getRightOperand() and + result = getLeftOperand().getFirstInstruction() + or + child = getLeftOperand() and + result = getInstruction(AssignmentStoreTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = AssignmentStoreTag() and opcode instanceof Opcode::Store and resultType = getResultType() and isGLValue = false } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = AssignmentStoreTag() and ( - ( - operandTag instanceof AddressOperandTag and - result = getLeftOperand().getResult() - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getRightOperand().getResult() - ) + operandTag instanceof AddressOperandTag and + result = getLeftOperand().getResult() + or + operandTag instanceof StoreValueOperandTag and + result = getRightOperand().getResult() ) } - override Instruction getStoredValue() { - result = getRightOperand().getResult() - } + override Instruction getStoredValue() { result = getRightOperand().getResult() } } class TranslatedAssignOperation extends TranslatedAssignment { override AssignOperation expr; - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( ( tag = AssignOperationLoadTag() and - if leftOperandNeedsConversion() then - result = getInstruction(AssignOperationConvertLeftTag()) - else - result = getInstruction(AssignOperationOpTag()) - ) or - ( - tag = AssignOperationConvertLeftTag() and - result = getInstruction(AssignOperationOpTag()) - ) or + if leftOperandNeedsConversion() + then result = getInstruction(AssignOperationConvertLeftTag()) + else result = getInstruction(AssignOperationOpTag()) + ) + or + tag = AssignOperationConvertLeftTag() and + result = getInstruction(AssignOperationOpTag()) + or ( tag = AssignOperationOpTag() and - if leftOperandNeedsConversion() then - result = getInstruction(AssignOperationConvertResultTag()) - else - result = getInstruction(AssignmentStoreTag()) - ) or - ( - tag = AssignOperationConvertResultTag() and - result = getInstruction(AssignmentStoreTag()) - ) or - ( - tag = AssignmentStoreTag() and - result = getParent().getChildSuccessor(this) + if leftOperandNeedsConversion() + then result = getInstruction(AssignOperationConvertResultTag()) + else result = getInstruction(AssignmentStoreTag()) ) + or + tag = AssignOperationConvertResultTag() and + result = getInstruction(AssignmentStoreTag()) + or + tag = AssignmentStoreTag() and + result = getParent().getChildSuccessor(this) ) } override Instruction getChildSuccessor(TranslatedElement child) { // Operands are evaluated right-to-left. - ( - child = getRightOperand() and - result = getLeftOperand().getFirstInstruction() - ) or - ( - child = getLeftOperand() and - result = getInstruction(AssignOperationLoadTag()) - ) + child = getRightOperand() and + result = getLeftOperand().getFirstInstruction() + or + child = getLeftOperand() and + result = getInstruction(AssignOperationLoadTag()) } override Instruction getStoredValue() { - if leftOperandNeedsConversion() then - result = getInstruction(AssignOperationConvertResultTag()) - else - result = getInstruction(AssignOperationOpTag()) + if leftOperandNeedsConversion() + then result = getInstruction(AssignOperationConvertResultTag()) + else result = getInstruction(AssignOperationOpTag()) } private Type getConvertedLeftOperandType() { - if(expr instanceof AssignLShiftExpr or + if + expr instanceof AssignLShiftExpr or expr instanceof AssignRShiftExpr or expr instanceof AssignPointerAddExpr or - expr instanceof AssignPointerSubExpr) then ( + expr instanceof AssignPointerSubExpr + then // No need to convert for a shift. Technically, the left side should // undergo integral promotion, and then the result would be converted back // to the destination type. There's not much point to this, though, @@ -1592,10 +1366,9 @@ class TranslatedAssignOperation extends TranslatedAssignment { // extractor to tell us what the promoted type of the left operand would // be. result = getLeftOperand().getResultType() - ) else ( + else // The right operand has already been converted to the type of the op. result = getRightOperand().getResultType() - ) } private predicate leftOperandNeedsConversion() { @@ -1603,52 +1376,56 @@ class TranslatedAssignOperation extends TranslatedAssignment { } private Opcode getOpcode() { - expr instanceof AssignAddExpr and result instanceof Opcode::Add or - expr instanceof AssignSubExpr and result instanceof Opcode::Sub or - expr instanceof AssignMulExpr and result instanceof Opcode::Mul or - expr instanceof AssignDivExpr and result instanceof Opcode::Div or - expr instanceof AssignRemExpr and result instanceof Opcode::Rem or - expr instanceof AssignAndExpr and result instanceof Opcode::BitAnd or - expr instanceof AssignOrExpr and result instanceof Opcode::BitOr or - expr instanceof AssignXorExpr and result instanceof Opcode::BitXor or - expr instanceof AssignLShiftExpr and result instanceof Opcode::ShiftLeft or - expr instanceof AssignRShiftExpr and result instanceof Opcode::ShiftRight or - expr instanceof AssignPointerAddExpr and result instanceof Opcode::PointerAdd or + expr instanceof AssignAddExpr and result instanceof Opcode::Add + or + expr instanceof AssignSubExpr and result instanceof Opcode::Sub + or + expr instanceof AssignMulExpr and result instanceof Opcode::Mul + or + expr instanceof AssignDivExpr and result instanceof Opcode::Div + or + expr instanceof AssignRemExpr and result instanceof Opcode::Rem + or + expr instanceof AssignAndExpr and result instanceof Opcode::BitAnd + or + expr instanceof AssignOrExpr and result instanceof Opcode::BitOr + or + expr instanceof AssignXorExpr and result instanceof Opcode::BitXor + or + expr instanceof AssignLShiftExpr and result instanceof Opcode::ShiftLeft + or + expr instanceof AssignRShiftExpr and result instanceof Opcode::ShiftRight + or + expr instanceof AssignPointerAddExpr and result instanceof Opcode::PointerAdd + or expr instanceof AssignPointerSubExpr and result instanceof Opcode::PointerSub } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { isGLValue = false and ( + tag = AssignOperationLoadTag() and + opcode instanceof Opcode::Load and + resultType = getLeftOperand().getResultType() + or + tag = AssignOperationOpTag() and + opcode = getOpcode() and + resultType = getConvertedLeftOperandType() + or + tag = AssignmentStoreTag() and + opcode instanceof Opcode::Store and + resultType = getResultType() + or + leftOperandNeedsConversion() and + opcode instanceof Opcode::Convert and ( - tag = AssignOperationLoadTag() and - opcode instanceof Opcode::Load and - resultType = getLeftOperand().getResultType() - ) or - ( - tag = AssignOperationOpTag() and - opcode = getOpcode() and + tag = AssignOperationConvertLeftTag() and resultType = getConvertedLeftOperandType() - ) or - ( - tag = AssignmentStoreTag() and - opcode instanceof Opcode::Store and - resultType = getResultType() - ) or - ( - leftOperandNeedsConversion() and - opcode instanceof Opcode::Convert and - ( - ( - tag = AssignOperationConvertLeftTag() and - resultType = getConvertedLeftOperandType() - ) or - ( - tag = AssignOperationConvertResultTag() and - resultType = getLeftOperand().getResultType() - ) - ) + or + tag = AssignOperationConvertResultTag() and + resultType = getLeftOperand().getResultType() ) ) } @@ -1662,61 +1439,46 @@ class TranslatedAssignOperation extends TranslatedAssignment { result = max(getResultType().(PointerType).getBaseType().getSize()) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = AssignOperationLoadTag() and + ( + operandTag instanceof AddressOperandTag and + result = getLeftOperand().getResult() + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() + ) + or + leftOperandNeedsConversion() and + tag = AssignOperationConvertLeftTag() and + operandTag instanceof UnaryOperandTag and + result = getInstruction(AssignOperationLoadTag()) + or + tag = AssignOperationOpTag() and ( - tag = AssignOperationLoadTag() and ( - ( - operandTag instanceof AddressOperandTag and - result = getLeftOperand().getResult() - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) + operandTag instanceof LeftOperandTag and + if leftOperandNeedsConversion() + then result = getInstruction(AssignOperationConvertLeftTag()) + else result = getInstruction(AssignOperationLoadTag()) ) - ) or + or + operandTag instanceof RightOperandTag and + result = getRightOperand().getResult() + ) + or + leftOperandNeedsConversion() and + tag = AssignOperationConvertResultTag() and + operandTag instanceof UnaryOperandTag and + result = getInstruction(AssignOperationOpTag()) + or + tag = AssignmentStoreTag() and ( - leftOperandNeedsConversion() and - tag = AssignOperationConvertLeftTag() and - operandTag instanceof UnaryOperandTag and - result = getInstruction(AssignOperationLoadTag()) - ) or - ( - tag = AssignOperationOpTag() and - ( - ( - operandTag instanceof LeftOperandTag and - if leftOperandNeedsConversion() then - result = getInstruction(AssignOperationConvertLeftTag()) - else - result = getInstruction(AssignOperationLoadTag()) - ) or - ( - operandTag instanceof RightOperandTag and - result = getRightOperand().getResult() - ) - ) - ) or - ( - leftOperandNeedsConversion() and - tag = AssignOperationConvertResultTag() and - operandTag instanceof UnaryOperandTag and - result = getInstruction(AssignOperationOpTag()) - ) or - ( - tag = AssignmentStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getLeftOperand().getResult() - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getStoredValue() - ) - ) + operandTag instanceof AddressOperandTag and + result = getLeftOperand().getResult() + or + operandTag instanceof StoreValueOperandTag and + result = getStoredValue() ) } } @@ -1728,25 +1490,16 @@ class TranslatedAssignOperation extends TranslatedAssignment { * We have to synthesize this because not all `NewExpr` nodes have an allocator * call, and even the ones that do pass an `ErrorExpr` as the argument. */ -abstract class TranslatedAllocationSize extends TranslatedExpr, - TTranslatedAllocationSize { +abstract class TranslatedAllocationSize extends TranslatedExpr, TTranslatedAllocationSize { override NewOrNewArrayExpr expr; - - TranslatedAllocationSize() { - this = TTranslatedAllocationSize(expr) - } - override final string toString() { - result = "Allocation size for " + expr.toString() - } + TranslatedAllocationSize() { this = TTranslatedAllocationSize(expr) } - override final predicate producesExprResult() { - none() - } + final override string toString() { result = "Allocation size for " + expr.toString() } - override final Instruction getResult() { - result = getInstruction(AllocationSizeTag()) - } + final override predicate producesExprResult() { none() } + + final override Instruction getResult() { result = getInstruction(AllocationSizeTag()) } } TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { @@ -1761,38 +1514,30 @@ TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) * is a compile-time constant. */ class TranslatedConstantAllocationSize extends TranslatedAllocationSize { - TranslatedConstantAllocationSize() { - not exists(expr.(NewArrayExpr).getExtent()) - } + TranslatedConstantAllocationSize() { not exists(expr.(NewArrayExpr).getExtent()) } - override final Instruction getFirstInstruction() { - result = getInstruction(AllocationSizeTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(AllocationSizeTag()) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = AllocationSizeTag() and opcode instanceof Opcode::Constant and resultType = expr.getAllocator().getParameter(0).getUnspecifiedType() and isGLValue = false } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = AllocationSizeTag() and kind instanceof GotoEdge and result = getParent().getChildSuccessor(this) } - override final TranslatedElement getChild(int id) { - none() - } + final override TranslatedElement getChild(int id) { none() } - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } + final override Instruction getChildSuccessor(TranslatedElement child) { none() } - override final string getInstructionConstantValue(InstructionTag tag) { + final override string getInstructionConstantValue(InstructionTag tag) { tag = AllocationSizeTag() and result = expr.getAllocatedType().getSize().toString() } @@ -1808,73 +1553,62 @@ class TranslatedConstantAllocationSize extends TranslatedAllocationSize { class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize { override NewArrayExpr expr; - TranslatedNonConstantAllocationSize() { - exists(expr.getExtent()) - } + TranslatedNonConstantAllocationSize() { exists(expr.getExtent()) } - override final Instruction getFirstInstruction() { - result = getExtent().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getExtent().getFirstInstruction() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { isGLValue = false and resultType = expr.getAllocator().getParameter(0).getUnspecifiedType() and ( // Convert the extent to `size_t`, because the AST doesn't do this already. - tag = AllocationExtentConvertTag() and opcode instanceof Opcode::Convert or - tag = AllocationElementSizeTag() and opcode instanceof Opcode::Constant or + tag = AllocationExtentConvertTag() and opcode instanceof Opcode::Convert + or + tag = AllocationElementSizeTag() and opcode instanceof Opcode::Constant + or tag = AllocationSizeTag() and opcode instanceof Opcode::Mul // REVIEW: Overflow? ) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = AllocationExtentConvertTag() and - result = getInstruction(AllocationElementSizeTag()) - ) or - ( - tag = AllocationElementSizeTag() and - result = getInstruction(AllocationSizeTag()) - ) or - ( - tag = AllocationSizeTag() and - result = getParent().getChildSuccessor(this) - ) + tag = AllocationExtentConvertTag() and + result = getInstruction(AllocationElementSizeTag()) + or + tag = AllocationElementSizeTag() and + result = getInstruction(AllocationSizeTag()) + or + tag = AllocationSizeTag() and + result = getParent().getChildSuccessor(this) ) } - override final TranslatedElement getChild(int id) { - id = 0 and result = getExtent() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getExtent() } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getExtent() and result = getInstruction(AllocationExtentConvertTag()) } - override final string getInstructionConstantValue(InstructionTag tag) { + final override string getInstructionConstantValue(InstructionTag tag) { tag = AllocationElementSizeTag() and result = expr.getAllocatedElementType().getSize().toString() } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = AllocationSizeTag() and ( - tag = AllocationSizeTag() and - ( - operandTag instanceof LeftOperandTag and result = getInstruction(AllocationExtentConvertTag()) or - operandTag instanceof RightOperandTag and result = getInstruction(AllocationElementSizeTag()) - ) - ) or - ( - tag = AllocationExtentConvertTag() and - operandTag instanceof UnaryOperandTag and - result = getExtent().getResult() + operandTag instanceof LeftOperandTag and result = getInstruction(AllocationExtentConvertTag()) + or + operandTag instanceof RightOperandTag and result = getInstruction(AllocationElementSizeTag()) ) + or + tag = AllocationExtentConvertTag() and + operandTag instanceof UnaryOperandTag and + result = getExtent().getResult() } private TranslatedExpr getExtent() { @@ -1886,58 +1620,48 @@ class TranslatedNonConstantAllocationSize extends TranslatedAllocationSize { * The IR translation of a call to `operator new` as part of a `new` or `new[]` * expression. */ -class TranslatedAllocatorCall extends TTranslatedAllocatorCall, - TranslatedDirectCall { +class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirectCall { override NewOrNewArrayExpr expr; - TranslatedAllocatorCall() { - this = TTranslatedAllocatorCall(expr) - } + TranslatedAllocatorCall() { this = TTranslatedAllocatorCall(expr) } - override final string toString() { - result = "Allocator call for " + expr.toString() - } + final override string toString() { result = "Allocator call for " + expr.toString() } - override final predicate producesExprResult() { - none() - } + final override predicate producesExprResult() { none() } override Function getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and result = expr.getAllocator() } - override final Type getCallResultType() { - result = expr.getAllocator().getUnspecifiedType() - } + final override Type getCallResultType() { result = expr.getAllocator().getUnspecifiedType() } - override final TranslatedExpr getQualifier() { - none() - } + final override TranslatedExpr getQualifier() { none() } - override final predicate hasArguments() { + final override predicate hasArguments() { // All allocator calls have at least one argument. any() } - override final TranslatedExpr getArgument(int index) { + final override TranslatedExpr getArgument(int index) { // If the allocator is the default operator new(void*), there will be no // allocator call in the AST. Otherwise, there will be an allocator call // that includes all arguments to the allocator, including the size, // alignment (if any), and placement args. However, the size argument is // an error node, so we need to provide the correct size argument in any // case. - if index = 0 then - result = getTranslatedAllocationSize(expr) - else if(index = 1 and expr.hasAlignedAllocation()) then - result = getTranslatedExpr(expr.getAlignmentArgument()) + if index = 0 + then result = getTranslatedAllocationSize(expr) else - result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index)) + if index = 1 and expr.hasAlignedAllocation() + then result = getTranslatedExpr(expr.getAlignmentArgument()) + else result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index)) } } TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { result.getAST() = newExpr } + /** * Abstract class implemented by any `TranslatedElement` that has a child * expression that is a call to a constructor or destructor, in order to @@ -1955,194 +1679,156 @@ abstract class StructorCallContext extends TranslatedElement { * Represents the IR translation of the destruction of a field from within * the destructor of the field's declaring class. */ -class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, - StructorCallContext { +class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, StructorCallContext { override DestructorFieldDestruction expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getDestructorCall() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getDestructorCall() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::FieldAddress and resultType = expr.getTarget().getUnspecifiedType() and isGLValue = true } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and result = getDestructorCall().getFirstInstruction() } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getDestructorCall() and result = getParent().getChildSuccessor(this) } - override final Instruction getResult() { - none() - } + final override Instruction getResult() { none() } - override final Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and result = getTranslatedFunction(expr.getEnclosingFunction()).getInitializeThisInstruction() } - override final Field getInstructionField(InstructionTag tag) { + final override Field getInstructionField(InstructionTag tag) { tag = OnlyInstructionTag() and result = expr.getTarget() } - override final Instruction getReceiver() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) } - private TranslatedExpr getDestructorCall() { - result = getTranslatedExpr(expr.getExpr()) - } + private TranslatedExpr getDestructorCall() { result = getTranslatedExpr(expr.getExpr()) } } -class TranslatedConditionalExpr extends TranslatedNonConstantExpr, - ConditionContext { +class TranslatedConditionalExpr extends TranslatedNonConstantExpr, ConditionContext { override ConditionalExpr expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getCondition() or - id = 1 and result = getThen() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getCondition() + or + id = 1 and result = getThen() + or id = 2 and result = getElse() } - override Instruction getFirstInstruction() { - result = getCondition().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { not resultIsVoid() and ( ( - ( - (not thenIsVoid() and (tag = ConditionValueTrueTempAddressTag())) or - (not elseIsVoid() and (tag = ConditionValueFalseTempAddressTag())) or - tag = ConditionValueResultTempAddressTag() - ) and - opcode instanceof Opcode::VariableAddress and - resultType = getResultType() and - isGLValue = true - ) or + not thenIsVoid() and tag = ConditionValueTrueTempAddressTag() + or + not elseIsVoid() and tag = ConditionValueFalseTempAddressTag() + or + tag = ConditionValueResultTempAddressTag() + ) and + opcode instanceof Opcode::VariableAddress and + resultType = getResultType() and + isGLValue = true + or ( - ( - (not thenIsVoid() and (tag = ConditionValueTrueStoreTag())) or - (not elseIsVoid() and (tag = ConditionValueFalseStoreTag())) - ) and - opcode instanceof Opcode::Store and - resultType = getResultType() and - isGLValue = false - ) or - ( - tag = ConditionValueResultLoadTag() and - opcode instanceof Opcode::Load and - resultType = getResultType() and - isGLValue = isResultGLValue() - ) + not thenIsVoid() and tag = ConditionValueTrueStoreTag() + or + not elseIsVoid() and tag = ConditionValueFalseStoreTag() + ) and + opcode instanceof Opcode::Store and + resultType = getResultType() and + isGLValue = false + or + tag = ConditionValueResultLoadTag() and + opcode instanceof Opcode::Load and + resultType = getResultType() and + isGLValue = isResultGLValue() ) } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { not resultIsVoid() and kind instanceof GotoEdge and ( + not thenIsVoid() and ( - not thenIsVoid() and - ( - ( - tag = ConditionValueTrueTempAddressTag() and - result = getInstruction(ConditionValueTrueStoreTag()) - ) or - ( - tag = ConditionValueTrueStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) - ) - ) - ) or - ( - not elseIsVoid() and - ( - ( - tag = ConditionValueFalseTempAddressTag() and - result = getInstruction(ConditionValueFalseStoreTag()) - ) or - ( - tag = ConditionValueFalseStoreTag() and - result = getInstruction(ConditionValueResultTempAddressTag()) - ) - ) - ) or - ( - tag = ConditionValueResultTempAddressTag() and - result = getInstruction(ConditionValueResultLoadTag()) - ) or - ( - tag = ConditionValueResultLoadTag() and - result = getParent().getChildSuccessor(this) + tag = ConditionValueTrueTempAddressTag() and + result = getInstruction(ConditionValueTrueStoreTag()) + or + tag = ConditionValueTrueStoreTag() and + result = getInstruction(ConditionValueResultTempAddressTag()) ) + or + not elseIsVoid() and + ( + tag = ConditionValueFalseTempAddressTag() and + result = getInstruction(ConditionValueFalseStoreTag()) + or + tag = ConditionValueFalseStoreTag() and + result = getInstruction(ConditionValueResultTempAddressTag()) + ) + or + tag = ConditionValueResultTempAddressTag() and + result = getInstruction(ConditionValueResultLoadTag()) + or + tag = ConditionValueResultLoadTag() and + result = getParent().getChildSuccessor(this) ) } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { not resultIsVoid() and ( + not thenIsVoid() and + tag = ConditionValueTrueStoreTag() and ( - not thenIsVoid() and - tag = ConditionValueTrueStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueTrueTempAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getThen().getResult() - ) - ) - ) or + operandTag instanceof AddressOperandTag and + result = getInstruction(ConditionValueTrueTempAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getThen().getResult() + ) + or + not elseIsVoid() and + tag = ConditionValueFalseStoreTag() and ( - not elseIsVoid() and - tag = ConditionValueFalseStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueFalseTempAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getElse().getResult() - ) - ) - ) or + operandTag instanceof AddressOperandTag and + result = getInstruction(ConditionValueFalseTempAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getElse().getResult() + ) + or + tag = ConditionValueResultLoadTag() and ( - tag = ConditionValueResultLoadTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ConditionValueResultTempAddressTag()) - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(ConditionValueResultTempAddressTag()) + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) ) } @@ -2171,17 +1857,16 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, override Instruction getChildSuccessor(TranslatedElement child) { ( child = getThen() and - if thenIsVoid() then - result = getParent().getChildSuccessor(this) - else - result = getInstruction(ConditionValueTrueTempAddressTag()) - ) or + if thenIsVoid() + then result = getParent().getChildSuccessor(this) + else result = getInstruction(ConditionValueTrueTempAddressTag()) + ) + or ( child = getElse() and - if elseIsVoid() then - result = getParent().getChildSuccessor(this) - else - result = getInstruction(ConditionValueFalseTempAddressTag()) + if elseIsVoid() + then result = getParent().getChildSuccessor(this) + else result = getInstruction(ConditionValueFalseTempAddressTag()) ) } @@ -2194,7 +1879,7 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, child = getCondition() and result = getElse().getFirstInstruction() } - + private TranslatedCondition getCondition() { result = getTranslatedCondition(expr.getCondition().getFullyConverted()) } @@ -2208,22 +1893,22 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, } private predicate thenIsVoid() { - getThen().getResultType() instanceof VoidType or + getThen().getResultType() instanceof VoidType + or // A `ThrowExpr.getType()` incorrectly returns the type of exception being // thrown, rather than `void`. Handle that case here. expr.getThen() instanceof ThrowExpr } private predicate elseIsVoid() { - getElse().getResultType() instanceof VoidType or + getElse().getResultType() instanceof VoidType + or // A `ThrowExpr.getType()` incorrectly returns the type of exception being // thrown, rather than `void`. Handle that case here. expr.getElse() instanceof ThrowExpr } - private predicate resultIsVoid() { - getResultType() instanceof VoidType - } + private predicate resultIsVoid() { getResultType() instanceof VoidType } } /** @@ -2232,25 +1917,22 @@ class TranslatedConditionalExpr extends TranslatedNonConstantExpr, abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr { override ThrowExpr expr; - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = ThrowTag() and opcode = getThrowOpcode() and resultType instanceof VoidType and isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = ThrowTag() and kind instanceof ExceptionEdge and result = getParent().getExceptionSuccessorInstruction() } - override Instruction getResult() { - none() - } + override Instruction getResult() { none() } abstract Opcode getThrowOpcode(); } @@ -2259,37 +1941,32 @@ abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr { * IR translation of a `throw` expression with an argument * (e.g. `throw std::bad_alloc()`). */ -class TranslatedThrowValueExpr extends TranslatedThrowExpr, - InitializationContext { - TranslatedThrowValueExpr() { - not expr instanceof ReThrowExpr - } +class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContext { + TranslatedThrowValueExpr() { not expr instanceof ReThrowExpr } - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } + override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } override Instruction getFirstInstruction() { result = getInstruction(InitializerVariableAddressTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - TranslatedThrowExpr.super.hasInstruction(opcode, tag, resultType, isGLValue) or + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + TranslatedThrowExpr.super.hasInstruction(opcode, tag, resultType, isGLValue) + or tag = InitializerVariableAddressTag() and opcode instanceof Opcode::VariableAddress and resultType = getExceptionType() and isGLValue = true } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - result = TranslatedThrowExpr.super.getInstructionSuccessor(tag, kind) or - ( - tag = InitializerVariableAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge - ) + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + result = TranslatedThrowExpr.super.getInstructionSuccessor(tag, kind) + or + tag = InitializerVariableAddressTag() and + result = getInitialization().getFirstInstruction() and + kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { @@ -2302,28 +1979,23 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, result = getIRTempVariable(expr, ThrowTempVar()) } - override final predicate hasTempVariable(TempVariableTag tag, Type type) { + final override predicate hasTempVariable(TempVariableTag tag, Type type) { tag = ThrowTempVar() and type = getExceptionType() } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = ThrowTag() and ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(InitializerVariableAddressTag()) + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) } - override final Type getInstructionOperandType(InstructionTag tag, - TypedOperandTag operandTag) { + final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { tag = ThrowTag() and operandTag instanceof LoadOperandTag and result = getExceptionType() @@ -2333,22 +2005,15 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, result = getInstruction(InitializerVariableAddressTag()) } - override Type getTargetType() { - result = getExceptionType() - } + override Type getTargetType() { result = getExceptionType() } TranslatedInitialization getInitialization() { - result = getTranslatedInitialization( - expr.getExpr().getFullyConverted()) + result = getTranslatedInitialization(expr.getExpr().getFullyConverted()) } - override final Opcode getThrowOpcode() { - result instanceof Opcode::ThrowValue - } + final override Opcode getThrowOpcode() { result instanceof Opcode::ThrowValue } - private Type getExceptionType() { - result = expr.getUnspecifiedType() - } + private Type getExceptionType() { result = expr.getUnspecifiedType() } } /** @@ -2357,21 +2022,13 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, class TranslatedReThrowExpr extends TranslatedThrowExpr { override ReThrowExpr expr; - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { - result = getInstruction(ThrowTag()) - } + override Instruction getFirstInstruction() { result = getInstruction(ThrowTag()) } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } - override final Opcode getThrowOpcode() { - result instanceof Opcode::ReThrow - } + final override Opcode getThrowOpcode() { result instanceof Opcode::ReThrow } } /** @@ -2382,51 +2039,48 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr { override BuiltInOperation expr; TranslatedBuiltInOperation() { - not expr instanceof BuiltInOperationBuiltInAddressOf // Handled specially + not expr instanceof BuiltInOperationBuiltInAddressOf // Handled specially } - override final Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) + final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + + final override Instruction getFirstInstruction() { + if exists(getChild(0)) + then result = getChild(0).getFirstInstruction() + else result = getInstruction(OnlyInstructionTag()) } - override final Instruction getFirstInstruction() { - if exists(getChild(0)) then - result = getChild(0).getFirstInstruction() - else - result = getInstruction(OnlyInstructionTag()) - } - - override final TranslatedElement getChild(int id) { + final override TranslatedElement getChild(int id) { result = getTranslatedExpr(expr.getChild(id).getFullyConverted()) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and result = getParent().getChildSuccessor(this) } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { exists(int id | child = getChild(id) and ( - result = getChild(id + 1).getFirstInstruction() or + result = getChild(id + 1).getFirstInstruction() + or not exists(getChild(id + 1)) and result = getInstruction(OnlyInstructionTag()) ) ) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode = getOpcode() and resultType = getResultType() and isGLValue = isResultGLValue() } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and exists(int index | operandTag = positionalArgumentOperand(index) and @@ -2434,11 +2088,9 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr { ) } - Opcode getOpcode() { - result instanceof Opcode::BuiltIn - } + Opcode getOpcode() { result instanceof Opcode::BuiltIn } - override final BuiltInOperation getInstructionBuiltInOperation(InstructionTag tag) { + final override BuiltInOperation getInstructionBuiltInOperation(InstructionTag tag) { tag = OnlyInstructionTag() and result = expr } @@ -2450,9 +2102,7 @@ class TranslatedBuiltInOperation extends TranslatedNonConstantExpr { class TranslatedVarArgsStart extends TranslatedBuiltInOperation { override BuiltInVarArgsStart expr; - override final Opcode getOpcode() { - result instanceof Opcode::VarArgsStart - } + final override Opcode getOpcode() { result instanceof Opcode::VarArgsStart } } /** @@ -2461,9 +2111,7 @@ class TranslatedVarArgsStart extends TranslatedBuiltInOperation { class TranslatedVarArgsEnd extends TranslatedBuiltInOperation { override BuiltInVarArgsEnd expr; - override final Opcode getOpcode() { - result instanceof Opcode::VarArgsEnd - } + final override Opcode getOpcode() { result instanceof Opcode::VarArgsEnd } } /** @@ -2472,9 +2120,7 @@ class TranslatedVarArgsEnd extends TranslatedBuiltInOperation { class TranslatedVarArg extends TranslatedBuiltInOperation { override BuiltInVarArg expr; - override final Opcode getOpcode() { - result instanceof Opcode::VarArg - } + final override Opcode getOpcode() { result instanceof Opcode::VarArg } } /** @@ -2483,68 +2129,59 @@ class TranslatedVarArg extends TranslatedBuiltInOperation { class TranslatedVarArgCopy extends TranslatedBuiltInOperation { override BuiltInVarArgCopy expr; - override final Opcode getOpcode() { - result instanceof Opcode::VarArgCopy - } + final override Opcode getOpcode() { result instanceof Opcode::VarArgCopy } } /** * The IR translation of a `new` or `new[]` expression. */ -abstract class TranslatedNewOrNewArrayExpr extends TranslatedNonConstantExpr, - InitializationContext { +abstract class TranslatedNewOrNewArrayExpr extends TranslatedNonConstantExpr, InitializationContext { override NewOrNewArrayExpr expr; - override final TranslatedElement getChild(int id) { - id = 0 and result = getAllocatorCall() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getAllocatorCall() + or id = 1 and result = getInitialization() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::Convert and resultType = getResultType() and isGLValue = false } - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { result = getAllocatorCall().getFirstInstruction() } - override final Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and tag = OnlyInstructionTag() and - if exists(getInitialization()) then - result = getInitialization().getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if exists(getInitialization()) + then result = getInitialization().getFirstInstruction() + else result = getParent().getChildSuccessor(this) } - override final Instruction getChildSuccessor(TranslatedElement child) { - child = getAllocatorCall() and result = getInstruction(OnlyInstructionTag()) or + final override Instruction getChildSuccessor(TranslatedElement child) { + child = getAllocatorCall() and result = getInstruction(OnlyInstructionTag()) + or child = getInitialization() and result = getParent().getChildSuccessor(this) } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and result = getAllocatorCall().getResult() } - - override final Instruction getTargetAddress() { - result = getInstruction(OnlyInstructionTag()) - } - private TranslatedAllocatorCall getAllocatorCall() { - result = getTranslatedAllocatorCall(expr) - } + final override Instruction getTargetAddress() { result = getInstruction(OnlyInstructionTag()) } + + private TranslatedAllocatorCall getAllocatorCall() { result = getTranslatedAllocatorCall(expr) } abstract TranslatedInitialization getInitialization(); } @@ -2555,11 +2192,9 @@ abstract class TranslatedNewOrNewArrayExpr extends TranslatedNonConstantExpr, class TranslatedNewExpr extends TranslatedNewOrNewArrayExpr { override NewExpr expr; - override final Type getTargetType() { - result = expr.getAllocatedType().getUnspecifiedType() - } + final override Type getTargetType() { result = expr.getAllocatedType().getUnspecifiedType() } - override final TranslatedInitialization getInitialization() { + final override TranslatedInitialization getInitialization() { result = getTranslatedInitialization(expr.getInitializer()) } } @@ -2570,11 +2205,9 @@ class TranslatedNewExpr extends TranslatedNewOrNewArrayExpr { class TranslatedNewArrayExpr extends TranslatedNewOrNewArrayExpr { override NewArrayExpr expr; - override final Type getTargetType() { - result = expr.getAllocatedType().getUnspecifiedType() - } + final override Type getTargetType() { result = expr.getAllocatedType().getUnspecifiedType() } - override final TranslatedInitialization getInitialization() { + final override TranslatedInitialization getInitialization() { // REVIEW: Figure out how we want to model array initialization in the IR. none() } @@ -2589,32 +2222,25 @@ class TranslatedNewArrayExpr extends TranslatedNewOrNewArrayExpr { class TranslatedDeleteArrayExprPlaceHolder extends TranslatedSingleInstructionExpr { override DeleteArrayExpr expr; - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getOperand() and result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } - override final Opcode getOpcode() { - result instanceof Opcode::NoOp - } + final override Opcode getOpcode() { result instanceof Opcode::NoOp } private TranslatedExpr getOperand() { result = getTranslatedExpr(expr.getExpr().getFullyConverted()) @@ -2630,32 +2256,25 @@ class TranslatedDeleteArrayExprPlaceHolder extends TranslatedSingleInstructionEx class TranslatedDeleteExprPlaceHolder extends TranslatedSingleInstructionExpr { override DeleteExpr expr; - override final Instruction getFirstInstruction() { - result = getOperand().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getOperand() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getOperand() and result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } - override final Opcode getOpcode() { - result instanceof Opcode::NoOp - } + final override Opcode getOpcode() { result instanceof Opcode::NoOp } private TranslatedExpr getOperand() { result = getTranslatedExpr(expr.getExpr().getFullyConverted()) @@ -2673,39 +2292,32 @@ class TranslatedDeleteExprPlaceHolder extends TranslatedSingleInstructionExpr { class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr { override ConditionDeclExpr expr; - override final Instruction getFirstInstruction() { - result = getDecl().getFirstInstruction() - } + final override Instruction getFirstInstruction() { result = getDecl().getFirstInstruction() } - override final TranslatedElement getChild(int id) { - id = 0 and result = getDecl() or + final override TranslatedElement getChild(int id) { + id = 0 and result = getDecl() + or id = 1 and result = getConditionExpr() } - override Instruction getResult() { - result = getConditionExpr().getResult() - } + override Instruction getResult() { result = getConditionExpr().getResult() } - override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getDecl() and - result = getConditionExpr().getFirstInstruction() - ) or + child = getDecl() and + result = getConditionExpr().getFirstInstruction() + or child = getConditionExpr() and result = getParent().getChildSuccessor(this) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, - boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - private TranslatedConditionDecl getDecl() { - result = getTranslatedConditionDecl(expr) - } + private TranslatedConditionDecl getDecl() { result = getTranslatedConditionDecl(expr) } private TranslatedExpr getConditionExpr() { result = getTranslatedExpr(expr.getVariableAccess().getFullyConverted()) @@ -2719,37 +2331,30 @@ class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr { class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationContext { override LambdaExpression expr; - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { result = getInstruction(InitializerVariableAddressTag()) } - override final TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } + final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } - override Instruction getResult() { - result = getInstruction(LoadTag()) - } + override Instruction getResult() { result = getInstruction(LoadTag()) } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = InitializerVariableAddressTag() and + kind instanceof GotoEdge and + result = getInstruction(InitializerStoreTag()) + or + tag = InitializerStoreTag() and + kind instanceof GotoEdge and ( - tag = InitializerVariableAddressTag() and - kind instanceof GotoEdge and - result = getInstruction(InitializerStoreTag()) - ) or - ( - tag = InitializerStoreTag() and - kind instanceof GotoEdge and - ( - result = getInitialization().getFirstInstruction() or - not hasInitializer() and result = getInstruction(LoadTag()) - ) - ) or - ( - tag = LoadTag() and - kind instanceof GotoEdge and - result = getParent().getChildSuccessor(this) + result = getInitialization().getFirstInstruction() + or + not hasInitializer() and result = getInstruction(LoadTag()) ) + or + tag = LoadTag() and + kind instanceof GotoEdge and + result = getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { @@ -2757,47 +2362,37 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont result = getInstruction(LoadTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, - boolean isGLValue) { - ( - tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = getResultType() and - isGLValue = true - ) or - ( - tag = InitializerStoreTag() and - opcode instanceof Opcode::Uninitialized and - resultType = getResultType() and - isGLValue = false - ) or - ( - tag = LoadTag() and - opcode instanceof Opcode::Load and - resultType = getResultType() and - isGLValue = false - ) + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getResultType() and + isGLValue = true + or + tag = InitializerStoreTag() and + opcode instanceof Opcode::Uninitialized and + resultType = getResultType() and + isGLValue = false + or + tag = LoadTag() and + opcode instanceof Opcode::Load and + resultType = getResultType() and + isGLValue = false } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = InitializerStoreTag() and + operandTag instanceof AddressOperandTag and + result = getInstruction(InitializerVariableAddressTag()) + or + tag = LoadTag() and ( - tag = InitializerStoreTag() and operandTag instanceof AddressOperandTag and result = getInstruction(InitializerVariableAddressTag()) - ) or - ( - tag = LoadTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) - ) + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() ) } @@ -2814,17 +2409,13 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont type = getResultType() } - override final Instruction getTargetAddress() { + final override Instruction getTargetAddress() { result = getInstruction(InitializerVariableAddressTag()) } - override final Type getTargetType() { - result = getResultType() - } + final override Type getTargetType() { result = getResultType() } - private predicate hasInitializer() { - exists(getInitialization()) - } + private predicate hasInitializer() { exists(getInitialization()) } private TranslatedInitialization getInitialization() { result = getTranslatedInitialization(expr.getChild(0).getFullyConverted()) @@ -2837,72 +2428,60 @@ class TranslatedLambdaExpr extends TranslatedNonConstantExpr, InitializationCont */ class TranslatedStmtExpr extends TranslatedNonConstantExpr { override StmtExpr expr; - - override final Instruction getFirstInstruction() { - result = getStmt().getFirstInstruction() - } - - override final TranslatedElement getChild(int id) { - id = 0 and result = getStmt() - } - + + final override Instruction getFirstInstruction() { result = getStmt().getFirstInstruction() } + + final override TranslatedElement getChild(int id) { id = 0 and result = getStmt() } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag instanceof OnlyInstructionTag and kind instanceof GotoEdge and result = getParent().getChildSuccessor(this) } - + override Instruction getChildSuccessor(TranslatedElement child) { child = getStmt() and result = getInstruction(OnlyInstructionTag()) } - - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, - boolean isGLValue) { + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { opcode instanceof Opcode::CopyValue and tag instanceof OnlyInstructionTag and resultType = expr.getType() and isGLValue = false } - - override Instruction getResult() { - result = getInstruction(OnlyInstructionTag()) - } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + + override Instruction getResult() { result = getInstruction(OnlyInstructionTag()) } + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag instanceof OnlyInstructionTag and operandTag instanceof UnaryOperandTag and result = getTranslatedExpr(expr.getResultExpr().getFullyConverted()).getResult() } - - TranslatedStmt getStmt() { - result = getTranslatedStmt(expr.getStmt()) - } + + TranslatedStmt getStmt() { result = getTranslatedStmt(expr.getStmt()) } } class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { override ErrorExpr expr; - override final Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override final TranslatedElement getChild(int id) { none() } + final override TranslatedElement getChild(int id) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override final Instruction getChildSuccessor(TranslatedElement child) { none() } + final override Instruction getChildSuccessor(TranslatedElement child) { none() } - override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } - override final Opcode getOpcode() { - result instanceof Opcode::Error - } + final override Opcode getOpcode() { result instanceof Opcode::Error } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 80b077960c2..a035f8b9b31 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -13,256 +13,214 @@ private import TranslatedStmt /** * Gets the `TranslatedFunction` that represents function `func`. */ -TranslatedFunction getTranslatedFunction(Function func) { - result.getAST() = func -} +TranslatedFunction getTranslatedFunction(Function func) { result.getAST() = func } /** * Represents the IR translation of a function. This is the root elements for * all other elements associated with this function. */ -class TranslatedFunction extends TranslatedElement, - TTranslatedFunction { +class TranslatedFunction extends TranslatedElement, TTranslatedFunction { Function func; - TranslatedFunction() { - this = TTranslatedFunction(func) - } + TranslatedFunction() { this = TTranslatedFunction(func) } - override final string toString() { - result = func.toString() - } + final override string toString() { result = func.toString() } - override final Locatable getAST() { - result = func - } + final override Locatable getAST() { result = func } /** * Gets the function being translated. */ - override final Function getFunction() { - result = func - } + final override Function getFunction() { result = func } - override final TranslatedElement getChild(int id) { - id = -3 and result = getConstructorInitList() or - id = -2 and result = getBody() or - id = -1 and result = getDestructorDestructionList() or + final override TranslatedElement getChild(int id) { + id = -3 and result = getConstructorInitList() + or + id = -2 and result = getBody() + or + id = -1 and result = getDestructorDestructionList() + or id >= 0 and result = getParameter(id) } - private final TranslatedConstructorInitList getConstructorInitList() { + final private TranslatedConstructorInitList getConstructorInitList() { result = getTranslatedConstructorInitList(func) } - private final TranslatedDestructorDestructionList getDestructorDestructionList() { + final private TranslatedDestructorDestructionList getDestructorDestructionList() { result = getTranslatedDestructorDestructionList(func) } - private final TranslatedStmt getBody() { - result = getTranslatedStmt(func.getEntryPoint()) - } + final private TranslatedStmt getBody() { result = getTranslatedStmt(func.getEntryPoint()) } - private final TranslatedParameter getParameter(int index) { + final private TranslatedParameter getParameter(int index) { result = getTranslatedParameter(func.getParameter(index)) } - override final Instruction getFirstInstruction() { - result = getInstruction(EnterFunctionTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(EnterFunctionTag()) } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = EnterFunctionTag() and - result = getInstruction(AliasedDefinitionTag()) - ) or ( - tag = AliasedDefinitionTag() and - result = getInstruction(UnmodeledDefinitionTag()) - ) or + tag = EnterFunctionTag() and + result = getInstruction(AliasedDefinitionTag()) + or + tag = AliasedDefinitionTag() and + result = getInstruction(UnmodeledDefinitionTag()) + or ( tag = UnmodeledDefinitionTag() and - if exists(getThisType()) then - result = getInstruction(InitializeThisTag()) - else if exists(getParameter(0)) then - result = getParameter(0).getFirstInstruction() + if exists(getThisType()) + then result = getInstruction(InitializeThisTag()) else - result = getBody().getFirstInstruction() - ) or + if exists(getParameter(0)) + then result = getParameter(0).getFirstInstruction() + else result = getBody().getFirstInstruction() + ) + or ( tag = InitializeThisTag() and - if exists(getParameter(0)) then - result = getParameter(0).getFirstInstruction() - else - result = getConstructorInitList().getFirstInstruction() - ) or - ( - tag = ReturnValueAddressTag() and - result = getInstruction(ReturnTag()) - ) or - ( - tag = ReturnTag() and - result = getInstruction(UnmodeledUseTag()) - ) or - ( - tag = UnwindTag() and - result = getInstruction(UnmodeledUseTag()) - ) or - ( - tag = UnmodeledUseTag() and - result = getInstruction(ExitFunctionTag()) + if exists(getParameter(0)) + then result = getParameter(0).getFirstInstruction() + else result = getConstructorInitList().getFirstInstruction() ) + or + tag = ReturnValueAddressTag() and + result = getInstruction(ReturnTag()) + or + tag = ReturnTag() and + result = getInstruction(UnmodeledUseTag()) + or + tag = UnwindTag() and + result = getInstruction(UnmodeledUseTag()) + or + tag = UnmodeledUseTag() and + result = getInstruction(ExitFunctionTag()) ) } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { exists(int paramIndex | child = getParameter(paramIndex) and - if exists(func.getParameter(paramIndex + 1)) then - result = getParameter(paramIndex + 1).getFirstInstruction() - else - result = getConstructorInitList().getFirstInstruction() - ) or - ( - child = getConstructorInitList() and - result = getBody().getFirstInstruction() - ) or - ( - child = getBody() and - result = getReturnSuccessorInstruction() - ) or + if exists(func.getParameter(paramIndex + 1)) + then result = getParameter(paramIndex + 1).getFirstInstruction() + else result = getConstructorInitList().getFirstInstruction() + ) + or + child = getConstructorInitList() and + result = getBody().getFirstInstruction() + or + child = getBody() and + result = getReturnSuccessorInstruction() + or ( child = getDestructorDestructionList() and - if getReturnType() instanceof VoidType then - result = getInstruction(ReturnTag()) - else - result = getInstruction(ReturnValueAddressTag()) + if getReturnType() instanceof VoidType + then result = getInstruction(ReturnTag()) + else result = getInstruction(ReturnValueAddressTag()) ) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { ( - ( - tag = EnterFunctionTag() and - opcode instanceof Opcode::EnterFunction and - resultType instanceof VoidType and - isGLValue = false - ) or - ( - tag = UnmodeledDefinitionTag() and - opcode instanceof Opcode::UnmodeledDefinition and - resultType instanceof UnknownType and - isGLValue = false - ) or - ( - tag = AliasedDefinitionTag() and - opcode instanceof Opcode::AliasedDefinition and - resultType instanceof UnknownType and - isGLValue = false - ) or - ( - tag = InitializeThisTag() and - opcode instanceof Opcode::InitializeThis and - resultType = getThisType() and - isGLValue = true - ) or - ( - tag = ReturnValueAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = getReturnType() and - not resultType instanceof VoidType and - isGLValue = true - ) or + tag = EnterFunctionTag() and + opcode instanceof Opcode::EnterFunction and + resultType instanceof VoidType and + isGLValue = false + or + tag = UnmodeledDefinitionTag() and + opcode instanceof Opcode::UnmodeledDefinition and + resultType instanceof UnknownType and + isGLValue = false + or + tag = AliasedDefinitionTag() and + opcode instanceof Opcode::AliasedDefinition and + resultType instanceof UnknownType and + isGLValue = false + or + tag = InitializeThisTag() and + opcode instanceof Opcode::InitializeThis and + resultType = getThisType() and + isGLValue = true + or + tag = ReturnValueAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getReturnType() and + not resultType instanceof VoidType and + isGLValue = true + or ( tag = ReturnTag() and resultType instanceof VoidType and isGLValue = false and - if getReturnType() instanceof VoidType then - opcode instanceof Opcode::ReturnVoid - else - opcode instanceof Opcode::ReturnValue - ) or - ( - tag = UnwindTag() and - opcode instanceof Opcode::Unwind and - resultType instanceof VoidType and - isGLValue = false and - ( - // Only generate the `Unwind` instruction if there is any exception - // handling present in the function. - exists(TryStmt try | - try.getEnclosingFunction() = func - ) or - exists(ThrowExpr throw | - throw.getEnclosingFunction() = func - ) - ) - ) or - ( - tag = UnmodeledUseTag() and - opcode instanceof Opcode::UnmodeledUse and - resultType instanceof VoidType and - isGLValue = false - ) or - ( - tag = ExitFunctionTag() and - opcode instanceof Opcode::ExitFunction and - resultType instanceof VoidType and - isGLValue = false + if getReturnType() instanceof VoidType + then opcode instanceof Opcode::ReturnVoid + else opcode instanceof Opcode::ReturnValue ) + or + tag = UnwindTag() and + opcode instanceof Opcode::Unwind and + resultType instanceof VoidType and + isGLValue = false and + ( + // Only generate the `Unwind` instruction if there is any exception + // handling present in the function. + exists(TryStmt try | try.getEnclosingFunction() = func) or + exists(ThrowExpr throw | throw.getEnclosingFunction() = func) + ) + or + tag = UnmodeledUseTag() and + opcode instanceof Opcode::UnmodeledUse and + resultType instanceof VoidType and + isGLValue = false + or + tag = ExitFunctionTag() and + opcode instanceof Opcode::ExitFunction and + resultType instanceof VoidType and + isGLValue = false ) } - override final Instruction getExceptionSuccessorInstruction() { - result = getInstruction(UnwindTag()) + final override Instruction getExceptionSuccessorInstruction() { + result = getInstruction(UnwindTag()) } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = UnmodeledUseTag() and + operandTag instanceof UnmodeledUseOperandTag and + result.getEnclosingFunction() = func and + result.hasMemoryResult() + or + tag = UnmodeledUseTag() and + operandTag instanceof UnmodeledUseOperandTag and + result = getUnmodeledDefinitionInstruction() + or + tag = ReturnTag() and + not getReturnType() instanceof VoidType and ( - tag = UnmodeledUseTag() and - operandTag instanceof UnmodeledUseOperandTag and - result.getEnclosingFunction() = func and - result.hasMemoryResult() - ) or - ( - tag = UnmodeledUseTag() and - operandTag instanceof UnmodeledUseOperandTag and + operandTag instanceof AddressOperandTag and + result = getInstruction(ReturnValueAddressTag()) + or + operandTag instanceof LoadOperandTag and result = getUnmodeledDefinitionInstruction() - ) or - ( - tag = ReturnTag() and - not getReturnType() instanceof VoidType and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ReturnValueAddressTag()) - ) or - ( - operandTag instanceof LoadOperandTag and - result = getUnmodeledDefinitionInstruction() - ) - ) ) } - override final Type getInstructionOperandType(InstructionTag tag, - TypedOperandTag operandTag) { + final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { tag = ReturnTag() and not getReturnType() instanceof VoidType and operandTag instanceof LoadOperandTag and result = getReturnType() } - - override final IRVariable getInstructionVariable(InstructionTag tag) { + + final override IRVariable getInstructionVariable(InstructionTag tag) { tag = ReturnValueAddressTag() and result = getReturnVariable() } - override final predicate hasTempVariable(TempVariableTag tag, Type type) { + final override predicate hasTempVariable(TempVariableTag tag, Type type) { tag = ReturnValueTempVar() and type = getReturnType() and not type instanceof VoidType @@ -294,10 +252,8 @@ class TranslatedFunction extends TranslatedElement, * Gets the single `InitializeThis` instruction for this function. Holds only * if the function is an instance member function, constructor, or destructor. */ - final Instruction getInitializeThisInstruction() { - result = getInstruction(InitializeThisTag()) - } - + final Instruction getInitializeThisInstruction() { result = getInstruction(InitializeThisTag()) } + /** * Gets the type pointed to by the `this` pointer for this function (i.e. `*this`). * Holds only if the function is an instance member function, constructor, or destructor. @@ -318,32 +274,29 @@ class TranslatedFunction extends TranslatedElement, final predicate hasUserVariable(Variable var, Type type) { ( ( - ( - var instanceof GlobalOrNamespaceVariable or - var instanceof MemberVariable and not var instanceof Field - ) and - exists(VariableAccess access | - access.getTarget() = var and - access.getEnclosingFunction() = func - ) - ) or - var.(LocalScopeVariable).getFunction() = func or + var instanceof GlobalOrNamespaceVariable + or + var instanceof MemberVariable and not var instanceof Field + ) and + exists(VariableAccess access | + access.getTarget() = var and + access.getEnclosingFunction() = func + ) + or + var.(LocalScopeVariable).getFunction() = func + or var.(Parameter).getCatchBlock().getEnclosingFunction() = func ) and type = getVariableType(var) } - private final Type getReturnType() { - result = func.getUnspecifiedType() - } + final private Type getReturnType() { result = func.getUnspecifiedType() } } /** * Gets the `TranslatedParameter` that represents parameter `param`. */ -TranslatedParameter getTranslatedParameter(Parameter param) { - result.getAST() = param -} +TranslatedParameter getTranslatedParameter(Parameter param) { result.getAST() = param } /** * Represents the IR translation of a function parameter, including the @@ -352,67 +305,51 @@ TranslatedParameter getTranslatedParameter(Parameter param) { class TranslatedParameter extends TranslatedElement, TTranslatedParameter { Parameter param; - TranslatedParameter() { - this = TTranslatedParameter(param) - } + TranslatedParameter() { this = TTranslatedParameter(param) } - override final string toString() { - result = param.toString() - } + final override string toString() { result = param.toString() } - override final Locatable getAST() { - result = param - } + final override Locatable getAST() { result = param } - override final Function getFunction() { + final override Function getFunction() { result = param.getFunction() or result = param.getCatchBlock().getEnclosingFunction() } - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { result = getInstruction(InitializerVariableAddressTag()) } - override final TranslatedElement getChild(int id) { - none() - } + final override TranslatedElement getChild(int id) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and - ( - ( - tag = InitializerVariableAddressTag() and - result = getInstruction(InitializerStoreTag()) - ) or - ( - tag = InitializerStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - } - - override final Instruction getChildSuccessor(TranslatedElement child) { - none() - } - - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { ( tag = InitializerVariableAddressTag() and - opcode instanceof Opcode::VariableAddress and - resultType = getVariableType(param) and - isGLValue = true - ) or - ( + result = getInstruction(InitializerStoreTag()) + or tag = InitializerStoreTag() and - opcode instanceof Opcode::InitializeParameter and - resultType = getVariableType(param) and - isGLValue = false + result = getParent().getChildSuccessor(this) ) } - override final IRVariable getInstructionVariable(InstructionTag tag) { + final override Instruction getChildSuccessor(TranslatedElement child) { none() } + + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = InitializerVariableAddressTag() and + opcode instanceof Opcode::VariableAddress and + resultType = getVariableType(param) and + isGLValue = true + or + tag = InitializerStoreTag() and + opcode instanceof Opcode::InitializeParameter and + resultType = getVariableType(param) and + isGLValue = false + } + + final override IRVariable getInstructionVariable(InstructionTag tag) { ( tag = InitializerStoreTag() or tag = InitializerVariableAddressTag() @@ -420,20 +357,16 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter { result = getIRUserVariable(getFunction(), param) } - override final Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = InitializerStoreTag() and ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(InitializerVariableAddressTag()) - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(InitializerVariableAddressTag()) ) } } -private TranslatedConstructorInitList -getTranslatedConstructorInitList(Function func) { +private TranslatedConstructorInitList getTranslatedConstructorInitList(Function func) { result.getAST() = func } @@ -443,27 +376,22 @@ getTranslatedConstructorInitList(Function func) { * exists for every function, not just for constructors. Of course, only the * instances for constructors can actually contain initializers. */ -class TranslatedConstructorInitList extends TranslatedElement, - InitializationContext, TTranslatedConstructorInitList { +class TranslatedConstructorInitList extends TranslatedElement, InitializationContext, + TTranslatedConstructorInitList { Function func; - TranslatedConstructorInitList() { - this = TTranslatedConstructorInitList(func) - } + TranslatedConstructorInitList() { this = TTranslatedConstructorInitList(func) } - override string toString() { - result = "ctor init: " + func.toString() - } + override string toString() { result = "ctor init: " + func.toString() } - override Locatable getAST() { - result = func - } + override Locatable getAST() { result = func } override TranslatedElement getChild(int id) { exists(ConstructorFieldInit fieldInit | fieldInit = func.(Constructor).getInitializer(id) and result = getTranslatedConstructorFieldInitialization(fieldInit) - ) or + ) + or exists(ConstructorBaseInit baseInit | baseInit = func.(Constructor).getInitializer(id) and result = getTranslatedConstructorBaseInit(baseInit) @@ -471,33 +399,27 @@ class TranslatedConstructorInitList extends TranslatedElement, } override Instruction getFirstInstruction() { - if exists(getChild(0)) then - result = getChild(0).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if exists(getChild(0)) + then result = getChild(0).getFirstInstruction() + else result = getParent().getChildSuccessor(this) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override Function getFunction() { - result = func - } + override Function getFunction() { result = func } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { exists(int id | child = getChild(id) and - if exists(getChild(id + 1)) then - result = getChild(id + 1).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if exists(getChild(id + 1)) + then result = getChild(id + 1).getFirstInstruction() + else result = getParent().getChildSuccessor(this) ) } @@ -505,19 +427,16 @@ class TranslatedConstructorInitList extends TranslatedElement, result = getTranslatedFunction(func).getInitializeThisInstruction() } - override Type getTargetType() { - result = getTranslatedFunction(func).getThisType() - } + override Type getTargetType() { result = getTranslatedFunction(func).getThisType() } } -private TranslatedDestructorDestructionList -getTranslatedDestructorDestructionList(Function func) { +private TranslatedDestructorDestructionList getTranslatedDestructorDestructionList(Function func) { result.getAST() = func } /** * Represents the IR translation of a destructor's implicit calls to destructors - * for fields and base classes. To simplify the implementation of `TranslatedFunction`, + * for fields and base classes. To simplify the implementation of `TranslatedFunction`, * a `TranslatedDestructorDestructionList` exists for every function, not just for * destructors. Of course, only the instances for destructors can actually contain * destructions. @@ -526,23 +445,18 @@ class TranslatedDestructorDestructionList extends TranslatedElement, TTranslatedDestructorDestructionList { Function func; - TranslatedDestructorDestructionList() { - this = TTranslatedDestructorDestructionList(func) - } + TranslatedDestructorDestructionList() { this = TTranslatedDestructorDestructionList(func) } - override string toString() { - result = "dtor destruction: " + func.toString() - } + override string toString() { result = "dtor destruction: " + func.toString() } - override Locatable getAST() { - result = func - } + override Locatable getAST() { result = func } override TranslatedElement getChild(int id) { exists(DestructorFieldDestruction fieldDestruction | fieldDestruction = func.(Destructor).getDestruction(id) and result = getTranslatedExpr(fieldDestruction) - ) or + ) + or exists(DestructorBaseDestruction baseDestruction | baseDestruction = func.(Destructor).getDestruction(id) and result = getTranslatedDestructorBaseDestruction(baseDestruction) @@ -550,33 +464,27 @@ class TranslatedDestructorDestructionList extends TranslatedElement, } override Instruction getFirstInstruction() { - if exists(getChild(0)) then - result = getChild(0).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if exists(getChild(0)) + then result = getChild(0).getFirstInstruction() + else result = getParent().getChildSuccessor(this) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override Function getFunction() { - result = func - } + override Function getFunction() { result = func } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { exists(int id | child = getChild(id) and - if exists(getChild(id + 1)) then - result = getChild(id + 1).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if exists(getChild(id + 1)) + then result = getChild(id + 1).getFirstInstruction() + else result = getParent().getChildSuccessor(this) ) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 5eee7fd2998..01c29d422f4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -9,9 +9,7 @@ private import TranslatedFunction /** * Gets the `TranslatedInitialization` for the expression `expr`. */ -TranslatedInitialization getTranslatedInitialization(Expr expr) { - result.getExpr() = expr -} +TranslatedInitialization getTranslatedInitialization(Expr expr) { result.getExpr() = expr } /** * Base class for any `TranslatedElement` that has an initialization as a child. @@ -24,7 +22,7 @@ abstract class InitializationContext extends TranslatedElement { * initialized. */ abstract Instruction getTargetAddress(); - + /** * Gets the type of the location to be initialized. */ @@ -38,36 +36,24 @@ abstract class InitializationContext extends TranslatedElement { abstract class TranslatedInitialization extends TranslatedElement, TTranslatedInitialization { Expr expr; - TranslatedInitialization() { - this = TTranslatedInitialization(expr) - } + TranslatedInitialization() { this = TTranslatedInitialization(expr) } - override final string toString() { - result = "init: " + expr.toString() - } + final override string toString() { result = "init: " + expr.toString() } - override final Function getFunction() { - result = expr.getEnclosingFunction() - } + final override Function getFunction() { result = expr.getEnclosingFunction() } - override final Locatable getAST() { - result = expr - } + final override Locatable getAST() { result = expr } /** * Gets the expression that is doing the initialization. */ - final Expr getExpr() { - result = expr - } + final Expr getExpr() { result = expr } /** * Gets the initialization context that describes the location being * initialized. */ - final InitializationContext getContext() { - result = getParent() - } + final InitializationContext getContext() { result = getParent() } final TranslatedFunction getEnclosingFunction() { result = getTranslatedFunction(expr.getEnclosingFunction()) @@ -79,45 +65,38 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn */ abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext { override Instruction getFirstInstruction() { - result = getChild(0).getFirstInstruction() or + result = getChild(0).getFirstInstruction() + or not exists(getChild(0)) and result = getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | child = getChild(index) and - if exists(getChild(index + 1)) then - result = getChild(index + 1).getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if exists(getChild(index + 1)) + then result = getChild(index + 1).getFirstInstruction() + else result = getParent().getChildSuccessor(this) ) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override Instruction getTargetAddress() { - result = getContext().getTargetAddress() - } + override Instruction getTargetAddress() { result = getContext().getTargetAddress() } - override Type getTargetType() { - result = getContext().getTargetType() - } + override Type getTargetType() { result = getContext().getTargetType() } } /** * Represents the IR translation of an initialization of a class object from an * initializer list. */ -class TranslatedClassListInitialization extends TranslatedListInitialization -{ +class TranslatedClassListInitialization extends TranslatedListInitialization { override ClassAggregateLiteral expr; override TranslatedElement getChild(int id) { @@ -139,9 +118,10 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization { override TranslatedElement getChild(int id) { // The children are in initialization order result = rank[id + 1](TranslatedElementInitialization init | - init.getInitList() = expr | - init order by init.getElementIndex() - ) + init.getInitList() = expr + | + init order by init.getElementIndex() + ) } } @@ -150,21 +130,13 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization { * expression. */ abstract class TranslatedDirectInitialization extends TranslatedInitialization { - TranslatedDirectInitialization() { - not expr instanceof AggregateLiteral - } + TranslatedDirectInitialization() { not expr instanceof AggregateLiteral } - override TranslatedElement getChild(int id) { - id = 0 and result = getInitializer() - } + override TranslatedElement getChild(int id) { id = 0 and result = getInitializer() } - override Instruction getFirstInstruction() { - result = getInitializer().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getInitializer().getFirstInstruction() } - final TranslatedExpr getInitializer() { - result = getTranslatedExpr(expr) - } + final TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) } } /** @@ -178,7 +150,9 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio not expr instanceof StringLiteral } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = InitializerStoreTag() and opcode instanceof Opcode::Store and resultType = getContext().getTargetType() and @@ -198,14 +172,11 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = InitializerStoreTag() and ( - ( - operandTag instanceof AddressOperandTag and - result = getContext().getTargetAddress() - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInitializer().getResult() - ) + operandTag instanceof AddressOperandTag and + result = getContext().getTargetAddress() + or + operandTag instanceof StoreValueOperandTag and + result = getInitializer().getResult() ) } } @@ -217,56 +188,51 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio class TranslatedStringLiteralInitialization extends TranslatedDirectInitialization { override StringLiteral expr; - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { - ( - // Load the string literal to make it a prvalue of type `char[len]` - tag = InitializerLoadStringTag() and - opcode instanceof Opcode::Load and - resultType = getInitializer().getResultType() and - isGLValue = false - ) or - ( - // Store the string into the target. - tag = InitializerStoreTag() and - opcode instanceof Opcode::Store and - resultType = getInitializer().getResultType() and - isGLValue = false - ) or + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + // Load the string literal to make it a prvalue of type `char[len]` + tag = InitializerLoadStringTag() and + opcode instanceof Opcode::Load and + resultType = getInitializer().getResultType() and + isGLValue = false + or + // Store the string into the target. + tag = InitializerStoreTag() and + opcode instanceof Opcode::Store and + resultType = getInitializer().getResultType() and + isGLValue = false + or exists(int startIndex, int elementCount | // If the initializer string isn't large enough to fill the target, then // we have to generate another instruction sequence to store a constant // zero into the remainder of the array. zeroInitRange(startIndex, elementCount) and ( - ( - // Create a constant zero whose size is the size of the remaining - // space in the target array. - tag = ZeroPadStringConstantTag() and - opcode instanceof Opcode::Constant and - resultType instanceof UnknownType and - isGLValue = false - ) or - ( - // The index of the first element to be zero initialized. - tag = ZeroPadStringElementIndexTag() and - opcode instanceof Opcode::Constant and - resultType = getIntType() and - isGLValue = false - ) or - ( - // Compute the address of the first element to be zero initialized. - tag = ZeroPadStringElementAddressTag() and - opcode instanceof Opcode::PointerAdd and - resultType = getElementType() and - isGLValue = true - ) or - ( - // Store the constant zero into the remainder of the string. - tag = ZeroPadStringStoreTag() and - opcode instanceof Opcode::Store and - resultType instanceof UnknownType and - isGLValue = false - ) + // Create a constant zero whose size is the size of the remaining + // space in the target array. + tag = ZeroPadStringConstantTag() and + opcode instanceof Opcode::Constant and + resultType instanceof UnknownType and + isGLValue = false + or + // The index of the first element to be zero initialized. + tag = ZeroPadStringElementIndexTag() and + opcode instanceof Opcode::Constant and + resultType = getIntType() and + isGLValue = false + or + // Compute the address of the first element to be zero initialized. + tag = ZeroPadStringElementAddressTag() and + opcode instanceof Opcode::PointerAdd and + resultType = getElementType() and + isGLValue = true + or + // Store the constant zero into the remainder of the string. + tag = ZeroPadStringStoreTag() and + opcode instanceof Opcode::Store and + resultType instanceof UnknownType and + isGLValue = false ) ) } @@ -274,33 +240,26 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = InitializerLoadStringTag() and - result = getInstruction(InitializerStoreTag()) - ) or - if zeroInitRange(_, _) then ( - ( - tag = InitializerStoreTag() and - result = getInstruction(ZeroPadStringConstantTag()) - ) or - ( - tag = ZeroPadStringConstantTag() and - result = getInstruction(ZeroPadStringElementIndexTag()) - ) or - ( - tag = ZeroPadStringElementIndexTag() and - result = getInstruction(ZeroPadStringElementAddressTag()) - ) or - ( - tag = ZeroPadStringElementAddressTag() and - result = getInstruction(ZeroPadStringStoreTag()) - ) or - ( - tag = ZeroPadStringStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) - else ( + tag = InitializerLoadStringTag() and + result = getInstruction(InitializerStoreTag()) + or + if zeroInitRange(_, _) + then ( + tag = InitializerStoreTag() and + result = getInstruction(ZeroPadStringConstantTag()) + or + tag = ZeroPadStringConstantTag() and + result = getInstruction(ZeroPadStringElementIndexTag()) + or + tag = ZeroPadStringElementIndexTag() and + result = getInstruction(ZeroPadStringElementAddressTag()) + or + tag = ZeroPadStringElementAddressTag() and + result = getInstruction(ZeroPadStringStoreTag()) + or + tag = ZeroPadStringStoreTag() and + result = getParent().getChildSuccessor(this) + ) else ( tag = InitializerStoreTag() and result = getParent().getChildSuccessor(this) ) @@ -312,57 +271,40 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = InitializerLoadStringTag() and ( - tag = InitializerLoadStringTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInitializer().getResult() - ) or - ( - operandTag instanceof LoadOperandTag and - result = getEnclosingFunction().getUnmodeledDefinitionInstruction() - ) - ) - ) or + operandTag instanceof AddressOperandTag and + result = getInitializer().getResult() + or + operandTag instanceof LoadOperandTag and + result = getEnclosingFunction().getUnmodeledDefinitionInstruction() + ) + or + tag = InitializerStoreTag() and ( - tag = InitializerStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getContext().getTargetAddress() - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(InitializerLoadStringTag()) - ) - ) - ) or + operandTag instanceof AddressOperandTag and + result = getContext().getTargetAddress() + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(InitializerLoadStringTag()) + ) + or + tag = ZeroPadStringElementAddressTag() and ( - tag = ZeroPadStringElementAddressTag() and - ( - ( - operandTag instanceof LeftOperandTag and - result = getContext().getTargetAddress() - ) or - ( - operandTag instanceof RightOperandTag and - result = getInstruction(ZeroPadStringElementIndexTag()) - ) - ) - ) or + operandTag instanceof LeftOperandTag and + result = getContext().getTargetAddress() + or + operandTag instanceof RightOperandTag and + result = getInstruction(ZeroPadStringElementIndexTag()) + ) + or + tag = ZeroPadStringStoreTag() and ( - tag = ZeroPadStringStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(ZeroPadStringElementAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(ZeroPadStringConstantTag()) - ) - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(ZeroPadStringElementAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(ZeroPadStringConstantTag()) ) } @@ -375,14 +317,11 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati exists(int startIndex | zeroInitRange(startIndex, _) and ( - ( - tag = ZeroPadStringConstantTag() and - result = "0" - ) or - ( - tag = ZeroPadStringElementIndexTag() and - result = startIndex.toString() - ) + tag = ZeroPadStringConstantTag() and + result = "0" + or + tag = ZeroPadStringElementIndexTag() and + result = startIndex.toString() ) ) } @@ -416,35 +355,34 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati } } -class TranslatedConstructorInitialization extends TranslatedDirectInitialization, StructorCallContext { +class TranslatedConstructorInitialization extends TranslatedDirectInitialization, + StructorCallContext { override ConstructorCall expr; - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { child = getInitializer() and result = getParent().getChildSuccessor(this) } - override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { - none() - } + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() } - override Instruction getReceiver() { - result = getContext().getTargetAddress() - } + override Instruction getReceiver() { result = getContext().getTargetAddress() } } /** * Gets the `TranslatedFieldInitialization` for field `field` within initializer * list `initList`. */ -TranslatedFieldInitialization getTranslatedFieldInitialization(ClassAggregateLiteral initList, Field field) { +TranslatedFieldInitialization getTranslatedFieldInitialization( + ClassAggregateLiteral initList, Field field +) { result.getAST() = initList and result.getField() = field } @@ -460,31 +398,23 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { Expr ast; Field field; - override final string toString() { - result = ast.toString() + "." + field.toString() - } + final override string toString() { result = ast.toString() + "." + field.toString() } - override final Locatable getAST() { - result = ast - } + final override Locatable getAST() { result = ast } - override final Function getFunction() { - result = ast.getEnclosingFunction() - } + final override Function getFunction() { result = ast.getEnclosingFunction() } - override final Instruction getFirstInstruction() { - result = getInstruction(getFieldAddressTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(getFieldAddressTag()) } /** * Gets the zero-based index describing the order in which this field is to be * initialized relative to the other fields in the class. */ - final int getOrder() { - result = field.getInitializationOrder() - } + final int getOrder() { result = field.getInitializationOrder() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = getFieldAddressTag() and opcode instanceof Opcode::FieldAddress and resultType = field.getUnspecifiedType() and @@ -501,34 +431,26 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { tag = getFieldAddressTag() and result = field } - final InstructionTag getFieldAddressTag() { - result = InitializerFieldAddressTag() - } + final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() } - final Field getField() { - result = field - } + final Field getField() { result = field } } /** * Represents the IR translation of the initialization of a field from an * explicit element in an initializer list. */ -class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization, InitializationContext, - TTranslatedExplicitFieldInitialization { +class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization, + InitializationContext, TTranslatedExplicitFieldInitialization { Expr expr; TranslatedExplicitFieldInitialization() { this = TTranslatedExplicitFieldInitialization(ast, field, expr) } - override Instruction getTargetAddress() { - result = getInstruction(getFieldAddressTag()) - } + override Instruction getTargetAddress() { result = getInstruction(getFieldAddressTag()) } - override Type getTargetType() { - result = field.getUnspecifiedType() - } + override Type getTargetType() { result = field.getUnspecifiedType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = getFieldAddressTag() and @@ -540,9 +462,7 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio child = getInitialization() and result = getParent().getChildSuccessor(this) } - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } + override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } private TranslatedInitialization getInitialization() { result = getTranslatedInitialization(expr) @@ -550,52 +470,44 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio } private string getZeroValue(Type type) { - if type instanceof FloatingPointType then - result = "0.0" - else - result = "0" + if type instanceof FloatingPointType then result = "0.0" else result = "0" } /** * Represents the IR translation of the initialization of a field without a * corresponding element in the initializer list. */ -class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, TTranslatedFieldValueInitialization { - TranslatedFieldValueInitialization() { - this = TTranslatedFieldValueInitialization(ast, field) - } +class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, + TTranslatedFieldValueInitialization { + TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { - TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) or - ( - tag = getFieldDefaultValueTag() and - opcode instanceof Opcode::Constant and - resultType = field.getUnspecifiedType() and - isGLValue = false - ) or - ( - tag = getFieldDefaultValueStoreTag() and - opcode instanceof Opcode::Store and - resultType = field.getUnspecifiedType() and - isGLValue = false - ) + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) + or + tag = getFieldDefaultValueTag() and + opcode instanceof Opcode::Constant and + resultType = field.getUnspecifiedType() and + isGLValue = false + or + tag = getFieldDefaultValueStoreTag() and + opcode instanceof Opcode::Store and + resultType = field.getUnspecifiedType() and + isGLValue = false } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { kind instanceof GotoEdge and ( - ( - tag = getFieldAddressTag() and - result = getInstruction(getFieldDefaultValueTag()) - ) or - ( - tag = getFieldDefaultValueTag() and - result = getInstruction(getFieldDefaultValueStoreTag()) - ) or - ( - tag = getFieldDefaultValueStoreTag() and - result = getParent().getChildSuccessor(this) - ) + tag = getFieldAddressTag() and + result = getInstruction(getFieldDefaultValueTag()) + or + tag = getFieldDefaultValueTag() and + result = getInstruction(getFieldDefaultValueStoreTag()) + or + tag = getFieldDefaultValueStoreTag() and + result = getParent().getChildSuccessor(this) ) } @@ -605,33 +517,23 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { - result = TranslatedFieldInitialization.super.getInstructionOperand(tag, operandTag) or + result = TranslatedFieldInitialization.super.getInstructionOperand(tag, operandTag) + or + tag = getFieldDefaultValueStoreTag() and ( - tag = getFieldDefaultValueStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(getFieldAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(getFieldDefaultValueTag()) - ) - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(getFieldAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(getFieldDefaultValueTag()) ) } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } - private InstructionTag getFieldDefaultValueTag() { - result = InitializerFieldDefaultValueTag() - } + private InstructionTag getFieldDefaultValueTag() { result = InitializerFieldDefaultValueTag() } private InstructionTag getFieldDefaultValueStoreTag() { result = InitializerFieldDefaultValueStoreTag() @@ -645,35 +547,28 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, abstract class TranslatedElementInitialization extends TranslatedElement { ArrayOrVectorAggregateLiteral initList; - override final string toString() { + final override string toString() { result = initList.toString() + "[" + getElementIndex().toString() + "]" } - override final Locatable getAST() { - result = initList - } + final override Locatable getAST() { result = initList } - override final Function getFunction() { - result = initList.getEnclosingFunction() - } + final override Function getFunction() { result = initList.getEnclosingFunction() } - override final Instruction getFirstInstruction() { - result = getInstruction(getElementIndexTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { - ( - tag = getElementIndexTag() and - opcode instanceof Opcode::Constant and - resultType = getIntType() and - isGLValue = false - ) or - ( - tag = getElementAddressTag() and - opcode instanceof Opcode::PointerAdd and - resultType = getElementType() and - isGLValue = true - ) + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = getElementIndexTag() and + opcode instanceof Opcode::Constant and + resultType = getIntType() and + isGLValue = false + or + tag = getElementAddressTag() and + opcode instanceof Opcode::PointerAdd and + resultType = getElementType() and + isGLValue = true } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { @@ -685,14 +580,11 @@ abstract class TranslatedElementInitialization extends TranslatedElement { override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = getElementAddressTag() and ( - ( - operandTag instanceof LeftOperandTag and - result = getParent().(InitializationContext).getTargetAddress() - ) or - ( - operandTag instanceof RightOperandTag and - result = getInstruction(getElementIndexTag()) - ) + operandTag instanceof LeftOperandTag and + result = getParent().(InitializationContext).getTargetAddress() + or + operandTag instanceof RightOperandTag and + result = getInstruction(getElementIndexTag()) ) } @@ -708,21 +600,13 @@ abstract class TranslatedElementInitialization extends TranslatedElement { abstract int getElementIndex(); - final InstructionTag getElementAddressTag() { - result = InitializerElementAddressTag() - } + final InstructionTag getElementAddressTag() { result = InitializerElementAddressTag() } - final InstructionTag getElementIndexTag() { - result = InitializerElementIndexTag() - } + final InstructionTag getElementIndexTag() { result = InitializerElementIndexTag() } - final ArrayOrVectorAggregateLiteral getInitList() { - result = initList - } + final ArrayOrVectorAggregateLiteral getInitList() { result = initList } - final Type getElementType() { - result = initList.getElementType().getUnspecifiedType() - } + final Type getElementType() { result = initList.getElementType().getUnspecifiedType() } } /** @@ -730,45 +614,35 @@ abstract class TranslatedElementInitialization extends TranslatedElement { * an explicit element in an initializer list. */ class TranslatedExplicitElementInitialization extends TranslatedElementInitialization, - TTranslatedExplicitElementInitialization, InitializationContext { + TTranslatedExplicitElementInitialization, InitializationContext { int elementIndex; TranslatedExplicitElementInitialization() { this = TTranslatedExplicitElementInitialization(initList, elementIndex) } - override Instruction getTargetAddress() { - result = getInstruction(getElementAddressTag()) - } + override Instruction getTargetAddress() { result = getInstruction(getElementAddressTag()) } - override Type getTargetType() { - result = getElementType() - } + override Type getTargetType() { result = getElementType() } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or - ( - tag = getElementAddressTag() and - result = getInitialization().getFirstInstruction() and - kind instanceof GotoEdge - ) + result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) + or + tag = getElementAddressTag() and + result = getInitialization().getFirstInstruction() and + kind instanceof GotoEdge } override Instruction getChildSuccessor(TranslatedElement child) { child = getInitialization() and result = getParent().getChildSuccessor(this) } - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } + override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } - override int getElementIndex() { - result = elementIndex - } + override int getElementIndex() { result = elementIndex } TranslatedInitialization getInitialization() { - result = getTranslatedInitialization( - initList.getElementExpr(elementIndex).getFullyConverted()) + result = getTranslatedInitialization(initList.getElementExpr(elementIndex).getFullyConverted()) } } @@ -777,58 +651,51 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ * elements without corresponding elements in the initializer list. */ class TranslatedElementValueInitialization extends TranslatedElementInitialization, - TTranslatedElementValueInitialization { + TTranslatedElementValueInitialization { int elementIndex; int elementCount; TranslatedElementValueInitialization() { - this = TTranslatedElementValueInitialization(initList, elementIndex, - elementCount) + this = TTranslatedElementValueInitialization(initList, elementIndex, elementCount) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { - TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) or - ( - tag = getElementDefaultValueTag() and - opcode instanceof Opcode::Constant and - resultType = getDefaultValueType() and - isGLValue = false - ) or - ( - tag = getElementDefaultValueStoreTag() and - opcode instanceof Opcode::Store and - resultType = getDefaultValueType() and - isGLValue = false - ) + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType, isGLValue) + or + tag = getElementDefaultValueTag() and + opcode instanceof Opcode::Constant and + resultType = getDefaultValueType() and + isGLValue = false + or + tag = getElementDefaultValueStoreTag() and + opcode instanceof Opcode::Store and + resultType = getDefaultValueType() and + isGLValue = false } override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) or + result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind) + or + kind instanceof GotoEdge and ( - kind instanceof GotoEdge and - ( - ( - tag = getElementAddressTag() and - result = getInstruction(getElementDefaultValueTag()) - ) or - ( - tag = getElementDefaultValueTag() and - result = getInstruction(getElementDefaultValueStoreTag()) - ) or - ( - tag = getElementDefaultValueStoreTag() and - result = getParent().getChildSuccessor(this) - ) - ) + tag = getElementAddressTag() and + result = getInstruction(getElementDefaultValueTag()) + or + tag = getElementDefaultValueTag() and + result = getInstruction(getElementDefaultValueStoreTag()) + or + tag = getElementDefaultValueStoreTag() and + result = getParent().getChildSuccessor(this) ) } override string getInstructionConstantValue(InstructionTag tag) { - result = TranslatedElementInitialization.super.getInstructionConstantValue(tag) or - ( - tag = getElementDefaultValueTag() and - result = getZeroValue(getElementType()) - ) + result = TranslatedElementInitialization.super.getInstructionConstantValue(tag) + or + tag = getElementDefaultValueTag() and + result = getZeroValue(getElementType()) } override int getInstructionResultSize(InstructionTag tag) { @@ -841,34 +708,24 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati } override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { - result = TranslatedElementInitialization.super.getInstructionOperand(tag, operandTag) or + result = TranslatedElementInitialization.super.getInstructionOperand(tag, operandTag) + or + tag = getElementDefaultValueStoreTag() and ( - tag = getElementDefaultValueStoreTag() and - ( - ( - operandTag instanceof AddressOperandTag and - result = getInstruction(getElementAddressTag()) - ) or - ( - operandTag instanceof StoreValueOperandTag and - result = getInstruction(getElementDefaultValueTag()) - ) - ) + operandTag instanceof AddressOperandTag and + result = getInstruction(getElementAddressTag()) + or + operandTag instanceof StoreValueOperandTag and + result = getInstruction(getElementDefaultValueTag()) ) } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } + + override int getElementIndex() { result = elementIndex } - override int getElementIndex() { - result = elementIndex - } - private InstructionTag getElementDefaultValueTag() { result = InitializerElementDefaultValueTag() } @@ -878,37 +735,28 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati } private Type getDefaultValueType() { - if elementCount = 1 then - result = getElementType() - else - result instanceof UnknownType + if elementCount = 1 then result = getElementType() else result instanceof UnknownType } } abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext { FunctionCall call; - override final Locatable getAST() { - result = call - } + final override Locatable getAST() { result = call } - override final TranslatedElement getChild(int id) { + final override TranslatedElement getChild(int id) { id = 0 and result = getStructorCall() } - override final Function getFunction() { - result = call.getEnclosingFunction() - } + final override Function getFunction() { result = call.getEnclosingFunction() } - override final Instruction getChildSuccessor(TranslatedElement child) { + final override Instruction getChildSuccessor(TranslatedElement child) { child = getStructorCall() and result = getParent().getChildSuccessor(this) } - final TranslatedExpr getStructorCall() { - result = getTranslatedExpr(call) - } + final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) } } /** @@ -916,34 +764,34 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str * destructor from within a derived class constructor or destructor. */ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor { - override final Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::ConvertToBase and resultType = call.getTarget().getDeclaringType().getUnspecifiedType() and isGLValue = true } - override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and result = getStructorCall().getFirstInstruction() } - override final Instruction getReceiver() { - result = getInstruction(OnlyInstructionTag()) - } + final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) } - override final Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = OnlyInstructionTag() and operandTag instanceof UnaryOperandTag and result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() } - override final predicate getInstructionInheritance(InstructionTag tag, Class baseClass, Class derivedClass) { + final override predicate getInstructionInheritance( + InstructionTag tag, Class baseClass, Class derivedClass + ) { tag = OnlyInstructionTag() and baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and derivedClass = getFunction().getDeclaringType().getUnspecifiedType() @@ -954,10 +802,8 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru * Represents a call to a delegating or base class constructor from within a constructor. */ abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor, - TTranslatedConstructorBaseInit { - TranslatedConstructorCallFromConstructor() { - this = TTranslatedConstructorBaseInit(call) - } + TTranslatedConstructorBaseInit { + TranslatedConstructorCallFromConstructor() { this = TTranslatedConstructorBaseInit(call) } } TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) { @@ -970,23 +816,21 @@ TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(Constr class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromConstructor { override ConstructorDelegationInit call; - override final string toString() { - result = "delegation construct: " + call.toString() - } + final override string toString() { result = "delegation construct: " + call.toString() } - override final Instruction getFirstInstruction() { + final override Instruction getFirstInstruction() { result = getStructorCall().getFirstInstruction() } - override final predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue) { + final override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - none() - } + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override final Instruction getReceiver() { + final override Instruction getReceiver() { result = getTranslatedFunction(getFunction()).getInitializeThisInstruction() } } @@ -995,17 +839,16 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC * Represents the IR translation of a call to a base class constructor from within a * derived class constructor */ -class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, TranslatedBaseStructorCall { - TranslatedConstructorBaseInit() { - not call instanceof ConstructorDelegationInit - } +class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, + TranslatedBaseStructorCall { + TranslatedConstructorBaseInit() { not call instanceof ConstructorDelegationInit } - override final string toString() { - result = "construct base: " + call.toString() - } + final override string toString() { result = "construct base: " + call.toString() } } -TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) { +TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction( + DestructorBaseDestruction destruction +) { result.getAST() = destruction } @@ -1013,12 +856,9 @@ TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(Destr * Represents the IR translation of a call to a base class destructor from within a * derived class destructor. */ -class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, TTranslatedDestructorBaseDestruction { - TranslatedDestructorBaseDestruction() { - this = TTranslatedDestructorBaseDestruction(call) - } +class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, + TTranslatedDestructorBaseDestruction { + TranslatedDestructorBaseDestruction() { this = TTranslatedDestructorBaseDestruction(call) } - override final string toString() { - result = "destroy base: " + call.toString() - } + final override string toString() { result = "destroy base: " + call.toString() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index f2317399899..d84e9fc1c4e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -10,28 +10,18 @@ private import TranslatedExpr private import TranslatedFunction private import TranslatedInitialization -TranslatedStmt getTranslatedStmt(Stmt stmt) { - result.getAST() = stmt -} +TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAST() = stmt } abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { Stmt stmt; - TranslatedStmt() { - this = TTranslatedStmt(stmt) - } + TranslatedStmt() { this = TTranslatedStmt(stmt) } - override final string toString() { - result = stmt.toString() - } + final override string toString() { result = stmt.toString() } - override final Locatable getAST() { - result = stmt - } + final override Locatable getAST() { result = stmt } - override final Function getFunction() { - result = stmt.getEnclosingFunction() - } + final override Function getFunction() { result = stmt.getEnclosingFunction() } } class TranslatedEmptyStmt extends TranslatedStmt { @@ -41,32 +31,26 @@ class TranslatedEmptyStmt extends TranslatedStmt { stmt instanceof SwitchCase } - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::NoOp and resultType instanceof VoidType and isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } } /** @@ -77,23 +61,21 @@ class TranslatedEmptyStmt extends TranslatedStmt { class TranslatedDeclStmt extends TranslatedStmt { override DeclStmt stmt; - override TranslatedElement getChild(int id) { - result = getDeclarationEntry(id) - } + override TranslatedElement getChild(int id) { result = getDeclarationEntry(id) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } override Instruction getFirstInstruction() { - result = getDeclarationEntry(0).getFirstInstruction() or + result = getDeclarationEntry(0).getFirstInstruction() + or not exists(getDeclarationEntry(0)) and result = getParent().getChildSuccessor(this) } - private int getChildCount() { - result = count(getDeclarationEntry(_)) - } + private int getChildCount() { result = count(getDeclarationEntry(_)) } /** * Gets the `TranslatedDeclarationEntry` child at zero-based index `index`. Since not all @@ -103,23 +85,20 @@ class TranslatedDeclStmt extends TranslatedStmt { */ private TranslatedDeclarationEntry getDeclarationEntry(int index) { result = rank[index + 1](TranslatedDeclarationEntry entry, int originalIndex | - entry = getTranslatedDeclarationEntry(stmt.getDeclarationEntry(originalIndex)) | - entry order by originalIndex - ) + entry = getTranslatedDeclarationEntry(stmt.getDeclarationEntry(originalIndex)) + | + entry order by originalIndex + ) } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | child = getDeclarationEntry(index) and - if index = (getChildCount() - 1) then - result = getParent().getChildSuccessor(this) - else - result = getDeclarationEntry(index + 1).getFirstInstruction() + if index = (getChildCount() - 1) + then result = getParent().getChildSuccessor(this) + else result = getDeclarationEntry(index + 1).getFirstInstruction() ) } } @@ -131,23 +110,17 @@ class TranslatedExprStmt extends TranslatedStmt { result = getTranslatedExpr(stmt.(ExprStmt).getExpr().getFullyConverted()) } - override TranslatedElement getChild(int id) { - id = 0 and result = getExpr() - } + override TranslatedElement getChild(int id) { id = 0 and result = getExpr() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override Instruction getFirstInstruction() { - result = getExpr().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildSuccessor(TranslatedElement child) { child = getExpr() and @@ -163,30 +136,25 @@ abstract class TranslatedReturnStmt extends TranslatedStmt { } } -class TranslatedReturnValueStmt extends TranslatedReturnStmt, - InitializationContext { - TranslatedReturnValueStmt() { - stmt.hasExpr() - } +class TranslatedReturnValueStmt extends TranslatedReturnStmt, InitializationContext { + TranslatedReturnValueStmt() { stmt.hasExpr() } - override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() - } + override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() } override Instruction getFirstInstruction() { result = getInstruction(InitializerVariableAddressTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = InitializerVariableAddressTag() and opcode instanceof Opcode::VariableAddress and resultType = getEnclosingFunction().getReturnVariable().getType() and isGLValue = true } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = InitializerVariableAddressTag() and result = getInitialization().getFirstInstruction() and kind instanceof GotoEdge @@ -206,47 +174,36 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, result = getInstruction(InitializerVariableAddressTag()) } - override Type getTargetType() { - result = getEnclosingFunction().getReturnVariable().getType() - } + override Type getTargetType() { result = getEnclosingFunction().getReturnVariable().getType() } TranslatedInitialization getInitialization() { - result = getTranslatedInitialization( - stmt.getExpr().getFullyConverted()) + result = getTranslatedInitialization(stmt.getExpr().getFullyConverted()) } } class TranslatedReturnVoidStmt extends TranslatedReturnStmt { - TranslatedReturnVoidStmt() { - not stmt.hasExpr() - } + TranslatedReturnVoidStmt() { not stmt.hasExpr() } - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::NoOp and resultType instanceof VoidType and isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getEnclosingFunction().getReturnSuccessorInstruction() and kind instanceof GotoEdge } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } } /** @@ -256,23 +213,20 @@ class TranslatedTryStmt extends TranslatedStmt { override TryStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getBody() or + id = 0 and result = getBody() + or result = getHandler(id - 1) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { - none() + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + none() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override Instruction getFirstInstruction() { - result = getBody().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { // All children go to the successor of the `try`. @@ -283,17 +237,16 @@ class TranslatedTryStmt extends TranslatedStmt { exists(int index | handler = getHandler(index) and result = getHandler(index + 1).getFirstInstruction() - ) or - ( - // The last catch clause flows to the exception successor of the parent - // of the `try`, because the exception successor of the `try` itself is - // the first catch clause. - handler = getHandler(stmt.getNumberOfCatchClauses() - 1) and - result = getParent().getExceptionSuccessorInstruction() ) + or + // The last catch clause flows to the exception successor of the parent + // of the `try`, because the exception successor of the `try` itself is + // the first catch clause. + handler = getHandler(stmt.getNumberOfCatchClauses() - 1) and + result = getParent().getExceptionSuccessorInstruction() } - override final Instruction getExceptionSuccessorInstruction() { + final override Instruction getExceptionSuccessorInstruction() { result = getHandler(0).getFirstInstruction() } @@ -301,20 +254,17 @@ class TranslatedTryStmt extends TranslatedStmt { result = getTranslatedStmt(stmt.getChild(index + 1)) } - private TranslatedStmt getBody() { - result = getTranslatedStmt(stmt.getStmt()) - } + private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } } class TranslatedBlock extends TranslatedStmt { override Block stmt; - override TranslatedElement getChild(int id) { - result = getStmt(id) - } + override TranslatedElement getChild(int id) { result = getStmt(id) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { isEmpty() and opcode instanceof Opcode::NoOp and tag = OnlyInstructionTag() and @@ -323,26 +273,18 @@ class TranslatedBlock extends TranslatedStmt { } override Instruction getFirstInstruction() { - if isEmpty() then - result = getInstruction(OnlyInstructionTag()) - else - result = getStmt(0).getFirstInstruction() + if isEmpty() + then result = getInstruction(OnlyInstructionTag()) + else result = getStmt(0).getFirstInstruction() } - private predicate isEmpty() { - not exists(stmt.getStmt(0)) - } + private predicate isEmpty() { not exists(stmt.getStmt(0)) } - private TranslatedStmt getStmt(int index) { - result = getTranslatedStmt(stmt.getStmt(index)) - } + private TranslatedStmt getStmt(int index) { result = getTranslatedStmt(stmt.getStmt(index)) } - private int getStmtCount() { - result = stmt.getNumStmt() - } + private int getStmtCount() { result = stmt.getNumStmt() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge @@ -351,10 +293,9 @@ class TranslatedBlock extends TranslatedStmt { override Instruction getChildSuccessor(TranslatedElement child) { exists(int index | child = getStmt(index) and - if index = (getStmtCount() - 1) then - result = getParent().getChildSuccessor(this) - else - result = getStmt(index + 1).getFirstInstruction() + if index = (getStmtCount() - 1) + then result = getParent().getChildSuccessor(this) + else result = getStmt(index + 1).getFirstInstruction() ) } } @@ -365,13 +306,9 @@ class TranslatedBlock extends TranslatedStmt { abstract class TranslatedHandler extends TranslatedStmt { override Handler stmt; - override TranslatedElement getChild(int id) { - id = 1 and result = getBlock() - } + override TranslatedElement getChild(int id) { id = 1 and result = getBlock() } - override Instruction getFirstInstruction() { - result = getInstruction(CatchTag()) - } + override Instruction getFirstInstruction() { result = getInstruction(CatchTag()) } override Instruction getChildSuccessor(TranslatedElement child) { child = getBlock() and result = getParent().getChildSuccessor(this) @@ -383,9 +320,7 @@ abstract class TranslatedHandler extends TranslatedStmt { result = getParent().getParent().getExceptionSuccessorInstruction() } - TranslatedStmt getBlock() { - result = getTranslatedStmt(stmt.getBlock()) - } + TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) } } /** @@ -393,12 +328,11 @@ abstract class TranslatedHandler extends TranslatedStmt { * specific type (e.g. `catch (const std::exception&)`). */ class TranslatedCatchByTypeHandler extends TranslatedHandler { - TranslatedCatchByTypeHandler() { - exists(stmt.getParameter()) - } + TranslatedCatchByTypeHandler() { exists(stmt.getParameter()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = CatchTag() and opcode instanceof Opcode::CatchByType and resultType instanceof VoidType and @@ -406,27 +340,25 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler { } override TranslatedElement getChild(int id) { - result = super.getChild(id) or + result = super.getChild(id) + or id = 0 and result = getParameter() } override Instruction getChildSuccessor(TranslatedElement child) { - result = super.getChildSuccessor(child) or + result = super.getChildSuccessor(child) + or child = getParameter() and result = getBlock().getFirstInstruction() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = CatchTag() and ( - ( - kind instanceof GotoEdge and - result = getParameter().getFirstInstruction() - ) or - ( - kind instanceof ExceptionEdge and - result = getParent().(TranslatedTryStmt).getNextHandler(this) - ) + kind instanceof GotoEdge and + result = getParameter().getFirstInstruction() + or + kind instanceof ExceptionEdge and + result = getParent().(TranslatedTryStmt).getNextHandler(this) ) } @@ -444,20 +376,18 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler { * The IR translation of a C++ `catch (...)` block. */ class TranslatedCatchAnyHandler extends TranslatedHandler { - TranslatedCatchAnyHandler() { - not exists(stmt.getParameter()) - } + TranslatedCatchAnyHandler() { not exists(stmt.getParameter()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = CatchTag() and opcode instanceof Opcode::CatchAny and resultType instanceof VoidType and isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = CatchTag() and kind instanceof GotoEdge and result = getBlock().getFirstInstruction() @@ -467,14 +397,13 @@ class TranslatedCatchAnyHandler extends TranslatedHandler { class TranslatedIfStmt extends TranslatedStmt, ConditionContext { override IfStmt stmt; - - override Instruction getFirstInstruction() { - result = getCondition().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() or - id = 1 and result = getThen() or + id = 0 and result = getCondition() + or + id = 1 and result = getThen() + or id = 2 and result = getElse() } @@ -482,22 +411,13 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext { result = getTranslatedCondition(stmt.getCondition().getFullyConverted()) } - private TranslatedStmt getThen() { - result = getTranslatedStmt(stmt.getThen()) - } + private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) } - private TranslatedStmt getElse() { - result = getTranslatedStmt(stmt.getElse()) - } + private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) } - private predicate hasElse() { - exists(stmt.getElse()) - } + private predicate hasElse() { exists(stmt.getElse()) } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildTrueSuccessor(TranslatedCondition child) { child = getCondition() and @@ -506,10 +426,9 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext { override Instruction getChildFalseSuccessor(TranslatedCondition child) { child = getCondition() and - if hasElse() then - result = getElse().getFirstInstruction() - else - result = getParent().getChildSuccessor(this) + if hasElse() + then result = getElse().getFirstInstruction() + else result = getParent().getChildSuccessor(this) } override Instruction getChildSuccessor(TranslatedElement child) { @@ -517,8 +436,9 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext { result = getParent().getChildSuccessor(this) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } } @@ -530,53 +450,43 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext { result = getTranslatedCondition(stmt.getCondition().getFullyConverted()) } - final TranslatedStmt getBody() { - result = getTranslatedStmt(stmt.getStmt()) - } + final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } final Instruction getFirstConditionInstruction() { - if hasCondition() then - result = getCondition().getFirstInstruction() - else - result = getBody().getFirstInstruction() + if hasCondition() + then result = getCondition().getFirstInstruction() + else result = getBody().getFirstInstruction() } - final predicate hasCondition() { - exists(stmt.getCondition()) - } + final predicate hasCondition() { exists(stmt.getCondition()) } override TranslatedElement getChild(int id) { - id = 0 and result = getCondition() or + id = 0 and result = getCondition() + or id = 1 and result = getBody() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override final Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { - none() - } + final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } - override final Instruction getChildTrueSuccessor(TranslatedCondition child) { + final override Instruction getChildTrueSuccessor(TranslatedCondition child) { child = getCondition() and result = getBody().getFirstInstruction() } - override final Instruction getChildFalseSuccessor(TranslatedCondition child) { + final override Instruction getChildFalseSuccessor(TranslatedCondition child) { child = getCondition() and result = getParent().getChildSuccessor(this) } } class TranslatedWhileStmt extends TranslatedLoop { - TranslatedWhileStmt() { - stmt instanceof WhileStmt - } + TranslatedWhileStmt() { stmt instanceof WhileStmt } - override Instruction getFirstInstruction() { - result = getFirstConditionInstruction() - } + override Instruction getFirstInstruction() { result = getFirstConditionInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { child = getBody() and result = getFirstConditionInstruction() @@ -584,14 +494,10 @@ class TranslatedWhileStmt extends TranslatedLoop { } class TranslatedDoStmt extends TranslatedLoop { - TranslatedDoStmt() { - stmt instanceof DoStmt - } + TranslatedDoStmt() { stmt instanceof DoStmt } + + override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() } - override Instruction getFirstInstruction() { - result = getBody().getFirstInstruction() - } - override Instruction getChildSuccessor(TranslatedElement child) { child = getBody() and result = getFirstConditionInstruction() } @@ -601,9 +507,12 @@ class TranslatedForStmt extends TranslatedLoop { override ForStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getInitialization() or - id = 1 and result = getCondition() or - id = 2 and result = getUpdate() or + id = 0 and result = getInitialization() + or + id = 1 and result = getCondition() + or + id = 2 and result = getUpdate() + or id = 3 and result = getBody() } @@ -611,37 +520,29 @@ class TranslatedForStmt extends TranslatedLoop { result = getTranslatedStmt(stmt.getInitialization()) } - private predicate hasInitialization() { - exists(stmt.getInitialization()) - } - - TranslatedExpr getUpdate() { - result = getTranslatedExpr(stmt.getUpdate().getFullyConverted()) - } + private predicate hasInitialization() { exists(stmt.getInitialization()) } - private predicate hasUpdate() { - exists(stmt.getUpdate()) - } + TranslatedExpr getUpdate() { result = getTranslatedExpr(stmt.getUpdate().getFullyConverted()) } + + private predicate hasUpdate() { exists(stmt.getUpdate()) } override Instruction getFirstInstruction() { - if hasInitialization() then - result = getInitialization().getFirstInstruction() - else - result = getFirstConditionInstruction() + if hasInitialization() + then result = getInitialization().getFirstInstruction() + else result = getFirstConditionInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getInitialization() and - result = getFirstConditionInstruction() - ) or + child = getInitialization() and + result = getFirstConditionInstruction() + or ( child = getBody() and - if hasUpdate() then - result = getUpdate().getFirstInstruction() - else - result = getFirstConditionInstruction() - ) or + if hasUpdate() + then result = getUpdate().getFirstInstruction() + else result = getFirstConditionInstruction() + ) + or child = getUpdate() and result = getFirstConditionInstruction() } } @@ -657,12 +558,18 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext { override RangeBasedForStmt stmt; override TranslatedElement getChild(int id) { - id = 0 and result = getRangeVariableDeclaration() or - id = 1 and result = getBeginVariableDeclaration() or - id = 2 and result = getEndVariableDeclaration() or - id = 3 and result = getCondition() or - id = 4 and result = getUpdate() or - id = 5 and result = getVariableDeclaration() or + id = 0 and result = getRangeVariableDeclaration() + or + id = 1 and result = getBeginVariableDeclaration() + or + id = 2 and result = getEndVariableDeclaration() + or + id = 3 and result = getCondition() + or + id = 4 and result = getUpdate() + or + id = 5 and result = getVariableDeclaration() + or id = 6 and result = getBody() } @@ -671,40 +578,32 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext { } override Instruction getChildSuccessor(TranslatedElement child) { - ( - child = getRangeVariableDeclaration() and - result = getBeginVariableDeclaration().getFirstInstruction() - ) or - ( - child = getBeginVariableDeclaration() and - result = getEndVariableDeclaration().getFirstInstruction() - ) or - ( - child = getEndVariableDeclaration() and - result = getCondition().getFirstInstruction() - ) or - ( - child = getVariableDeclaration() and - result = getBody().getFirstInstruction() - ) or - ( - child = getBody() and - result = getUpdate().getFirstInstruction() - ) or - ( - child = getUpdate() and - result = getCondition().getFirstInstruction() - ) + child = getRangeVariableDeclaration() and + result = getBeginVariableDeclaration().getFirstInstruction() + or + child = getBeginVariableDeclaration() and + result = getEndVariableDeclaration().getFirstInstruction() + or + child = getEndVariableDeclaration() and + result = getCondition().getFirstInstruction() + or + child = getVariableDeclaration() and + result = getBody().getFirstInstruction() + or + child = getBody() and + result = getUpdate().getFirstInstruction() + or + child = getUpdate() and + result = getCondition().getFirstInstruction() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type resultType, - boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { none() } - override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { - none() - } + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } override Instruction getChildTrueSuccessor(TranslatedCondition child) { child = getCondition() and result = getVariableDeclaration().getFirstInstruction() @@ -740,48 +639,41 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext { result = getTranslatedRangeBasedForVariableDeclaration(stmt.getVariable()) } - private TranslatedStmt getBody() { - result = getTranslatedStmt(stmt.getStmt()) - } + private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } } class TranslatedJumpStmt extends TranslatedStmt { override JumpStmt stmt; - override Instruction getFirstInstruction() { - result = getInstruction(OnlyInstructionTag()) - } + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = OnlyInstructionTag() and opcode instanceof Opcode::NoOp and resultType instanceof VoidType and isGLValue = false } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind instanceof GotoEdge and result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction() } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } } private EdgeKind getCaseEdge(SwitchCase switchCase) { exists(CaseEdge edge | result = edge and hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue()) - ) or - (switchCase instanceof DefaultCase and result instanceof DefaultEdge) + ) + or + switchCase instanceof DefaultCase and result instanceof DefaultEdge } class TranslatedSwitchStmt extends TranslatedStmt { @@ -791,36 +683,32 @@ class TranslatedSwitchStmt extends TranslatedStmt { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) } - private TranslatedStmt getBody() { - result = getTranslatedStmt(stmt.getStmt()) - } + private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } - override Instruction getFirstInstruction() { - result = getExpr().getFirstInstruction() - } + override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() } override TranslatedElement getChild(int id) { - id = 0 and result = getExpr() or + id = 0 and result = getExpr() + or id = 1 and result = getBody() } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = SwitchBranchTag() and opcode instanceof Opcode::Switch and resultType instanceof VoidType and isGLValue = false } - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = SwitchBranchTag() and operandTag instanceof ConditionOperandTag and result = getExpr().getResult() } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = SwitchBranchTag() and exists(SwitchCase switchCase | switchCase = stmt.getASwitchCase() and @@ -830,7 +718,8 @@ class TranslatedSwitchStmt extends TranslatedStmt { } override Instruction getChildSuccessor(TranslatedElement child) { - child = getExpr() and result = getInstruction(SwitchBranchTag()) or + child = getExpr() and result = getInstruction(SwitchBranchTag()) + or child = getBody() and result = getParent().getChildSuccessor(this) } } @@ -838,9 +727,7 @@ class TranslatedSwitchStmt extends TranslatedStmt { class TranslatedAsmStmt extends TranslatedStmt { override AsmStmt stmt; - override TranslatedElement getChild(int id) { - none() - } + override TranslatedElement getChild(int id) { none() } override Instruction getFirstInstruction() { if exists(stmt.getChild(0)) @@ -848,8 +735,9 @@ class TranslatedAsmStmt extends TranslatedStmt { else result = getInstruction(AsmTag()) } - override predicate hasInstruction(Opcode opcode, InstructionTag tag, - Type resultType, boolean isGLValue) { + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { tag = AsmTag() and opcode instanceof Opcode::InlineAsm and resultType instanceof UnknownType and @@ -867,12 +755,12 @@ class TranslatedAsmStmt extends TranslatedStmt { override IRVariable getInstructionVariable(InstructionTag tag) { exists(int index | tag = AsmInputTag(index) and - result = getIRUserVariable(stmt.getEnclosingFunction(), stmt.getChild(index).(VariableAccess).getTarget()) + result = getIRUserVariable(stmt.getEnclosingFunction(), + stmt.getChild(index).(VariableAccess).getTarget()) ) } - - override Instruction getInstructionOperand(InstructionTag tag, - OperandTag operandTag) { + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { tag = AsmTag() and operandTag instanceof SideEffectOperandTag and result = getTranslatedFunction(stmt.getEnclosingFunction()).getUnmodeledDefinitionInstruction() @@ -884,15 +772,13 @@ class TranslatedAsmStmt extends TranslatedStmt { ) } - override final Type getInstructionOperandType(InstructionTag tag, - TypedOperandTag operandTag) { + final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { tag = AsmTag() and operandTag instanceof SideEffectOperandTag and result instanceof UnknownType } - override Instruction getInstructionSuccessor(InstructionTag tag, - EdgeKind kind) { + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = AsmTag() and result = getParent().getChildSuccessor(this) and kind instanceof GotoEdge @@ -901,14 +787,10 @@ class TranslatedAsmStmt extends TranslatedStmt { tag = AsmInputTag(index) and kind instanceof GotoEdge and if exists(stmt.getChild(index + 1)) - then - result = getInstruction(AsmInputTag(index + 1)) - else - result = getInstruction(AsmTag()) + then result = getInstruction(AsmInputTag(index + 1)) + else result = getInstruction(AsmTag()) ) } - override Instruction getChildSuccessor(TranslatedElement child) { - none() - } + override Instruction getChildSuccessor(TranslatedElement child) { none() } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/DominanceInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/DominanceInternal.qll index dfe9b52f1a4..cee8fa1543b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/DominanceInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/DominanceInternal.qll @@ -1,7 +1,9 @@ private import ReachableBlock as Reachability + private module ReachabilityGraph = Reachability::Graph; module Graph { import Reachability::Graph + class Block = Reachability::ReachableBlock; } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll index 5242b135f4e..71a3a88ef8d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll @@ -9,13 +9,13 @@ private class DominancePropertyProvider extends IRPropertyProvider { blockImmediatelyDominates(dominator, block) and key = "ImmediateDominator" and result = "Block " + dominator.getDisplayIndex().toString() - ) or - ( - key = "DominanceFrontier" and - result = strictconcat(IRBlock frontierBlock | - frontierBlock = getDominanceFrontier(block) | + ) + or + key = "DominanceFrontier" and + result = strictconcat(IRBlock frontierBlock | + frontierBlock = getDominanceFrontier(block) + | frontierBlock.getDisplayIndex().toString(), ", " order by frontierBlock.getDisplayIndex() ) - ) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintReachableBlock.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintReachableBlock.qll index 1af465d6ec9..6befad72336 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintReachableBlock.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintReachableBlock.qll @@ -4,17 +4,14 @@ import IR private class ReachableBlockPropertyProvider extends IRPropertyProvider { override string getBlockProperty(IRBlock block, string key) { - ( - not block instanceof ReachableBlock and - key = "Unreachable" and + not block instanceof ReachableBlock and + key = "Unreachable" and + result = "true" + or + exists(EdgeKind kind | + isInfeasibleEdge(block, kind) and + key = "Infeasible(" + kind.toString() + ")" and result = "true" - ) or - ( - exists(EdgeKind kind | - isInfeasibleEdge(block, kind) and - key = "Infeasible(" + kind.toString() + ")" and - result = "true" - ) ) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlock.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlock.qll index 10f6c7a310d..25a53bbefe8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlock.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlock.qll @@ -5,10 +5,7 @@ private import ConstantAnalysis predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) { exists(int conditionValue | conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and - if conditionValue = 0 then - kind instanceof TrueEdge - else - kind instanceof FalseEdge + if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge ) } @@ -25,9 +22,7 @@ private IRBlock getAFeasiblePredecessorBlock(IRBlock successor) { } private predicate isBlockReachable(IRBlock block) { - exists(IRFunction f | - getAFeasiblePredecessorBlock*(block) = f.getEntryBlock() - ) + exists(IRFunction f | getAFeasiblePredecessorBlock*(block) = f.getEntryBlock()) } /** @@ -35,34 +30,22 @@ private predicate isBlockReachable(IRBlock block) { * edges. */ class ReachableBlock extends IRBlockBase { - ReachableBlock() { - isBlockReachable(this) - } + ReachableBlock() { isBlockReachable(this) } - final ReachableBlock getAFeasiblePredecessor() { - result = getAFeasiblePredecessorBlock(this) - } + final ReachableBlock getAFeasiblePredecessor() { result = getAFeasiblePredecessorBlock(this) } - final ReachableBlock getAFeasibleSuccessor() { - this = getAFeasiblePredecessorBlock(result) - } + final ReachableBlock getAFeasibleSuccessor() { this = getAFeasiblePredecessorBlock(result) } } /** * An instruction that is contained in a reachable block. */ class ReachableInstruction extends Instruction { - ReachableInstruction() { - this.getBlock() instanceof ReachableBlock - } + ReachableInstruction() { this.getBlock() instanceof ReachableBlock } } module Graph { - predicate isEntryBlock(ReachableBlock block) { - exists(IRFunction f | - block = f.getEntryBlock() - ) - } + predicate isEntryBlock(ReachableBlock block) { exists(IRFunction f | block = f.getEntryBlock()) } predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) { succ = pred.getAFeasibleSuccessor() diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlockInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlockInternal.qll index e58552be10f..3041b662962 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlockInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/ReachableBlockInternal.qll @@ -1,2 +1,2 @@ import semmle.code.cpp.ir.implementation.raw.IR as IR -import semmle.code.cpp.ir.implementation.raw.constant.ConstantAnalysis as ConstantAnalysis \ No newline at end of file +import semmle.code.cpp.ir.implementation.raw.constant.ConstantAnalysis as ConstantAnalysis diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.ql b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.ql index eabdb8e31b2..eee45030caf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.ql +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.ql @@ -1,6 +1,6 @@ /** * @name SSA IR Sanity Check - * @description Performs sanity checks on the Intermediate Representation. This query should have no results. + * @description Performs sanity checks on the Intermediate Representation. This query should have no results. * @kind table * @id cpp/ssa-ir-sanity-check */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll index 01adf74efa8..40076b817a1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll @@ -4,10 +4,14 @@ private import IR language[monotonicAggregates] int getConstantValue(Instruction instr) { - result = instr.(IntegerConstantInstruction).getValue().toInt() or - result = getBinaryInstructionValue(instr) or - result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) or - result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or + result = instr.(IntegerConstantInstruction).getValue().toInt() + or + result = getBinaryInstructionValue(instr) + or + result = neg(getConstantValue(instr.(NegateInstruction).getUnary())) + or + result = getConstantValue(instr.(CopyInstruction).getSourceValue()) + or exists(PhiInstruction phi | phi = instr and result = max(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef())) and @@ -26,15 +30,24 @@ private int getBinaryInstructionValue(BinaryInstruction instr) { exists(int left, int right | binaryInstructionOperands(instr, left, right) and ( - instr instanceof AddInstruction and result = add(left, right) or - instr instanceof SubInstruction and result = sub(left, right) or - instr instanceof MulInstruction and result = mul(left, right) or - instr instanceof DivInstruction and result = div(left, right) or - instr instanceof CompareEQInstruction and result = compareEQ(left, right) or - instr instanceof CompareNEInstruction and result = compareNE(left, right) or - instr instanceof CompareLTInstruction and result = compareLT(left, right) or - instr instanceof CompareGTInstruction and result = compareGT(left, right) or - instr instanceof CompareLEInstruction and result = compareLE(left, right) or + instr instanceof AddInstruction and result = add(left, right) + or + instr instanceof SubInstruction and result = sub(left, right) + or + instr instanceof MulInstruction and result = mul(left, right) + or + instr instanceof DivInstruction and result = div(left, right) + or + instr instanceof CompareEQInstruction and result = compareEQ(left, right) + or + instr instanceof CompareNEInstruction and result = compareNE(left, right) + or + instr instanceof CompareLTInstruction and result = compareLT(left, right) + or + instr instanceof CompareGTInstruction and result = compareGT(left, right) + or + instr instanceof CompareLEInstruction and result = compareLE(left, right) + or instr instanceof CompareGEInstruction and result = compareGE(left, right) ) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll index 9488e708f59..e3e52df8931 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll @@ -10,10 +10,7 @@ class ValueNumberPropertyProvider extends IRPropertyProvider { exists(ValueNumber vn | vn = valueNumber(instr) and key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 then - result = vn.toString() - else - result = "unique" + if strictcount(vn.getAnInstruction()) > 1 then result = vn.toString() else result = "unique" ) } } @@ -25,9 +22,7 @@ newtype TValueNumber = TInitializeParameterValueNumber(IRFunction irFunc, IRVariable var) { initializeParameterValueNumber(_, irFunc, var) } or - TInitializeThisValueNumber(IRFunction irFunc) { - initializeThisValueNumber(_, irFunc) - } or + TInitializeThisValueNumber(IRFunction irFunc) { initializeThisValueNumber(_, irFunc) } or TConstantValueNumber(IRFunction irFunc, Type type, string value) { constantValueNumber(_, irFunc, type, value) } or @@ -37,44 +32,40 @@ newtype TValueNumber = TFieldAddressValueNumber(IRFunction irFunc, Field field, ValueNumber objectAddress) { fieldAddressValueNumber(_, irFunc, field, objectAddress) } or - TBinaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, - ValueNumber rightOperand) { + TBinaryValueNumber( + IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand + ) { binaryValueNumber(_, irFunc, opcode, type, leftOperand, rightOperand) } or - TPointerArithmeticValueNumber(IRFunction irFunc, Opcode opcode, Type type, int elementSize, - ValueNumber leftOperand, ValueNumber rightOperand) { + TPointerArithmeticValueNumber( + IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, + ValueNumber rightOperand + ) { pointerArithmeticValueNumber(_, irFunc, opcode, type, elementSize, leftOperand, rightOperand) } or TUnaryValueNumber(IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand) { unaryValueNumber(_, irFunc, opcode, type, operand) } or - TInheritanceConversionValueNumber(IRFunction irFunc, Opcode opcode, Class baseClass, - Class derivedClass, ValueNumber operand) { + TInheritanceConversionValueNumber( + IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand + ) { inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand) } or - TUniqueValueNumber(IRFunction irFunc, Instruction instr) { - uniqueValueNumber(instr, irFunc) - } + TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } /** * The value number assigned to a particular set of instructions that produce equivalent results. */ class ValueNumber extends TValueNumber { - final string toString() { - result = getExampleInstruction().getResultId() - } + final string toString() { result = getExampleInstruction().getResultId() } - final Location getLocation() { - result = getExampleInstruction().getLocation() - } + final Location getLocation() { result = getExampleInstruction().getLocation() } /** * Gets the instructions that have been assigned this value number. This will always produce at * least one result. */ - final Instruction getAnInstruction() { - this = valueNumber(result) - } + final Instruction getAnInstruction() { this = valueNumber(result) } /** * Gets one of the instructions that was assigned this value number. The chosen instuction is @@ -82,17 +73,16 @@ class ValueNumber extends TValueNumber { */ final Instruction getExampleInstruction() { result = min(Instruction instr | - instr = getAnInstruction() | - instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() - ) + instr = getAnInstruction() + | + instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() + ) } /** * Gets an `Operand` whose definition is exact and has this value number. */ - final Operand getAUse() { - this = valueNumber(result.getDef()) - } + final Operand getAUse() { this = valueNumber(result.getDef()) } } /** @@ -120,26 +110,37 @@ private class CongruentCopyInstruction extends CopyInstruction { * a `unique` value number that is never shared by multiple instructions. */ private predicate numberableInstruction(Instruction instr) { - instr instanceof VariableAddressInstruction or - instr instanceof InitializeParameterInstruction or - instr instanceof InitializeThisInstruction or - instr instanceof ConstantInstruction or - instr instanceof StringConstantInstruction or - instr instanceof FieldAddressInstruction or - instr instanceof BinaryInstruction or - (instr instanceof UnaryInstruction and not instr instanceof CopyInstruction) or - instr instanceof PointerArithmeticInstruction or + instr instanceof VariableAddressInstruction + or + instr instanceof InitializeParameterInstruction + or + instr instanceof InitializeThisInstruction + or + instr instanceof ConstantInstruction + or + instr instanceof StringConstantInstruction + or + instr instanceof FieldAddressInstruction + or + instr instanceof BinaryInstruction + or + instr instanceof UnaryInstruction and not instr instanceof CopyInstruction + or + instr instanceof PointerArithmeticInstruction + or instr instanceof CongruentCopyInstruction } -private predicate variableAddressValueNumber(VariableAddressInstruction instr, IRFunction irFunc, - IRVariable var) { +private predicate variableAddressValueNumber( + VariableAddressInstruction instr, IRFunction irFunc, IRVariable var +) { instr.getEnclosingIRFunction() = irFunc and instr.getVariable() = var } -private predicate initializeParameterValueNumber(InitializeParameterInstruction instr, - IRFunction irFunc, IRVariable var) { +private predicate initializeParameterValueNumber( + InitializeParameterInstruction instr, IRFunction irFunc, IRVariable var +) { instr.getEnclosingIRFunction() = irFunc and instr.getVariable() = var } @@ -148,40 +149,46 @@ private predicate initializeThisValueNumber(InitializeThisInstruction instr, IRF instr.getEnclosingIRFunction() = irFunc } -private predicate constantValueNumber(ConstantInstruction instr, IRFunction irFunc, Type type, - string value) { +private predicate constantValueNumber( + ConstantInstruction instr, IRFunction irFunc, Type type, string value +) { instr.getEnclosingIRFunction() = irFunc and instr.getResultType() = type and instr.getValue() = value } -private predicate stringConstantValueNumber(StringConstantInstruction instr, IRFunction irFunc, Type type, - string value) { +private predicate stringConstantValueNumber( + StringConstantInstruction instr, IRFunction irFunc, Type type, string value +) { instr.getEnclosingIRFunction() = irFunc and instr.getResultType() = type and instr.getValue().getValue() = value } -private predicate fieldAddressValueNumber(FieldAddressInstruction instr, IRFunction irFunc, - Field field, ValueNumber objectAddress) { +private predicate fieldAddressValueNumber( + FieldAddressInstruction instr, IRFunction irFunc, Field field, ValueNumber objectAddress +) { instr.getEnclosingIRFunction() = irFunc and instr.getField() = field and valueNumber(instr.getObjectAddress()) = objectAddress } -private predicate binaryValueNumber(BinaryInstruction instr, IRFunction irFunc, Opcode opcode, - Type type, ValueNumber leftOperand, ValueNumber rightOperand) { +private predicate binaryValueNumber( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber leftOperand, + ValueNumber rightOperand +) { instr.getEnclosingIRFunction() = irFunc and - (not instr instanceof PointerArithmeticInstruction) and + not instr instanceof PointerArithmeticInstruction and instr.getOpcode() = opcode and instr.getResultType() = type and valueNumber(instr.getLeft()) = leftOperand and valueNumber(instr.getRight()) = rightOperand } -private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction instr, - IRFunction irFunc, Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, - ValueNumber rightOperand) { +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, Type type, int elementSize, + ValueNumber leftOperand, ValueNumber rightOperand +) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getResultType() = type and @@ -190,18 +197,21 @@ private predicate pointerArithmeticValueNumber(PointerArithmeticInstruction inst valueNumber(instr.getRight()) = rightOperand } -private predicate unaryValueNumber(UnaryInstruction instr, IRFunction irFunc, Opcode opcode, - Type type, ValueNumber operand) { +private predicate unaryValueNumber( + UnaryInstruction instr, IRFunction irFunc, Opcode opcode, Type type, ValueNumber operand +) { instr.getEnclosingIRFunction() = irFunc and - (not instr instanceof InheritanceConversionInstruction) and - (not instr instanceof CopyInstruction) and + not instr instanceof InheritanceConversionInstruction and + not instr instanceof CopyInstruction and instr.getOpcode() = opcode and instr.getResultType() = type and valueNumber(instr.getUnary()) = operand } -private predicate inheritanceConversionValueNumber(InheritanceConversionInstruction instr, - IRFunction irFunc, Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand) { +private predicate inheritanceConversionValueNumber( + InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode, Class baseClass, + Class derivedClass, ValueNumber operand +) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getBaseClass() = baseClass and @@ -215,15 +225,17 @@ private predicate inheritanceConversionValueNumber(InheritanceConversionInstruct */ private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) { instr.getEnclosingIRFunction() = irFunc and - (not instr.getResultType() instanceof VoidType) and + not instr.getResultType() instanceof VoidType and not numberableInstruction(instr) } /** * Gets the value number assigned to `instr`, if any. Returns at most one result. */ -cached ValueNumber valueNumber(Instruction instr) { - result = nonUniqueValueNumber(instr) or +cached +ValueNumber valueNumber(Instruction instr) { + result = nonUniqueValueNumber(instr) + or exists(IRFunction irFunc | uniqueValueNumber(instr, irFunc) and result = TUniqueValueNumber(irFunc, instr) @@ -234,9 +246,7 @@ cached ValueNumber valueNumber(Instruction instr) { * Gets the value number assigned to the exact definition of `op`, if any. * Returns at most one result. */ -ValueNumber valueNumberOfOperand(Operand op) { - result = valueNumber(op.getDef()) -} +ValueNumber valueNumberOfOperand(Operand op) { result = valueNumber(op.getDef()) } /** * Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique @@ -249,47 +259,55 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) { exists(IRVariable var | variableAddressValueNumber(instr, irFunc, var) and result = TVariableAddressValueNumber(irFunc, var) - ) or + ) + or exists(IRVariable var | initializeParameterValueNumber(instr, irFunc, var) and result = TInitializeParameterValueNumber(irFunc, var) - ) or - ( - initializeThisValueNumber(instr, irFunc) and - result = TInitializeThisValueNumber(irFunc) - ) or + ) + or + initializeThisValueNumber(instr, irFunc) and + result = TInitializeThisValueNumber(irFunc) + or exists(Type type, string value | constantValueNumber(instr, irFunc, type, value) and result = TConstantValueNumber(irFunc, type, value) - ) or + ) + or exists(Type type, string value | stringConstantValueNumber(instr, irFunc, type, value) and result = TStringConstantValueNumber(irFunc, type, value) - ) or + ) + or exists(Field field, ValueNumber objectAddress | fieldAddressValueNumber(instr, irFunc, field, objectAddress) and result = TFieldAddressValueNumber(irFunc, field, objectAddress) - ) or + ) + or exists(Opcode opcode, Type type, ValueNumber leftOperand, ValueNumber rightOperand | binaryValueNumber(instr, irFunc, opcode, type, leftOperand, rightOperand) and result = TBinaryValueNumber(irFunc, opcode, type, leftOperand, rightOperand) - ) or + ) + or exists(Opcode opcode, Type type, ValueNumber operand | unaryValueNumber(instr, irFunc, opcode, type, operand) and result = TUnaryValueNumber(irFunc, opcode, type, operand) - ) or + ) + or exists(Opcode opcode, Class baseClass, Class derivedClass, ValueNumber operand | - inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, - operand) and + inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand) - ) or - exists(Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, - ValueNumber rightOperand | + ) + or + exists( + Opcode opcode, Type type, int elementSize, ValueNumber leftOperand, ValueNumber rightOperand + | pointerArithmeticValueNumber(instr, irFunc, opcode, type, elementSize, leftOperand, - rightOperand) and + rightOperand) and result = TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand) - ) or + ) + or // The value number of a copy is just the value number of its source value. result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue()) ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 3c50cea6206..dc50ef01354 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -2,7 +2,6 @@ private import AliasAnalysisInternal private import cpp private import InputIR private import semmle.code.cpp.ir.internal.IntegerConstant as Ints - private import semmle.code.cpp.models.interfaces.Alias private class IntValue = Ints::IntValue; @@ -12,35 +11,28 @@ private class IntValue = Ints::IntValue; * bytes:bits. */ bindingset[bits] -string bitsToBytesAndBits(int bits) { - result = (bits / 8).toString() + ":" + (bits % 8).toString() -} +string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() } /** * Gets a printable string for a bit offset with possibly unknown value. */ bindingset[bitOffset] string getBitOffsetString(IntValue bitOffset) { - if Ints::hasValue(bitOffset) then - if bitOffset >= 0 then - result = "+" + bitsToBytesAndBits(bitOffset) - else - result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) - else - result = "+?" + if Ints::hasValue(bitOffset) + then + if bitOffset >= 0 + then result = "+" + bitsToBytesAndBits(bitOffset) + else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset)) + else result = "+?" } /** * Gets the offset of field `field` in bits. */ private IntValue getFieldBitOffset(Field field) { - if (field instanceof BitField) then ( - result = Ints::add(Ints::mul(field.getByteOffset(), 8), - field.(BitField).getBitOffset()) - ) - else ( - result = Ints::mul(field.getByteOffset(), 8) - ) + if field instanceof BitField + then result = Ints::add(Ints::mul(field.getByteOffset(), 8), field.(BitField).getBitOffset()) + else result = Ints::mul(field.getByteOffset(), 8) } /** @@ -51,18 +43,22 @@ private IntValue getFieldBitOffset(Field field) { private predicate operandIsConsumedWithoutEscaping(Operand operand) { // The source/destination address of a Load/Store does not escape (but the // loaded/stored value could). - operand instanceof AddressOperand or - exists (Instruction instr | + operand instanceof AddressOperand + or + exists(Instruction instr | instr = operand.getUse() and ( // Neither operand of a Compare escapes. - instr instanceof CompareInstruction or + instr instanceof CompareInstruction + or // Neither operand of a PointerDiff escapes. - instr instanceof PointerDiffInstruction or + instr instanceof PointerDiffInstruction + or // Converting an address to a `bool` does not escape the address. instr.(ConvertInstruction).getResultType() instanceof BoolType ) - ) or + ) + or // Some standard function arguments never escape isNeverEscapesArgument(operand) } @@ -81,10 +77,9 @@ private predicate operandEscapesDomain(Operand operand) { * value of that constant. Otherwise, returns unknown. */ IntValue getConstantValue(Instruction instr) { - if instr instanceof IntegerConstantInstruction then - result = instr.(IntegerConstantInstruction).getValue().toInt() - else - result = Ints::unknown() + if instr instanceof IntegerConstantInstruction + then result = instr.(IntegerConstantInstruction).getValue().toInt() + else result = Ints::unknown() } /** @@ -94,12 +89,10 @@ IntValue getConstantValue(Instruction instr) { */ IntValue getPointerBitOffset(PointerOffsetInstruction instr) { exists(IntValue bitOffset | + bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRight()), instr.getElementSize()), 8) and ( - bitOffset = Ints::mul(Ints::mul(getConstantValue(instr.getRight()), - instr.getElementSize()), 8) - ) and - ( - instr instanceof PointerAddInstruction and result = bitOffset or + instr instanceof PointerAddInstruction and result = bitOffset + or instr instanceof PointerSubInstruction and result = Ints::neg(bitOffset) ) ) @@ -119,35 +112,40 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { exists(ConvertToBaseInstruction convert | convert = instr and bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) - ) or + ) + or // Converting to a derived class subtracts the offset of the base class. exists(ConvertToDerivedInstruction convert | convert = instr and bitOffset = Ints::neg(Ints::mul(convert.getDerivation().getByteOffset(), 8)) - ) or + ) + or // Converting to a virtual base class adds an unknown offset. - ( - instr instanceof ConvertToVirtualBaseInstruction and - bitOffset = Ints::unknown() - ) or + instr instanceof ConvertToVirtualBaseInstruction and + bitOffset = Ints::unknown() + or // Conversion to another pointer type propagates the source address. exists(ConvertInstruction convert, Type resultType | convert = instr and resultType = convert.getResultType() and ( resultType instanceof PointerType or - resultType instanceof Class //REVIEW: Remove when all glvalues are pointers + resultType instanceof Class //REVIEW: Remove when all glvalues are pointers ) and bitOffset = 0 - ) or + ) + or // Adding an integer to or subtracting an integer from a pointer propagates // the address with an offset. - bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) or + bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction)) + or // Computing a field address from a pointer propagates the address plus the // offset of the field. - bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or + bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) + or // A copy propagates the source value. - operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 or + operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 + or // Some functions are known to propagate an argument isAlwaysReturnedArgument(operand) and bitOffset = 0 ) @@ -212,14 +210,14 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) { resultReturned(init, bitOffset1) and resultReturned(ci, bitOffset2) and bitOffset = Ints::add(bitOffset1, bitOffset2) - ) or // The address is returned operand.getUse() instanceof ReturnValueInstruction and bitOffset = 0 or - isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUse(), _) and + isOnlyEscapesViaReturnArgument(operand) and + resultReturned(operand.getUse(), _) and bitOffset = Ints::unknown() } @@ -228,7 +226,8 @@ private predicate isArgumentForParameter(CallInstruction ci, Operand operand, In ci = operand.getUse() and f = ci.getStaticCallTarget() and ( - init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex()) + init.(InitializeParameterInstruction).getParameter() = f + .getParameter(operand.(PositionalArgumentOperand).getIndex()) or init instanceof InitializeThisInstruction and init.getEnclosingFunction() = f and @@ -264,9 +263,7 @@ private predicate resultReturned(Instruction instr, IntValue bitOffset) { operandReturned(instr.getAUse(), bitOffset) } -private predicate resultMayReachReturn(Instruction instr) { - operandMayReachReturn(instr.getAUse()) -} +private predicate resultMayReachReturn(Instruction instr) { operandMayReachReturn(instr.getAUse()) } /** * Holds if any address held in the result of instruction `instr` escapes @@ -295,7 +292,8 @@ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { * analysis. */ predicate variableAddressEscapes(IRVariable var) { - automaticVariableAddressEscapes(var.(IRAutomaticVariable)) or + automaticVariableAddressEscapes(var.(IRAutomaticVariable)) + or // All variables with static storage duration have their address escape. not var instanceof IRAutomaticVariable } @@ -306,11 +304,10 @@ predicate variableAddressEscapes(IRVariable var) { * `var`, but at an unknown or non-constant offset, then `bitOffset` is unknown. */ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) { - ( - // The address of a variable points to that variable, at offset 0. - instr.(VariableAddressInstruction).getVariable() = var and - bitOffset = 0 - ) or + // The address of a variable points to that variable, at offset 0. + instr.(VariableAddressInstruction).getVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/DominanceInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/DominanceInternal.qll index dfe9b52f1a4..cee8fa1543b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/DominanceInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/DominanceInternal.qll @@ -1,7 +1,9 @@ private import ReachableBlock as Reachability + private module ReachabilityGraph = Reachability::Graph; module Graph { import Reachability::Graph + class Block = Reachability::ReachableBlock; } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll index 5242b135f4e..71a3a88ef8d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll @@ -9,13 +9,13 @@ private class DominancePropertyProvider extends IRPropertyProvider { blockImmediatelyDominates(dominator, block) and key = "ImmediateDominator" and result = "Block " + dominator.getDisplayIndex().toString() - ) or - ( - key = "DominanceFrontier" and - result = strictconcat(IRBlock frontierBlock | - frontierBlock = getDominanceFrontier(block) | + ) + or + key = "DominanceFrontier" and + result = strictconcat(IRBlock frontierBlock | + frontierBlock = getDominanceFrontier(block) + | frontierBlock.getDisplayIndex().toString(), ", " order by frontierBlock.getDisplayIndex() ) - ) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintReachableBlock.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintReachableBlock.qll index 1af465d6ec9..6befad72336 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintReachableBlock.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintReachableBlock.qll @@ -4,17 +4,14 @@ import IR private class ReachableBlockPropertyProvider extends IRPropertyProvider { override string getBlockProperty(IRBlock block, string key) { - ( - not block instanceof ReachableBlock and - key = "Unreachable" and + not block instanceof ReachableBlock and + key = "Unreachable" and + result = "true" + or + exists(EdgeKind kind | + isInfeasibleEdge(block, kind) and + key = "Infeasible(" + kind.toString() + ")" and result = "true" - ) or - ( - exists(EdgeKind kind | - isInfeasibleEdge(block, kind) and - key = "Infeasible(" + kind.toString() + ")" and - result = "true" - ) ) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlock.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlock.qll index 10f6c7a310d..25a53bbefe8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlock.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlock.qll @@ -5,10 +5,7 @@ private import ConstantAnalysis predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) { exists(int conditionValue | conditionValue = getConstantValue(instr.(ConditionalBranchInstruction).getCondition()) and - if conditionValue = 0 then - kind instanceof TrueEdge - else - kind instanceof FalseEdge + if conditionValue = 0 then kind instanceof TrueEdge else kind instanceof FalseEdge ) } @@ -25,9 +22,7 @@ private IRBlock getAFeasiblePredecessorBlock(IRBlock successor) { } private predicate isBlockReachable(IRBlock block) { - exists(IRFunction f | - getAFeasiblePredecessorBlock*(block) = f.getEntryBlock() - ) + exists(IRFunction f | getAFeasiblePredecessorBlock*(block) = f.getEntryBlock()) } /** @@ -35,34 +30,22 @@ private predicate isBlockReachable(IRBlock block) { * edges. */ class ReachableBlock extends IRBlockBase { - ReachableBlock() { - isBlockReachable(this) - } + ReachableBlock() { isBlockReachable(this) } - final ReachableBlock getAFeasiblePredecessor() { - result = getAFeasiblePredecessorBlock(this) - } + final ReachableBlock getAFeasiblePredecessor() { result = getAFeasiblePredecessorBlock(this) } - final ReachableBlock getAFeasibleSuccessor() { - this = getAFeasiblePredecessorBlock(result) - } + final ReachableBlock getAFeasibleSuccessor() { this = getAFeasiblePredecessorBlock(result) } } /** * An instruction that is contained in a reachable block. */ class ReachableInstruction extends Instruction { - ReachableInstruction() { - this.getBlock() instanceof ReachableBlock - } + ReachableInstruction() { this.getBlock() instanceof ReachableBlock } } module Graph { - predicate isEntryBlock(ReachableBlock block) { - exists(IRFunction f | - block = f.getEntryBlock() - ) - } + predicate isEntryBlock(ReachableBlock block) { exists(IRFunction f | block = f.getEntryBlock()) } predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) { succ = pred.getAFeasibleSuccessor() diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlockInternal.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlockInternal.qll index bcaaaaf69d0..61dc1a50399 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlockInternal.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/ReachableBlockInternal.qll @@ -1,2 +1,2 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as IR -import semmle.code.cpp.ir.implementation.unaliased_ssa.constant.ConstantAnalysis as ConstantAnalysis \ No newline at end of file +import semmle.code.cpp.ir.implementation.unaliased_ssa.constant.ConstantAnalysis as ConstantAnalysis diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 84b6d7fbeb9..cda661bd216 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -3,13 +3,19 @@ private import semmle.code.cpp.Print as Print private import IRUtilities class Function = Cpp::Function; + class Location = Cpp::Location; + class AST = Cpp::Locatable; class Type = Cpp::Type; + class UnknownType = Cpp::UnknownType; + class VoidType = Cpp::VoidType; + class IntegralType = Cpp::IntegralType; + class FloatingPointType = Cpp::FloatingPointType; // REVIEW: May need to synthesize this for other languages. Or do we really need it at all? @@ -18,49 +24,40 @@ class ClassDerivation = Cpp::ClassDerivation; class StringLiteral = Cpp::StringLiteral; class Variable = Cpp::Variable; + class AutomaticVariable = Cpp::LocalScopeVariable; + class StaticVariable = Cpp::Variable; + class Parameter = Cpp::Parameter; + class Field = Cpp::Field; class BuiltInOperation = Cpp::BuiltInOperation; // TODO: Remove necessity for these. class Expr = Cpp::Expr; -class Class = Cpp::Class; // Used for inheritance conversions + +class Class = Cpp::Class; // Used for inheritance conversions predicate getIdentityString = Print::getIdentityString/1; predicate hasCaseEdge(string minValue, string maxValue) { - exists(Cpp::SwitchCase switchCase | - hasCaseEdge(switchCase, minValue, maxValue) - ) + exists(Cpp::SwitchCase switchCase | hasCaseEdge(switchCase, minValue, maxValue)) } predicate hasPositionalArgIndex(int argIndex) { - exists(Cpp::FunctionCall call | - exists(call.getArgument(argIndex)) - ) or - exists(Cpp::BuiltInOperation op | - exists(op.getChild(argIndex)) - ) + exists(Cpp::FunctionCall call | exists(call.getArgument(argIndex))) or + exists(Cpp::BuiltInOperation op | exists(op.getChild(argIndex))) } predicate hasAsmOperandIndex(int operandIndex) { - exists(Cpp::AsmStmt asm | - exists(asm.getChild(operandIndex)) - ) + exists(Cpp::AsmStmt asm | exists(asm.getChild(operandIndex))) } -int getTypeSize(Type type) { - result = type.getSize() -} +int getTypeSize(Type type) { result = type.getSize() } -int getPointerSize() { - exists(Cpp::NullPointerType nullptr | - result = nullptr.getSize() - ) -} +int getPointerSize() { exists(Cpp::NullPointerType nullptr | result = nullptr.getSize()) } predicate isVariableAutomatic(Variable var) { var instanceof Cpp::LocalScopeVariable and @@ -76,6 +73,4 @@ predicate hasPotentialLoop(Function f) { exists(Cpp::GotoStmt s | s.getEnclosingFunction() = f) } -predicate hasGoto(Function f) { - exists(Cpp::GotoStmt s | s.getEnclosingFunction() = f) -} +predicate hasGoto(Function f) { exists(Cpp::GotoStmt s | s.getEnclosingFunction() = f) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll index d19ac11338d..53c15663796 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll @@ -19,24 +19,24 @@ private Type getDecayedType(Type type) { Type getVariableType(Variable v) { exists(Type declaredType | declaredType = v.getUnspecifiedType() and - if v instanceof Parameter then ( - result = getDecayedType(declaredType) or + if v instanceof Parameter + then + result = getDecayedType(declaredType) + or not exists(getDecayedType(declaredType)) and result = declaredType - ) - else if declaredType instanceof ArrayType and not declaredType.(ArrayType).hasArraySize() then ( - result = v.getInitializer().getExpr().getUnspecifiedType() or - not exists(v.getInitializer()) and result = declaredType - ) - else ( - result = declaredType - ) + else + if declaredType instanceof ArrayType and not declaredType.(ArrayType).hasArraySize() + then + result = v.getInitializer().getExpr().getUnspecifiedType() + or + not exists(v.getInitializer()) and result = declaredType + else result = declaredType ) } predicate hasCaseEdge(SwitchCase switchCase, string minValue, string maxValue) { minValue = switchCase.getExpr().getFullyConverted().getValue() and - if exists(switchCase.getEndExpr()) then - maxValue = switchCase.getEndExpr().getFullyConverted().getValue() - else - maxValue = minValue + if exists(switchCase.getEndExpr()) + then maxValue = switchCase.getEndExpr().getFullyConverted().getValue() + else maxValue = minValue } diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll index 1e66923aae5..04bef55768c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/TempVariableTag.qll @@ -5,8 +5,11 @@ newtype TTempVariableTag = LambdaTempVar() string getTempVariableTagId(TTempVariableTag tag) { - tag = ConditionValueTempVar() and result = "CondVal" or - tag = ReturnValueTempVar() and result = "Ret" or - tag = ThrowTempVar() and result = "Throw" or + tag = ConditionValueTempVar() and result = "CondVal" + or + tag = ReturnValueTempVar() and result = "Ret" + or + tag = ThrowTempVar() and result = "Throw" + or tag = LambdaTempVar() and result = "Lambda" } diff --git a/cpp/ql/src/semmle/code/cpp/metrics/MetricClass.qll b/cpp/ql/src/semmle/code/cpp/metrics/MetricClass.qll index c59f2927d49..73ce421aaf4 100644 --- a/cpp/ql/src/semmle/code/cpp/metrics/MetricClass.qll +++ b/cpp/ql/src/semmle/code/cpp/metrics/MetricClass.qll @@ -3,17 +3,15 @@ import cpp /** * A wrapper that provides metrics for a C++ class. */ -class MetricClass extends Class { - +class MetricClass extends Class { /** * Gets the nesting level of this class. A class that is _not_ nested * directly inside another class has nesting level 0. */ int getNestingLevel() { - if not this instanceof NestedClass then - result = 0 - else - result = this.(NestedClass).getDeclaringType().(MetricClass).getNestingLevel() + 1 + if not this instanceof NestedClass + then result = 0 + else result = this.(NestedClass).getDeclaringType().(MetricClass).getNestingLevel() + 1 } /** @@ -22,19 +20,16 @@ class MetricClass extends Class { */ int getADepth() { not this.getABaseClass+() = this and - if not exists(this.getABaseClass()) then - result = 0 - else - result = this.getABaseClass().(MetricClass).getADepth() + 1 + if not exists(this.getABaseClass()) + then result = 0 + else result = this.getABaseClass().(MetricClass).getADepth() + 1 } /** * Gets the maximum depth of inheritance of this class. A class with no base * class has depth 0. */ - int getInheritanceDepth() { - result = max(this.getADepth()) - } + int getInheritanceDepth() { result = max(this.getADepth()) } /** Gets the number of member functions in this class. */ int getNumberOfMemberFunctions() { @@ -42,29 +37,19 @@ class MetricClass extends Class { } /** Gets the number of nested classes defined in this class. */ - int getNumberOfNestedClasses() { - result = count(NestedClass nc | nc.getDeclaringType() = this) - } + int getNumberOfNestedClasses() { result = count(NestedClass nc | nc.getDeclaringType() = this) } /** Gets the number of non-static data members defined in this class. */ - int getNumberOfFields() { - result = count(Field f | f.getDeclaringType() = this) - } + int getNumberOfFields() { result = count(Field f | f.getDeclaringType() = this) } /** Gets the total number of members defined in this class. */ - int getNumberOfMembers() { - result = count(Declaration m | m.getDeclaringType() = this) - } + int getNumberOfMembers() { result = count(Declaration m | m.getDeclaringType() = this) } /** Gets the number of incoming class dependencies. */ - int getAfferentCoupling() { - result = count(MetricClass that | that.getAClassDependency() = this) - } + int getAfferentCoupling() { result = count(MetricClass that | that.getAClassDependency() = this) } /** Gets the number of outgoing class dependencies. */ - int getEfferentCoupling() { - result = count(MetricClass that | this.getAClassDependency() = that) - } + int getEfferentCoupling() { result = count(MetricClass that | this.getAClassDependency() = that) } /** Gets the number of outgoing source class dependencies. */ int getEfferentSourceCoupling() { @@ -72,37 +57,35 @@ class MetricClass extends Class { } /** Gets a class dependency of this element. */ - Class getAClassDependency() { - dependsOnClassSimple(this, result) - } + Class getAClassDependency() { dependsOnClassSimple(this, result) } /* * -------- HENDERSON-SELLERS LACK OF COHESION IN METHODS -------- - + * * The aim of this metric is to try and determine whether a class * represents one abstraction (good) or multiple abstractions (bad). * If a class represents multiple abstractions, it should be split * up into multiple classes. - + * * In the Henderson-Sellers method, this is measured as follows: * M = set of methods in class * F = set of fields in class * r(f) = number of methods that access field f * = mean of r(f) over f in F * The lack of cohesion is then given by - + * * - |M| * --------- * 1 - |M| - + * * We follow the Eclipse metrics plugin by restricting M to methods * that access some field in the same class, and restrict F to * fields that are read by methods in the same class. - + * * Classes where the value of this metric is higher than 0.9 ought * to be scrutinised for possible splitting. Here is a query * to find such classes: - + * * from MetricRefType t, float loc * where loc = t.getLackOfCohesionHS() and loc > 0.9 * select t, loc order by loc desc @@ -116,62 +99,57 @@ class MetricClass extends Class { } /** Gets any method that accesses some local field. */ - Function getAccessingMethod() { - exists(Field f | this.accessesLocalField(result,f)) - } + Function getAccessingMethod() { exists(Field f | this.accessesLocalField(result, f)) } /** Gets any field that is accessed by a local method. */ - Field getAccessedField() { - exists(Function func | this.accessesLocalField(func,result)) - } + Field getAccessedField() { exists(Function func | this.accessesLocalField(func, result)) } /** Gets the Henderson-Sellers lack-of-cohesion metric. */ - float getLackOfCohesionHS() { - exists(int m, float r | - // m = number of methods that access some field - m = count(this.getAccessingMethod()) - and - // r = average (over f) of number of methods that access field f - r = avg(Field f | - f = this.getAccessedField() | - count(Function x | this.accessesLocalField(x,f))) - and - // avoid division by zero - m != 1 - and - // compute LCOM - result = ((r-m)/(1-m)) - ) + float getLackOfCohesionHS() { + exists(int m, float r | + // m = number of methods that access some field + m = count(this.getAccessingMethod()) and + // r = average (over f) of number of methods that access field f + r = avg(Field f | + f = this.getAccessedField() + | + count(Function x | this.accessesLocalField(x, f)) + ) and + // avoid division by zero + m != 1 and + // compute LCOM + result = ((r - m) / (1 - m)) + ) } /* * -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ - + * * The aim of this metric is to try and determine whether a class * represents one abstraction (good) or multiple abstractions (bad). * If a class represents multiple abstractions, it should be split * up into multiple classes. - + * * In the Chidamber and Kemerer method, this is measured as follows: * n1 = number of pairs of distinct methods in a class that do *not* * have at least one commonly accessed field * n2 = number of pairs of distinct methods in a class that do * have at least one commonly accessed field * lcom = ((n1 - n2)/2 max 0) - + * * We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2. */ /** Holds if `f` should be excluded from the CK cohesion computation. */ predicate ignoreLackOfCohesionCK(Function f) { - none() // by default, nothing is ignored + none() // by default, nothing is ignored } /** Holds if `m1` and `m2` are distinct member functions of this class. */ predicate distinctMembers(MemberFunction m1, MemberFunction m2) { - m1.getDeclaringType() = this and - m2.getDeclaringType() = this and - m1 != m2 + m1.getDeclaringType() = this and + m2.getDeclaringType() = this and + m1 != m2 } /** @@ -183,354 +161,439 @@ class MetricClass extends Class { m1.accesses(f) and m1.getDeclaringType() = this and m2.accesses(f) and - m2.getDeclaringType() = this) and + m2.getDeclaringType() = this + ) and m1 != m2 } /** Gets the Chidamber and Kemerer lack-of-cohesion metric. */ float getLackOfCohesionCK() { - exists(int n1, int n2, float n | - n1 = count(MemberFunction m1, MemberFunction m2 | - not this.ignoreLackOfCohesionCK(m1) and - not this.ignoreLackOfCohesionCK(m2) and - this.distinctMembers(m1,m2) and - not(this.shareField(m1,m2))) - and - n2 = count(MemberFunction m1, MemberFunction m2 | - this.shareField(m1,m2)) - and - n = (n1 - n2)/2.0 - and - ( (n < 0 and result = 0) - or - (n>=0 and result = n) ) + exists(int n1, int n2, float n | + n1 = count(MemberFunction m1, MemberFunction m2 | + not this.ignoreLackOfCohesionCK(m1) and + not this.ignoreLackOfCohesionCK(m2) and + this.distinctMembers(m1, m2) and + not this.shareField(m1, m2) + ) and + n2 = count(MemberFunction m1, MemberFunction m2 | this.shareField(m1, m2)) and + n = (n1 - n2) / 2.0 and + ( + n < 0 and result = 0 + or + n >= 0 and result = n ) - } - - /* - * ----------------- RESPONSE FOR A CLASS --------------------------------- - */ - - /** - * Gets the _response_ for this class. This estimates the number of - * different functions that can be executed when a function is invoked on - * this class. - */ - int getResponse() { - result = sum(MemberFunction f | f.getDeclaringType()=this | count(Call call | call.getEnclosingFunction() = f)) - } - - /* - * ----------------- SPECIALIZATION INDEX -------------------------------- - */ - - /** - * Gets a function that should be excluded when reporting the number of - * overriding methods. By default, no functions are excluded. - */ - predicate ignoreOverride(MemberFunction m) { - none() - } - - /** Gets some method that overrides a non-abstract method in a base class. */ - MemberFunction getOverrides() { - this.getAMemberFunction() = result and - exists(MemberFunction c | result.overrides(c) and - not c instanceof PureVirtualFunction) and - not this.ignoreOverride(result) - } - - /** Gets the number of methods that are overridden by this class (NORM). */ - int getNumberOverridden() { - result = count(this.getOverrides()) - } - - /** - * Gets the _specialization index_ of this class. - * - * The specialization index metric measures the extent to which derived - * classes override (replace) the behavior of their base classes. If they - * override many methods, it is an indication that the original abstraction - * in the base classes may have been inappropriate. On the whole, derived - * classes should add behavior to their base classes, but not alter that - * behavior dramatically. - */ - float getSpecialisationIndex() { - this.getNumberOfMemberFunctions() != 0 - and - result = (this.getNumberOverridden() * this.getInheritanceDepth()) - / - this.getNumberOfMemberFunctions().(float) - } - - /* - * ----------------- HALSTEAD METRICS ------------------------------------ - */ - - /** - * Gets the Halstead "N1" metric for this class. This is the total number of - * operators in the class. Operators are taken to be all operators in - * expressions (`+`, `*`, `&`, `->`, `=`, ...) as well as most statements. - */ - int getHalsteadN1() { - result = - // account for the class itself - 1 + - sum(MetricFunction mf, int toSum | (mf.(MemberFunction).getDeclaringType() = this) and (toSum = mf.getHalsteadN1()) | toSum) + - // Each member variable declaration counts once as an operator - count(MemberVariable mv | mv.getDeclaringType() = this) + - // Friend declarations - count(FriendDecl f | f.getDeclaringClass() = this) - } - - /** - * Gets the Halstead "N2" metric for this class: this is the total number of operands. - * An operand is either a variable, constant, type name, class name, or function name. - */ - int getHalsteadN2() { - result = - // the class itself - 1 + - sum(MetricFunction mf, int toSum | (mf.(MemberFunction).getDeclaringType() = this) and (toSum = mf.getHalsteadN2()) | toSum) + - // Each variable declaration that is not in a function counts once as an operand - count(MemberVariable mv | mv.getDeclaringType() = this) - } - - /** - * Gets an expression contained anywhere in this class: member functions (including - * constructors, destructors and operators), initializers... - */ - Expr getAnEnclosedExpression() { - exists(MemberFunction mf | mf.getDeclaringType() = this and - result.getEnclosingFunction() = mf) - or exists(MemberVariable mv | mv.getDeclaringType() = this and - mv.getInitializer().getExpr().getAChild*() = result) - } - - /** Gets a statement in a member function of this class. */ - Stmt getAnEnclosedStmt() { - result.getEnclosingFunction().(MemberFunction).getDeclaringType() = this - } - - private string getAUsedHalsteadN1Operator() { - exists(CommaExpr e | e = this.getAnEnclosedExpression()) and result = "comma" or - exists(ReferenceToExpr e | e = this.getAnEnclosedExpression()) and result = "refTo" or - exists(PointerDereferenceExpr e | e = this.getAnEnclosedExpression()) and result = "dereference" or - exists(CStyleCast e | e = this.getAnEnclosedExpression()) and result = "cCast" or - exists(StaticCast e | e = this.getAnEnclosedExpression()) and result = "staticCast" or - exists(ConstCast e | e = this.getAnEnclosedExpression()) and result = "constCast" or - exists(ReinterpretCast e | e = this.getAnEnclosedExpression()) and result = "reinterpretCast" or - exists(DynamicCast e | e = this.getAnEnclosedExpression()) and result = "dynamicCast" or - exists(SizeofExprOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofExpr" or - exists(SizeofTypeOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofType" or - exists(IfStmt e | e = this.getAnEnclosedStmt()) and result = "ifVal" or - exists(SwitchStmt e | e = this.getAnEnclosedStmt()) and result = "switchVal" or - exists(ForStmt e | e = this.getAnEnclosedStmt()) and result = "forVal" or - exists(DoStmt e | e = this.getAnEnclosedStmt()) and result = "doVal" or - exists(WhileStmt e | e = this.getAnEnclosedStmt()) and result = "whileVal" or - exists(GotoStmt e | e = this.getAnEnclosedStmt()) and result = "gotoVal" or - exists(ContinueStmt e | e = this.getAnEnclosedStmt()) and result = "continueVal" or - exists(BreakStmt e | e = this.getAnEnclosedStmt()) and result = "breakVal" or - exists(ReturnStmt e | e = this.getAnEnclosedStmt()) and result = "returnVal" or - exists(SwitchCase e | e = this.getAnEnclosedStmt()) and result = "caseVal" or - exists(IfStmt s | s = this.getAnEnclosedStmt() and s.hasElse()) and result = "elseVal" or - exists(MemberFunction f | f.getDeclaringType() = this) and result = "function" or - exists(FriendDecl e | e.getDeclaringClass() = this) and result = "friendDecl" - } - - /** - * Gets the Halstead "n1" metric: this is the total number of distinct operators - * in this class. Operators are defined as in the "N1" metric (`getHalsteadN1`). - */ - int getHalsteadN1Distinct() { - result = - // avoid 0 values - 1 + - count(string s | exists(Operation op | op = this.getAnEnclosedExpression() and s = op.getOperator())) + - count(string s | s = getAUsedHalsteadN1Operator()) - } - - /** - * Gets the Halstead "n2" metric: this is the number of distinct operands in this - * class. An operand is either a variable, constant, type name, or function name. - */ - int getHalsteadN2Distinct() { - result = - // avoid 0 values - 1 + - count(string s | exists(Access a | a = this.getAnEnclosedExpression() and s = a.getTarget().getName())) + - count(Function f | exists(FunctionCall fc | fc = this.getAnEnclosedExpression() and f = fc.getTarget())) + - // Approximate: count declarations once more to account for the type name - count(Declaration d | d.getParentScope*() = this) - } - - /** - * Gets the Halstead length of this class. This is the sum of the N1 and N2 Halstead metrics. - */ - int getHalsteadLength() { - result = this.getHalsteadN1() + this.getHalsteadN2() - } - - /** - * Gets the Halstead vocabulary size of this class. This is the sum of the n1 and n2 Halstead metrics. - */ - int getHalsteadVocabulary() { - result = this.getHalsteadN1Distinct() + this.getHalsteadN2Distinct() - } - - /** - * Gets the Halstead volume of this class. This is the Halstead size multiplied by the log of the - * Halstead vocabulary. It represents the information content of the class. - */ - float getHalsteadVolume() { - result = this.getHalsteadLength().(float) * this.getHalsteadVocabulary().log2() - } - - /** - * Gets the Halstead difficulty value of this class. This is proportional to the number of unique - * operators, and further proportional to the ratio of total operands to unique operands. - */ - float getHalsteadDifficulty() { - result = (float)(this.getHalsteadN1Distinct() * this.getHalsteadN2()) / (float)(2 * this.getHalsteadN2Distinct()) - } - - /** - * Gets the Halstead level of this class. This is the inverse of the _difficulty_ of the class. - */ - float getHalsteadLevel() { - exists(float difficulty | - difficulty = this.getHalsteadDifficulty() and - if difficulty != 0.0 then - result = 1.0 / difficulty - else - result = 0.0 - ) - } - - /** - * Gets the Halstead implementation effort for this class. This is the product of the volume and difficulty. - */ - float getHalsteadEffort() { - result = this.getHalsteadVolume() * this.getHalsteadDifficulty() - } - - /** - * Gets the Halstead _delivered bugs_ metric for this class. This metric correlates with the complexity of - * the software but is known to be an underestimate of bug counts. - */ - float getHalsteadDeliveredBugs() { - result = this.getHalsteadEffort().pow(2.0/3.0) / 3000.0 - } -} - -private pragma[noopt] -predicate dependsOnClassSimple(Class source, Class dest) { - ( - // a class depends on the classes it inherits from - source.derivesFrom(dest) - - // a nested class depends on its enclosing class - or source.getDeclaringType() = dest and source instanceof Class - - // a class depends on its friend classes - or exists(FriendDecl fd | source.getAFriendDecl() = fd and fd.getFriend() = dest) - // a friend functions return type - or exists(FriendDecl fd, Function f, Type t | source.getAFriendDecl() = fd and fd.getFriend() = f and f.getType() = t and t.refersTo(dest)) - // the type of the arguments to a friend function - or exists(FriendDecl fd, Function f, Parameter p, Type t | source.getAFriendDecl() = fd and fd.getFriend() = f and f.getAParameter() = p and p.getType() = t and t.refersTo(dest)) - - - // a class depends on the types of its member variables - or exists(MemberVariable v, Type t | v.getDeclaringType() = source and v.getType() = t and t.refersTo(dest) and v instanceof MemberVariable) - - // a class depends on the return types of its member functions - or exists(MemberFunction f, Type t | f.getDeclaringType() = source and f instanceof MemberFunction and f.getType() = t and t.refersTo(dest)) - // a class depends on the argument types of its member functions - or exists(MemberFunction f, Parameter p, Type t | f.getDeclaringType() = source and f instanceof MemberFunction and f.getAParameter() = p and p.getType() = t and t.refersTo(dest)) - - // a class depends on the base types of type def types nested in it - or exists(NestedTypedefType t, Type td | t.getDeclaringType() = source and t.getBaseType() = td and t instanceof NestedTypedefType and td.refersTo(dest)) - - // a class depends on the type names used in a casts in functions nested in it - or exists(Cast c, Function m, Type t | m.getDeclaringType() = source and m = c.getEnclosingFunction() and c instanceof Cast and c.getType() = t and t.refersTo(dest)) - // a class depends on the type names used in casts in initialization of member variables - or exists(Cast c, Variable m, Type t | m.getDeclaringType() = source and m = c.getEnclosingVariable() and c instanceof Cast and c.getType() = t and t.refersTo(dest)) - - // a class depends on classes for which a call to its member function is done from a function - or exists(MemberFunction target, MemberFunction f, Locatable l | - f.getDeclaringType() = source - and f instanceof MemberFunction - and f.calls(target, l) - and target instanceof MemberFunction - and target.getDeclaringType() = dest) - // a class depends on classes for which a call to its member function is done from a member variable initializer - or exists(MemberFunction target, FunctionCall c, MemberVariable v | - v.getDeclaringType() = source - and v instanceof MemberVariable - and c.getEnclosingVariable() = v - and c instanceof FunctionCall - and c.getTarget() = target - and target instanceof MemberFunction - and target.getDeclaringType() = dest) - - // a class(source) depends on classes(dest) for which its member functions(mf) are accessed(fa) from a member function(f) - or exists(MemberFunction f, FunctionAccess fa, MemberFunction mf | - f.getDeclaringType() = source - and f instanceof MemberFunction - and fa.getEnclosingFunction() = f - and fa.getTarget() = mf - and mf.getDeclaringType() = dest - and mf instanceof MemberFunction - and fa instanceof FunctionAccess) - - // a class depends on classes for which its member functions are accessed from a member variable initializer - or exists(MemberVariable v, FunctionAccess fa, MemberFunction mf | - v.getDeclaringType() = source - and v instanceof MemberVariable - and fa.getEnclosingVariable() = v - and fa.getTarget() = mf - and mf.getDeclaringType() = dest - and fa instanceof FunctionAccess - and mf instanceof MemberFunction) - - // a class depends on classes for which its member variables are accessed from a member function - or exists(MemberFunction f, VariableAccess va, MemberVariable mv | - f.getDeclaringType() = source - and f instanceof MemberFunction - and va.getEnclosingFunction() = f - and va instanceof VariableAccess - and va.getTarget() = mv - and mv.getDeclaringType() = dest - and mv instanceof MemberVariable) - - // a class depends on classes for which its member variables are accessed from a member variable initializer - or exists(MemberVariable v, VariableAccess va, MemberVariable mv | - v.getDeclaringType() = source - and v instanceof MemberVariable - and va.getEnclosingVariable() = v - and va instanceof VariableAccess - and va.getTarget() = mv - and mv.getDeclaringType() = dest - and mv instanceof MemberVariable) - - // a class depends on enums for which its enum constants are accessed from a member function - or exists(MemberFunction f, EnumConstantAccess ea, EnumConstant e | - f.getDeclaringType() = source - and f instanceof MemberFunction - and ea.getEnclosingFunction() = f - and ea.getTarget() = e - and e.getDeclaringEnum() = dest - and ea instanceof EnumConstantAccess) - - // a class depends on enums for which its enum constants are accessed from a member variable initializer - or exists(MemberVariable v, EnumConstantAccess ea, EnumConstant e | - v.getDeclaringType() = source - and v instanceof MemberVariable - and ea.getEnclosingVariable() = v - and ea instanceof EnumConstantAccess - and ea.getTarget() = e - and e.getDeclaringEnum() = dest) - ) - and dest instanceof Class + } + + /* + * ----------------- RESPONSE FOR A CLASS --------------------------------- + */ + + /** + * Gets the _response_ for this class. This estimates the number of + * different functions that can be executed when a function is invoked on + * this class. + */ + int getResponse() { + result = sum(MemberFunction f | + f.getDeclaringType() = this + | + count(Call call | call.getEnclosingFunction() = f) + ) + } + + /* + * ----------------- SPECIALIZATION INDEX -------------------------------- + */ + + /** + * Gets a function that should be excluded when reporting the number of + * overriding methods. By default, no functions are excluded. + */ + predicate ignoreOverride(MemberFunction m) { none() } + + /** Gets some method that overrides a non-abstract method in a base class. */ + MemberFunction getOverrides() { + this.getAMemberFunction() = result and + exists(MemberFunction c | + result.overrides(c) and + not c instanceof PureVirtualFunction + ) and + not this.ignoreOverride(result) + } + + /** Gets the number of methods that are overridden by this class (NORM). */ + int getNumberOverridden() { result = count(this.getOverrides()) } + + /** + * Gets the _specialization index_ of this class. + * + * The specialization index metric measures the extent to which derived + * classes override (replace) the behavior of their base classes. If they + * override many methods, it is an indication that the original abstraction + * in the base classes may have been inappropriate. On the whole, derived + * classes should add behavior to their base classes, but not alter that + * behavior dramatically. + */ + float getSpecialisationIndex() { + this.getNumberOfMemberFunctions() != 0 and + result = (this.getNumberOverridden() * this.getInheritanceDepth()) / + this.getNumberOfMemberFunctions().(float) + } + + /* + * ----------------- HALSTEAD METRICS ------------------------------------ + */ + + /** + * Gets the Halstead "N1" metric for this class. This is the total number of + * operators in the class. Operators are taken to be all operators in + * expressions (`+`, `*`, `&`, `->`, `=`, ...) as well as most statements. + */ + int getHalsteadN1() { + result = + // account for the class itself + 1 + + sum(MetricFunction mf, int toSum | + mf.(MemberFunction).getDeclaringType() = this and toSum = mf.getHalsteadN1() + | + toSum + ) + + // Each member variable declaration counts once as an operator + count(MemberVariable mv | mv.getDeclaringType() = this) + + // Friend declarations + count(FriendDecl f | f.getDeclaringClass() = this) + } + + /** + * Gets the Halstead "N2" metric for this class: this is the total number of operands. + * An operand is either a variable, constant, type name, class name, or function name. + */ + int getHalsteadN2() { + result = + // the class itself + 1 + + sum(MetricFunction mf, int toSum | + mf.(MemberFunction).getDeclaringType() = this and toSum = mf.getHalsteadN2() + | + toSum + ) + + // Each variable declaration that is not in a function counts once as an operand + count(MemberVariable mv | mv.getDeclaringType() = this) + } + + /** + * Gets an expression contained anywhere in this class: member functions (including + * constructors, destructors and operators), initializers... + */ + Expr getAnEnclosedExpression() { + exists(MemberFunction mf | + mf.getDeclaringType() = this and + result.getEnclosingFunction() = mf + ) + or + exists(MemberVariable mv | + mv.getDeclaringType() = this and + mv.getInitializer().getExpr().getAChild*() = result + ) + } + + /** Gets a statement in a member function of this class. */ + Stmt getAnEnclosedStmt() { + result.getEnclosingFunction().(MemberFunction).getDeclaringType() = this + } + + private string getAUsedHalsteadN1Operator() { + exists(CommaExpr e | e = this.getAnEnclosedExpression()) and result = "comma" + or + exists(ReferenceToExpr e | e = this.getAnEnclosedExpression()) and result = "refTo" + or + exists(PointerDereferenceExpr e | e = this.getAnEnclosedExpression()) and result = "dereference" + or + exists(CStyleCast e | e = this.getAnEnclosedExpression()) and result = "cCast" + or + exists(StaticCast e | e = this.getAnEnclosedExpression()) and result = "staticCast" + or + exists(ConstCast e | e = this.getAnEnclosedExpression()) and result = "constCast" + or + exists(ReinterpretCast e | e = this.getAnEnclosedExpression()) and result = "reinterpretCast" + or + exists(DynamicCast e | e = this.getAnEnclosedExpression()) and result = "dynamicCast" + or + exists(SizeofExprOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofExpr" + or + exists(SizeofTypeOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofType" + or + exists(IfStmt e | e = this.getAnEnclosedStmt()) and result = "ifVal" + or + exists(SwitchStmt e | e = this.getAnEnclosedStmt()) and result = "switchVal" + or + exists(ForStmt e | e = this.getAnEnclosedStmt()) and result = "forVal" + or + exists(DoStmt e | e = this.getAnEnclosedStmt()) and result = "doVal" + or + exists(WhileStmt e | e = this.getAnEnclosedStmt()) and result = "whileVal" + or + exists(GotoStmt e | e = this.getAnEnclosedStmt()) and result = "gotoVal" + or + exists(ContinueStmt e | e = this.getAnEnclosedStmt()) and result = "continueVal" + or + exists(BreakStmt e | e = this.getAnEnclosedStmt()) and result = "breakVal" + or + exists(ReturnStmt e | e = this.getAnEnclosedStmt()) and result = "returnVal" + or + exists(SwitchCase e | e = this.getAnEnclosedStmt()) and result = "caseVal" + or + exists(IfStmt s | s = this.getAnEnclosedStmt() and s.hasElse()) and + result = "elseVal" + or + exists(MemberFunction f | f.getDeclaringType() = this) and result = "function" + or + exists(FriendDecl e | e.getDeclaringClass() = this) and result = "friendDecl" + } + + /** + * Gets the Halstead "n1" metric: this is the total number of distinct operators + * in this class. Operators are defined as in the "N1" metric (`getHalsteadN1`). + */ + int getHalsteadN1Distinct() { + result = + // avoid 0 values + 1 + + count(string s | + exists(Operation op | op = this.getAnEnclosedExpression() and s = op.getOperator()) + ) + count(string s | s = getAUsedHalsteadN1Operator()) + } + + /** + * Gets the Halstead "n2" metric: this is the number of distinct operands in this + * class. An operand is either a variable, constant, type name, or function name. + */ + int getHalsteadN2Distinct() { + result = + // avoid 0 values + 1 + + count(string s | + exists(Access a | a = this.getAnEnclosedExpression() and s = a.getTarget().getName()) + ) + + count(Function f | + exists(FunctionCall fc | fc = this.getAnEnclosedExpression() and f = fc.getTarget()) + ) + + // Approximate: count declarations once more to account for the type name + count(Declaration d | d.getParentScope*() = this) + } + + /** + * Gets the Halstead length of this class. This is the sum of the N1 and N2 Halstead metrics. + */ + int getHalsteadLength() { result = this.getHalsteadN1() + this.getHalsteadN2() } + + /** + * Gets the Halstead vocabulary size of this class. This is the sum of the n1 and n2 Halstead metrics. + */ + int getHalsteadVocabulary() { + result = this.getHalsteadN1Distinct() + this.getHalsteadN2Distinct() + } + + /** + * Gets the Halstead volume of this class. This is the Halstead size multiplied by the log of the + * Halstead vocabulary. It represents the information content of the class. + */ + float getHalsteadVolume() { + result = this.getHalsteadLength().(float) * this.getHalsteadVocabulary().log2() + } + + /** + * Gets the Halstead difficulty value of this class. This is proportional to the number of unique + * operators, and further proportional to the ratio of total operands to unique operands. + */ + float getHalsteadDifficulty() { + result = (this.getHalsteadN1Distinct() * this.getHalsteadN2()).(float) / + (2 * this.getHalsteadN2Distinct()).(float) + } + + /** + * Gets the Halstead level of this class. This is the inverse of the _difficulty_ of the class. + */ + float getHalsteadLevel() { + exists(float difficulty | + difficulty = this.getHalsteadDifficulty() and + if difficulty != 0.0 then result = 1.0 / difficulty else result = 0.0 + ) + } + + /** + * Gets the Halstead implementation effort for this class. This is the product of the volume and difficulty. + */ + float getHalsteadEffort() { result = this.getHalsteadVolume() * this.getHalsteadDifficulty() } + + /** + * Gets the Halstead _delivered bugs_ metric for this class. This metric correlates with the complexity of + * the software but is known to be an underestimate of bug counts. + */ + float getHalsteadDeliveredBugs() { result = this.getHalsteadEffort().pow(2.0 / 3.0) / 3000.0 } +} + +pragma[noopt] +private predicate dependsOnClassSimple(Class source, Class dest) { + ( + // a class depends on the classes it inherits from + source.derivesFrom(dest) + or + // a nested class depends on its enclosing class + source.getDeclaringType() = dest and source instanceof Class + or + // a class depends on its friend classes + exists(FriendDecl fd | source.getAFriendDecl() = fd and fd.getFriend() = dest) + or + // a friend functions return type + exists(FriendDecl fd, Function f, Type t | + source.getAFriendDecl() = fd and fd.getFriend() = f and f.getType() = t and t.refersTo(dest) + ) + or + // the type of the arguments to a friend function + exists(FriendDecl fd, Function f, Parameter p, Type t | + source.getAFriendDecl() = fd and + fd.getFriend() = f and + f.getAParameter() = p and + p.getType() = t and + t.refersTo(dest) + ) + or + // a class depends on the types of its member variables + exists(MemberVariable v, Type t | + v.getDeclaringType() = source and + v.getType() = t and + t.refersTo(dest) and + v instanceof MemberVariable + ) + or + // a class depends on the return types of its member functions + exists(MemberFunction f, Type t | + f.getDeclaringType() = source and + f instanceof MemberFunction and + f.getType() = t and + t.refersTo(dest) + ) + or + // a class depends on the argument types of its member functions + exists(MemberFunction f, Parameter p, Type t | + f.getDeclaringType() = source and + f instanceof MemberFunction and + f.getAParameter() = p and + p.getType() = t and + t.refersTo(dest) + ) + or + // a class depends on the base types of type def types nested in it + exists(NestedTypedefType t, Type td | + t.getDeclaringType() = source and + t.getBaseType() = td and + t instanceof NestedTypedefType and + td.refersTo(dest) + ) + or + // a class depends on the type names used in a casts in functions nested in it + exists(Cast c, Function m, Type t | + m.getDeclaringType() = source and + m = c.getEnclosingFunction() and + c instanceof Cast and + c.getType() = t and + t.refersTo(dest) + ) + or + // a class depends on the type names used in casts in initialization of member variables + exists(Cast c, Variable m, Type t | + m.getDeclaringType() = source and + m = c.getEnclosingVariable() and + c instanceof Cast and + c.getType() = t and + t.refersTo(dest) + ) + or + // a class depends on classes for which a call to its member function is done from a function + exists(MemberFunction target, MemberFunction f, Locatable l | + f.getDeclaringType() = source and + f instanceof MemberFunction and + f.calls(target, l) and + target instanceof MemberFunction and + target.getDeclaringType() = dest + ) + or + // a class depends on classes for which a call to its member function is done from a member variable initializer + exists(MemberFunction target, FunctionCall c, MemberVariable v | + v.getDeclaringType() = source and + v instanceof MemberVariable and + c.getEnclosingVariable() = v and + c instanceof FunctionCall and + c.getTarget() = target and + target instanceof MemberFunction and + target.getDeclaringType() = dest + ) + or + // a class(source) depends on classes(dest) for which its member functions(mf) are accessed(fa) from a member function(f) + exists(MemberFunction f, FunctionAccess fa, MemberFunction mf | + f.getDeclaringType() = source and + f instanceof MemberFunction and + fa.getEnclosingFunction() = f and + fa.getTarget() = mf and + mf.getDeclaringType() = dest and + mf instanceof MemberFunction and + fa instanceof FunctionAccess + ) + or + // a class depends on classes for which its member functions are accessed from a member variable initializer + exists(MemberVariable v, FunctionAccess fa, MemberFunction mf | + v.getDeclaringType() = source and + v instanceof MemberVariable and + fa.getEnclosingVariable() = v and + fa.getTarget() = mf and + mf.getDeclaringType() = dest and + fa instanceof FunctionAccess and + mf instanceof MemberFunction + ) + or + // a class depends on classes for which its member variables are accessed from a member function + exists(MemberFunction f, VariableAccess va, MemberVariable mv | + f.getDeclaringType() = source and + f instanceof MemberFunction and + va.getEnclosingFunction() = f and + va instanceof VariableAccess and + va.getTarget() = mv and + mv.getDeclaringType() = dest and + mv instanceof MemberVariable + ) + or + // a class depends on classes for which its member variables are accessed from a member variable initializer + exists(MemberVariable v, VariableAccess va, MemberVariable mv | + v.getDeclaringType() = source and + v instanceof MemberVariable and + va.getEnclosingVariable() = v and + va instanceof VariableAccess and + va.getTarget() = mv and + mv.getDeclaringType() = dest and + mv instanceof MemberVariable + ) + or + // a class depends on enums for which its enum constants are accessed from a member function + exists(MemberFunction f, EnumConstantAccess ea, EnumConstant e | + f.getDeclaringType() = source and + f instanceof MemberFunction and + ea.getEnclosingFunction() = f and + ea.getTarget() = e and + e.getDeclaringEnum() = dest and + ea instanceof EnumConstantAccess + ) + or + // a class depends on enums for which its enum constants are accessed from a member variable initializer + exists(MemberVariable v, EnumConstantAccess ea, EnumConstant e | + v.getDeclaringType() = source and + v instanceof MemberVariable and + ea.getEnclosingVariable() = v and + ea instanceof EnumConstantAccess and + ea.getTarget() = e and + e.getDeclaringEnum() = dest + ) + ) and + dest instanceof Class } diff --git a/cpp/ql/src/semmle/code/cpp/metrics/MetricFile.qll b/cpp/ql/src/semmle/code/cpp/metrics/MetricFile.qll index 54547da359a..fc92264e071 100644 --- a/cpp/ql/src/semmle/code/cpp/metrics/MetricFile.qll +++ b/cpp/ql/src/semmle/code/cpp/metrics/MetricFile.qll @@ -4,270 +4,298 @@ import cpp * A wrapper that provides metrics for a C/C++ file. */ class MetricFile extends File { - /** Gets the number of functions defined in this file. */ int getNumberOfTopLevelFunctions() { result = count(Function f | f.isTopLevel() and f.getFile() = this) } /** Gets the number of classes defined in this file. */ - int getNumberOfClasses() { - result = count(Class c | c.getFile() = this) - } + int getNumberOfClasses() { result = count(Class c | c.getFile() = this) } /** Gets the number of user-defined types defined in this file. */ - int getNumberOfUserTypes() { - result = count(UserType t | t.getFile() = this) - } + int getNumberOfUserTypes() { result = count(UserType t | t.getFile() = this) } /** Gets the number of lines in this file. */ - int getNumberOfLines() { - numlines(underlyingElement(this),result,_,_) - } + int getNumberOfLines() { numlines(underlyingElement(this), result, _, _) } /** Gets the number of lines of code in this file. */ - int getNumberOfLinesOfCode() { - numlines(underlyingElement(this),_,result,_) - } + int getNumberOfLinesOfCode() { numlines(underlyingElement(this), _, result, _) } /** Gets the number of lines of comments in this file. */ - int getNumberOfLinesOfComments() { - numlines(underlyingElement(this),_,_,result) - } + int getNumberOfLinesOfComments() { numlines(underlyingElement(this), _, _, result) } /** Gets the number of incoming file dependencies. */ - int getAfferentCoupling() { - result = count(MetricFile that | that.getAFileDependency() = this) - } + int getAfferentCoupling() { result = count(MetricFile that | that.getAFileDependency() = this) } /** Gets the number of outgoing file dependencies. */ - int getEfferentCoupling() { - result = count(MetricFile that | this.getAFileDependency() = that) - } + int getEfferentCoupling() { result = count(MetricFile that | this.getAFileDependency() = that) } /* * HALSTEAD METRICS */ - /** - * Gets the Halstead "N1" metric for this file. This is the total number of - * operators in the file. Operators are taken to be all operators in - * expressions (`+`, `*`, `&`, `->`, `=`, ...) as well as most statements. - */ - int getHalsteadN1() { - result = - sum(MetricFunction mf, int toSum | (mf.getFile() = this) and (toSum = mf.getHalsteadN1()) | toSum) + - // Each class counts once as an operator - count(Class c | c.getFile() = this) + - // Each variable declaration that is not in a function counts once as an operator - count(GlobalVariable gv | gv.getFile() = this) + - count(MemberVariable mv | mv.getFile() = this) + - // Type declarations - to count the definition tokens - count(TypeDeclarationEntry decl | decl.getFile() = this) + - // Friend declarations - count(FriendDecl f | f.getFile() = this) - } + /** + * Gets the Halstead "N1" metric for this file. This is the total number of + * operators in the file. Operators are taken to be all operators in + * expressions (`+`, `*`, `&`, `->`, `=`, ...) as well as most statements. + */ + int getHalsteadN1() { + result = sum(MetricFunction mf, int toSum | + mf.getFile() = this and toSum = mf.getHalsteadN1() + | + toSum + ) + + // Each class counts once as an operator + count(Class c | c.getFile() = this) + + // Each variable declaration that is not in a function counts once as an operator + count(GlobalVariable gv | gv.getFile() = this) + + count(MemberVariable mv | mv.getFile() = this) + + // Type declarations - to count the definition tokens + count(TypeDeclarationEntry decl | decl.getFile() = this) + + // Friend declarations + count(FriendDecl f | f.getFile() = this) + } - /** - * Gets the Halstead "N2" metric for this file: this is the total number of operands. - * An operand is either a variable, constant, type name, class name, or function name. - */ - int getHalsteadN2() { - result = - sum(MetricFunction mf, int toSum | (mf.getFile() = this) and (toSum = mf.getHalsteadN2()) | toSum) + - // Each class counts once as an operand - count(Class c | c.getFile() = this) + - // Each variable declaration that is not in a function counts once as an operand - count(GlobalVariable gv | gv.getFile() = this) + - count(MemberVariable mv | mv.getFile() = this) + - // Type declarations - to count the type names - count(TypeDeclarationEntry decl | decl.getFile() = this) + - // Enum constant declarations to count the name - count(EnumConstant ec | ec.getFile() = this) - } + /** + * Gets the Halstead "N2" metric for this file: this is the total number of operands. + * An operand is either a variable, constant, type name, class name, or function name. + */ + int getHalsteadN2() { + result = sum(MetricFunction mf, int toSum | + mf.getFile() = this and toSum = mf.getHalsteadN2() + | + toSum + ) + + // Each class counts once as an operand + count(Class c | c.getFile() = this) + + // Each variable declaration that is not in a function counts once as an operand + count(GlobalVariable gv | gv.getFile() = this) + + count(MemberVariable mv | mv.getFile() = this) + + // Type declarations - to count the type names + count(TypeDeclarationEntry decl | decl.getFile() = this) + + // Enum constant declarations to count the name + count(EnumConstant ec | ec.getFile() = this) + } - private string getAUsedHalsteadN1Operator() { - exists(CommaExpr e | e.getFile() = this) and result = "comma" or - exists(ReferenceToExpr e | e.getFile() = this) and result = "refTo" or - exists(PointerDereferenceExpr e | e.getFile() = this) and result = "dereference" or - exists(CStyleCast e | e.getFile() = this) and result = "cCast" or - exists(StaticCast e | e.getFile() = this) and result = "staticCast" or - exists(ConstCast e | e.getFile() = this) and result = "constCast" or - exists(ReinterpretCast e | e.getFile() = this) and result = "reinterpretCast" or - exists(DynamicCast e | e.getFile() = this) and result = "dynamicCast" or - exists(SizeofExprOperator e | e.getFile() = this) and result = "sizeofExpr" or - exists(SizeofTypeOperator e | e.getFile() = this) and result = "sizeofType" or - exists(IfStmt e | e.getFile() = this) and result = "ifVal" or - exists(SwitchStmt e | e.getFile() = this) and result = "switchVal" or - exists(ForStmt e | e.getFile() = this) and result = "forVal" or - exists(DoStmt e | e.getFile() = this) and result = "doVal" or - exists(WhileStmt e | e.getFile() = this) and result = "whileVal" or - exists(GotoStmt e | e.getFile() = this) and result = "gotoVal" or - exists(ContinueStmt e | e.getFile() = this) and result = "continueVal" or - exists(BreakStmt e | e.getFile() = this) and result = "breakVal" or - exists(ReturnStmt e | e.getFile() = this) and result = "returnVal" or - exists(SwitchCase e | e.getFile() = this) and result = "caseVal" or - exists(IfStmt s | s.getFile() = this and s.hasElse()) and result = "elseVal" or - exists(Function f | f.getFile() = this) and result = "function" or - exists(Class c | c.getFile() = this) and result = "classDef" or - exists(TypeDeclarationEntry e | e.getFile() = this) and result = "typeDecl" or - exists(FriendDecl e | e.getFile() = this) and result = "friendDecl" - } + private string getAUsedHalsteadN1Operator() { + exists(CommaExpr e | e.getFile() = this) and result = "comma" + or + exists(ReferenceToExpr e | e.getFile() = this) and result = "refTo" + or + exists(PointerDereferenceExpr e | e.getFile() = this) and result = "dereference" + or + exists(CStyleCast e | e.getFile() = this) and result = "cCast" + or + exists(StaticCast e | e.getFile() = this) and result = "staticCast" + or + exists(ConstCast e | e.getFile() = this) and result = "constCast" + or + exists(ReinterpretCast e | e.getFile() = this) and result = "reinterpretCast" + or + exists(DynamicCast e | e.getFile() = this) and result = "dynamicCast" + or + exists(SizeofExprOperator e | e.getFile() = this) and result = "sizeofExpr" + or + exists(SizeofTypeOperator e | e.getFile() = this) and result = "sizeofType" + or + exists(IfStmt e | e.getFile() = this) and result = "ifVal" + or + exists(SwitchStmt e | e.getFile() = this) and result = "switchVal" + or + exists(ForStmt e | e.getFile() = this) and result = "forVal" + or + exists(DoStmt e | e.getFile() = this) and result = "doVal" + or + exists(WhileStmt e | e.getFile() = this) and result = "whileVal" + or + exists(GotoStmt e | e.getFile() = this) and result = "gotoVal" + or + exists(ContinueStmt e | e.getFile() = this) and result = "continueVal" + or + exists(BreakStmt e | e.getFile() = this) and result = "breakVal" + or + exists(ReturnStmt e | e.getFile() = this) and result = "returnVal" + or + exists(SwitchCase e | e.getFile() = this) and result = "caseVal" + or + exists(IfStmt s | s.getFile() = this and s.hasElse()) and + result = "elseVal" + or + exists(Function f | f.getFile() = this) and result = "function" + or + exists(Class c | c.getFile() = this) and result = "classDef" + or + exists(TypeDeclarationEntry e | e.getFile() = this) and result = "typeDecl" + or + exists(FriendDecl e | e.getFile() = this) and result = "friendDecl" + } - /** - * Gets the Halstead "n1" metric: this is the total number of distinct operators - * in this file. Operators are defined as in the "N1" metric (`getHalsteadN1`). - */ - int getHalsteadN1Distinct() { - result = - // avoid 0 values - 1 + - count(string s | exists(Operation op | op.getFile() = this and s = op.getOperator())) + - count(string s | s = getAUsedHalsteadN1Operator()) - } + /** + * Gets the Halstead "n1" metric: this is the total number of distinct operators + * in this file. Operators are defined as in the "N1" metric (`getHalsteadN1`). + */ + int getHalsteadN1Distinct() { + result = + // avoid 0 values + 1 + count(string s | exists(Operation op | op.getFile() = this and s = op.getOperator())) + + count(string s | s = getAUsedHalsteadN1Operator()) + } - /** - * Gets the Halstead "n2" metric: this is the number of distinct operands in this - * file. An operand is either a variable, constant, type name, or function name. - */ - int getHalsteadN2Distinct() { - result = - // avoid 0 values - 1 + - count(string s | exists(Access a | a.getFile() = this and s = a.getTarget().getName())) + - count(Function f | exists(FunctionCall fc | fc.getFile() = this and f = fc.getTarget())) + - // Approximate: count declarations once more to account for the type name - count(Declaration d | d.getFile() = this) - } + /** + * Gets the Halstead "n2" metric: this is the number of distinct operands in this + * file. An operand is either a variable, constant, type name, or function name. + */ + int getHalsteadN2Distinct() { + result = + // avoid 0 values + 1 + count(string s | exists(Access a | a.getFile() = this and s = a.getTarget().getName())) + + count(Function f | exists(FunctionCall fc | fc.getFile() = this and f = fc.getTarget())) + + // Approximate: count declarations once more to account for the type name + count(Declaration d | d.getFile() = this) + } - /** - * Gets the Halstead length of this file. This is the sum of the N1 and N2 Halstead metrics. - */ - int getHalsteadLength() { - result = this.getHalsteadN1() + this.getHalsteadN2() - } + /** + * Gets the Halstead length of this file. This is the sum of the N1 and N2 Halstead metrics. + */ + int getHalsteadLength() { result = this.getHalsteadN1() + this.getHalsteadN2() } - /** - * Gets the Halstead vocabulary size of this file. This is the sum of the n1 and n2 Halstead metrics. - */ - int getHalsteadVocabulary() { - result = this.getHalsteadN1Distinct() + this.getHalsteadN2Distinct() - } + /** + * Gets the Halstead vocabulary size of this file. This is the sum of the n1 and n2 Halstead metrics. + */ + int getHalsteadVocabulary() { + result = this.getHalsteadN1Distinct() + this.getHalsteadN2Distinct() + } - /** - * Gets the Halstead volume of this file. This is the Halstead size multiplied by the log of the - * Halstead vocabulary. It represents the information content of the file. - */ - float getHalsteadVolume() { - result = this.getHalsteadLength().(float) * this.getHalsteadVocabulary().log2() - } + /** + * Gets the Halstead volume of this file. This is the Halstead size multiplied by the log of the + * Halstead vocabulary. It represents the information content of the file. + */ + float getHalsteadVolume() { + result = this.getHalsteadLength().(float) * this.getHalsteadVocabulary().log2() + } - /** - * Gets the Halstead difficulty value of this file. This is proportional to the number of unique - * operators, and further proportional to the ratio of total operands to unique operands. - */ - float getHalsteadDifficulty() { - result = (float)(this.getHalsteadN1Distinct() * this.getHalsteadN2()) / (float)(2 * this.getHalsteadN2Distinct()) - } + /** + * Gets the Halstead difficulty value of this file. This is proportional to the number of unique + * operators, and further proportional to the ratio of total operands to unique operands. + */ + float getHalsteadDifficulty() { + result = (this.getHalsteadN1Distinct() * this.getHalsteadN2()).(float) / + (2 * this.getHalsteadN2Distinct()).(float) + } - /** - * Gets the Halstead level of this file. This is the inverse of the difficulty of the file. - */ - float getHalsteadLevel() { - exists(float difficulty | - difficulty = this.getHalsteadDifficulty() and - if difficulty != 0.0 then result = 1.0 / difficulty else result = 0.0 - ) - } + /** + * Gets the Halstead level of this file. This is the inverse of the difficulty of the file. + */ + float getHalsteadLevel() { + exists(float difficulty | + difficulty = this.getHalsteadDifficulty() and + if difficulty != 0.0 then result = 1.0 / difficulty else result = 0.0 + ) + } - /** - * Gets the Halstead implementation effort for this file. This is the product of the volume and difficulty. - */ - float getHalsteadEffort() { - result = this.getHalsteadVolume() * this.getHalsteadDifficulty() - } - - /** - * Gets the Halstead 'delivered bugs' metric for this file. This metric correlates with the complexity of - * the software, but is known to be an underestimate of bug counts. - */ - float getHalsteadDeliveredBugs() { - result = this.getHalsteadEffort().pow(2.0/3.0) / 3000.0 - } + /** + * Gets the Halstead implementation effort for this file. This is the product of the volume and difficulty. + */ + float getHalsteadEffort() { result = this.getHalsteadVolume() * this.getHalsteadDifficulty() } + /** + * Gets the Halstead 'delivered bugs' metric for this file. This metric correlates with the complexity of + * the software, but is known to be an underestimate of bug counts. + */ + float getHalsteadDeliveredBugs() { result = this.getHalsteadEffort().pow(2.0 / 3.0) / 3000.0 } /** Gets a file dependency of this file. */ - File getAFileDependency() { - dependsOnFileSimple(this, result.getMetrics()) - } - + File getAFileDependency() { dependsOnFileSimple(this, result.getMetrics()) } } -private predicate aClassFile(Class c, File file) -{ - c.getDefinitionLocation().getFile() = file +private predicate aClassFile(Class c, File file) { c.getDefinitionLocation().getFile() = file } + +pragma[noopt] +private predicate dependsOnFileSimple(MetricFile source, MetricFile dest) { + // class derives from classs + exists(Class fromClass, Class toClass | + aClassFile(fromClass, source) and + fromClass.derivesFrom(toClass) and + aClassFile(toClass, dest) + ) + or + // class nested in another class + exists(Class fromClass, Class toClass | + aClassFile(fromClass, source) and + fromClass.getDeclaringType() = toClass and + toClass.getFile() = dest + ) + or + // class has friend class + exists(Class fromClass, Class toClass, FriendDecl fd | + aClassFile(fromClass, source) and + fromClass.getAFriendDecl() = fd and + fd.getFriend() = toClass and + toClass instanceof Class and + dest = toClass.getFile() + ) + or + exists(FunctionCall ca, Function f | + ca instanceof FunctionCall and + ca.getFile() = source and + ca.getTarget() = f and + f.getFile() = dest and + not f.isMultiplyDefined() and + not exists(Function ef | ef = ca.getEnclosingFunction() and ef.isMultiplyDefined()) + ) + or + exists(Access a, Declaration d | + a instanceof Access and + a.getFile() = source and + a.getTarget() = d and + d.getFile() = dest and + not exists(Function ef | ef = a.getEnclosingFunction() and ef.isMultiplyDefined()) + ) + or + exists(Variable v, VariableDeclarationEntry e, Type vt, UserType t | + e instanceof VariableDeclarationEntry and + e.getFile() = source and + v.getADeclarationEntry() = e and + vt = v.getType() and + vt.refersTo(t) and + t instanceof UserType and + t.getFile() = dest + ) + or + exists(Function f, FunctionDeclarationEntry e, Type ft, UserType t | + e instanceof FunctionDeclarationEntry and + e.getFile() = source and + f.getADeclarationEntry() = e and + ft = f.getType() and + ft.refersTo(t) and + t instanceof UserType and + t.getFile() = dest + ) + or + exists(MacroInvocation mi, Macro m | + mi instanceof MacroInvocation and + mi.getFile() = source and + mi.getMacro() = m and + m.getFile() = dest + ) + or + exists(TypedefType t, TypeDeclarationEntry e, Type bt, UserType u | + e instanceof TypeDeclarationEntry and + e.getFile() = source and + t.getADeclarationEntry() = e and + bt = t.getBaseType() and + bt.refersTo(u) and + u instanceof UserType and + u.getFile() = dest + ) + or + exists(Cast c, Type t, UserType u | + c instanceof Cast and + c.getFile() = source and + c.getType() = t and + t.refersTo(u) and + u instanceof UserType and + u.getFile() = dest and + not exists(Function ef | ef = c.getEnclosingFunction() and ef.isMultiplyDefined()) + ) } - -private pragma[noopt] -predicate dependsOnFileSimple(MetricFile source, MetricFile dest) { - // class derives from classs - exists(Class fromClass, Class toClass | - aClassFile(fromClass, source) and - fromClass.derivesFrom(toClass) and - aClassFile(toClass, dest) - ) - or - // class nested in another class - exists(Class fromClass, Class toClass | - aClassFile(fromClass, source) and - fromClass.getDeclaringType() = toClass and - toClass.getFile() = dest - ) - or - // class has friend class - exists(Class fromClass, Class toClass, FriendDecl fd | - aClassFile(fromClass, source) and - fromClass.getAFriendDecl() = fd and - fd.getFriend() = toClass and - toClass instanceof Class and - dest = toClass.getFile() - ) - or exists(FunctionCall ca, Function f | - ca instanceof FunctionCall and - ca.getFile() = source and ca.getTarget() = f and f.getFile() = dest - and not f.isMultiplyDefined() - and not exists(Function ef | ef = ca.getEnclosingFunction() and ef.isMultiplyDefined()) - ) - or exists(Access a, Declaration d | - a instanceof Access and - a.getFile() = source and a.getTarget() = d and d.getFile() = dest - and not exists(Function ef | ef = a.getEnclosingFunction() and ef.isMultiplyDefined()) - ) - or exists(Variable v, VariableDeclarationEntry e, Type vt, UserType t | - e instanceof VariableDeclarationEntry and - e.getFile() = source and v.getADeclarationEntry() = e and vt = v.getType() and - vt.refersTo(t) and t instanceof UserType and t.getFile() = dest - ) - or exists(Function f, FunctionDeclarationEntry e, Type ft, UserType t | - e instanceof FunctionDeclarationEntry and - e.getFile() = source and f.getADeclarationEntry() = e and ft = f.getType() and - ft.refersTo(t) and t instanceof UserType and t.getFile() = dest - ) - or exists(MacroInvocation mi, Macro m | - mi instanceof MacroInvocation and - mi.getFile() = source and mi.getMacro() = m and - m.getFile() = dest - ) - - or exists(TypedefType t, TypeDeclarationEntry e, Type bt, UserType u | - e instanceof TypeDeclarationEntry and - e.getFile() = source and t.getADeclarationEntry() = e and bt = t.getBaseType() and - bt.refersTo(u) and u instanceof UserType and u.getFile() = dest - ) - or exists(Cast c, Type t, UserType u | - c instanceof Cast and - c.getFile() = source and c.getType() = t and - t.refersTo(u) and u instanceof UserType and u.getFile() = dest - and not exists(Function ef | ef = c.getEnclosingFunction() and ef.isMultiplyDefined()) - ) - } diff --git a/cpp/ql/src/semmle/code/cpp/metrics/MetricFunction.qll b/cpp/ql/src/semmle/code/cpp/metrics/MetricFunction.qll index c32e0bc4fdf..b29736a04b1 100644 --- a/cpp/ql/src/semmle/code/cpp/metrics/MetricFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/metrics/MetricFunction.qll @@ -4,51 +4,45 @@ import cpp * A wrapper that provides metrics for a C/C++ function. */ class MetricFunction extends Function { - /** Gets the number of parameters. */ - override int getNumberOfParameters() { - result = count(this.getAParameter()) - } + override int getNumberOfParameters() { result = count(this.getAParameter()) } /** Gets the number of lines in this function. */ - int getNumberOfLines() { - numlines(underlyingElement(this),result,_,_) - } + int getNumberOfLines() { numlines(underlyingElement(this), result, _, _) } /** Gets the number of lines of code in this function. */ - int getNumberOfLinesOfCode() { - numlines(underlyingElement(this),_,result,_) - } + int getNumberOfLinesOfCode() { numlines(underlyingElement(this), _, result, _) } /** Gets the number of lines of comments in this function. */ - int getNumberOfLinesOfComments() { - numlines(underlyingElement(this),_,_,result) - } + int getNumberOfLinesOfComments() { numlines(underlyingElement(this), _, _, result) } /** Gets the ratio of lines of comments to total lines in this function (between 0.0 and 1.0). */ float getCommentRatio() { - if this.getNumberOfLines() = 0 then - result = 0.0 - else - result = this.getNumberOfLinesOfComments().(float) / this.getNumberOfLines().(float) + if this.getNumberOfLines() = 0 + then result = 0.0 + else result = this.getNumberOfLinesOfComments().(float) / this.getNumberOfLines().(float) } /** Gets the number of function calls in this function. */ int getNumberOfCalls() { // Checking that the name of the target exists is a workaround for a DB inconsistency - result = count(FunctionCall c | c.getEnclosingFunction() = this and not (c.getTarget() instanceof Operator) and exists(c.getTarget().getName())) + result = count(FunctionCall c | + c.getEnclosingFunction() = this and + not c.getTarget() instanceof Operator and + exists(c.getTarget().getName()) + ) } - /** - * Gets the cyclomatic complexity of this function. This is defined as the - * number of branching statements (`if`, `while`, `do`, `for`, and - * non-fallthrough `case`) plus the number of branching expressions (`?`, - * `&&`, and `||`) plus one. - */ - int getCyclomaticComplexity() { - result = 1 + cyclomaticComplexityBranches(getBlock()) - and not this.isMultiplyDefined() - } + /** + * Gets the cyclomatic complexity of this function. This is defined as the + * number of branching statements (`if`, `while`, `do`, `for`, and + * non-fallthrough `case`) plus the number of branching expressions (`?`, + * `&&`, and `||`) plus one. + */ + int getCyclomaticComplexity() { + result = 1 + cyclomaticComplexityBranches(getBlock()) and + not this.isMultiplyDefined() + } /** * Gets the branching complexity of this function. This is a measure derived @@ -57,14 +51,15 @@ class MetricFunction extends Function { * attempts to evaluate how difficult the code is to test). */ int getBranchingComplexity() { - result = - count(IfStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + - count(WhileStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + - count(DoStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + - count(ForStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + - count(SwitchStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + - 1 - and not this.isMultiplyDefined() + result = count(IfStmt stmt | + stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion() + ) + + count(WhileStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + + count(DoStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + + count(ForStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + + count(SwitchStmt stmt | stmt.getEnclosingFunction() = this and not stmt.isInMacroExpansion()) + + 1 and + not this.isMultiplyDefined() } /** @@ -73,11 +68,11 @@ class MetricFunction extends Function { */ int getAfferentCoupling() { result = count(Function f | - exists(Locatable l | - f.calls(this, l) or - f.accesses(this, l) + exists(Locatable l | + f.calls(this, l) or + f.accesses(this, l) + ) ) - ) } /** @@ -86,205 +81,236 @@ class MetricFunction extends Function { */ int getEfferentCoupling() { result = count(Function f | - exists(Locatable l | - this.calls(f, l) or - this.accesses(f, l) + exists(Locatable l | + this.calls(f, l) or + this.accesses(f, l) + ) ) - ) } /* * Halstead Metrics */ - /** - * Gets the Halstead "N1" metric: this is the total number of operators in - * this function. Operators are taken to be all operators in expressions - * (`+`, `*`, `&`, `->`, `=`, ...) as well as most statements. - */ - int getHalsteadN1() { - // The `1 +` is to account for the function itself - result = - 1 + - count(Operation op | op.getEnclosingFunction() = this) + - count(CommaExpr e | e.getEnclosingFunction() = this) + - count(ReferenceToExpr e | e.getEnclosingFunction() = this) + - count(PointerDereferenceExpr e | e.getEnclosingFunction() = this) + - count(Cast e | e.getEnclosingFunction() = this) + - count(SizeofOperator e | e.getEnclosingFunction() = this) + - count(TypeidOperator e | e.getEnclosingFunction() = this) + - count(ControlStructure s | s.getEnclosingFunction() = this) + - count(JumpStmt s | s.getEnclosingFunction() = this) + - count(ReturnStmt s | s.getEnclosingFunction() = this) + - count(SwitchCase c | c.getEnclosingFunction() = this) + - // Count the 'else' branches - count(IfStmt s | s.getEnclosingFunction() = this and s.hasElse()) - } + /** + * Gets the Halstead "N1" metric: this is the total number of operators in + * this function. Operators are taken to be all operators in expressions + * (`+`, `*`, `&`, `->`, `=`, ...) as well as most statements. + */ + int getHalsteadN1() { + // The `1 +` is to account for the function itself + result = 1 + count(Operation op | op.getEnclosingFunction() = this) + + count(CommaExpr e | e.getEnclosingFunction() = this) + + count(ReferenceToExpr e | e.getEnclosingFunction() = this) + + count(PointerDereferenceExpr e | e.getEnclosingFunction() = this) + + count(Cast e | e.getEnclosingFunction() = this) + + count(SizeofOperator e | e.getEnclosingFunction() = this) + + count(TypeidOperator e | e.getEnclosingFunction() = this) + + count(ControlStructure s | s.getEnclosingFunction() = this) + + count(JumpStmt s | s.getEnclosingFunction() = this) + + count(ReturnStmt s | s.getEnclosingFunction() = this) + + count(SwitchCase c | c.getEnclosingFunction() = this) + + // Count the 'else' branches + count(IfStmt s | s.getEnclosingFunction() = this and s.hasElse()) + } - /** - * Gets the Halstead "N2" metric: this is the total number of operands in this - * function. An operand is either a variable, constant, type name, or function name. - */ - int getHalsteadN2() { - // The `1 +` is to account for the function itself - result = - 1 + - count(Access a | a.getEnclosingFunction() = this) + - count(FunctionCall fc | fc.getEnclosingFunction() = this) + - // Approximate: count declarations twice to account for the type name - // and the identifier - 2 * count(Declaration d | d.getParentScope+() = this) - } + /** + * Gets the Halstead "N2" metric: this is the total number of operands in this + * function. An operand is either a variable, constant, type name, or function name. + */ + int getHalsteadN2() { + // The `1 +` is to account for the function itself + result = 1 + count(Access a | a.getEnclosingFunction() = this) + + count(FunctionCall fc | fc.getEnclosingFunction() = this) + + // Approximate: count declarations twice to account for the type name + // and the identifier + 2 * count(Declaration d | d.getParentScope+() = this) + } - /** - * Gets the Halstead "n1" metric: this is the total number of distinct operators - * in this function. Operators (as in the N1 metric) are all operators in expressions - * as well as most statements. - */ - int getHalsteadN1Distinct() { - exists( - int comma, int refTo, int dereference, int cCast, int staticCast, int constCast, int reinterpretCast, int dynamicCast, - int sizeofExpr, int sizeofType, int ifVal, int switchVal, int forVal, int doVal, int whileVal, int gotoVal, int continueVal, - int breakVal, int returnVal, int caseVal, int elseVal | + /** + * Gets the Halstead "n1" metric: this is the total number of distinct operators + * in this function. Operators (as in the N1 metric) are all operators in expressions + * as well as most statements. + */ + int getHalsteadN1Distinct() { + exists( + int comma, int refTo, int dereference, int cCast, int staticCast, int constCast, + int reinterpretCast, int dynamicCast, int sizeofExpr, int sizeofType, int ifVal, + int switchVal, int forVal, int doVal, int whileVal, int gotoVal, int continueVal, + int breakVal, int returnVal, int caseVal, int elseVal + | + (if exists(CommaExpr e | e.getEnclosingFunction() = this) then comma = 1 else comma = 0) and + (if exists(ReferenceToExpr e | e.getEnclosingFunction() = this) then refTo = 1 else refTo = 0) and + ( + if exists(PointerDereferenceExpr e | e.getEnclosingFunction() = this) + then dereference = 1 + else dereference = 0 + ) and + (if exists(CStyleCast e | e.getEnclosingFunction() = this) then cCast = 1 else cCast = 0) and + ( + if exists(StaticCast e | e.getEnclosingFunction() = this) + then staticCast = 1 + else staticCast = 0 + ) and + ( + if exists(ConstCast e | e.getEnclosingFunction() = this) + then constCast = 1 + else constCast = 0 + ) and + ( + if exists(ReinterpretCast e | e.getEnclosingFunction() = this) + then reinterpretCast = 1 + else reinterpretCast = 0 + ) and + ( + if exists(DynamicCast e | e.getEnclosingFunction() = this) + then dynamicCast = 1 + else dynamicCast = 0 + ) and + ( + if exists(SizeofExprOperator e | e.getEnclosingFunction() = this) + then sizeofExpr = 1 + else sizeofExpr = 0 + ) and + ( + if exists(SizeofTypeOperator e | e.getEnclosingFunction() = this) + then sizeofType = 1 + else sizeofType = 0 + ) and + (if exists(IfStmt e | e.getEnclosingFunction() = this) then ifVal = 1 else ifVal = 0) and + ( + if exists(SwitchStmt e | e.getEnclosingFunction() = this) + then switchVal = 1 + else switchVal = 0 + ) and + (if exists(ForStmt e | e.getEnclosingFunction() = this) then forVal = 1 else forVal = 0) and + (if exists(DoStmt e | e.getEnclosingFunction() = this) then doVal = 1 else doVal = 0) and + (if exists(WhileStmt e | e.getEnclosingFunction() = this) then whileVal = 1 else whileVal = 0) and + (if exists(GotoStmt e | e.getEnclosingFunction() = this) then gotoVal = 1 else gotoVal = 0) and + ( + if exists(ContinueStmt e | e.getEnclosingFunction() = this) + then continueVal = 1 + else continueVal = 0 + ) and + (if exists(BreakStmt e | e.getEnclosingFunction() = this) then breakVal = 1 else breakVal = 0) and + ( + if exists(ReturnStmt e | e.getEnclosingFunction() = this) + then returnVal = 1 + else returnVal = 0 + ) and + (if exists(SwitchCase e | e.getEnclosingFunction() = this) then caseVal = 1 else caseVal = 0) and + ( + if exists(IfStmt s | s.getEnclosingFunction() = this and s.hasElse()) + then elseVal = 1 + else elseVal = 0 + ) and + // The `1 +` is to account for the function itself + result = 1 + + count(string s | + exists(Operation op | op.getEnclosingFunction() = this and s = op.getOperator()) + ) + comma + refTo + dereference + cCast + staticCast + constCast + reinterpretCast + + dynamicCast + sizeofExpr + sizeofType + ifVal + switchVal + forVal + doVal + whileVal + + gotoVal + continueVal + breakVal + returnVal + caseVal + elseVal + ) + } - (if exists(CommaExpr e | e.getEnclosingFunction() = this) then comma = 1 else comma = 0) and - (if exists(ReferenceToExpr e | e.getEnclosingFunction() = this) then refTo = 1 else refTo = 0) and - (if exists(PointerDereferenceExpr e | e.getEnclosingFunction() = this) then dereference = 1 else dereference = 0) and - (if exists(CStyleCast e | e.getEnclosingFunction() = this) then cCast = 1 else cCast = 0) and - (if exists(StaticCast e | e.getEnclosingFunction() = this) then staticCast = 1 else staticCast = 0) and - (if exists(ConstCast e | e.getEnclosingFunction() = this) then constCast = 1 else constCast = 0) and - (if exists(ReinterpretCast e | e.getEnclosingFunction() = this) then reinterpretCast = 1 else reinterpretCast = 0) and - (if exists(DynamicCast e | e.getEnclosingFunction() = this) then dynamicCast = 1 else dynamicCast = 0) and - (if exists(SizeofExprOperator e | e.getEnclosingFunction() = this) then sizeofExpr = 1 else sizeofExpr = 0) and - (if exists(SizeofTypeOperator e | e.getEnclosingFunction() = this) then sizeofType = 1 else sizeofType = 0) and - (if exists(IfStmt e | e.getEnclosingFunction() = this) then ifVal = 1 else ifVal = 0) and - (if exists(SwitchStmt e | e.getEnclosingFunction() = this) then switchVal = 1 else switchVal = 0) and - (if exists(ForStmt e | e.getEnclosingFunction() = this) then forVal = 1 else forVal = 0) and - (if exists(DoStmt e | e.getEnclosingFunction() = this) then doVal = 1 else doVal = 0) and - (if exists(WhileStmt e | e.getEnclosingFunction() = this) then whileVal = 1 else whileVal = 0) and - (if exists(GotoStmt e | e.getEnclosingFunction() = this) then gotoVal = 1 else gotoVal = 0) and - (if exists(ContinueStmt e | e.getEnclosingFunction() = this) then continueVal = 1 else continueVal = 0) and - (if exists(BreakStmt e | e.getEnclosingFunction() = this) then breakVal = 1 else breakVal = 0) and - (if exists(ReturnStmt e | e.getEnclosingFunction() = this) then returnVal = 1 else returnVal = 0) and - (if exists(SwitchCase e | e.getEnclosingFunction() = this) then caseVal = 1 else caseVal = 0) and - (if exists(IfStmt s | s.getEnclosingFunction() = this and s.hasElse()) then elseVal = 1 else elseVal = 0) - and - // The `1 +` is to account for the function itself - result = - 1 + - count(string s | exists(Operation op | op.getEnclosingFunction() = this and s = op.getOperator())) + - comma + - refTo + - dereference + - cCast + staticCast + constCast + reinterpretCast + dynamicCast + - sizeofExpr + sizeofType + - ifVal + switchVal + forVal + doVal + whileVal + - gotoVal + continueVal + breakVal + - returnVal + - caseVal + - elseVal - ) - } + /** + * Gets the Halstead "n2" metric: this is the number of distinct operands in this + * function. An operand is either a variable, constant, type name, or function name. + */ + int getHalsteadN2Distinct() { + // The `1 +` is to account for the function itself + result = 1 + + count(string s | + exists(Access a | a.getEnclosingFunction() = this and s = a.getTarget().getName()) + ) + + count(Function f | + exists(FunctionCall fc | fc.getEnclosingFunction() = this and f = fc.getTarget()) + ) + + // Approximate: count declarations once more to account for the type name + count(Declaration d | d.getParentScope+() = this) + } - /** - * Gets the Halstead "n2" metric: this is the number of distinct operands in this - * function. An operand is either a variable, constant, type name, or function name. - */ - int getHalsteadN2Distinct() { - // The `1 +` is to account for the function itself - result = - 1 + - count(string s | exists(Access a | a.getEnclosingFunction() = this and s = a.getTarget().getName())) + - count(Function f | exists(FunctionCall fc | fc.getEnclosingFunction() = this and f = fc.getTarget())) + - // Approximate: count declarations once more to account for the type name - count(Declaration d | d.getParentScope+() = this) - } + /** + * Gets the Halstead length of this function. This is the sum of the N1 and N2 Halstead metrics. + */ + int getHalsteadLength() { result = this.getHalsteadN1() + this.getHalsteadN2() } - /** - * Gets the Halstead length of this function. This is the sum of the N1 and N2 Halstead metrics. - */ - int getHalsteadLength() { - result = this.getHalsteadN1() + this.getHalsteadN2() - } + /** + * Gets the Halstead vocabulary size of this function. This is the sum of the n1 and n2 Halstead metrics. + */ + int getHalsteadVocabulary() { + result = this.getHalsteadN1Distinct() + this.getHalsteadN2Distinct() + } - /** - * Gets the Halstead vocabulary size of this function. This is the sum of the n1 and n2 Halstead metrics. - */ - int getHalsteadVocabulary() { - result = this.getHalsteadN1Distinct() + this.getHalsteadN2Distinct() - } + /** + * Gets the Halstead volume of this function. This is the Halstead size multiplied by the log of the + * Halstead vocabulary. It represents the information content of the function. + */ + float getHalsteadVolume() { + result = this.getHalsteadLength().(float) * this.getHalsteadVocabulary().log2() + } - /** - * Gets the Halstead volume of this function. This is the Halstead size multiplied by the log of the - * Halstead vocabulary. It represents the information content of the function. - */ - float getHalsteadVolume() { - result = this.getHalsteadLength().(float) * this.getHalsteadVocabulary().log2() - } + /** + * Gets the Halstead difficulty value of this function. This is proportional to the number of unique + * operators, and further proportional to the ratio of total operands to unique operands. + */ + float getHalsteadDifficulty() { + result = (this.getHalsteadN1Distinct() * this.getHalsteadN2()).(float) / + (2 * this.getHalsteadN2Distinct()).(float) + } - /** - * Gets the Halstead difficulty value of this function. This is proportional to the number of unique - * operators, and further proportional to the ratio of total operands to unique operands. - */ - float getHalsteadDifficulty() { - result = (float)(this.getHalsteadN1Distinct() * this.getHalsteadN2()) / (float)(2 * this.getHalsteadN2Distinct()) - } + /** + * Gets the Halstead level of this function. This is the inverse of the difficulty of the function. + */ + float getHalsteadLevel() { + exists(float difficulty | + difficulty = this.getHalsteadDifficulty() and + if difficulty != 0.0 then result = 1.0 / difficulty else result = 0.0 + ) + } - /** - * Gets the Halstead level of this function. This is the inverse of the difficulty of the function. - */ - float getHalsteadLevel() { - exists(float difficulty | - difficulty = this.getHalsteadDifficulty() and - if difficulty != 0.0 then result = 1.0 / difficulty else result = 0.0 - ) - } + /** + * Gets the Halstead implementation effort for this function. This is the product of the volume and difficulty. + */ + float getHalsteadEffort() { result = this.getHalsteadVolume() * this.getHalsteadDifficulty() } - /** - * Gets the Halstead implementation effort for this function. This is the product of the volume and difficulty. - */ - float getHalsteadEffort() { - result = this.getHalsteadVolume() * this.getHalsteadDifficulty() - } - - /** - * Gets the Halstead 'delivered bugs' metric for this function. This metric correlates with the complexity of - * the software, but is known to be an underestimate of bug counts. - */ - float getHalsteadDeliveredBugs() { - result = this.getHalsteadEffort().pow(2.0/3.0) / 3000.0 - } - - /** - * Gets the maximum nesting level of complex statements such as if, while in the function. A nesting depth of - * 2 would mean that there is, for example, an if statement nested in another if statement. - */ - int getNestingDepth() { - result = max(Stmt s, int aDepth | s.getEnclosingFunction() = this and nestingDepth(s, aDepth) | aDepth) - and not isMultiplyDefined() - } + /** + * Gets the Halstead 'delivered bugs' metric for this function. This metric correlates with the complexity of + * the software, but is known to be an underestimate of bug counts. + */ + float getHalsteadDeliveredBugs() { result = this.getHalsteadEffort().pow(2.0 / 3.0) / 3000.0 } + /** + * Gets the maximum nesting level of complex statements such as if, while in the function. A nesting depth of + * 2 would mean that there is, for example, an if statement nested in another if statement. + */ + int getNestingDepth() { + result = max(Stmt s, int aDepth | + s.getEnclosingFunction() = this and nestingDepth(s, aDepth) + | + aDepth + ) and + not isMultiplyDefined() + } } // Branching points in the sense of cyclomatic complexity are binary, // so there should be a branching point for each non-default switch // case (ignoring those that just fall through to the next case). -private -predicate branchingSwitchCase(SwitchCase sc) { +private predicate branchingSwitchCase(SwitchCase sc) { not sc.isDefault() and not sc.getASuccessor() instanceof SwitchCase and not defaultFallThrough(sc) } -private -predicate defaultFallThrough(SwitchCase sc) { +private predicate defaultFallThrough(SwitchCase sc) { sc.isDefault() or defaultFallThrough(sc.getAPredecessor()) } // A branching statement used for the computation of cyclomatic complexity. -private -predicate branchingStmt(Stmt stmt) { +private predicate branchingStmt(Stmt stmt) { stmt instanceof IfStmt or stmt instanceof WhileStmt or stmt instanceof DoStmt or @@ -293,8 +319,7 @@ predicate branchingStmt(Stmt stmt) { } // A branching expression used for the computation of cyclomatic complexity. -private -predicate branchingExpr(Expr expr) { +private predicate branchingExpr(Expr expr) { expr instanceof NotExpr or expr instanceof LogicalAndExpr or expr instanceof LogicalOrExpr or @@ -306,13 +331,16 @@ predicate branchingExpr(Expr expr) { * for computing cyclomatic complexity. */ int cyclomaticComplexityBranches(Block b) { - result = - count(Stmt stmt | - branchingStmt(stmt) and b.getAChild+() = stmt - and not stmt.isInMacroExpansion()) + - count(Expr expr | - branchingExpr(expr) and b.getAChild+() = expr.getEnclosingStmt() - and not expr.isInMacroExpansion()) + result = count(Stmt stmt | + branchingStmt(stmt) and + b.getAChild+() = stmt and + not stmt.isInMacroExpansion() + ) + + count(Expr expr | + branchingExpr(expr) and + b.getAChild+() = expr.getEnclosingStmt() and + not expr.isInMacroExpansion() + ) } /** @@ -321,13 +349,11 @@ int cyclomaticComplexityBranches(Block b) { * `if (...) { } else if (...) { }`: we don't consider the second if nested. * Blocks are also skipped, as are parents that have the same location as the * child (typically they come from macros). - * */ -private -predicate realParent(Stmt inner, Stmt outer) { - if skipParent(inner) then - realParent(inner.getParentStmt(), outer) - else - outer = inner.getParentStmt() + */ +private predicate realParent(Stmt inner, Stmt outer) { + if skipParent(inner) + then realParent(inner.getParentStmt(), outer) + else outer = inner.getParentStmt() } private predicate startsAt(Stmt s, File f, int line, int col) { @@ -338,10 +364,9 @@ private predicate startsAt(Stmt s, File f, int line, int col) { ) } -private -predicate skipParent(Stmt s) { +private predicate skipParent(Stmt s) { exists(Stmt parent | parent = s.getParentStmt() | - (s instanceof IfStmt and parent.(IfStmt).getElse() = s) + s instanceof IfStmt and parent.(IfStmt).getElse() = s or parent instanceof Block or @@ -352,7 +377,6 @@ predicate skipParent(Stmt s) { ) } -private -predicate nestingDepth(Stmt s, int depth) { +private predicate nestingDepth(Stmt s, int depth) { depth = count(Stmt enclosing | realParent+(s, enclosing)) } diff --git a/cpp/ql/src/semmle/code/cpp/metrics/MetricNamespace.qll b/cpp/ql/src/semmle/code/cpp/metrics/MetricNamespace.qll index 0aaa3bf18c7..9a26fe85115 100644 --- a/cpp/ql/src/semmle/code/cpp/metrics/MetricNamespace.qll +++ b/cpp/ql/src/semmle/code/cpp/metrics/MetricNamespace.qll @@ -4,7 +4,6 @@ import cpp * A wrapper that provides metrics for a C/C++ namespace. */ class MetricNamespace extends Namespace { - /** Gets the number of incoming dependencies from other namespaces. */ int getAfferentCoupling() { result = count(MetricNamespace that | that.getANamespaceDependency() = this) @@ -23,11 +22,12 @@ class MetricNamespace extends Namespace { * outgoing dependencies relative to the total number of dependencies. */ float getInstability() { - exists(int ecoupling, int sumcoupling | - ecoupling = this.getEfferentCoupling() and - sumcoupling = ecoupling + this.getAfferentCoupling() and - sumcoupling > 0 and - result = ecoupling / ((float)sumcoupling)) + exists(int ecoupling, int sumcoupling | + ecoupling = this.getEfferentCoupling() and + sumcoupling = ecoupling + this.getAfferentCoupling() and + sumcoupling > 0 and + result = ecoupling / sumcoupling.(float) + ) } /** @@ -39,10 +39,15 @@ class MetricNamespace extends Namespace { * abstract classes are not heavily used. */ float getAbstractness() { - exists(int i, int j | i = count(Class c | c.getNamespace()=this) and - j = count(Class c | c.getNamespace()=this and - c.isAbstract()) and - result = j / ((float)i) and i > 0) + exists(int i, int j | + i = count(Class c | c.getNamespace() = this) and + j = count(Class c | + c.getNamespace() = this and + c.isAbstract() + ) and + result = j / i.(float) and + i > 0 + ) } /** @@ -55,29 +60,53 @@ class MetricNamespace extends Namespace { * ideal situation. */ float getDistanceFromMain() { - exists(float r | - r = this.getAbstractness() + this.getInstability() - 1 - and - ( (r >= 0 and result = r) - or - (r < 0 and result = -r) ) ) - } + exists(float r | + r = this.getAbstractness() + this.getInstability() - 1 and + ( + r >= 0 and result = r + or + r < 0 and result = -r + ) + ) + } /** Gets a namespace dependency of this element. */ MetricNamespace getANamespaceDependency() { - exists(MetricClass c | c.getNamespace() = this - and c.getAClassDependency().getNamespace() = result) - or exists(FunctionCall c | c.getEnclosingFunction().getNamespace() = this - and c.getTarget().getNamespace() = result) - or exists(FunctionCall c | c.getEnclosingVariable().getNamespace() = this - and c.getTarget().getNamespace() = result) - or exists(Access a | a.getEnclosingFunction().getNamespace() = this - and a.getTarget().getNamespace() = result) - or exists(Access a | a.getEnclosingVariable().getNamespace() = this - and a.getTarget().getNamespace() = result) - or exists(Variable v, UserType t | v.getNamespace() = this - and v.getType().refersTo(t) and t.getNamespace() = result) - or exists(Function f, UserType t | f.getNamespace() = this - and f.getType().refersTo(t) and t.getNamespace() = result) + exists(MetricClass c | + c.getNamespace() = this and + c.getAClassDependency().getNamespace() = result + ) + or + exists(FunctionCall c | + c.getEnclosingFunction().getNamespace() = this and + c.getTarget().getNamespace() = result + ) + or + exists(FunctionCall c | + c.getEnclosingVariable().getNamespace() = this and + c.getTarget().getNamespace() = result + ) + or + exists(Access a | + a.getEnclosingFunction().getNamespace() = this and + a.getTarget().getNamespace() = result + ) + or + exists(Access a | + a.getEnclosingVariable().getNamespace() = this and + a.getTarget().getNamespace() = result + ) + or + exists(Variable v, UserType t | + v.getNamespace() = this and + v.getType().refersTo(t) and + t.getNamespace() = result + ) + or + exists(Function f, UserType t | + f.getNamespace() = this and + f.getType().refersTo(t) and + t.getNamespace() = result + ) } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll index 169d5903b56..8e36b5c7210 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/IdentityFunction.qll @@ -10,23 +10,17 @@ class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFuncti IdentityFunction() { this.getNamespace().getParentNamespace() instanceof GlobalNamespace and this.getNamespace().getName() = "std" and - ( + ( this.getName() = "move" or this.getName() = "forward" ) } - override predicate neverReadsMemory() { - any() - } + override predicate neverReadsMemory() { any() } - override predicate neverWritesMemory() { - any() - } + override predicate neverWritesMemory() { any() } - override predicate parameterNeverEscapes(int index) { - none() - } + override predicate parameterNeverEscapes(int index) { none() } override predicate parameterEscapesOnlyViaReturn(int index) { // These functions simply return the argument value. diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Inet.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Inet.qll index 655bec40dd1..a62ed77ebf2 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Inet.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Inet.qll @@ -2,10 +2,8 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.ArrayFunction class InetNtoa extends TaintFunction { - InetNtoa() { - hasGlobalName("inet_ntoa") - } - + InetNtoa() { hasGlobalName("inet_ntoa") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameter(0) and output.isOutReturnPointer() @@ -13,26 +11,18 @@ class InetNtoa extends TaintFunction { } class InetAton extends TaintFunction, ArrayFunction { - InetAton() { - hasGlobalName("inet_aton") - } - + InetAton() { hasGlobalName("inet_aton") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameterPointer(0) and output.isOutParameterPointer(1) } - override predicate hasArrayInput(int bufParam) { - bufParam = 0 - } - - override predicate hasArrayOutput(int bufParam) { - bufParam = 1 - } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 0 - } + override predicate hasArrayInput(int bufParam) { bufParam = 0 } + + override predicate hasArrayOutput(int bufParam) { bufParam = 1 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } override predicate hasArrayWithFixedSize(int bufParam, int elemCount) { bufParam = 1 and @@ -41,48 +31,34 @@ class InetAton extends TaintFunction, ArrayFunction { } class InetAddr extends TaintFunction, ArrayFunction { - InetAddr() { - hasGlobalName("inet_addr") - } - + InetAddr() { hasGlobalName("inet_addr") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameterPointer(0) and output.isOutReturnValue() } - override predicate hasArrayInput(int bufParam) { - bufParam = 0 - } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 0 - } + override predicate hasArrayInput(int bufParam) { bufParam = 0 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } } class InetNetwork extends TaintFunction, ArrayFunction { - InetNetwork() { - hasGlobalName("inet_network") - } + InetNetwork() { hasGlobalName("inet_network") } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameterPointer(1) and output.isOutReturnValue() } - - override predicate hasArrayInput(int bufParam) { - bufParam = 0 - } - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 0 - } + override predicate hasArrayInput(int bufParam) { bufParam = 0 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } } class InetMakeaddr extends TaintFunction { - InetMakeaddr() { - hasGlobalName("inet_makeaddr") - } - + InetMakeaddr() { hasGlobalName("inet_makeaddr") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( input.isInParameter(0) or @@ -93,10 +69,8 @@ class InetMakeaddr extends TaintFunction { } class InetLnaof extends TaintFunction { - InetLnaof() { - hasGlobalName("inet_lnaof") - } - + InetLnaof() { hasGlobalName("inet_lnaof") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameter(0) and output.isOutReturnValue() @@ -104,21 +78,17 @@ class InetLnaof extends TaintFunction { } class InetNetof extends TaintFunction { - InetNetof() { - hasGlobalName("inet_netof") - } - + InetNetof() { hasGlobalName("inet_netof") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameter(0) and output.isOutReturnValue() } } - + class InetPton extends TaintFunction, ArrayFunction { - InetPton() { - hasGlobalName("inet_pton") - } - + InetPton() { hasGlobalName("inet_pton") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( input.isInParameter(0) or @@ -126,48 +96,32 @@ class InetPton extends TaintFunction, ArrayFunction { ) and output.isOutParameterPointer(2) } - - override predicate hasArrayInput(int bufParam) { - bufParam = 1 - } - - override predicate hasArrayOutput(int bufParam) { - bufParam = 2 - } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 1 - } - - override predicate hasArrayWithUnknownSize(int bufParam) { - bufParam = 2 - } + + override predicate hasArrayInput(int bufParam) { bufParam = 1 } + + override predicate hasArrayOutput(int bufParam) { bufParam = 2 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 1 } + + override predicate hasArrayWithUnknownSize(int bufParam) { bufParam = 2 } } class Gethostbyname extends TaintFunction, ArrayFunction { - Gethostbyname() { - hasGlobalName("gethostbyname") - } - + Gethostbyname() { hasGlobalName("gethostbyname") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isInParameterPointer(0) and output.isOutReturnPointer() } - - override predicate hasArrayInput(int bufParam) { - bufParam = 0 - } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 0 - } + + override predicate hasArrayInput(int bufParam) { bufParam = 0 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } } class Gethostbyaddr extends TaintFunction, ArrayFunction { - Gethostbyaddr() { - hasGlobalName("gethostbyaddr") - } - + Gethostbyaddr() { hasGlobalName("gethostbyaddr") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( input.isInParameterPointer(0) or @@ -176,12 +130,8 @@ class Gethostbyaddr extends TaintFunction, ArrayFunction { ) and output.isOutReturnPointer() } - - override predicate hasArrayInput(int bufParam) { - bufParam = 0 - } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 0 - } -} \ No newline at end of file + + override predicate hasArrayInput(int bufParam) { bufParam = 0 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll index e4cbe6cd3db..19fe6225cda 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Memcpy.qll @@ -14,35 +14,27 @@ class MemcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { this.hasName("__builtin___memcpy_chk") } - override predicate hasArrayInput(int bufParam) { - bufParam = 1 - } + override predicate hasArrayInput(int bufParam) { bufParam = 1 } - override predicate hasArrayOutput(int bufParam) { - bufParam = 0 - } + override predicate hasArrayOutput(int bufParam) { bufParam = 0 } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { - ( - input.isInParameterPointer(1) and - output.isOutParameterPointer(0) - ) or ( - input.isInParameterPointer(1) and - output.isOutReturnPointer() - ) or ( - input.isInParameter(0) and - output.isOutReturnValue() - ) + input.isInParameterPointer(1) and + output.isOutParameterPointer(0) + or + input.isInParameterPointer(1) and + output.isOutReturnPointer() + or + input.isInParameter(0) and + output.isOutReturnValue() } - + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - ( - input.isInParameter(2) and - output.isOutParameterPointer(0) - ) or ( - input.isInParameter(2) and - output.isOutReturnPointer() - ) + input.isInParameter(2) and + output.isOutParameterPointer(0) + or + input.isInParameter(2) and + output.isOutReturnPointer() } override predicate hasArrayWithVariableSize(int bufParam, int countParam) { @@ -52,4 +44,4 @@ class MemcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { ) and countParam = 2 } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 1b09d885b1e..c723e55718b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -3,44 +3,44 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Alias import semmle.code.cpp.models.interfaces.SideEffect -class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { +class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureStrFunction() { exists(string name | hasGlobalName(name) and ( - name = "atof" - or name = "atoi" - or name = "atol" - or name = "atoll" - or name = "strcasestr" - or name = "strchnul" - or name = "strchr" - or name = "strchrnul" - or name = "strstr" - or name = "strpbrk" - or name = "strcmp" - or name = "strcspn" - or name = "strlen" - or name = "strncmp" - or name = "strnlen" - or name = "strrchr" - or name = "strspn" - or name = "strtod" - or name = "strtof" - or name = "strtol" - or name = "strtoll" - or name = "strtoq" - or name = "strtoul" + name = "atof" or + name = "atoi" or + name = "atol" or + name = "atoll" or + name = "strcasestr" or + name = "strchnul" or + name = "strchr" or + name = "strchrnul" or + name = "strstr" or + name = "strpbrk" or + name = "strcmp" or + name = "strcspn" or + name = "strlen" or + name = "strncmp" or + name = "strnlen" or + name = "strrchr" or + name = "strspn" or + name = "strtod" or + name = "strtof" or + name = "strtol" or + name = "strtoll" or + name = "strtoq" or + name = "strtoul" ) ) } - + override predicate hasArrayInput(int bufParam) { getParameter(bufParam).getUnspecifiedType() instanceof PointerType } - + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - exists (ParameterIndex i | + exists(ParameterIndex i | input.isInParameter(i) and exists(getParameter(i)) or @@ -65,17 +65,11 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side getUnspecifiedType() instanceof PointerType } - override predicate parameterIsAlwaysReturned(int i) { - none() - } + override predicate parameterIsAlwaysReturned(int i) { none() } - override predicate neverReadsMemory() { - none() - } - - override predicate neverWritesMemory() { - any() - } + override predicate neverReadsMemory() { none() } + + override predicate neverWritesMemory() { any() } } class PureFunction extends TaintFunction, SideEffectFunction { @@ -90,18 +84,14 @@ class PureFunction extends TaintFunction, SideEffectFunction { } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - exists (ParameterIndex i | + exists(ParameterIndex i | input.isInParameter(i) and exists(getParameter(i)) ) and output.isOutReturnValue() } - override predicate neverReadsMemory() { - any() - } - - override predicate neverWritesMemory() { - any() - } -} \ No newline at end of file + override predicate neverReadsMemory() { any() } + + override predicate neverWritesMemory() { any() } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index 5e02939dfe6..36d61086631 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -1,69 +1,59 @@ - import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint - /** * The standard function `strcat` and its wide, sized, and Microsoft variants. */ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction { StrcatFunction() { - exists(string name | name = getName()| - name = "strcat" // strcat(dst, src) - or name = "strncat" // strncat(dst, src, max_amount) - or name = "wcscat" // wcscat(dst, src) - or name = "_mbscat" // _mbscat(dst, src) - or name = "wcsncat" // wcsncat(dst, src, max_amount) - or name = "_mbsncat" // _mbsncat(dst, src, max_amount) - or name = "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) + exists(string name | name = getName() | + name = "strcat" or // strcat(dst, src) + name = "strncat" or // strncat(dst, src, max_amount) + name = "wcscat" or // wcscat(dst, src) + name = "_mbscat" or // _mbscat(dst, src) + name = "wcsncat" or // wcsncat(dst, src, max_amount) + name = "_mbsncat" or // _mbsncat(dst, src, max_amount) + name = "_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale) ) } - + override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { input.isInParameter(0) and output.isOutReturnValue() } - + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - exists(string name | name = getName() - | ( - ( - name = "strncat" or - name = "wcsncat" or - name = "_mbsncat" or - name = "_mbsncat_l" - ) and - input.isInParameter(2) and - output.isOutParameterPointer(0) - ) or ( - name = "_mbsncat_l" and - input.isInParameter(3) and - output.isOutParameterPointer(0) - ) - ) or ( - input.isInParameterPointer(0) and + exists(string name | name = getName() | + ( + name = "strncat" or + name = "wcsncat" or + name = "_mbsncat" or + name = "_mbsncat_l" + ) and + input.isInParameter(2) and output.isOutParameterPointer(0) - ) or ( - input.isInParameter(1) and + or + name = "_mbsncat_l" and + input.isInParameter(3) and output.isOutParameterPointer(0) ) + or + input.isInParameterPointer(0) and + output.isOutParameterPointer(0) + or + input.isInParameter(1) and + output.isOutParameterPointer(0) } - + override predicate hasArrayInput(int param) { param = 0 or param = 1 } - - override predicate hasArrayOutput(int param) { - param = 0 - } - - override predicate hasArrayWithNullTerminator(int param) { - param = 1 - } - - override predicate hasArrayWithUnknownSize(int param) { - param = 0 - } -} \ No newline at end of file + + override predicate hasArrayOutput(int param) { param = 0 } + + override predicate hasArrayWithNullTerminator(int param) { param = 1 } + + override predicate hasArrayWithUnknownSize(int param) { param = 0 } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index e19ff969ba3..4ba9151e69b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -2,7 +2,6 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint - /** * The standard function `strcpy` and its wide, sized, and Microsoft variants. */ @@ -18,19 +17,13 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { this.hasName("wcsncpy") or this.hasName("_wcsncpy_l") } - - override predicate hasArrayInput(int bufParam) { - bufParam = 1 - } - - override predicate hasArrayOutput(int bufParam) { - bufParam = 0 - } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 1 - } - + + override predicate hasArrayInput(int bufParam) { bufParam = 1 } + + override predicate hasArrayOutput(int bufParam) { bufParam = 0 } + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 1 } + override predicate hasArrayWithVariableSize(int bufParam, int countParam) { ( this.hasName("strncpy") or @@ -55,25 +48,22 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { ( - ( - // These always copy the full value of the input buffer to the output - // buffer - this.hasName("strcpy") or - this.hasName("_mbscpy") or - this.hasName("wcscpy") - ) and ( - ( - input.isInParameterPointer(1) and - output.isOutParameterPointer(0) - ) or ( - input.isInParameterPointer(1) and - output.isOutReturnPointer() - ) - ) - ) or ( - input.isInParameter(0) and - output.isOutReturnValue() + // These always copy the full value of the input buffer to the output + // buffer + this.hasName("strcpy") or + this.hasName("_mbscpy") or + this.hasName("wcscpy") + ) and + ( + input.isInParameterPointer(1) and + output.isOutParameterPointer(0) + or + input.isInParameterPointer(1) and + output.isOutReturnPointer() ) + or + input.isInParameter(0) and + output.isOutReturnValue() } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -86,12 +76,14 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { this.hasName("_mbsncpy_l") or this.hasName("wcsncpy") or this.hasName("_wcsncpy_l") - ) and ( + ) and + ( input.isInParameter(2) or input.isInParameterPointer(1) - ) and ( + ) and + ( output.isOutParameterPointer(0) or output.isOutReturnPointer() ) } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strftime.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strftime.qll index bde5b4461bc..3987f8ac66d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strftime.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strftime.qll @@ -2,43 +2,36 @@ import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.ArrayFunction class Strftime extends TaintFunction, ArrayFunction { - Strftime() { - hasGlobalName("strftime") - } - + Strftime() { hasGlobalName("strftime") } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { ( input.isInParameter(1) or input.isInParameterPointer(2) or input.isInParameterPointer(3) - ) - and + ) and ( output.isOutParameterPointer(0) or output.isOutReturnValue() ) } - - override predicate hasArrayWithNullTerminator(int bufParam) { - bufParam = 2 - } - + + override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 2 } + override predicate hasArrayWithFixedSize(int bufParam, int elemCount) { bufParam = 3 and elemCount = 1 } - + override predicate hasArrayWithVariableSize(int bufParam, int countParam) { bufParam = 0 and countParam = 1 } - + override predicate hasArrayInput(int bufParam) { bufParam = 2 or bufParam = 3 } - - override predicate hasArrayOutput(int bufParam) { - bufParam = 0 - } + + override predicate hasArrayOutput(int bufParam) { bufParam = 0 } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll index ec8f963fdbf..1c1e54a6420 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Swap.qll @@ -5,19 +5,13 @@ import semmle.code.cpp.models.interfaces.Taint * The standard function `swap`. */ class Swap extends DataFlowFunction { - Swap() { - this.hasQualifiedName("std", "swap") - } + Swap() { this.hasQualifiedName("std", "swap") } override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { - ( - input.isInParameterPointer(0) and - output.isOutParameterPointer(1) - ) + input.isInParameterPointer(0) and + output.isOutParameterPointer(1) or - ( - input.isInParameterPointer(1) and - output.isOutParameterPointer(0) - ) + input.isInParameterPointer(1) and + output.isOutParameterPointer(0) } } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Alias.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Alias.qll index 0d489afa958..083bbf55c38 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Alias.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Alias.qll @@ -11,33 +11,33 @@ import semmle.code.cpp.Function import semmle.code.cpp.models.Models /** - * Models the aliasing behavior of a library function. - */ + * Models the aliasing behavior of a library function. + */ abstract class AliasFunction extends Function { /** - * Holds if the address passed to the parameter at the specified index is never retained after - * the function returns. - * - * Example: - * ``` - * int* g; - * int* func(int* p, int* q, int* r, int* s, int n) { - * *s = 1; // `s` does not escape. - * g = p; // Stored in global. `p` escapes. - * if (rand()) { - * return q; // `q` escapes via the return value. - * } - * else { - * return r + n; // `r` escapes via the return value, even though an offset has been added. - * } - * } - * ``` - * - * For the above function, the following terms hold: - * - `parameterEscapesOnlyViaReturn(1)` - * - `parameterEscapesOnlyViaReturn(2)` - * - `parameterNeverEscapes(3)` - */ + * Holds if the address passed to the parameter at the specified index is never retained after + * the function returns. + * + * Example: + * ``` + * int* g; + * int* func(int* p, int* q, int* r, int* s, int n) { + * *s = 1; // `s` does not escape. + * g = p; // Stored in global. `p` escapes. + * if (rand()) { + * return q; // `q` escapes via the return value. + * } + * else { + * return r + n; // `r` escapes via the return value, even though an offset has been added. + * } + * } + * ``` + * + * For the above function, the following terms hold: + * - `parameterEscapesOnlyViaReturn(1)` + * - `parameterEscapesOnlyViaReturn(2)` + * - `parameterNeverEscapes(3)` + */ abstract predicate parameterNeverEscapes(int index); /** @@ -48,7 +48,7 @@ abstract class AliasFunction extends Function { abstract predicate parameterEscapesOnlyViaReturn(int index); /** - * Holds if the function always returns the value of the parameter at the specified index. - */ + * Holds if the function always returns the value of the parameter at the specified index. + */ abstract predicate parameterIsAlwaysReturned(int index); } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/ArrayFunction.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/ArrayFunction.qll index 05dc013aaac..59b96d7eddf 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/ArrayFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/ArrayFunction.qll @@ -8,9 +8,8 @@ * statement to `CustomModels.qll` */ - import semmle.code.cpp.Function - import semmle.code.cpp.models.Models - +import semmle.code.cpp.Function +import semmle.code.cpp.models.Models /** * A library function with input and/or output buffer parameters @@ -20,51 +19,39 @@ abstract class ArrayFunction extends Function { * Holds if parameter `bufParam` is a null-terminated buffer and the * null-terminator will not be written past. */ - predicate hasArrayWithNullTerminator(int bufParam) { - none() - } + predicate hasArrayWithNullTerminator(int bufParam) { none() } /** * Holds if parameter `bufParam` should always point to a buffer with exactly * `elemCount` elements. */ - predicate hasArrayWithFixedSize(int bufParam, int elemCount) { - none() - } - + predicate hasArrayWithFixedSize(int bufParam, int elemCount) { none() } + /** * Holds if parameter `bufParam` should always point to a buffer with the * number of elements indicated by `countParam`. */ - predicate hasArrayWithVariableSize(int bufParam, int countParam) { - none() - } - + predicate hasArrayWithVariableSize(int bufParam, int countParam) { none() } + /** * Holds if parameter `bufParam` points to a buffer with no fixed size and no * size parameter, which is not null-terminated or which is null-terminated * but for which the null value may be written past. For example, the first * parameters of `sprintf` and `strcat`. */ - predicate hasArrayWithUnknownSize(int bufParam) { - none() - } - + predicate hasArrayWithUnknownSize(int bufParam) { none() } + /** * Holds if parameter `bufParam` is used as an input buffer. - * + * * Note that this is not mutually exclusive with isOutBuffer. */ - predicate hasArrayInput(int bufParam) { - none() - } - + predicate hasArrayInput(int bufParam) { none() } + /** * Holds if parameter `bufParam` is used as an output buffer. - * + * * Note that this is not mutually exclusive with isInBuffer. */ - predicate hasArrayOutput(int bufParam) { - none() - } -} \ No newline at end of file + predicate hasArrayOutput(int bufParam) { none() } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll index b7aecc8cb25..9037f1cae86 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll @@ -10,15 +10,14 @@ import semmle.code.cpp.Function import FunctionInputsAndOutputs import semmle.code.cpp.models.Models - /** * A library function for which a value is copied from a parameter or qualifier * to an output buffer, return value, or qualifier. - * + * * Note that this does not include partial copying of values or partial writes * to destinations; that is covered by `TaintModel.qll`. */ abstract class DataFlowFunction extends Function { abstract predicate hasDataFlow(FunctionInput input, FunctionOutput output); -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FormattingFunction.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FormattingFunction.qll index 584dbadc1bc..56cce6d01b0 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FormattingFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FormattingFunction.qll @@ -9,12 +9,10 @@ import semmle.code.cpp.Function private Type stripTopLevelSpecifiersOnly(Type t) { - ( - result = stripTopLevelSpecifiersOnly(t.(SpecifiedType).getBaseType()) - ) or ( - result = t and - not t instanceof SpecifiedType - ) + result = stripTopLevelSpecifiersOnly(t.(SpecifiedType).getBaseType()) + or + result = t and + not t instanceof SpecifiedType } /** @@ -32,11 +30,10 @@ Type getAFormatterWideType() { * there is none. */ private Type getAFormatterWideTypeOrDefault() { - result = getAFormatterWideType() or - ( - not exists(getAFormatterWideType()) and - result instanceof Wchar_t - ) + result = getAFormatterWideType() + or + not exists(getAFormatterWideType()) and + result instanceof Wchar_t } /** @@ -52,9 +49,7 @@ abstract class FormattingFunction extends Function { * Holds if this `FormattingFunction` is in a context that supports * Microsoft rules and extensions. */ - predicate isMicrosoft() { - any(File f).compiledAsMicrosoft() - } + predicate isMicrosoft() { any(File f).compiledAsMicrosoft() } /** * Holds if the default meaning of `%s` is a `wchar_t *`, rather than @@ -68,12 +63,9 @@ abstract class FormattingFunction extends Function { * Gets the character type used in the format string for this function. */ Type getFormatCharType() { - result = - stripTopLevelSpecifiersOnly( - stripTopLevelSpecifiersOnly( - getParameter(getFormatParameterIndex()).getType().getUnderlyingType() - ).(PointerType).getBaseType() - ) + result = stripTopLevelSpecifiersOnly(stripTopLevelSpecifiersOnly(getParameter(getFormatParameterIndex()) + .getType() + .getUnderlyingType()).(PointerType).getBaseType()) } /** @@ -81,13 +73,11 @@ abstract class FormattingFunction extends Function { * `char` or `wchar_t`. */ Type getDefaultCharType() { - ( - isMicrosoft() and - result = getFormatCharType() - ) or ( - not isMicrosoft() and - result instanceof PlainCharType - ) + isMicrosoft() and + result = getFormatCharType() + or + not isMicrosoft() and + result instanceof PlainCharType } /** @@ -96,13 +86,11 @@ abstract class FormattingFunction extends Function { * which is correct for a particular function. */ Type getNonDefaultCharType() { - ( - getDefaultCharType().getSize() = 1 and - result = getWideCharType() - ) or ( - not getDefaultCharType().getSize() = 1 and - result instanceof PlainCharType - ) + getDefaultCharType().getSize() = 1 and + result = getWideCharType() + or + not getDefaultCharType().getSize() = 1 and + result instanceof PlainCharType } /** @@ -111,13 +99,11 @@ abstract class FormattingFunction extends Function { * particular function. */ Type getWideCharType() { - ( - result = getFormatCharType() and - result.getSize() > 1 - ) or ( - not getFormatCharType().getSize() > 1 and - result = getAFormatterWideTypeOrDefault() // may have more than one result - ) + result = getFormatCharType() and + result.getSize() > 1 + or + not getFormatCharType().getSize() > 1 and + result = getAFormatterWideTypeOrDefault() // may have more than one result } /** @@ -135,4 +121,4 @@ abstract class FormattingFunction extends Function { * Gets the position of the buffer size argument, if any. */ int getSizeParameterIndex() { none() } -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll index 4ee4dc962d2..924051a6045 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll @@ -14,154 +14,94 @@ class ParameterIndex extends int { } newtype TFunctionInput = - TInParameter(ParameterIndex i) - or - TInParameterPointer(ParameterIndex i) - or + TInParameter(ParameterIndex i) or + TInParameterPointer(ParameterIndex i) or TInQualifier() class FunctionInput extends TFunctionInput { abstract string toString(); - - predicate isInParameter(ParameterIndex index) { - none() - } - - predicate isInParameterPointer(ParameterIndex index) { - none() - } - - predicate isInQualifier() { - none() - } + + predicate isInParameter(ParameterIndex index) { none() } + + predicate isInParameterPointer(ParameterIndex index) { none() } + + predicate isInQualifier() { none() } } class InParameter extends FunctionInput, TInParameter { ParameterIndex index; - - InParameter() { - this = TInParameter(index) - } - - override string toString() { - result = "InParameter " + index.toString() - } - - ParameterIndex getIndex() { - result = index - } - - override predicate isInParameter(ParameterIndex i) { - i = index - } + + InParameter() { this = TInParameter(index) } + + override string toString() { result = "InParameter " + index.toString() } + + ParameterIndex getIndex() { result = index } + + override predicate isInParameter(ParameterIndex i) { i = index } } class InParameterPointer extends FunctionInput, TInParameterPointer { ParameterIndex index; - - InParameterPointer() { - this = TInParameterPointer(index) - } - - override string toString() { - result = "InParameterPointer " + index.toString() - } - - ParameterIndex getIndex() { - result = index - } - override predicate isInParameterPointer(ParameterIndex i) { - i = index - } + InParameterPointer() { this = TInParameterPointer(index) } + + override string toString() { result = "InParameterPointer " + index.toString() } + + ParameterIndex getIndex() { result = index } + + override predicate isInParameterPointer(ParameterIndex i) { i = index } } class InQualifier extends FunctionInput, TInQualifier { - override string toString() { - result = "InQualifier" - } - - override predicate isInQualifier() { - any() - } + override string toString() { result = "InQualifier" } + + override predicate isInQualifier() { any() } } newtype TFunctionOutput = - TOutParameterPointer(ParameterIndex i) - or - TOutQualifier() - or - TOutReturnValue() - or + TOutParameterPointer(ParameterIndex i) or + TOutQualifier() or + TOutReturnValue() or TOutReturnPointer() - class FunctionOutput extends TFunctionOutput { abstract string toString(); - - predicate isOutParameterPointer(ParameterIndex i) { - none() - } - - predicate isOutQualifier() { - none() - } - - predicate isOutReturnValue() { - none() - } - - predicate isOutReturnPointer() { - none() - } + + predicate isOutParameterPointer(ParameterIndex i) { none() } + + predicate isOutQualifier() { none() } + + predicate isOutReturnValue() { none() } + + predicate isOutReturnPointer() { none() } } class OutParameterPointer extends FunctionOutput, TOutParameterPointer { ParameterIndex index; - - OutParameterPointer() { - this = TOutParameterPointer(index) - } - - override string toString() { - result = "OutParameterPointer " + index.toString() - } - - ParameterIndex getIndex() { - result = index - } - - override predicate isOutParameterPointer(ParameterIndex i) { - i = index - } + + OutParameterPointer() { this = TOutParameterPointer(index) } + + override string toString() { result = "OutParameterPointer " + index.toString() } + + ParameterIndex getIndex() { result = index } + + override predicate isOutParameterPointer(ParameterIndex i) { i = index } } class OutQualifier extends FunctionOutput, TOutQualifier { - override string toString() { - result = "OutQualifier" - } - - override predicate isOutQualifier() { - any() - } + override string toString() { result = "OutQualifier" } + + override predicate isOutQualifier() { any() } } class OutReturnValue extends FunctionOutput, TOutReturnValue { - override string toString() { - result = "OutReturnValue" - } - - override predicate isOutReturnValue() { - any() - } + override string toString() { result = "OutReturnValue" } + + override predicate isOutReturnValue() { any() } } class OutReturnPointer extends FunctionOutput, TOutReturnPointer { - override string toString() { - result = "OutReturnPointer" - } - - override predicate isOutReturnPointer() { - any() - } -} \ No newline at end of file + override string toString() { result = "OutReturnPointer" } + + override predicate isOutReturnPointer() { any() } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/SideEffect.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/SideEffect.qll index 4d358089896..0afd55501c6 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/SideEffect.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/SideEffect.qll @@ -11,20 +11,20 @@ import semmle.code.cpp.Function import semmle.code.cpp.models.Models /** - * Models the side effects of a library function. - */ + * Models the side effects of a library function. + */ abstract class SideEffectFunction extends Function { /** - * Holds if the function never reads from memory that was defined before entry to the function. - * This memory could be from global variables, or from other memory that was reachable from a - * pointer that was passed into the function. - */ + * Holds if the function never reads from memory that was defined before entry to the function. + * This memory could be from global variables, or from other memory that was reachable from a + * pointer that was passed into the function. + */ abstract predicate neverReadsMemory(); /** - * Holds if the function never writes to memory that remains allocated after the function - * returns. This memory could be from global variables, or from other memory that was reachable - * from a pointer that was passed into the function. - */ + * Holds if the function never writes to memory that remains allocated after the function + * returns. This memory could be from global variables, or from other memory that was reachable + * from a pointer that was passed into the function. + */ abstract predicate neverWritesMemory(); } diff --git a/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll b/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll index d70c9d707c1..3cdf3dcb418 100644 --- a/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll +++ b/cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll @@ -14,10 +14,10 @@ import semmle.code.cpp.models.Models /** * A library function for which a taint-tracking library should propagate taint * from a parameter or qualifier to an output buffer, return value, or qualifier. - * + * * Note that this does not include direct copying of values; that is covered by * DataFlowModel.qll */ abstract class TaintFunction extends Function { abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output); -} \ No newline at end of file +} diff --git a/cpp/ql/src/semmle/code/cpp/padding/Padding.qll b/cpp/ql/src/semmle/code/cpp/padding/Padding.qll index 41a5c6fba6c..b2065a0cb37 100644 --- a/cpp/ql/src/semmle/code/cpp/padding/Padding.qll +++ b/cpp/ql/src/semmle/code/cpp/padding/Padding.qll @@ -6,15 +6,14 @@ import cpp * and (i >= offset) */ bindingset[offset, alignment] -private -int alignUp(int offset, int alignment) { +private int alignUp(int offset, int alignment) { result = (offset.(float) / alignment).ceil() * alignment } -private -Type stripSpecifiers(Type t) { - result = t.getUnspecifiedType() or - (result = t and not exists(t.getUnspecifiedType())) +private Type stripSpecifiers(Type t) { + result = t.getUnspecifiedType() + or + result = t and not exists(t.getUnspecifiedType()) } /** @@ -30,19 +29,25 @@ abstract class Architecture extends string { /** Gets the size of a pointer, in bits. */ abstract int pointerSize(); + /** Gets the size of a 'long int', in bits. */ abstract int longSize(); + /** Gets the size of a 'long double', in bits. */ abstract int longDoubleSize(); + /** Gets the size of a 'long long', in bits. */ abstract int longLongSize(); + /** Gets the size of a 'wchar_t', in bits. */ abstract int wideCharSize(); /** Gets the alignment boundary for doubles, in bits. */ abstract int doubleAlign(); + /** Gets the alignment boundary for long doubles, in bits. */ abstract int longDoubleAlign(); + /** Gets the alignment boundary for long longs, in bits. */ abstract int longLongAlign(); @@ -63,17 +68,28 @@ abstract class Architecture extends string { */ cached int integralBitSize(Type t) { - (t instanceof BoolType and result = 8) or - (t instanceof CharType and result = 8) or - (t instanceof WideCharType and result = wideCharSize()) or - (t instanceof Char16Type and result = 16) or - (t instanceof Char32Type and result = 32) or - (t instanceof ShortType and result = 16) or - (t instanceof IntType and result = 32) or - (t instanceof LongType and result = longSize()) or - (t instanceof LongLongType and result = longLongSize()) or - result = enumBitSize(t.(Enum)) or - result = integralBitSize(t.(SpecifiedType).getBaseType()) or + t instanceof BoolType and result = 8 + or + t instanceof CharType and result = 8 + or + t instanceof WideCharType and result = wideCharSize() + or + t instanceof Char16Type and result = 16 + or + t instanceof Char32Type and result = 32 + or + t instanceof ShortType and result = 16 + or + t instanceof IntType and result = 32 + or + t instanceof LongType and result = longSize() + or + t instanceof LongLongType and result = longLongSize() + or + result = enumBitSize(t.(Enum)) + or + result = integralBitSize(t.(SpecifiedType).getBaseType()) + or result = integralBitSize(t.(TypedefType).getBaseType()) } @@ -81,7 +97,8 @@ abstract class Architecture extends string { * Gets the bit size of enum type `e`. */ int enumBitSize(Enum e) { - result = integralBitSize(e.getExplicitUnderlyingType()) or + result = integralBitSize(e.getExplicitUnderlyingType()) + or not exists(e.getExplicitUnderlyingType()) and result = 32 } @@ -89,7 +106,8 @@ abstract class Architecture extends string { * Gets the alignment of enum type `e`. */ int enumAlignment(Enum e) { - result = alignment(e.getExplicitUnderlyingType()) or + result = alignment(e.getExplicitUnderlyingType()) + or not exists(e.getExplicitUnderlyingType()) and result = 32 } @@ -100,17 +118,28 @@ abstract class Architecture extends string { */ cached int bitSize(Type t) { - result = integralBitSize(t) or - (t instanceof FloatType and result = 32) or - (t instanceof DoubleType and result = 64) or - (t instanceof LongDoubleType and result = longDoubleSize()) or - (t instanceof PointerType and result = pointerSize()) or - (t instanceof ReferenceType and result = pointerSize()) or - (t instanceof FunctionPointerType and result = pointerSize()) or - result = bitSize(t.(SpecifiedType).getBaseType()) or - result = bitSize(t.(TypedefType).getBaseType()) or + result = integralBitSize(t) + or + t instanceof FloatType and result = 32 + or + t instanceof DoubleType and result = 64 + or + t instanceof LongDoubleType and result = longDoubleSize() + or + t instanceof PointerType and result = pointerSize() + or + t instanceof ReferenceType and result = pointerSize() + or + t instanceof FunctionPointerType and result = pointerSize() + or + result = bitSize(t.(SpecifiedType).getBaseType()) + or + result = bitSize(t.(TypedefType).getBaseType()) + or exists(ArrayType array | array = t | - result = array.getArraySize() * paddedSize(array.getBaseType())) or + result = array.getArraySize() * paddedSize(array.getBaseType()) + ) + or result = t.(PaddedType).typeBitSize(this) } @@ -120,25 +149,44 @@ abstract class Architecture extends string { */ cached int alignment(Type t) { - (t instanceof BoolType and result = 8) or - (t instanceof CharType and result = 8) or - (t instanceof WideCharType and result = wideCharSize()) or - (t instanceof Char16Type and result = 16) or - (t instanceof Char32Type and result = 32) or - (t instanceof ShortType and result = 16) or - (t instanceof IntType and result = 32) or - (t instanceof FloatType and result = 32) or - (t instanceof DoubleType and result = doubleAlign()) or - (t instanceof LongType and result = longSize()) or - (t instanceof LongDoubleType and result = longDoubleAlign()) or - (t instanceof LongLongType and result = longLongAlign()) or - (t instanceof PointerType and result = pointerSize()) or - (t instanceof FunctionPointerType and result = pointerSize()) or - (t instanceof ReferenceType and result = pointerSize()) or - result = enumAlignment(t.(Enum)) or - result = alignment(t.(SpecifiedType).getBaseType()) or - result = alignment(t.(TypedefType).getBaseType()) or - result = alignment(t.(ArrayType).getBaseType()) or + t instanceof BoolType and result = 8 + or + t instanceof CharType and result = 8 + or + t instanceof WideCharType and result = wideCharSize() + or + t instanceof Char16Type and result = 16 + or + t instanceof Char32Type and result = 32 + or + t instanceof ShortType and result = 16 + or + t instanceof IntType and result = 32 + or + t instanceof FloatType and result = 32 + or + t instanceof DoubleType and result = doubleAlign() + or + t instanceof LongType and result = longSize() + or + t instanceof LongDoubleType and result = longDoubleAlign() + or + t instanceof LongLongType and result = longLongAlign() + or + t instanceof PointerType and result = pointerSize() + or + t instanceof FunctionPointerType and result = pointerSize() + or + t instanceof ReferenceType and result = pointerSize() + or + result = enumAlignment(t.(Enum)) + or + result = alignment(t.(SpecifiedType).getBaseType()) + or + result = alignment(t.(TypedefType).getBaseType()) + or + result = alignment(t.(ArrayType).getBaseType()) + or result = t.(PaddedType).typeAlignment(this) } @@ -149,10 +197,9 @@ abstract class Architecture extends string { */ int paddedSize(Type t) { exists(Type realType | realType = stripSpecifiers(t) | - if realType instanceof PaddedType then - result = realType.(PaddedType).paddedSize(this) - else - result = bitSize(realType) + if realType instanceof PaddedType + then result = realType.(PaddedType).paddedSize(this) + else result = bitSize(realType) ) } @@ -163,10 +210,7 @@ abstract class Architecture extends string { * counted. */ int wastedSpace(Type t) { - if t instanceof PaddedType then - result = t.(PaddedType).wastedSpace(this) - else - result = 0 + if t instanceof PaddedType then result = t.(PaddedType).wastedSpace(this) else result = 0 } } @@ -177,25 +221,22 @@ abstract class Architecture extends string { * either any field declared in type `t`, or an initial field of the type of any * field declared in `t`. */ -private -Field getAnInitialField(PaddedType t) { - if (t instanceof Union) then ( +private Field getAnInitialField(PaddedType t) { + if t instanceof Union + then // Any field of the union is an initial field - result = t.getAField() or + result = t.getAField() + or // Initial field of the type of a field of the union - result = getAnInitialField( - t.getAField().getUnspecifiedType().(PaddedType)) - ) - else ( - exists(Field firstField | - t.fieldIndex(firstField) = 1 | + result = getAnInitialField(t.getAField().getUnspecifiedType().(PaddedType)) + else + exists(Field firstField | t.fieldIndex(firstField) = 1 | // The first field of `t` - result = firstField or + result = firstField + or // Initial field of the first field of `t` - result = getAnInitialField( - firstField.getUnspecifiedType().(PaddedType)) + result = getAnInitialField(firstField.getUnspecifiedType().(PaddedType)) ) - ) } /** @@ -209,28 +250,28 @@ abstract class UnixArchitecture extends Architecture { UnixArchitecture() { any() } override int baseClassSize(ClassDerivation cd) { - if(not exists(cd.getBaseClass().getABaseClass*().getAField()) and + if + not exists(cd.getBaseClass().getABaseClass*().getAField()) and not exists(PaddedType fieldType | - fieldType = getAnInitialField(cd.getDerivedClass()). - getUnspecifiedType() and ( - // Check if the type of the field is a base type of the class, or - // vice versa. This is an approximation of the actual rule, which is - // that the field type and the class must not share a common - // ancestor. This approximation should be sufficient for the vast - // majority of cases. - (fieldType.getABaseClass*() = cd.getBaseClass()) or - (fieldType = cd.getBaseClass().getABaseClass*()) - ) - )) then ( + fieldType = getAnInitialField(cd.getDerivedClass()).getUnspecifiedType() and + ( + // Check if the type of the field is a base type of the class, or + // vice versa. This is an approximation of the actual rule, which is + // that the field type and the class must not share a common + // ancestor. This approximation should be sufficient for the vast + // majority of cases. + fieldType.getABaseClass*() = cd.getBaseClass() or + fieldType = cd.getBaseClass().getABaseClass*() + ) + ) + then // No fields in this class or any base classes. result = 0 - ) - else ( - result = cd.getBaseClass().(PaddedType).paddedSize(this) - ) + else result = cd.getBaseClass().(PaddedType).paddedSize(this) } override int longLongSize() { result = 64 } + override int wideCharSize() { result = 32 } override predicate allowHeterogeneousBitfields() { any() } @@ -244,11 +285,15 @@ class ILP32 extends UnixArchitecture { ILP32() { this = "ILP32" } override int pointerSize() { result = 32 } + override int longSize() { result = 32 } + override int longDoubleSize() { result = 96 } override int doubleAlign() { result = 32 } + override int longLongAlign() { result = 32 } + override int longDoubleAlign() { result = 32 } } @@ -259,11 +304,15 @@ class LP64 extends UnixArchitecture { LP64() { this = "LP64" } override int pointerSize() { result = 64 } + override int longSize() { result = 64 } + override int longDoubleSize() { result = 128 } override int doubleAlign() { result = 64 } + override int longLongAlign() { result = 64 } + override int longDoubleAlign() { result = 128 } } @@ -275,22 +324,25 @@ abstract class WindowsArchitecture extends Architecture { WindowsArchitecture() { any() } override int baseClassSize(ClassDerivation cd) { - if not exists(cd.getBaseClass().getABaseClass*().getAField()) then ( + if not exists(cd.getBaseClass().getABaseClass*().getAField()) + then // No fields in this class or any base classes. result = 0 - ) - else ( - result = cd.getBaseClass().(PaddedType).paddedSize(this) - ) + else result = cd.getBaseClass().(PaddedType).paddedSize(this) } override int longSize() { result = 32 } + override int longDoubleSize() { result = 64 } + override int longLongSize() { result = 64 } + override int wideCharSize() { result = 16 } override int doubleAlign() { result = 64 } + override int longLongAlign() { result = 64 } + override int longDoubleAlign() { result = 64 } override predicate allowHeterogeneousBitfields() { none() } @@ -328,16 +380,15 @@ class PaddedType extends Class { not this instanceof TemplateClass and // If the class has any virtual functions, the layout will be more // complicated due to the presence of a virtual function table pointer. - not exists(MemberFunction f | - f = this.getAMemberFunction() and f.isVirtual()) and - not exists(ClassDerivation cd | - cd = this.getADerivation() | + not exists(MemberFunction f | f = this.getAMemberFunction() and f.isVirtual()) and + not exists(ClassDerivation cd | cd = this.getADerivation() | // If the class has any virtual functions, the layout will be more // complicated due to the presence of a virtual base table pointer. - cd.hasSpecifier("virtual") or + cd.hasSpecifier("virtual") + or // If one of the base classes was not a PaddedType, then we should not // attempt to lay out the derived class, either. - not (cd.getBaseClass() instanceof PaddedType) + not cd.getBaseClass() instanceof PaddedType ) and // Support only single inheritance for now. If multiple inheritance is // supported, be sure to fix up the calls to getABaseClass*() to correctly @@ -352,9 +403,7 @@ class PaddedType extends Class { * defined in different compilations with different sizes, normally * due to use of the preprocessor in its definition. */ - predicate isPrecise() { - forex(Architecture arch | 1 = strictcount(arch.paddedSize(this))) - } + predicate isPrecise() { forex(Architecture arch | 1 = strictcount(arch.paddedSize(this))) } /** * Gets the padded size of this type on architecture `arch`, in bits. @@ -376,9 +425,7 @@ class PaddedType extends Class { * Gets the number of bits wasted by padding at the end of this * struct. */ - int trailingPadding(Architecture arch) { - result = paddedSize(arch) - arch.bitSize(this) - } + int trailingPadding(Architecture arch) { result = paddedSize(arch) - arch.bitSize(this) } /** * Gets the number of bits wasted in this struct definition; that is. @@ -389,24 +436,16 @@ class PaddedType extends Class { * laid out one after another, and hence there is no padding between * them. */ - int wastedSpace(Architecture arch) { - result = arch.paddedSize(this) - dataSize(arch) - } + int wastedSpace(Architecture arch) { result = arch.paddedSize(this) - dataSize(arch) } /** * Gets the total size of all fields declared in this class, not including any * padding between fields. */ - private - int fieldDataSize(Architecture arch) { - if this instanceof Union then - result = max(Field f | - f = this.getAMember() | - fieldSize(f, arch)) - else - result = sum(Field f | - f = this.getAMember() | - fieldSize(f, arch)) + private int fieldDataSize(Architecture arch) { + if this instanceof Union + then result = max(Field f | f = this.getAMember() | fieldSize(f, arch)) + else result = sum(Field f | f = this.getAMember() | fieldSize(f, arch)) } /** @@ -438,17 +477,18 @@ class PaddedType extends Class { * any trailing padding that is necessary. */ int typeBitSize(Architecture arch) { - if this instanceof Union then - // A correct implementation for unions would be - // result = max(fieldSize(_, arch)) - // but that uses a recursive aggregate, which isn't supported in - // QL. We therefore use this slightly more complex implementation - // instead. - result = biggestFieldSizeUpTo(lastFieldIndex(), arch) - else - // If we're not a union type, the size is the padded - // sum of field sizes, padded. - result = fieldEnd(lastFieldIndex(), arch) + if this instanceof Union + then + // A correct implementation for unions would be + // result = max(fieldSize(_, arch)) + // but that uses a recursive aggregate, which isn't supported in + // QL. We therefore use this slightly more complex implementation + // instead. + result = biggestFieldSizeUpTo(lastFieldIndex(), arch) + else + // If we're not a union type, the size is the padded + // sum of field sizes, padded. + result = fieldEnd(lastFieldIndex(), arch) } /** @@ -460,9 +500,10 @@ class PaddedType extends Class { // The alignment of the type is the largest alignment of any of its fields, // including fields from base class subobjects. result = max(PaddedType c | - c = this.getABaseClass*() | - c.biggestAlignmentUpTo(c.lastFieldIndex(), arch) - ) + c = this.getABaseClass*() + | + c.biggestAlignmentUpTo(c.lastFieldIndex(), arch) + ) } /** @@ -471,15 +512,12 @@ class PaddedType extends Class { * `arch`. */ int biggestFieldSizeUpTo(int index, Architecture arch) { - if index = 0 then ( - result = 0 - ) - else ( - exists(Field f, int fSize | - index = fieldIndex(f) and fSize = fieldSize(f, arch) | - result = fSize.maximum(biggestFieldSizeUpTo(index-1, arch)) + if index = 0 + then result = 0 + else + exists(Field f, int fSize | index = fieldIndex(f) and fSize = fieldSize(f, arch) | + result = fSize.maximum(biggestFieldSizeUpTo(index - 1, arch)) ) - ) } /** @@ -488,43 +526,32 @@ class PaddedType extends Class { * `arch`. */ int biggestAlignmentUpTo(int index, Architecture arch) { - if index = 0 then ( - result = 1 // Minimum possible alignment - ) - else ( - exists(Field f, int fAlign | - index = fieldIndex(f) and fAlign = arch.alignment(f.getType()) | - result = fAlign.maximum(biggestAlignmentUpTo(index-1, arch)) + if index = 0 + then result = 1 // Minimum possible alignment + else + exists(Field f, int fAlign | index = fieldIndex(f) and fAlign = arch.alignment(f.getType()) | + result = fAlign.maximum(biggestAlignmentUpTo(index - 1, arch)) ) - ) } /** * Gets the 1-based index for each field. */ int fieldIndex(Field f) { - memberIndex(f) = rank[result](Field field, int index | - memberIndex(field) = index | - index - ) + memberIndex(f) = rank[result](Field field, int index | memberIndex(field) = index | index) } - private - int memberIndex(Field f) { - result = min(int i | getCanonicalMember(i) = f) - } + private int memberIndex(Field f) { result = min(int i | getCanonicalMember(i) = f) } /** * Gets the 1-based index for the last field. */ int lastFieldIndex() { - if exists(lastField()) then ( - result = fieldIndex(lastField()) - ) - else ( + if exists(lastField()) + then result = fieldIndex(lastField()) + else // Field indices are 1-based, so return 0 to represent the lack of fields. result = 0 - ) } /** @@ -533,35 +560,24 @@ class PaddedType extends Class { */ int fieldSize(Field f, Architecture arch) { exists(fieldIndex(f)) and - if f instanceof BitField then - result = f.(BitField).getNumBits() - else - result = arch.paddedSize(f.getType()) + if f instanceof BitField + then result = f.(BitField).getNumBits() + else result = arch.paddedSize(f.getType()) } /** Gets the last field of this type. */ - Field lastField() { - fieldIndex(result) = max(Field other | | fieldIndex(other)) - } + Field lastField() { fieldIndex(result) = max(Field other | | fieldIndex(other)) } /** * Gets the offset, in bits, of the end of the class' last base class * subobject, or zero if the class has no base classes. */ int baseClassEnd(Architecture arch) { - if exists(getABaseClass()) then ( - result = arch.baseClassSize(getADerivation()) - ) - else ( - result = 0 - ) + if exists(getABaseClass()) then result = arch.baseClassSize(getADerivation()) else result = 0 } /** Gets the bitfield at field index `index`, if that field is a bitfield. */ - private - BitField bitFieldAt(int index) { - fieldIndex(result) = index - } + private BitField bitFieldAt(int index) { fieldIndex(result) = index } /** * Gets the 0-based offset, in bits, of the first free bit after @@ -569,19 +585,19 @@ class PaddedType extends Class { * this type), taking padding into account, on architecture `arch`. */ int fieldEnd(int index, Architecture arch) { - if index = 0 then ( + if index = 0 + then // Base case: No fields seen yet, so return the offset of the end of the // base class subojects. result = baseClassEnd(arch) - ) - else ( + else exists(Field f | index = fieldIndex(f) | exists(int fSize | fSize = fieldSize(f, arch) | // Recursive case: Take previous field's end point, pad and add // this field's size - exists(int firstFree | - firstFree = fieldEnd(index-1, arch) | - if (f instanceof BitField) then ( + exists(int firstFree | firstFree = fieldEnd(index - 1, arch) | + if f instanceof BitField + then // Bitfield packing: // (1) A struct containing a bitfield with declared type T (e.g. T bf : 7) will be aligned as if it // contained an actual field of type T. Thus, a struct containing a bitfield 'unsigned int bf : 8' @@ -593,29 +609,32 @@ class PaddedType extends Class { // and sizeof(P) != sizeof(T), padding will be inserted to align the new bitfield to a boundary of // max(alignof(P), alignof(T)). exists(int nextSizeofBoundary, int nextAlignofBoundary | - (nextSizeofBoundary = alignUp(firstFree, arch.bitSize(f.getType()))) and - (nextAlignofBoundary = alignUp(firstFree, arch.alignment(f.getType()))) | - if (arch.allowHeterogeneousBitfields()) then ( - if (nextSizeofBoundary < (firstFree + fSize)) then ( + nextSizeofBoundary = alignUp(firstFree, arch.bitSize(f.getType())) and + nextAlignofBoundary = alignUp(firstFree, arch.alignment(f.getType())) + | + if arch.allowHeterogeneousBitfields() + then ( + if nextSizeofBoundary < (firstFree + fSize) + then // Straddles a sizeof(T) boundary, so pad for alignment. result = nextAlignofBoundary + fSize - ) - else ( + else // No additional restrictions, so just pack it in with no padding. result = firstFree + fSize - ) - ) - else ( - if exists(bitFieldAt(index-1)) then ( - exists (BitField previousBitField | - previousBitField = bitFieldAt(index-1) | + ) else ( + if exists(bitFieldAt(index - 1)) + then + exists(BitField previousBitField | previousBitField = bitFieldAt(index - 1) | // Previous field was a bitfield. - if ((nextSizeofBoundary >= (firstFree + fSize)) and arch.integralBitSize(previousBitField.getType()) = arch.integralBitSize(f.getType())) then ( + if + nextSizeofBoundary >= (firstFree + fSize) and + arch.integralBitSize(previousBitField.getType()) = arch + .integralBitSize(f.getType()) + then // The new bitfield can be stored in the same allocation unit as the previous one, // so we can avoid padding. result = firstFree + fSize - ) - else ( + else // Either we switched types, or we would overlap a sizeof(T) boundary, so we have to insert padding. // Note that we have to align to max(alignof(T), alignof(P)), where P is the type of the previous // bitfield. Without the alignof(P) term, we'll get the wrong layout for: @@ -626,29 +645,24 @@ class PaddedType extends Class { // If we only aligned to sizeof(T), we'd align 'y' to a 2-byte boundary. This is incorrect. The allocation // unit that started with 'x' has to consume an entire unsigned int (4 bytes). result = max(int boundary | - boundary = nextAlignofBoundary or - boundary = alignUp(firstFree, - arch.alignment(previousBitField.getType())) | - boundary - ) + fSize - ) + boundary = nextAlignofBoundary or + boundary = alignUp(firstFree, + arch.alignment(previousBitField.getType())) + | + boundary + ) + fSize ) - ) - else ( + else // Previous field was not a bitfield. Align up to an // alignof(T) boundary. result = nextSizeofBoundary + fSize - ) ) ) - ) - else ( + else // Normal case: Pad as necessary, then add the field. result = alignUp(firstFree, arch.alignment(f.getType())) + fSize - ) ) ) ) - ) } } diff --git a/cpp/ql/src/semmle/code/cpp/padding/SanityCheck.ql b/cpp/ql/src/semmle/code/cpp/padding/SanityCheck.ql index fde2db0a100..cbd5410ffde 100644 --- a/cpp/ql/src/semmle/code/cpp/padding/SanityCheck.ql +++ b/cpp/ql/src/semmle/code/cpp/padding/SanityCheck.ql @@ -1,6 +1,6 @@ /** * @name Padding Sanity Check - * @description Performs sanity checks for the padding library. This query should have no results. + * @description Performs sanity checks for the padding library. This query should have no results. * @kind table * @id cpp/padding-sanity-check */ @@ -33,4 +33,3 @@ import Padding from PaddedType t, LP64 a where a.wastedSpace(t) != 0 select t, a.paddedSize(t) as size, a.wastedSpace(t) as waste order by waste desc - diff --git a/cpp/ql/src/semmle/code/cpp/pointsto/CallGraph.qll b/cpp/ql/src/semmle/code/cpp/pointsto/CallGraph.qll index ac29f2dc881..b6b8fd6e60e 100644 --- a/cpp/ql/src/semmle/code/cpp/pointsto/CallGraph.qll +++ b/cpp/ql/src/semmle/code/cpp/pointsto/CallGraph.qll @@ -14,64 +14,64 @@ class TargetPointsToExpr extends PointsToExpr { } // resolve a virtual-call where this is the qualifier - VirtualFunction resolve() - { - pointstosets(this.resolveToSet(), unresolveElement(result)) - } + VirtualFunction resolve() { pointstosets(this.resolveToSet(), unresolveElement(result)) } - int resolveToSet() - { + int resolveToSet() { exists(int cset, VirtualFunction static | this.interesting() and parentSetFor(cset, underlyingElement(this)) and static = this.staticTarget() and childrenByElement(cset, static, result) - ) + ) } - VirtualFunction staticTarget() - { + VirtualFunction staticTarget() { exists(Function f, DeleteExpr d | f.calls(result, d) and - d.getExpr() = this) + d.getExpr() = this + ) or exists(Function f, FunctionCall c | f.calls(result, c) and - c.getQualifier() = this) + c.getQualifier() = this + ) } } -predicate resolvedCall(Call call, Function called) -{ +predicate resolvedCall(Call call, Function called) { call.(FunctionCall).getTarget() = called or call.(DestructorCall).getTarget() = called or exists(ExprCall ec, TargetPointsToExpr pte | - ec = call and ec.getExpr() = pte and pte.pointsTo() = called) + ec = call and ec.getExpr() = pte and pte.pointsTo() = called + ) or exists(TargetPointsToExpr pte | call.getQualifier() = pte and - pte.resolve() = called) + pte.resolve() = called + ) } predicate ptrCalls(Function f, Function g) { exists(ExprCall ec | ec.getEnclosingFunction() = f and - ec.getExpr().(TargetPointsToExpr).pointsTo() = g) + ec.getExpr().(TargetPointsToExpr).pointsTo() = g + ) } predicate virtualCalls(Function f, VirtualFunction g) { exists(DeleteExpr d, TargetPointsToExpr ptexpr, VirtualFunction static | f.calls(static, d) and d.getExpr() = ptexpr and - ptexpr.resolve() = g) or + ptexpr.resolve() = g + ) + or exists(Call c, TargetPointsToExpr ptexpr, VirtualFunction static | f.calls(static, c) and c.getQualifier() = ptexpr and - ptexpr.resolve() = g) + ptexpr.resolve() = g + ) } -predicate allCalls(Function f, Function g) { - f.calls(g) or ptrCalls(f,g) or virtualCalls(f,g) -} +predicate allCalls(Function f, Function g) { f.calls(g) or ptrCalls(f, g) or virtualCalls(f, g) } diff --git a/cpp/ql/src/semmle/code/cpp/pointsto/PointsTo.qll b/cpp/ql/src/semmle/code/cpp/pointsto/PointsTo.qll index 09cfe5e785e..a9802fad4b7 100644 --- a/cpp/ql/src/semmle/code/cpp/pointsto/PointsTo.qll +++ b/cpp/ql/src/semmle/code/cpp/pointsto/PointsTo.qll @@ -30,8 +30,9 @@ import semmle.code.cpp.exprs.Expr */ predicate resolve(Class dynamic, VirtualFunction resolved, VirtualFunction actual) { if resolved.getAnOverridingFunction*().getDeclaringType() = dynamic - then (actual = resolved.getAnOverridingFunction*() and - dynamic = actual.getDeclaringType()) + then + actual = resolved.getAnOverridingFunction*() and + dynamic = actual.getDeclaringType() else resolve(dynamic.getABaseClass(), resolved, actual) } @@ -53,15 +54,21 @@ predicate lvalue(Element e) { or exists(AddressOfExpr addof | e = addof.getOperand().getFullyConverted()) or - exists(FieldAccess fa | fa.getQualifier().getFullyConverted() = e - and not(pointerValue(e))) + exists(FieldAccess fa | + fa.getQualifier().getFullyConverted() = e and + not pointerValue(e) + ) or - exists(Call c | c.getQualifier().getFullyConverted() = e - and not(pointerValue(e))) + exists(Call c | + c.getQualifier().getFullyConverted() = e and + not pointerValue(e) + ) or e.(Expr).getConversion() instanceof ArrayToPointerConversion or - exists(ParenthesisExpr paren | exprconv(unresolveElement(e), unresolveElement(paren)) and lvalue(paren)) + exists(ParenthesisExpr paren | + exprconv(unresolveElement(e), unresolveElement(paren)) and lvalue(paren) + ) or exists(Cast c | lvalue(c) and e.(Expr).getConversion() = c) or @@ -69,14 +76,20 @@ predicate lvalue(Element e) { or // If f is a function-pointer, then the following two // calls are equivalent: f() and (*f)() - exists(PointerDereferenceExpr deref | e = deref and - deref.getUnderlyingType() instanceof FunctionPointerType) + exists(PointerDereferenceExpr deref | + e = deref and + deref.getUnderlyingType() instanceof FunctionPointerType + ) or - exists(Variable v | e = v.getInitializer() and - v.getType().getUnderlyingType() instanceof Struct) + exists(Variable v | + e = v.getInitializer() and + v.getType().getUnderlyingType() instanceof Struct + ) or - exists(Variable v | e = v.getInitializer() and - v.getType().getUnderlyingType() instanceof ArrayType) + exists(Variable v | + e = v.getInitializer() and + v.getType().getUnderlyingType() instanceof ArrayType + ) or e instanceof AggregateLiteral } @@ -84,8 +97,7 @@ predicate lvalue(Element e) { /** * Gets an access for the value of `p` on line `line`. */ -private -VariableAccess param_rvalue_access_line(Parameter p, int line) { +private VariableAccess param_rvalue_access_line(Parameter p, int line) { p.getAnAccess() = result and not lvalue(result) and result.getLocation().getStartLine() = line @@ -98,8 +110,7 @@ VariableAccess param_rvalue_access_line(Parameter p, int line) { * than one access, but we try to have few results to cut down the * number of flow edges. */ -private -VariableAccess pick_rvalue_access(Parameter p) { +private VariableAccess pick_rvalue_access(Parameter p) { result = min(int line | | param_rvalue_access_line(p, line) order by line) } @@ -112,8 +123,7 @@ VariableAccess pick_rvalue_access(Parameter p) { * the parameter to the function argument. This is less precise, because * it can equate more points-to sets. */ -private -predicate has_rvalue_access(Parameter p) { +private predicate has_rvalue_access(Parameter p) { exists(VariableAccess a | a = p.getAnAccess() | not lvalue(a)) } @@ -121,10 +131,14 @@ predicate has_rvalue_access(Parameter p) { * Holds if `e` has a pointer type. */ predicate pointerValue(Expr e) { - exists(Type t | t = e.getType().getUnderlyingType() and - (t instanceof PointerType or - t instanceof ArrayType or - t instanceof ReferenceType)) + exists(Type t | + t = e.getType().getUnderlyingType() and + ( + t instanceof PointerType or + t instanceof ArrayType or + t instanceof ReferenceType + ) + ) } private predicate pointerEntity(@element src, @element dest) { @@ -134,130 +148,211 @@ private predicate pointerEntity(@element src, @element dest) { /** * The source is a pointer to the destination. */ -predicate pointer(Element src, Element dest) -{ - exists(Variable v | not(lvalue(dest)) and - src = v and (dest = v.getAnAccess() or dest = v.getInitializer())) +predicate pointer(Element src, Element dest) { + exists(Variable v | + not lvalue(dest) and + src = v and + (dest = v.getAnAccess() or dest = v.getInitializer()) + ) or - exists(AssignExpr assign | not lvalue(assign) and - src = assign.getLValue().getFullyConverted() and dest = assign) + exists(AssignExpr assign | + not lvalue(assign) and + src = assign.getLValue().getFullyConverted() and + dest = assign + ) or exists(AssignExpr assign | src = assign.getLValue().getFullyConverted() and - dest = assign.getRValue().getFullyConverted()) + dest = assign.getRValue().getFullyConverted() + ) or exists(FunctionCall c, Function f, Parameter p, int i | - p = f.getParameter(i) and not has_rvalue_access(p) and - dest = c.getArgument(i).getFullyConverted() and not(f.isVirtual()) and - src = p.getAnAccess() and c.getTarget() = f) + p = f.getParameter(i) and + not has_rvalue_access(p) and + dest = c.getArgument(i).getFullyConverted() and + not f.isVirtual() and + src = p.getAnAccess() and + c.getTarget() = f + ) or - exists(PointerDereferenceExpr deref | not(lvalue(deref)) and - src = deref.getOperand().getFullyConverted() and dest = deref) + exists(PointerDereferenceExpr deref | + not lvalue(deref) and + src = deref.getOperand().getFullyConverted() and + dest = deref + ) or - exists(ArrayExpr ae | not(lvalue(dest)) and dest = ae and - src = ae.getArrayBase().getFullyConverted() and pointerValue(src)) + exists(ArrayExpr ae | + not lvalue(dest) and + dest = ae and + src = ae.getArrayBase().getFullyConverted() and + pointerValue(src) + ) or - exists(ArrayExpr ae | not(lvalue(dest)) and dest = ae and - src = ae.getArrayOffset().getFullyConverted() and pointerValue(src)) + exists(ArrayExpr ae | + not lvalue(dest) and + dest = ae and + src = ae.getArrayOffset().getFullyConverted() and + pointerValue(src) + ) or - exists(ReferenceDereferenceExpr deref | not(lvalue(deref)) and - dest = deref and exprconv(unresolveElement(src), unresolveElement(deref))) + exists(ReferenceDereferenceExpr deref | + not lvalue(deref) and + dest = deref and + exprconv(unresolveElement(src), unresolveElement(deref)) + ) or - exists(AggregateLiteral agg | not(lvalue(dest)) and + exists(AggregateLiteral agg | + not lvalue(dest) and agg.getType().getUnderlyingType() instanceof ArrayType and - src = agg and dest = agg.getAChild().getFullyConverted()) + src = agg and + dest = agg.getAChild().getFullyConverted() + ) or - // field points to constructor field initializer + // field points to constructor field initializer exists(ConstructorFieldInit cfi | dest = cfi and src = cfi.getTarget() and - not(lvalue(dest)) + not lvalue(dest) ) // // add more cases here // } -private predicate flowEntity(@element src, @element dest) { - flow(mkElement(src), mkElement(dest)) -} +private predicate flowEntity(@element src, @element dest) { flow(mkElement(src), mkElement(dest)) } /** * The value held in the source flows to the value held in the destination. */ -predicate flow(Element src, Element dest) -{ - exists(Variable v | lvalue(dest) and - src = v and (dest = v.getAnAccess() or dest = v.getInitializer())) +predicate flow(Element src, Element dest) { + exists(Variable v | + lvalue(dest) and + src = v and + (dest = v.getAnAccess() or dest = v.getInitializer()) + ) or exists(FunctionAccess fa | src = fa.getTarget() and dest = fa) or - exists(AssignExpr assign | lvalue(assign) and - src = assign.getLValue().getFullyConverted() and dest = assign) + exists(AssignExpr assign | + lvalue(assign) and + src = assign.getLValue().getFullyConverted() and + dest = assign + ) or - exists(AddressOfExpr addof | dest = addof and - src = addof.getOperand().getFullyConverted()) - or - exists(FunctionCall c, Function f, int i | not lvalue(dest) and - src = c.getArgument(i).getFullyConverted() and not(f.isVirtual()) and - dest = pick_rvalue_access(f.getParameter(i)) and c.getTarget() = f) + exists(AddressOfExpr addof | + dest = addof and + src = addof.getOperand().getFullyConverted() + ) or exists(FunctionCall c, Function f, int i | - src = c.getArgument(i).getFullyConverted() and not(f.isVirtual()) and - c.getTarget() = f and i >= f.getNumberOfParameters() and - varArgRead(f, dest)) + not lvalue(dest) and + src = c.getArgument(i).getFullyConverted() and + not f.isVirtual() and + dest = pick_rvalue_access(f.getParameter(i)) and + c.getTarget() = f + ) + or + exists(FunctionCall c, Function f, int i | + src = c.getArgument(i).getFullyConverted() and + not f.isVirtual() and + c.getTarget() = f and + i >= f.getNumberOfParameters() and + varArgRead(f, dest) + ) or exists(FunctionCall c, Function f, ReturnStmt r | c.getTarget() = f and - not(f.isVirtual()) and + not f.isVirtual() and r.getEnclosingFunction() = f and - src = r.getExpr().getFullyConverted() and dest = c) + src = r.getExpr().getFullyConverted() and + dest = c + ) or - exists(PointerDereferenceExpr deref | lvalue(deref) and - src = deref.getAChild().getFullyConverted() and dest = deref) + exists(PointerDereferenceExpr deref | + lvalue(deref) and + src = deref.getAChild().getFullyConverted() and + dest = deref + ) or - exists(Variable v | dest = v.getInitializer() and - src = v.getInitializer().getExpr().getFullyConverted()) + exists(Variable v | + dest = v.getInitializer() and + src = v.getInitializer().getExpr().getFullyConverted() + ) or - exists(ArrayExpr ae | lvalue(dest) and dest = ae and - src = ae.getArrayBase().getFullyConverted() and pointerValue(src)) + exists(ArrayExpr ae | + lvalue(dest) and + dest = ae and + src = ae.getArrayBase().getFullyConverted() and + pointerValue(src) + ) or - exists(ArrayExpr ae | lvalue(dest) and dest = ae and - src = ae.getArrayOffset().getFullyConverted() and pointerValue(src)) + exists(ArrayExpr ae | + lvalue(dest) and + dest = ae and + src = ae.getArrayOffset().getFullyConverted() and + pointerValue(src) + ) or - exists(Expr arg, BinaryArithmeticOperation binop | dest = binop and src = arg and - pointerValue(binop) and pointerValue(arg) and - ( arg = binop.getLeftOperand().getFullyConverted() or - arg = binop.getRightOperand().getFullyConverted())) + exists(Expr arg, BinaryArithmeticOperation binop | + dest = binop and + src = arg and + pointerValue(binop) and + pointerValue(arg) and + ( + arg = binop.getLeftOperand().getFullyConverted() or + arg = binop.getRightOperand().getFullyConverted() + ) + ) or exists(Cast c | src = c.getExpr() and dest = c) or - exists(ReferenceToExpr toref | exprconv(unresolveElement(src), unresolveElement(toref)) and dest = toref) + exists(ReferenceToExpr toref | + exprconv(unresolveElement(src), unresolveElement(toref)) and dest = toref + ) or - exists(ReferenceDereferenceExpr deref | lvalue(deref) and - dest = deref and exprconv(unresolveElement(src), unresolveElement(deref))) + exists(ReferenceDereferenceExpr deref | + lvalue(deref) and + dest = deref and + exprconv(unresolveElement(src), unresolveElement(deref)) + ) or - exists(ArrayToPointerConversion conv | exprconv(unresolveElement(src), unresolveElement(conv)) and dest = conv) + exists(ArrayToPointerConversion conv | + exprconv(unresolveElement(src), unresolveElement(conv)) and dest = conv + ) or exists(ParenthesisExpr paren | // these can appear on the LHS of an assignment - (exprconv(unresolveElement(src), unresolveElement(paren)) and dest = paren) or - (exprconv(unresolveElement(dest), unresolveElement(paren)) and src = paren)) + exprconv(unresolveElement(src), unresolveElement(paren)) and dest = paren + or + exprconv(unresolveElement(dest), unresolveElement(paren)) and src = paren + ) or - exists(ConditionalExpr cond | dest = cond and - ( src = cond.getThen().getFullyConverted() or - src = cond.getElse().getFullyConverted())) + exists(ConditionalExpr cond | + dest = cond and + ( + src = cond.getThen().getFullyConverted() or + src = cond.getElse().getFullyConverted() + ) + ) or - exists(IncrementOperation inc | dest = inc and - src = inc.getOperand().getFullyConverted()) + exists(IncrementOperation inc | + dest = inc and + src = inc.getOperand().getFullyConverted() + ) or - exists(IncrementOperation dec | dest = dec and - src = dec.getOperand().getFullyConverted()) + exists(IncrementOperation dec | + dest = dec and + src = dec.getOperand().getFullyConverted() + ) or - exists(CommaExpr comma | dest = comma and - src = comma.getRightOperand().getFullyConverted()) + exists(CommaExpr comma | + dest = comma and + src = comma.getRightOperand().getFullyConverted() + ) or - exists(ParenthesisExpr paren | dest = paren and exprconv(unresolveElement(src), unresolveElement(paren))) + exists(ParenthesisExpr paren | + dest = paren and exprconv(unresolveElement(src), unresolveElement(paren)) + ) or // "vtable" for new-expressions exists(NewExpr new | src = new and dest = new.getAllocatedType()) @@ -265,9 +360,12 @@ predicate flow(Element src, Element dest) // "vtable" for class-typed variables exists(Variable v, Class c | v.getType().getUnderlyingType() = c and src = v and dest = c) or - exists(AggregateLiteral agg | lvalue(dest) and + exists(AggregateLiteral agg | + lvalue(dest) and agg.getType().getUnderlyingType() instanceof ArrayType and - src = agg and dest = agg.getAChild().getFullyConverted()) + src = agg and + dest = agg.getAChild().getFullyConverted() + ) or // contained expr -> constructor field initializer exists(ConstructorFieldInit cfi | @@ -281,43 +379,45 @@ predicate flow(Element src, Element dest) // Try to find the expression corresponding to the return value // of va_arg(...,...) - which is a macro. -predicate varArgRead(Function f, Expr e) -{ +predicate varArgRead(Function f, Expr e) { exists(Macro m, MacroInvocation mi | m.getHead().matches("va\\_arg(%") and mi.getMacro() = m and e = mi.getAGeneratedElement() and - not(e.getParent() = mi.getAGeneratedElement()) - and e.getEnclosingFunction() = f) + not e.getParent() = mi.getAGeneratedElement() and + e.getEnclosingFunction() = f + ) } /** * There is a flow from src to the compound (destParent, destLabel). */ -predicate flowToCompound(Element destParent, string destLabel, Element src) -{ +predicate flowToCompound(Element destParent, string destLabel, Element src) { exists(ExprCall call, int i | src = call.getArgument(i).getFullyConverted() and destParent = call.getExpr().getFullyConverted() and - if i < call.getType().(FunctionPointerType).getNumberOfParameters() then - destLabel = "+arg" + i.toString() - else - destLabel = "+vararg") + if i < call.getType().(FunctionPointerType).getNumberOfParameters() + then destLabel = "+arg" + i.toString() + else destLabel = "+vararg" + ) or exists(Function f, ReturnStmt ret | f = ret.getEnclosingFunction() and src = ret.getExpr().getFullyConverted() and - destLabel = "+ret" and destParent = f) + destLabel = "+ret" and + destParent = f + ) or exists(AggregateLiteral agg, Struct s, int i | - destParent = agg and lvalue(src) and + destParent = agg and + lvalue(src) and aggregateLiteralChild(agg, s, i, src) and destLabel = s.getCanonicalMember(i).getName() ) or exists(FunctionCall c, Function f | c.getTarget() = f and - not(f.isVirtual()) and + not f.isVirtual() and src = c.getQualifier().getFullyConverted() and destParent = f and destLabel = "+this" @@ -325,7 +425,7 @@ predicate flowToCompound(Element destParent, string destLabel, Element src) or exists(ConstructorCall c, Function f, Variable v | c.getTarget() = f and - not(f.isVirtual()) and + not f.isVirtual() and v.getAnAssignedValue() = c and src = v and destParent = f and @@ -334,7 +434,7 @@ predicate flowToCompound(Element destParent, string destLabel, Element src) or exists(NewExpr ne, ConstructorCall c, Function f | c.getTarget() = f and - not(f.isVirtual()) and + not f.isVirtual() and ne.getInitializer() = c and src = ne and destParent = f and @@ -354,22 +454,31 @@ predicate flowToCompound(Element destParent, string destLabel, Element src) /** * There is a flow from the compound (parent, label) to dest. */ -predicate flowFromCompound(Element parent, string label, Element dest) -{ +predicate flowFromCompound(Element parent, string label, Element dest) { exists(ExprCall call | - dest = call and label = "+ret" and parent = call.getExpr().getFullyConverted()) + dest = call and label = "+ret" and parent = call.getExpr().getFullyConverted() + ) or - exists(Function f, int i | dest = f.getParameter(i).getAnAccess() - and label = "+arg" + i.toString() and parent = f) + exists(Function f, int i | + dest = f.getParameter(i).getAnAccess() and + label = "+arg" + i.toString() and + parent = f + ) or - exists(Function f | - parent = f and label = "+vararg" and varArgRead(f, dest)) + exists(Function f | parent = f and label = "+vararg" and varArgRead(f, dest)) or - exists(FieldAccess fa | dest = fa and parent = fa.getQualifier().getFullyConverted() - and label = fa.getTarget().getName() and lvalue(dest)) + exists(FieldAccess fa | + dest = fa and + parent = fa.getQualifier().getFullyConverted() and + label = fa.getTarget().getName() and + lvalue(dest) + ) or - exists(ThisExpr thisexpr | dest = thisexpr and label = "+this" - and parent = thisexpr.getEnclosingFunction()) + exists(ThisExpr thisexpr | + dest = thisexpr and + label = "+this" and + parent = thisexpr.getEnclosingFunction() + ) // // add more cases here // @@ -377,9 +486,8 @@ predicate flowFromCompound(Element parent, string label, Element dest) /** * The values stored in src point to the compounds (destParent, destLabel). - */ -predicate pointerToCompound(Element destParent, string destLabel, Element src) -{ + */ +predicate pointerToCompound(Element destParent, string destLabel, Element src) { none() // // add more cases here @@ -394,10 +502,12 @@ pragma[noopt] predicate aggregateLiteralChild(AggregateLiteral agg, Struct s, int i, Expr child) { // s = agg.getType().getUnderlyingType() exists(Type t | - t = agg.getType() and agg instanceof AggregateLiteral and s = t.getUnderlyingType() and s instanceof Struct - ) - and - exists(Expr beforeConversion | + t = agg.getType() and + agg instanceof AggregateLiteral and + s = t.getUnderlyingType() and + s instanceof Struct + ) and + exists(Expr beforeConversion | beforeConversion = agg.getChild(i) and child = beforeConversion.getFullyConverted() ) @@ -406,13 +516,17 @@ predicate aggregateLiteralChild(AggregateLiteral agg, Struct s, int i, Expr chil /** * The compound (parent, label) holds pointers to dest. */ -predicate pointerFromCompound(Element parent, string label, Element dest) -{ - exists(FieldAccess fa | dest = fa and parent = fa.getQualifier().getFullyConverted() - and label = fa.getTarget().getName() and not(lvalue(dest))) +predicate pointerFromCompound(Element parent, string label, Element dest) { + exists(FieldAccess fa | + dest = fa and + parent = fa.getQualifier().getFullyConverted() and + label = fa.getTarget().getName() and + not lvalue(dest) + ) or exists(AggregateLiteral agg, Struct s, int i | - parent = agg and not(lvalue(dest)) and + parent = agg and + not lvalue(dest) and aggregateLiteralChild(agg, s, i, dest) and label = s.getCanonicalMember(i).getName() ) @@ -421,31 +535,39 @@ predicate pointerFromCompound(Element parent, string label, Element dest) // } -predicate virtualArg(Expr receiver, VirtualFunction called, string arglabel, Expr arg) -{ +predicate virtualArg(Expr receiver, VirtualFunction called, string arglabel, Expr arg) { exists(FunctionCall c, int i | - receiver = c.getQualifier().getFullyConverted() and called = c.getTarget() and called.isVirtual() - and arg = c.getArgument(i) and i >= 0 and - if i < called.getNumberOfParameters() then - arglabel = "+arg" + i.toString() - else - arglabel = "+vararg") + receiver = c.getQualifier().getFullyConverted() and + called = c.getTarget() and + called.isVirtual() and + arg = c.getArgument(i) and + i >= 0 and + if i < called.getNumberOfParameters() + then arglabel = "+arg" + i.toString() + else arglabel = "+vararg" + ) } -predicate virtualThis(Expr receiver, VirtualFunction called, string thislabel, Expr thisexpr) -{ +predicate virtualThis(Expr receiver, VirtualFunction called, string thislabel, Expr thisexpr) { exists(FunctionCall c | - receiver = c.getQualifier().getFullyConverted() and called = c.getTarget() and thislabel = "+this" - and called.isVirtual() and thisexpr = receiver) + receiver = c.getQualifier().getFullyConverted() and + called = c.getTarget() and + thislabel = "+this" and + called.isVirtual() and + thisexpr = receiver + ) } -predicate virtualRet(Expr receiver, VirtualFunction called, string retlabel, FunctionCall c) -{ - receiver = c.getQualifier().getFullyConverted() and called = c.getTarget() - and called.isVirtual() and retlabel = "+ret" +predicate virtualRet(Expr receiver, VirtualFunction called, string retlabel, FunctionCall c) { + receiver = c.getQualifier().getFullyConverted() and + called = c.getTarget() and + called.isVirtual() and + retlabel = "+ret" } -private predicate compoundEdgeEntity(@element parent, @element element, string label, @element other, int kind) { +private predicate compoundEdgeEntity( + @element parent, @element element, string label, @element other, int kind +) { compoundEdge(mkElement(parent), mkElement(element), label, mkElement(other), kind) } @@ -471,23 +593,22 @@ private predicate compoundEdgeEntity(@element parent, @element element, string l * 10 - pointer from <,label> to other * 11 - pointer from other to <,label> */ -predicate compoundEdge(Element parent, Element element, string label, Element other, int kind) -{ - (flowFromCompound(parent, label, other) and element = parent and kind = 0) +predicate compoundEdge(Element parent, Element element, string label, Element other, int kind) { + flowFromCompound(parent, label, other) and element = parent and kind = 0 or - (flowToCompound(parent, label, other) and element = parent and kind = 1) + flowToCompound(parent, label, other) and element = parent and kind = 1 or - (pointerFromCompound(parent, label, other) and element = parent and kind = 2) + pointerFromCompound(parent, label, other) and element = parent and kind = 2 or - (pointerToCompound(parent, label, other) and element = parent and kind = 3) + pointerToCompound(parent, label, other) and element = parent and kind = 3 or - (resolve(parent, element, other) and label = "" and kind = 5) + resolve(parent, element, other) and label = "" and kind = 5 or - (virtualRet(parent, element, label, other) and kind = 8) + virtualRet(parent, element, label, other) and kind = 8 or - (virtualArg(parent, element, label, other) and kind = 9) + virtualArg(parent, element, label, other) and kind = 9 or - (virtualThis(parent, element, label, other) and kind = 9) + virtualThis(parent, element, label, other) and kind = 9 } /** @@ -510,47 +631,42 @@ predicate compoundEdge(Element parent, Element element, string label, Element ot * * If the label is "--element--", then the tuple declares that the set "ptset" is * a child of "parent", where the label of the child is "elem". - * + * * In any other case, the tuple declares that set "ptset" is a child of * "parent", where the label is "label". */ -cached +cached predicate pointstoinfo(int parent, @element elem, string label, int ptset) = - collapse(flowEntity/2, pointerEntity/2, compoundEdgeEntity/5, locationEntity/1)(parent, elem, label, ptset) + collapse(flowEntity/2, pointerEntity/2, compoundEdgeEntity/5, locationEntity/1)(parent, elem, + label, ptset) /** * Which elements are in which points-to sets. */ cached -predicate pointstosets(int ptset, @element elem) -{ - pointstoinfo(_, elem, "", ptset) -} +predicate pointstosets(int ptset, @element elem) { pointstoinfo(_, elem, "", ptset) } /** * The points-to set src flows to the points-to set dest. * This relation is not transitively closed. */ -predicate setflow(int src, int dest) -{ - pointstoinfo(src, _, "--flow--", dest) -} +predicate setflow(int src, int dest) { pointstoinfo(src, _, "--flow--", dest) } /** * The points-to set parentset, when dereferenced using the * given label, gives values in the points-to set childset. */ -predicate children(int parentset, string label, int childset) -{ - pointstoinfo(parentset, _, label, childset) - and label != "" and label != "--element--" and label != "--flow--" +predicate children(int parentset, string label, int childset) { + pointstoinfo(parentset, _, label, childset) and + label != "" and + label != "--element--" and + label != "--flow--" } /** * The same as children(), except that the label is an element. */ -predicate childrenByElement(int parentset, Element label, int childset) -{ +predicate childrenByElement(int parentset, Element label, int childset) { pointstoinfo(parentset, unresolveElement(label), "--element--", childset) } @@ -560,20 +676,16 @@ predicate childrenByElement(int parentset, Element label, int childset) * childrenByElement() using this ID. */ pragma[noopt] -predicate parentSetFor(int cset, @element expr) -{ +predicate parentSetFor(int cset, @element expr) { exists(string s | s = "" and pointstoinfo(cset, expr, s, _)) } -private predicate locationEntity(@element location) { - location(mkElement(location)) -} +private predicate locationEntity(@element location) { location(mkElement(location)) } /** * Things that are elements of points-to sets. */ -predicate location(Element location) -{ +predicate location(Element location) { location instanceof Variable or location instanceof Function or isAllocationExpr(location) or @@ -584,25 +696,24 @@ predicate location(Element location) /** * A call to the Unix system function socket(2). */ -predicate allocateDescriptorCall(FunctionCall fc) -{ +predicate allocateDescriptorCall(FunctionCall fc) { exists(string name | name = "socket" and - fc.getTarget().hasGlobalName(name)) + fc.getTarget().hasGlobalName(name) + ) } /** * A points-to set that contains at least one interesting element, or * flows to one that does. */ -private int interestingSet() -{ +private int interestingSet() { exists(PointsToExpr e | e.interesting() and pointstosets(result, unresolveElement(e)) - ) or ( - setflow(result, interestingSet()) ) + or + setflow(result, interestingSet()) } /** @@ -611,19 +722,16 @@ private int interestingSet() * to sets which are interesting. */ cached -predicate setlocations(int set, @element location) -{ +predicate setlocations(int set, @element location) { set = interestingSet() and ( - ( - location(mkElement(location)) and pointstosets(set, location) - ) or + location(mkElement(location)) and pointstosets(set, location) + or exists(int middle | setlocations(middle, location) and setflow(middle, set)) ) } -class PointsToExpr extends Expr -{ +class PointsToExpr extends Expr { /** * This predicate is empty by default. It should be overridden and defined to * include just those expressions for which points-to information is desired. @@ -631,8 +739,7 @@ class PointsToExpr extends Expr predicate interesting() { none() } pragma[noopt] - Element pointsTo() - { + Element pointsTo() { this.interesting() and exists(int set, @element thisEntity, @element resultEntity | thisEntity = underlyingElement(this) and @@ -647,9 +754,7 @@ class PointsToExpr extends Expr // This is used above in a `pragma[noopt]` context, which prevents its // customary inlining. We materialise it explicitly here. -private @element localUnresolveElement(Element e) { - result = unresolveElement(e) -} +private @element localUnresolveElement(Element e) { result = unresolveElement(e) } /** * Holds if anything points to an element, that is, is equivalent to: @@ -657,8 +762,6 @@ private @element localUnresolveElement(Element e) { * exists(PointsToExpr e | e.pointsTo() = elem) * ``` */ -predicate anythingPointsTo(Element elem) -{ +predicate anythingPointsTo(Element elem) { location(elem) and pointstosets(interestingSet(), unresolveElement(elem)) } - diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/Bound.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/Bound.qll index 54a825e2ffc..fe0e211087c 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/Bound.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/Bound.qll @@ -53,28 +53,27 @@ abstract class Bound extends TBound { class ZeroBound extends Bound, TBoundZero { override string toString() { result = "0" } - override Instruction getInstruction(int delta) { result.(ConstantValueInstruction).getValue().toInt() = delta } - - override Location getLocation() { - result instanceof UnknownDefaultLocation + override Instruction getInstruction(int delta) { + result.(ConstantValueInstruction).getValue().toInt() = delta } + + override Location getLocation() { result instanceof UnknownDefaultLocation } } + /** * A bound corresponding to the value of an `Instruction`. */ class ValueNumberBound extends Bound, TBoundValueNumber { ValueNumber vn; - - ValueNumberBound() { - this = TBoundValueNumber(vn) - } - + + ValueNumberBound() { this = TBoundValueNumber(vn) } + /** Gets the SSA variable that equals this bound. */ - override Instruction getInstruction(int delta) { this = TBoundValueNumber(valueNumber(result)) and delta = 0} + override Instruction getInstruction(int delta) { + this = TBoundValueNumber(valueNumber(result)) and delta = 0 + } override string toString() { result = vn.getExampleInstruction().toString() } - override Location getLocation() { - result = vn.getLocation() - } + override Location getLocation() { result = vn.getLocation() } } diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/PointlessComparison.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/PointlessComparison.qll index f927beb8689..3c9177ad9db 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/PointlessComparison.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/PointlessComparison.qll @@ -1,20 +1,19 @@ /** * Provides utility predicates used by the pointless comparison queries. */ + import cpp import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis /** Gets the lower bound of the fully converted expression. */ -private float lowerBoundFC(Expr expr) { - result = lowerBound(expr.getFullyConverted()) -} +private float lowerBoundFC(Expr expr) { result = lowerBound(expr.getFullyConverted()) } /** Gets the upper bound of the fully converted expression. */ -private float upperBoundFC(Expr expr) { - result = upperBound(expr.getFullyConverted()) -} +private float upperBoundFC(Expr expr) { result = upperBound(expr.getFullyConverted()) } -newtype SmallSide = LeftIsSmaller() or RightIsSmaller() +newtype SmallSide = + LeftIsSmaller() or + RightIsSmaller() /** * Holds if `cmp` is a comparison operation in which the left hand @@ -25,8 +24,7 @@ newtype SmallSide = LeftIsSmaller() or RightIsSmaller() * Note that the comparison operation could be any binary comparison * operator, for example,`==`, `>`, or `<=`. */ -private -predicate alwaysLT(ComparisonOperation cmp, float left, float right, SmallSide ss) { +private predicate alwaysLT(ComparisonOperation cmp, float left, float right, SmallSide ss) { ss = LeftIsSmaller() and left = upperBoundFC(cmp.getLeftOperand()) and right = lowerBoundFC(cmp.getRightOperand()) and @@ -42,13 +40,11 @@ predicate alwaysLT(ComparisonOperation cmp, float left, float right, SmallSide s * Note that the comparison operation could be any binary comparison * operator, for example,`==`, `>`, or `<=`. */ -private -predicate alwaysLE(ComparisonOperation cmp, float left, float right, SmallSide ss) { +private predicate alwaysLE(ComparisonOperation cmp, float left, float right, SmallSide ss) { ss = LeftIsSmaller() and left = upperBoundFC(cmp.getLeftOperand()) and right = lowerBoundFC(cmp.getRightOperand()) and left <= right and - // Range analysis is not able to precisely represent large 64 bit numbers, // because it stores the range as a `float`, which only has a 53 bit mantissa. // For example, the number `2^64-1` is rounded to `2^64`. This means that we @@ -68,8 +64,7 @@ predicate alwaysLE(ComparisonOperation cmp, float left, float right, SmallSide s * Note that the comparison operation could be any binary comparison * operator, for example,`==`, `>`, or `<=`. */ -private -predicate alwaysGT(ComparisonOperation cmp, float left, float right, SmallSide ss) { +private predicate alwaysGT(ComparisonOperation cmp, float left, float right, SmallSide ss) { ss = RightIsSmaller() and left = lowerBoundFC(cmp.getLeftOperand()) and right = upperBoundFC(cmp.getRightOperand()) and @@ -85,13 +80,11 @@ predicate alwaysGT(ComparisonOperation cmp, float left, float right, SmallSide s * Note that the comparison operation could be any binary comparison * operator, for example,`==`, `>`, or `<=`. */ -private -predicate alwaysGE(ComparisonOperation cmp, float left, float right, SmallSide ss) { +private predicate alwaysGE(ComparisonOperation cmp, float left, float right, SmallSide ss) { ss = RightIsSmaller() and left = lowerBoundFC(cmp.getLeftOperand()) and right = upperBoundFC(cmp.getRightOperand()) and left >= right and - // Range analysis is not able to precisely represent large 64 bit numbers, // because it stores the range as a `float`, which only has a 53 bit mantissa. // For example, the number 2^64-1 is rounded to 2^64. This means that we @@ -120,21 +113,32 @@ predicate alwaysGE(ComparisonOperation cmp, float left, float right, SmallSide s * and `7 >= y` then * `pointlessComparison(x < y, 9, 7, false, RightIsSmaller)` holds. */ -predicate pointlessComparison(ComparisonOperation cmp, - float left, float right, - boolean value, SmallSide ss) { - (alwaysLT(cmp.(LTExpr), left, right, ss) and value = true) or - (alwaysLE(cmp.(LEExpr), left, right, ss) and value = true) or - (alwaysGT(cmp.(GTExpr), left, right, ss) and value = true) or - (alwaysGE(cmp.(GEExpr), left, right, ss) and value = true) or - (alwaysLT(cmp.(NEExpr), left, right, ss) and value = true) or - (alwaysGT(cmp.(NEExpr), left, right, ss) and value = true) or - (alwaysGE(cmp.(LTExpr), left, right, ss) and value = false) or - (alwaysGT(cmp.(LEExpr), left, right, ss) and value = false) or - (alwaysLE(cmp.(GTExpr), left, right, ss) and value = false) or - (alwaysLT(cmp.(GEExpr), left, right, ss) and value = false) or - (alwaysLT(cmp.(EQExpr), left, right, ss) and value = false) or - (alwaysGT(cmp.(EQExpr), left, right, ss) and value = false) +predicate pointlessComparison( + ComparisonOperation cmp, float left, float right, boolean value, SmallSide ss +) { + alwaysLT(cmp.(LTExpr), left, right, ss) and value = true + or + alwaysLE(cmp.(LEExpr), left, right, ss) and value = true + or + alwaysGT(cmp.(GTExpr), left, right, ss) and value = true + or + alwaysGE(cmp.(GEExpr), left, right, ss) and value = true + or + alwaysLT(cmp.(NEExpr), left, right, ss) and value = true + or + alwaysGT(cmp.(NEExpr), left, right, ss) and value = true + or + alwaysGE(cmp.(LTExpr), left, right, ss) and value = false + or + alwaysGT(cmp.(LEExpr), left, right, ss) and value = false + or + alwaysLE(cmp.(GTExpr), left, right, ss) and value = false + or + alwaysLT(cmp.(GEExpr), left, right, ss) and value = false + or + alwaysLT(cmp.(EQExpr), left, right, ss) and value = false + or + alwaysGT(cmp.(EQExpr), left, right, ss) and value = false } /** @@ -149,18 +153,13 @@ predicate pointlessComparison(ComparisonOperation cmp, * return x; // x has an empty range: 10 < x && x < 5 * } * } - */ -predicate reachablePointlessComparison(ComparisonOperation cmp, - float left, float right, - boolean value, SmallSide ss) { - pointlessComparison(cmp, left, right, value, ss) - +predicate reachablePointlessComparison( + ComparisonOperation cmp, float left, float right, boolean value, SmallSide ss +) { + pointlessComparison(cmp, left, right, value, ss) and // Reachable according to control flow analysis. - and - reachable(cmp) - + reachable(cmp) and // Reachable according to range analysis. - and - not (exprWithEmptyRange(cmp.getAChild+())) + not exprWithEmptyRange(cmp.getAChild+()) } diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysis.qll index 4fd32a3756c..50fe6ab9a55 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysis.qll @@ -42,7 +42,7 @@ * a constant bound), or they are relative to some program value. This value is * represented by the `ValueNumber` class, each instance of which represents a * set of `Instructions` that must have the same value. - * + * * Phi nodes need a little bit of extra handling. Consider `x0 = phi(x1, x2)`. * There are essentially two cases: * - If `x1 <= B + d1` and `x2 <= B + d2` then `x0 <= B + max(d1,d2)`. @@ -65,10 +65,9 @@ * We prevent this by weakening the bound to a small finite set of bounds when * a path follows a second back-edge (we postpone weakening till the second * back-edge as a precise bound might require traversing a loop once). -*/ + */ import cpp - private import semmle.code.cpp.ir.IR private import semmle.code.cpp.controlflow.IRGuards private import semmle.code.cpp.ir.ValueNumbering @@ -76,9 +75,10 @@ private import RangeUtils private import SignAnalysis import Bound -cached private module RangeAnalysisCache { - - cached module RangeAnalysisPublic { +cached +private module RangeAnalysisCache { + cached + module RangeAnalysisPublic { /** * Holds if `b + delta` is a valid bound for `i`. * - `upper = true` : `i <= b + delta` @@ -88,10 +88,11 @@ cached private module RangeAnalysisCache { * or `NoReason` if the bound was proven directly without the use of a bounding * condition. */ - cached predicate boundedInstruction(Instruction i, Bound b, int delta, boolean upper, Reason reason) { + cached + predicate boundedInstruction(Instruction i, Bound b, int delta, boolean upper, Reason reason) { boundedInstruction(i, b, delta, upper, _, _, reason) } - + /** * Holds if `b + delta` is a valid bound for `op`. * - `upper = true` : `op <= b + delta` @@ -101,7 +102,8 @@ cached private module RangeAnalysisCache { * or `NoReason` if the bound was proven directly without the use of a bounding * condition. */ - cached predicate boundedOperand(Operand op, Bound b, int delta, boolean upper, Reason reason) { + cached + predicate boundedOperand(Operand op, Bound b, int delta, boolean upper, Reason reason) { boundedNonPhiOperand(op, b, delta, upper, _, _, reason) or boundedPhiOperand(op, b, delta, upper, _, _, reason) @@ -111,13 +113,14 @@ cached private module RangeAnalysisCache { /** * Holds if `guard = boundFlowCond(_, _, _, _, _) or guard = eqFlowCond(_, _, _, _, _)`. */ - cached predicate possibleReason(IRGuardCondition guard) { + cached + predicate possibleReason(IRGuardCondition guard) { guard = boundFlowCond(_, _, _, _, _) or guard = eqFlowCond(_, _, _, _, _) } - } + private import RangeAnalysisCache import RangeAnalysisPublic @@ -128,9 +131,9 @@ import RangeAnalysisPublic * - `isEq = true` : `vn == bound + delta` * - `isEq = false` : `vn != bound + delta` */ -private IRGuardCondition eqFlowCond(ValueNumber vn, Operand bound, int delta, - boolean isEq, boolean testIsTrue) -{ +private IRGuardCondition eqFlowCond( + ValueNumber vn, Operand bound, int delta, boolean isEq, boolean testIsTrue +) { result.comparesEq(vn.getAUse(), bound, delta, isEq, testIsTrue) } @@ -156,17 +159,15 @@ private predicate boundFlowStepSsa( * - `upper = true` : `vn <= bound + delta` * - `upper = false` : `vn >= bound + delta` */ -private IRGuardCondition boundFlowCond(ValueNumber vn, NonPhiOperand bound, int delta, boolean upper, - boolean testIsTrue) -{ +private IRGuardCondition boundFlowCond( + ValueNumber vn, NonPhiOperand bound, int delta, boolean upper, boolean testIsTrue +) { exists(int d | result.comparesLt(vn.getAUse(), bound, d, upper, testIsTrue) and // `comparesLt` provides bounds of the form `x < y + k` or `x >= y + k`, but we need // `x <= y + k` so we strengthen here. `testIsTrue` has the same semantics in `comparesLt` as // it does here, so we don't need to account for it. - if upper = true - then delta = d-1 - else delta = d + if upper = true then delta = d - 1 else delta = d ) or result = eqFlowCond(vn, bound, delta, true, testIsTrue) and @@ -185,11 +186,14 @@ private newtype TReason = abstract class Reason extends TReason { abstract string toString(); } + class NoReason extends Reason, TNoReason { override string toString() { result = "NoReason" } } + class CondReason extends Reason, TCondReason { IRGuardCondition getCond() { this = TCondReason(result) } + override string toString() { result = getCond().toString() } } @@ -204,7 +208,8 @@ private predicate safeCast(IntegralType fromtyp, IntegralType totyp) { fromtyp.isUnsigned() or totyp.isSigned() - ) or + ) + or fromtyp.getSize() <= totyp.getSize() and ( fromtyp.isSigned() and @@ -245,8 +250,10 @@ private class NarrowingCastInstruction extends ConvertInstruction { not this instanceof SafeCastInstruction and typeBound(getResultType(), _, _) } + /** Gets the lower bound of the resulting type. */ int getLowerBound() { typeBound(getResultType(), result, _) } + /** Gets the upper bound of the resulting type. */ int getUpperBound() { typeBound(getResultType(), _, result) } } @@ -268,21 +275,21 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool i.(AddInstruction).getAnOperand() = op and i.(AddInstruction).getAnOperand() = x and op != x - | + | not exists(getValue(getConstantValue(op.getUse()))) and not exists(getValue(getConstantValue(x.getUse()))) and - if(strictlyPositive(x)) - then ( - upper = false and delta = 1 - ) else + if strictlyPositive(x) + then upper = false and delta = 1 + else if positive(x) - then ( - upper = false and delta = 0 - ) else + then upper = false and delta = 0 + else if strictlyNegative(x) - then ( - upper = true and delta = -1 - ) else if negative(x) then (upper = true and delta = 0) else none() + then upper = true and delta = -1 + else + if negative(x) + then upper = true and delta = 0 + else none() ) or exists(Operand x | @@ -295,17 +302,17 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool // `x` with constant value is covered by valueFlowStep not exists(getValue(getConstantValue(x.getUse()))) and if strictlyPositive(x) - then ( - upper = true and delta = -1 - ) else + then upper = true and delta = -1 + else if positive(x) - then ( - upper = true and delta = 0 - ) else + then upper = true and delta = 0 + else if strictlyNegative(x) - then ( - upper = false and delta = 1 - ) else if negative(x) then (upper = false and delta = 0) else none() + then upper = false and delta = 1 + else + if negative(x) + then upper = false and delta = 0 + else none() ) or i.(RemInstruction).getRightOperand() = op and positive(op) and delta = -1 and upper = true @@ -314,7 +321,10 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool or i.(BitAndInstruction).getAnOperand() = op and positive(op) and delta = 0 and upper = true or - i.(BitOrInstruction).getAnOperand() = op and positiveInstruction(i) and delta = 0 and upper = false + i.(BitOrInstruction).getAnOperand() = op and + positiveInstruction(i) and + delta = 0 and + upper = false // TODO: min, max, rand } @@ -344,8 +354,9 @@ private predicate boundFlowStepDiv(Instruction i1, Operand op, int factor) { * Holds if `b` is a valid bound for `op` */ pragma[noinline] -private predicate boundedNonPhiOperand(NonPhiOperand op, Bound b, int delta, boolean upper, - boolean fromBackEdge, int origdelta, Reason reason +private predicate boundedNonPhiOperand( + NonPhiOperand op, Bound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, + Reason reason ) { exists(NonPhiOperand op2, int d1, int d2 | boundFlowStepSsa(op, op2, d1, upper, reason) and @@ -361,7 +372,8 @@ private predicate boundedNonPhiOperand(NonPhiOperand op, Bound b, int delta, boo unequalOperand(op, b, d, r1) and ( upper = true and delta = d - 1 - or upper = false and delta = d + 1 + or + upper = false and delta = d + 1 ) and ( reason = r1 @@ -391,7 +403,6 @@ private predicate boundFlowStepPhi( ) } - private predicate boundedPhiOperand( PhiInputOperand op, Bound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, Reason reason @@ -411,7 +422,8 @@ private predicate boundedPhiOperand( unequalOperand(op, b, d, r1) and ( upper = true and delta = d - 1 - or upper = false and delta = d + 1 + or + upper = false and delta = d + 1 ) and ( reason = r1 @@ -422,9 +434,7 @@ private predicate boundedPhiOperand( } /** Holds if `op2 != op1 + delta` at `pos`. */ -private predicate unequalFlowStep( - Operand op2, Operand op1, int delta, Reason reason -) { +private predicate unequalFlowStep(Operand op2, Operand op1, int delta, Reason reason) { exists(IRGuardCondition guard, boolean testIsTrue | guard = eqFlowCond(valueNumberOfOperand(op2), op1, delta, false, testIsTrue) and guard.controls(op2.getUse().getBlock(), testIsTrue) and @@ -533,7 +543,9 @@ private predicate boundedPhiCand( * `upper = false` this means that the cast will not underflow. */ private predicate safeNarrowingCast(NarrowingCastInstruction cast, boolean upper) { - exists(int bound | boundedNonPhiOperand(cast.getAnOperand(), any(ZeroBound zb), bound, upper, _, _, _) | + exists(int bound | + boundedNonPhiOperand(cast.getAnOperand(), any(ZeroBound zb), bound, upper, _, _, _) + | upper = true and bound <= cast.getUpperBound() or upper = false and bound >= cast.getLowerBound() @@ -542,18 +554,20 @@ private predicate safeNarrowingCast(NarrowingCastInstruction cast, boolean upper pragma[noinline] private predicate boundedCastExpr( - NarrowingCastInstruction cast, Bound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, - Reason reason + NarrowingCastInstruction cast, Bound b, int delta, boolean upper, boolean fromBackEdge, + int origdelta, Reason reason ) { boundedNonPhiOperand(cast.getAnOperand(), b, delta, upper, fromBackEdge, origdelta, reason) } + /** * Holds if `b + delta` is a valid bound for `i`. * - `upper = true` : `i <= b + delta` * - `upper = false` : `i >= b + delta` */ private predicate boundedInstruction( - Instruction i, Bound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, Reason reason + Instruction i, Bound b, int delta, boolean upper, boolean fromBackEdge, int origdelta, + Reason reason ) { i instanceof PhiInstruction and forex(PhiInputOperand op | op = i.getAnOperand() | @@ -577,7 +591,7 @@ private predicate boundedInstruction( boundFlowStepMul(i, mid, factor) and boundedNonPhiOperand(mid, b, d, upper, fromBackEdge, origdelta, reason) and b instanceof ZeroBound and - delta = d*factor and + delta = d * factor and not exists(getValue(getConstantValue(i))) ) or diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll index 740ac563e5c..9e99fcb8204 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll @@ -4,34 +4,40 @@ import cpp * Describes whether a relation is 'strict' (that is, a `<` or `>` * relation) or 'non-strict' (a `<=` or `>=` relation). */ -newtype RelationStrictness = Strict() or Nonstrict() +newtype RelationStrictness = + Strict() or + Nonstrict() /** * Describes whether a relation is 'greater' (that is, a `>` or `>=` * relation) or 'lesser' (a `<` or `<=` relation). */ -newtype RelationDirection = Greater() or Lesser() +newtype RelationDirection = + Greater() or + Lesser() -private -RelationStrictness negateStrictness(RelationStrictness strict) { - (strict = Strict() and result = Nonstrict()) or - (strict = Nonstrict() and result = Strict()) +private RelationStrictness negateStrictness(RelationStrictness strict) { + strict = Strict() and result = Nonstrict() + or + strict = Nonstrict() and result = Strict() } -private -RelationDirection negateDirection(RelationDirection dir) { - (dir = Greater() and result = Lesser()) or - (dir = Lesser() and result = Greater()) +private RelationDirection negateDirection(RelationDirection dir) { + dir = Greater() and result = Lesser() + or + dir = Lesser() and result = Greater() } boolean directionIsGreater(RelationDirection dir) { - (dir = Greater() and result = true) or - (dir = Lesser() and result = false) + dir = Greater() and result = true + or + dir = Lesser() and result = false } boolean directionIsLesser(RelationDirection dir) { - (dir = Greater() and result = false) or - (dir = Lesser() and result = true) + dir = Greater() and result = false + or + dir = Lesser() and result = true } /** @@ -42,17 +48,20 @@ boolean directionIsLesser(RelationDirection dir) { * For example, if `rel` is `x < 5` then * `relOp(rel, x, 5, Lesser(), Strict())` holds. */ -private -predicate relOp( - RelationalOperation rel, Expr lhs, Expr rhs, - RelationDirection dir, RelationStrictness strict +private predicate relOp( + RelationalOperation rel, Expr lhs, Expr rhs, RelationDirection dir, RelationStrictness strict ) { lhs = rel.getLeftOperand().getFullyConverted() and rhs = rel.getRightOperand().getFullyConverted() and - ((rel instanceof LTExpr and dir = Lesser() and strict = Strict()) or - (rel instanceof LEExpr and dir = Lesser() and strict = Nonstrict()) or - (rel instanceof GTExpr and dir = Greater() and strict = Strict()) or - (rel instanceof GEExpr and dir = Greater() and strict = Nonstrict())) + ( + rel instanceof LTExpr and dir = Lesser() and strict = Strict() + or + rel instanceof LEExpr and dir = Lesser() and strict = Nonstrict() + or + rel instanceof GTExpr and dir = Greater() and strict = Strict() + or + rel instanceof GEExpr and dir = Greater() and strict = Nonstrict() + ) } /** @@ -65,10 +74,9 @@ predicate relOp( * `relOpWithSwap(rel, 5, x, Greater(), Strict())` hold. */ predicate relOpWithSwap( - RelationalOperation rel, Expr a, Expr b, - RelationDirection dir, RelationStrictness strict + RelationalOperation rel, Expr a, Expr b, RelationDirection dir, RelationStrictness strict ) { - relOp(rel, a, b, dir, strict) or + relOp(rel, a, b, dir, strict) or relOp(rel, b, a, negateDirection(dir), strict) } @@ -85,13 +93,13 @@ predicate relOpWithSwap( * `relOpWithSwapAndNegate(rel, 5, x, Lesser(), Nonstrict(), false)` hold. */ predicate relOpWithSwapAndNegate( - RelationalOperation rel, Expr a, Expr b, - RelationDirection dir, RelationStrictness strict, boolean branch + RelationalOperation rel, Expr a, Expr b, RelationDirection dir, RelationStrictness strict, + boolean branch ) { - (relOpWithSwap(rel, a, b, dir, strict) and branch = true) + relOpWithSwap(rel, a, b, dir, strict) and branch = true or - (relOpWithSwap(rel, a, b, negateDirection(dir), negateStrictness(strict)) and - branch = false) + relOpWithSwap(rel, a, b, negateDirection(dir), negateStrictness(strict)) and + branch = false } /** @@ -102,12 +110,14 @@ predicate relOpWithSwapAndNegate( * For example, if `rel` is `x == 5` then * `eqOpWithSwap(cmp, x, 5, true)` holds. */ -private -predicate eqOp(EqualityOperation cmp, Expr lhs, Expr rhs, boolean isEQ) { +private predicate eqOp(EqualityOperation cmp, Expr lhs, Expr rhs, boolean isEQ) { lhs = cmp.getLeftOperand().getFullyConverted() and rhs = cmp.getRightOperand().getFullyConverted() and - ((cmp instanceof EQExpr and isEQ = true) or - (cmp instanceof NEExpr and isEQ = false)) + ( + cmp instanceof EQExpr and isEQ = true + or + cmp instanceof NEExpr and isEQ = false + ) } /** @@ -120,8 +130,7 @@ predicate eqOp(EqualityOperation cmp, Expr lhs, Expr rhs, boolean isEQ) { * `eqOpWithSwap(cmp, x, 5, true)` and * `eqOpWithSwap(cmp, 5, x, true)` hold. */ -private -predicate eqOpWithSwap(EqualityOperation cmp, Expr a, Expr b, boolean isEQ) { +private predicate eqOpWithSwap(EqualityOperation cmp, Expr a, Expr b, boolean isEQ) { eqOp(cmp, a, b, isEQ) or eqOp(cmp, b, a, isEQ) } @@ -138,11 +147,10 @@ predicate eqOpWithSwap(EqualityOperation cmp, Expr a, Expr b, boolean isEQ) { * `eqOpWithSwapAndNegate(cmp, x, 5, false, false)` and * `eqOpWithSwapAndNegate(cmp, 5, x, false, false)` hold. */ -predicate eqOpWithSwapAndNegate( - EqualityOperation cmp, Expr a, Expr b, boolean isEQ, boolean branch -) { - (eqOpWithSwap(cmp, a, b, branch) and isEQ = true) or - (eqOpWithSwap(cmp, a, b, branch.booleanNot()) and isEQ = false) +predicate eqOpWithSwapAndNegate(EqualityOperation cmp, Expr a, Expr b, boolean isEQ, boolean branch) { + eqOpWithSwap(cmp, a, b, branch) and isEQ = true + or + eqOpWithSwap(cmp, a, b, branch.booleanNot()) and isEQ = false } /** @@ -161,92 +169,100 @@ predicate linearAccess(Expr expr, VariableAccess v, float p, float q) { * This takes into account the associativity, commutativity and * distributivity of arithmetic operations. */ -private -predicate linearAccessImpl(Expr expr, VariableAccess v, float p, float q) { +private predicate linearAccessImpl(Expr expr, VariableAccess v, float p, float q) { // Base case - (expr = v and p = 1.0 and q = 0.0) + expr = v and p = 1.0 and q = 0.0 or // a+(p*v+b) == p*v + (a+b) - exists (AddExpr addExpr, float a, float b - | addExpr.getLeftOperand().isConstant() and + exists(AddExpr addExpr, float a, float b | + addExpr.getLeftOperand().isConstant() and a = addExpr.getLeftOperand().getFullyConverted().getValue().toFloat() and linearAccess(addExpr.getRightOperand(), v, p, b) and expr = addExpr and - q = a+b) + q = a + b + ) or // (p*v+a)+b == p*v + (a+b) - exists (AddExpr addExpr, float a, float b - | addExpr.getRightOperand().isConstant() and + exists(AddExpr addExpr, float a, float b | + addExpr.getRightOperand().isConstant() and b = addExpr.getRightOperand().getFullyConverted().getValue().toFloat() and linearAccess(addExpr.getLeftOperand(), v, p, a) and expr = addExpr and - q = a+b) + q = a + b + ) or // a-(m*v+b) == -m*v + (a-b) - exists (SubExpr subExpr, float a, float b, float m - | subExpr.getLeftOperand().isConstant() and + exists(SubExpr subExpr, float a, float b, float m | + subExpr.getLeftOperand().isConstant() and a = subExpr.getLeftOperand().getFullyConverted().getValue().toFloat() and linearAccess(subExpr.getRightOperand(), v, m, b) and expr = subExpr and p = -m and - q = a-b) + q = a - b + ) or // (p*v+a)-b == p*v + (a-b) - exists (SubExpr subExpr, float a, float b - | subExpr.getRightOperand().isConstant() and + exists(SubExpr subExpr, float a, float b | + subExpr.getRightOperand().isConstant() and b = subExpr.getRightOperand().getFullyConverted().getValue().toFloat() and linearAccess(subExpr.getLeftOperand(), v, p, a) and expr = subExpr and - q = a-b) + q = a - b + ) or // +(p*v+q) == p*v + q - exists (UnaryPlusExpr unaryPlusExpr - | linearAccess(unaryPlusExpr.getOperand().getFullyConverted(), v, p, q) and - expr = unaryPlusExpr) + exists(UnaryPlusExpr unaryPlusExpr | + linearAccess(unaryPlusExpr.getOperand().getFullyConverted(), v, p, q) and + expr = unaryPlusExpr + ) or // (larger_type)(p*v+q) == p*v + q - exists (Cast cast, ArithmeticType sourceType, ArithmeticType targetType - | linearAccess(cast.getExpr(), v, p, q) and + exists(Cast cast, ArithmeticType sourceType, ArithmeticType targetType | + linearAccess(cast.getExpr(), v, p, q) and sourceType = cast.getExpr().getUnspecifiedType() and targetType = cast.getUnspecifiedType() and // This allows conversion between signed and unsigned, which is technically // lossy but common enough that we'll just have to assume the user knows // what they're doing. targetType.getSize() >= sourceType.getSize() and - expr = cast) + expr = cast + ) or // (p*v+q) == p*v + q - exists (ParenthesisExpr paren - | linearAccess(paren.getExpr(), v, p, q) and - expr = paren) + exists(ParenthesisExpr paren | + linearAccess(paren.getExpr(), v, p, q) and + expr = paren + ) or // -(a*v+b) == -a*v + (-b) - exists (UnaryMinusExpr unaryMinusExpr, float a, float b - | linearAccess(unaryMinusExpr.getOperand().getFullyConverted(), v, a, b) and + exists(UnaryMinusExpr unaryMinusExpr, float a, float b | + linearAccess(unaryMinusExpr.getOperand().getFullyConverted(), v, a, b) and expr = unaryMinusExpr and p = -a and - q = -b) + q = -b + ) or // m*(a*v+b) == (m*a)*v + (m*b) - exists (MulExpr mulExpr, float a, float b, float m - | mulExpr.getLeftOperand().isConstant() and + exists(MulExpr mulExpr, float a, float b, float m | + mulExpr.getLeftOperand().isConstant() and m = mulExpr.getLeftOperand().getFullyConverted().getValue().toFloat() and linearAccess(mulExpr.getRightOperand(), v, a, b) and expr = mulExpr and - p = m*a and - q = m*b) + p = m * a and + q = m * b + ) or // (a*v+b)*m == (m*a)*v + (m*b) - exists (MulExpr mulExpr, float a, float b, float m - | mulExpr.getRightOperand().isConstant() and + exists(MulExpr mulExpr, float a, float b, float m | + mulExpr.getRightOperand().isConstant() and m = mulExpr.getRightOperand().getFullyConverted().getValue().toFloat() and linearAccess(mulExpr.getLeftOperand(), v, a, b) and expr = mulExpr and - p = m*a and - q = m*b) + p = m * a and + q = m * b + ) } - /** * Holds if `guard` is a comparison operation (`<`, `<=`, `>`, `>=`, * `==` or `!=`), one of its arguments is equivalent (up to @@ -273,16 +289,20 @@ predicate cmpWithLinearBound( RelationDirection direction, // Is this a lower or an upper bound? boolean branch // Which control-flow branch is this bound valid on? ) { - exists (Expr lhs, float p, RelationDirection dir - | linearAccess(lhs, v, p, _) and + exists(Expr lhs, float p, RelationDirection dir | + linearAccess(lhs, v, p, _) and relOpWithSwapAndNegate(guard, lhs, _, dir, _, branch) and - ((p > 0 and direction = dir) or - (p < 0 and direction = negateDirection(dir)))) - + ( + p > 0 and direction = dir + or + p < 0 and direction = negateDirection(dir) + ) + ) or - exists (Expr lhs - | linearAccess(lhs, v, _, _) and - eqOpWithSwap(guard, lhs, _, branch)) + exists(Expr lhs | + linearAccess(lhs, v, _, _) and + eqOpWithSwap(guard, lhs, _, branch) + ) } /** @@ -292,18 +312,23 @@ predicate cmpWithLinearBound( * For example, if `t` is a signed 32-bit type then holds if `lb` is * `-2^31` and `ub` is `2^31 - 1`. */ -private -predicate typeBounds(ArithmeticType t, float lb, float ub) { - exists (IntegralType integralType, float limit - | integralType = t and limit = 2.pow(8 * integralType.getSize()) - | if integralType instanceof BoolType - then (lb = 0 and ub = 1) - else if integralType.isSigned() - then (lb = -(limit/2) and ub = (limit/2)-1) - else (lb = 0 and ub = limit-1)) +private predicate typeBounds(ArithmeticType t, float lb, float ub) { + exists(IntegralType integralType, float limit | + integralType = t and limit = 2.pow(8 * integralType.getSize()) + | + if integralType instanceof BoolType + then lb = 0 and ub = 1 + else + if integralType.isSigned() + then ( + lb = -(limit / 2) and ub = (limit / 2) - 1 + ) else ( + lb = 0 and ub = limit - 1 + ) + ) or // This covers all floating point types. The range is (-Inf, +Inf). - (t instanceof FloatingPointType and lb = -(1.0/0.0) and ub = 1.0/0.0) + t instanceof FloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0 } /** @@ -312,9 +337,7 @@ predicate typeBounds(ArithmeticType t, float lb, float ub) { * For example, if `t` is a signed 32-bit type then the result is * `-2^31`. */ -float typeLowerBound(ArithmeticType t) { - typeBounds(t, result, _) -} +float typeLowerBound(ArithmeticType t) { typeBounds(t, result, _) } /** * Gets the upper bound for the unspecified type `t`. @@ -322,9 +345,7 @@ float typeLowerBound(ArithmeticType t) { * For example, if `t` is a signed 32-bit type then the result is * `2^31 - 1`. */ -float typeUpperBound(ArithmeticType t) { - typeBounds(t, _, result) -} +float typeUpperBound(ArithmeticType t) { typeBounds(t, _, result) } /** * Gets the minimum value that this expression could represent, based on @@ -337,9 +358,7 @@ float typeUpperBound(ArithmeticType t) { * `exprMinVal(expr)` you will normally want to call * `exprMinVal(expr.getFullyConverted())`. */ -float exprMinVal(Expr expr) { - result = typeLowerBound(expr.getUnspecifiedType()) -} +float exprMinVal(Expr expr) { result = typeLowerBound(expr.getUnspecifiedType()) } /** * Gets the maximum value that this expression could represent, based on @@ -352,9 +371,7 @@ float exprMinVal(Expr expr) { * `exprMaxVal(expr)` you will normally want to call * `exprMaxVal(expr.getFullyConverted())`. */ -float exprMaxVal(Expr expr) { - result = typeUpperBound(expr.getUnspecifiedType()) -} +float exprMaxVal(Expr expr) { result = typeUpperBound(expr.getUnspecifiedType()) } /** * Gets the minimum value that this variable could represent, based on @@ -363,9 +380,7 @@ float exprMaxVal(Expr expr) { * For example, if `v` has a signed 32-bit type then the result is * `-2^31`. */ -float varMinVal(Variable v) { - result = typeLowerBound(v.getUnspecifiedType()) -} +float varMinVal(Variable v) { result = typeLowerBound(v.getUnspecifiedType()) } /** * Gets the maximum value that this variable could represent, based on @@ -374,6 +389,4 @@ float varMinVal(Variable v) { * For example, if `v` has a signed 32-bit type then the result is * `2^31 - 1`. */ -float varMaxVal(Variable v) { - result = typeUpperBound(v.getUnspecifiedType()) -} +float varMaxVal(Variable v) { result = typeUpperBound(v.getUnspecifiedType()) } diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeSSA.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeSSA.qll index 54788084cbf..a7d9b56a65c 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeSSA.qll @@ -26,35 +26,34 @@ import semmle.code.cpp.controlflow.SSAUtils private import RangeAnalysisUtils library class RangeSSA extends SSAHelper { - RangeSSA() { this = 1 } - - /** - * Add a phi node on the out-edge of a guard. - */ - override predicate custom_phi_node(LocalScopeVariable v, BasicBlock b) { guard_defn(v.getAnAccess(),_,b,_) } + RangeSSA() { this = 1 } + + /** + * Add a phi node on the out-edge of a guard. + */ + override predicate custom_phi_node(LocalScopeVariable v, BasicBlock b) { + guard_defn(v.getAnAccess(), _, b, _) + } } private predicate guard_defn( VariableAccess v, ComparisonOperation guard, BasicBlock b, boolean branch ) { - guardCondition(guard, v, branch) - and - guardSuccessor(guard, branch, b) + guardCondition(guard, v, branch) and + guardSuccessor(guard, branch, b) } -private predicate guardCondition( - ComparisonOperation guard, VariableAccess v, boolean branch -) { - exists (Expr lhs - | linearAccess(lhs, v, _, _) - | relOpWithSwapAndNegate(guard, lhs, _, _, _, branch) or - eqOpWithSwapAndNegate(guard, lhs, _, _, branch)) +private predicate guardCondition(ComparisonOperation guard, VariableAccess v, boolean branch) { + exists(Expr lhs | linearAccess(lhs, v, _, _) | + relOpWithSwapAndNegate(guard, lhs, _, _, _, branch) or + eqOpWithSwapAndNegate(guard, lhs, _, _, branch) + ) } private predicate guardSuccessor(ComparisonOperation guard, boolean branch, BasicBlock succ) { - (branch = true and succ = guard.getATrueSuccessor()) - or - (branch = false and succ = guard.getAFalseSuccessor()) + branch = true and succ = guard.getATrueSuccessor() + or + branch = false and succ = guard.getAFalseSuccessor() } /** @@ -65,111 +64,98 @@ private predicate guardSuccessor(ComparisonOperation guard, boolean branch, Basi * nodes. */ class RangeSsaDefinition extends ControlFlowNodeBase { + RangeSsaDefinition() { exists(RangeSSA x | x.ssa_defn(_, this, _, _)) } - RangeSsaDefinition() { - exists(RangeSSA x | x.ssa_defn(_, this, _, _)) - } + /** + * Gets a variable corresponding to a SSA LocalScopeVariable defined by + * this definition. + */ + LocalScopeVariable getAVariable() { exists(RangeSSA x | x.ssa_defn(result, this, _, _)) } - /** - * Gets a variable corresponding to a SSA LocalScopeVariable defined by - * this definition. - */ - LocalScopeVariable getAVariable() { - exists(RangeSSA x | x.ssa_defn(result, this, _, _)) - } + /** + * A string representation of the SSA variable represented by the pair + * (this, v). + */ + string toString(LocalScopeVariable v) { exists(RangeSSA x | result = x.toString(this, v)) } - /** - * A string representation of the SSA variable represented by the pair - * (this, v). - */ - string toString(LocalScopeVariable v) { - exists(RangeSSA x | result = x.toString(this, v)) - } + /** Gets a use of the SSA variable represented by the pair (this, v) */ + VariableAccess getAUse(LocalScopeVariable v) { exists(RangeSSA x | result = x.getAUse(this, v)) } - /** Gets a use of the SSA variable represented by the pair (this, v) */ - VariableAccess getAUse(LocalScopeVariable v) { - exists(RangeSSA x | result = x.getAUse(this, v)) - } + /** Gets the control flow node for this definition */ + ControlFlowNode getDefinition() { result = this } - /** Gets the control flow node for this definition */ - ControlFlowNode getDefinition() { - result = this - } + BasicBlock getBasicBlock() { result.contains(getDefinition()) } - BasicBlock getBasicBlock() { - result.contains(getDefinition()) - } + /** Whether this definition is a phi node for variable v */ + predicate isPhiNode(LocalScopeVariable v) { + exists(RangeSSA x | x.phi_node(v, this.(BasicBlock))) + } - /** Whether this definition is a phi node for variable v */ - predicate isPhiNode(LocalScopeVariable v) { - exists(RangeSSA x | x.phi_node(v, (BasicBlock)this)) - } + /** + * If this definition is a phi node corresponding to a guard, + * then return the variable and the guard. + */ + predicate isGuardPhi(VariableAccess v, ComparisonOperation guard, boolean branch) { + guard_defn(v, guard, this, branch) + } - /** - * If this definition is a phi node corresponding to a guard, - * then return the variable and the guard. - */ - predicate isGuardPhi(VariableAccess v, ComparisonOperation guard, boolean branch) { - guard_defn(v, guard, this, branch) - } + Location getLocation() { result = this.(ControlFlowNode).getLocation() } - Location getLocation() { - result = this.(ControlFlowNode).getLocation() - } + /** Whether this definition is from a parameter */ + predicate definedByParameter(Parameter p) { this = p.getFunction().getEntryPoint() } - /** Whether this definition is from a parameter */ - predicate definedByParameter(Parameter p) { - this = p.getFunction().getEntryPoint() - } + RangeSsaDefinition getAPhiInput(LocalScopeVariable v) { + this.isPhiNode(v) and + exists(BasicBlock pred | + pred = this.(BasicBlock).getAPredecessor() and + result.reachesEndOfBB(v, pred) and + // Suppose we have a CFG like this: + // + // 1: x_0 = ; + // 2: if () { + // 3: if (x_0 > 1) { + // 4: x_1 = phi(x_0); + // 5: } + // 6: } + // 7: x_2 = phi(x_0, x_1); + // + // The phi nodes on lines 4 and 7 are both guard phi nodes, + // because they have an incoming edge from the condition on + // line 3. Definition x_0 on line 1 should be considered a + // phi-input on line 7, but not on line 4. This is because + // the only CFG path from line 1 to line 4 goes through the + // condition on line 3, but there is a path from line 1 to + // line 7 which does not go through the condition. The logic + // below excludes definitions which can only reach guard phi + // nodes by going through the corresponding guard. + not exists(VariableAccess access | + v = access.getTarget() and + pred.contains(access) and + this.isGuardPhi(access, _, _) + ) + ) + } - RangeSsaDefinition getAPhiInput(LocalScopeVariable v) { - this.isPhiNode(v) - and - exists (BasicBlock pred - | pred = this.(BasicBlock).getAPredecessor() and - result.reachesEndOfBB(v, pred) and + /** Gets the expression assigned to this SsaDefinition */ + Expr getDefiningValue(LocalScopeVariable v) { + exists(ControlFlowNode def | def = this.getDefinition() | + def = v.getInitializer().getExpr() and def = result + or + exists(AssignExpr assign | + def = assign and + assign.getLValue() = v.getAnAccess() and + result = assign.getRValue() + ) + or + exists(AssignOperation assign | + def = assign and + assign.getLValue() = v.getAnAccess() and + result = assign + ) + ) + } - // Suppose we have a CFG like this: - // - // 1: x_0 = ; - // 2: if () { - // 3: if (x_0 > 1) { - // 4: x_1 = phi(x_0); - // 5: } - // 6: } - // 7: x_2 = phi(x_0, x_1); - // - // The phi nodes on lines 4 and 7 are both guard phi nodes, - // because they have an incoming edge from the condition on - // line 3. Definition x_0 on line 1 should be considered a - // phi-input on line 7, but not on line 4. This is because - // the only CFG path from line 1 to line 4 goes through the - // condition on line 3, but there is a path from line 1 to - // line 7 which does not go through the condition. The logic - // below excludes definitions which can only reach guard phi - // nodes by going through the corresponding guard. - not exists (VariableAccess access - | v = access.getTarget() and - pred.contains(access) and - this.isGuardPhi(access, _, _))) - } - - /** Gets the expression assigned to this SsaDefinition */ - Expr getDefiningValue(LocalScopeVariable v) { - exists(ControlFlowNode def | def = this.getDefinition() | - def = v.getInitializer().getExpr() and def = result - or - exists(AssignExpr assign | def = assign and - assign.getLValue() = v.getAnAccess() and result = assign.getRValue() - ) - or - exists(AssignOperation assign | def = assign and - assign.getLValue() = v.getAnAccess() and result = assign - ) - ) - } - - predicate reachesEndOfBB(LocalScopeVariable v, BasicBlock b) { - exists(RangeSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b)) - } + predicate reachesEndOfBB(LocalScopeVariable v, BasicBlock b) { + exists(RangeSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b)) + } } diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeUtils.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeUtils.qll index 4ae7e544aec..52782bcda30 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeUtils.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeUtils.qll @@ -1,5 +1,4 @@ import cpp - private import semmle.code.cpp.ir.IR // TODO: move this dependency import semmle.code.cpp.ir.internal.IntegerConstant @@ -7,23 +6,37 @@ import semmle.code.cpp.ir.internal.IntegerConstant // TODO: move this out of test code language[monotonicAggregates] IntValue getConstantValue(Instruction instr) { - result = instr.(IntegerConstantInstruction).getValue().toInt() or + result = instr.(IntegerConstantInstruction).getValue().toInt() + or exists(BinaryInstruction binInstr, IntValue left, IntValue right | binInstr = instr and left = getConstantValue(binInstr.getLeft()) and right = getConstantValue(binInstr.getRight()) and ( - binInstr instanceof AddInstruction and result = add(left, right) or - binInstr instanceof SubInstruction and result = sub(left, right) or - binInstr instanceof MulInstruction and result = mul(left, right) or + binInstr instanceof AddInstruction and result = add(left, right) + or + binInstr instanceof SubInstruction and result = sub(left, right) + or + binInstr instanceof MulInstruction and result = mul(left, right) + or binInstr instanceof DivInstruction and result = div(left, right) ) - ) or - result = getConstantValue(instr.(CopyInstruction).getSourceValue()) or + ) + or + result = getConstantValue(instr.(CopyInstruction).getSourceValue()) + or exists(PhiInstruction phi | phi = instr and - result = max(PhiInputOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDef())) and - result = min(PhiInputOperand operand | operand = phi.getAnOperand() | getConstantValue(operand.getDef())) + result = max(PhiInputOperand operand | + operand = phi.getAnOperand() + | + getConstantValue(operand.getDef()) + ) and + result = min(PhiInputOperand operand | + operand = phi.getAnOperand() + | + getConstantValue(operand.getDef()) + ) ) } @@ -33,33 +46,31 @@ predicate valueFlowStep(Instruction i, Operand op, int delta) { exists(Operand x | i.(AddInstruction).getAnOperand() = op and i.(AddInstruction).getAnOperand() = x and - op != x - | + op != x + | delta = getValue(getConstantValue(x.getDef())) ) or exists(Operand x | i.(SubInstruction).getLeftOperand() = op and i.(SubInstruction).getRightOperand() = x - | + | delta = -getValue(getConstantValue(x.getDef())) ) or exists(Operand x | i.(PointerAddInstruction).getAnOperand() = op and i.(PointerAddInstruction).getAnOperand() = x and - op != x - | - delta = i.(PointerAddInstruction).getElementSize() * - getValue(getConstantValue(x.getDef())) + op != x + | + delta = i.(PointerAddInstruction).getElementSize() * getValue(getConstantValue(x.getDef())) ) or exists(Operand x | i.(PointerSubInstruction).getLeftOperand() = op and i.(PointerSubInstruction).getRightOperand() = x - | - delta = i.(PointerSubInstruction).getElementSize() * - -getValue(getConstantValue(x.getDef())) + | + delta = i.(PointerSubInstruction).getElementSize() * -getValue(getConstantValue(x.getDef())) ) } diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll index 1e168f88ea9..ca641f826ef 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SignAnalysis.qll @@ -5,135 +5,212 @@ * The analysis is implemented as an abstract interpretation over the * three-valued domain `{negative, zero, positive}`. */ + import cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.controlflow.IRGuards private import semmle.code.cpp.ir.ValueNumbering private import SignAnalysisCached -private newtype TSign = TNeg() or TZero() or TPos() +private newtype TSign = + TNeg() or + TZero() or + TPos() + private class Sign extends TSign { string toString() { - result = "-" and this = TNeg() or - result = "0" and this = TZero() or + result = "-" and this = TNeg() + or + result = "0" and this = TZero() + or result = "+" and this = TPos() } + Sign inc() { - this = TNeg() and result = TNeg() or - this = TNeg() and result = TZero() or - this = TZero() and result = TPos() or + this = TNeg() and result = TNeg() + or + this = TNeg() and result = TZero() + or + this = TZero() and result = TPos() + or this = TPos() and result = TPos() } - Sign dec() { - result.inc() = this - } + + Sign dec() { result.inc() = this } + Sign neg() { - this = TNeg() and result = TPos() or - this = TZero() and result = TZero() or + this = TNeg() and result = TPos() + or + this = TZero() and result = TZero() + or this = TPos() and result = TNeg() } + Sign bitnot() { - this = TNeg() and result = TPos() or - this = TNeg() and result = TZero() or - this = TZero() and result = TNeg() or + this = TNeg() and result = TPos() + or + this = TNeg() and result = TZero() + or + this = TZero() and result = TNeg() + or this = TPos() and result = TNeg() } + Sign add(Sign s) { - this = TZero() and result = s or - s = TZero() and result = this or - this = s and this = result or - this = TPos() and s = TNeg() or + this = TZero() and result = s + or + s = TZero() and result = this + or + this = s and this = result + or + this = TPos() and s = TNeg() + or this = TNeg() and s = TPos() } + Sign mul(Sign s) { - result = TZero() and this = TZero() or - result = TZero() and s = TZero() or - result = TNeg() and this = TPos() and s = TNeg() or - result = TNeg() and this = TNeg() and s = TPos() or - result = TPos() and this = TPos() and s = TPos() or + result = TZero() and this = TZero() + or + result = TZero() and s = TZero() + or + result = TNeg() and this = TPos() and s = TNeg() + or + result = TNeg() and this = TNeg() and s = TPos() + or + result = TPos() and this = TPos() and s = TPos() + or result = TPos() and this = TNeg() and s = TNeg() } + Sign div(Sign s) { - result = TZero() and s = TNeg() or - result = TZero() and s = TPos() or - result = TNeg() and this = TPos() and s = TNeg() or - result = TNeg() and this = TNeg() and s = TPos() or - result = TPos() and this = TPos() and s = TPos() or + result = TZero() and s = TNeg() + or + result = TZero() and s = TPos() + or + result = TNeg() and this = TPos() and s = TNeg() + or + result = TNeg() and this = TNeg() and s = TPos() + or + result = TPos() and this = TPos() and s = TPos() + or result = TPos() and this = TNeg() and s = TNeg() } + Sign rem(Sign s) { - result = TZero() and s = TNeg() or - result = TZero() and s = TPos() or - result = this and s = TNeg() or + result = TZero() and s = TNeg() + or + result = TZero() and s = TPos() + or + result = this and s = TNeg() + or result = this and s = TPos() } + Sign bitand(Sign s) { - result = TZero() and this = TZero() or - result = TZero() and s = TZero() or - result = TZero() and this = TPos() or - result = TZero() and s = TPos() or - result = TNeg() and this = TNeg() and s = TNeg() or - result = TPos() and this = TNeg() and s = TPos() or - result = TPos() and this = TPos() and s = TNeg() or + result = TZero() and this = TZero() + or + result = TZero() and s = TZero() + or + result = TZero() and this = TPos() + or + result = TZero() and s = TPos() + or + result = TNeg() and this = TNeg() and s = TNeg() + or + result = TPos() and this = TNeg() and s = TPos() + or + result = TPos() and this = TPos() and s = TNeg() + or result = TPos() and this = TPos() and s = TPos() } + Sign bitor(Sign s) { - result = TZero() and this = TZero() and s = TZero() or - result = TNeg() and this = TNeg() or - result = TNeg() and s = TNeg() or - result = TPos() and this = TPos() and s = TZero() or - result = TPos() and this = TZero() and s = TPos() or + result = TZero() and this = TZero() and s = TZero() + or + result = TNeg() and this = TNeg() + or + result = TNeg() and s = TNeg() + or + result = TPos() and this = TPos() and s = TZero() + or + result = TPos() and this = TZero() and s = TPos() + or result = TPos() and this = TPos() and s = TPos() } + Sign bitxor(Sign s) { - result = TZero() and this = s or - result = this and s = TZero() or - result = s and this = TZero() or - result = TPos() and this = TPos() and s = TPos() or - result = TNeg() and this = TNeg() and s = TPos() or - result = TNeg() and this = TPos() and s = TNeg() or + result = TZero() and this = s + or + result = this and s = TZero() + or + result = s and this = TZero() + or + result = TPos() and this = TPos() and s = TPos() + or + result = TNeg() and this = TNeg() and s = TPos() + or + result = TNeg() and this = TPos() and s = TNeg() + or result = TPos() and this = TNeg() and s = TNeg() } + Sign lshift(Sign s) { - result = TZero() and this = TZero() or - result = this and s = TZero() or + result = TZero() and this = TZero() + or + result = this and s = TZero() + or this != TZero() and s != TZero() } + Sign rshift(Sign s) { - result = TZero() and this = TZero() or - result = this and s = TZero() or - result = TNeg() and this = TNeg() or + result = TZero() and this = TZero() + or + result = this and s = TZero() + or + result = TNeg() and this = TNeg() + or result != TNeg() and this = TPos() and s != TZero() } + Sign urshift(Sign s) { - result = TZero() and this = TZero() or - result = this and s = TZero() or - result != TZero() and this = TNeg() and s != TZero() or + result = TZero() and this = TZero() + or + result = this and s = TZero() + or + result != TZero() and this = TNeg() and s != TZero() + or result != TNeg() and this = TPos() and s != TZero() } } private Sign certainInstructionSign(Instruction inst) { exists(int i | inst.(IntegerConstantInstruction).getValue().toInt() = i | - i < 0 and result = TNeg() or - i = 0 and result = TZero() or + i < 0 and result = TNeg() + or + i = 0 and result = TZero() + or i > 0 and result = TPos() ) or exists(float f | f = inst.(FloatConstantInstruction).getValue().toFloat() | - f < 0 and result = TNeg() or - f = 0 and result = TZero() or + f < 0 and result = TNeg() + or + f = 0 and result = TZero() + or f > 0 and result = TPos() ) } -private newtype CastKind = TWiden() or TSame() or TNarrow() +private newtype CastKind = + TWiden() or + TSame() or + TNarrow() private CastKind getCastKind(ConvertInstruction ci) { exists(int fromSize, int toSize | toSize = ci.getResultSize() and fromSize = ci.getUnary().getResultSize() - | + | fromSize < toSize and result = TWiden() or @@ -219,7 +296,9 @@ private predicate unknownSign(Instruction i) { * Holds if `lowerbound` is a lower bound for `bounded`. This is restricted * to only include bounds for which we might determine a sign. */ -private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict) { +private predicate lowerBound( + IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict +) { exists(int adjustment, Operand compared | valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and ( @@ -228,17 +307,18 @@ private predicate lowerBound(IRGuardCondition comp, Operand lowerbound, Operand or isStrict = false and adjustment = 1 - ) and + ) and comp.ensuresLt(lowerbound, compared, adjustment, bounded.getUse().getBlock(), true) ) } - /** * Holds if `upperbound` is an upper bound for `bounded` at `pos`. This is restricted * to only include bounds for which we might determine a sign. */ -private predicate upperBound(IRGuardCondition comp, Operand upperbound, Operand bounded, boolean isStrict) { +private predicate upperBound( + IRGuardCondition comp, Operand upperbound, Operand bounded, boolean isStrict +) { exists(int adjustment, Operand compared | valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and ( @@ -266,8 +346,6 @@ private predicate eqBound(IRGuardCondition guard, Operand eqbound, Operand bound ) } - - /** * Holds if `bound` is a bound for `v` at `pos` that needs to be positive in * order for `v` to be positive. @@ -308,21 +386,22 @@ private predicate negBoundOk(IRGuardCondition comp, Operand bound, Operand op) { /** Holds if `bound` allows `v` to be zero at `pos`. */ private predicate zeroBoundOk(IRGuardCondition comp, Operand bound, Operand op) { - lowerBound(comp, bound, op, _) and TNeg() = operandSign(bound) or - lowerBound(comp, bound, op, false) and TZero() = operandSign(bound) or - upperBound(comp, bound, op, _) and TPos() = operandSign(bound) or - upperBound(comp, bound, op, false) and TZero() = operandSign(bound) or - eqBound(comp, bound, op, true) and TZero() = operandSign(bound) or + lowerBound(comp, bound, op, _) and TNeg() = operandSign(bound) + or + lowerBound(comp, bound, op, false) and TZero() = operandSign(bound) + or + upperBound(comp, bound, op, _) and TPos() = operandSign(bound) + or + upperBound(comp, bound, op, false) and TZero() = operandSign(bound) + or + eqBound(comp, bound, op, true) and TZero() = operandSign(bound) + or eqBound(comp, bound, op, false) and TZero() != operandSign(bound) } -private Sign binaryOpLhsSign(BinaryInstruction i) { - result = operandSign(i.getLeftOperand()) -} +private Sign binaryOpLhsSign(BinaryInstruction i) { result = operandSign(i.getLeftOperand()) } -private Sign binaryOpRhsSign(BinaryInstruction i) { - result = operandSign(i.getRightOperand()) -} +private Sign binaryOpRhsSign(BinaryInstruction i) { result = operandSign(i.getRightOperand()) } pragma[noinline] private predicate binaryOpSigns(BinaryInstruction i, Sign lhs, Sign rhs) { @@ -341,9 +420,20 @@ private Sign guardedOperandSign(Operand operand) { } private Sign guardedOperandSignOk(Operand operand) { - result = TPos() and forex(IRGuardCondition guard, Operand bound | posBound(guard, bound, operand) | posBoundOk(guard, bound, operand)) or - result = TNeg() and forex(IRGuardCondition guard, Operand bound | negBound(guard, bound, operand) | negBoundOk(guard, bound, operand)) or - result = TZero() and forex(IRGuardCondition guard, Operand bound | zeroBound(guard, bound, operand) | zeroBoundOk(guard, bound, operand)) + result = TPos() and + forex(IRGuardCondition guard, Operand bound | posBound(guard, bound, operand) | + posBoundOk(guard, bound, operand) + ) + or + result = TNeg() and + forex(IRGuardCondition guard, Operand bound | negBound(guard, bound, operand) | + negBoundOk(guard, bound, operand) + ) + or + result = TZero() and + forex(IRGuardCondition guard, Operand bound | zeroBound(guard, bound, operand) | + zeroBoundOk(guard, bound, operand) + ) } /** @@ -351,14 +441,15 @@ private Sign guardedOperandSignOk(Operand operand) { * at `pos`. */ private predicate hasGuard(Operand op, Sign s) { - s = TPos() and posBound(_, _, op) - or - s = TNeg() and negBound(_, _, op) - or - s = TZero() and zeroBound(_, _, op) + s = TPos() and posBound(_, _, op) + or + s = TNeg() and negBound(_, _, op) + or + s = TZero() and zeroBound(_, _, op) } -cached module SignAnalysisCached { +cached +module SignAnalysisCached { /** * Gets a sign that `operand` may have at `pos`, taking guards into account. */ @@ -372,7 +463,7 @@ cached module SignAnalysisCached { // `result` is unconstrained if the definition is inexact. Then any sign is possible. operand.isDefinitionInexact() } - + cached Sign instructionSign(Instruction i) { result = certainInstructionSign(i) @@ -388,11 +479,7 @@ cached module SignAnalysisCached { exists(ConvertInstruction ci, Instruction prior, boolean fromSigned, boolean toSigned | i = ci and prior = ci.getUnary() and - ( - if ci.getResultType().(IntegralType).isSigned() - then toSigned = true - else toSigned = false - ) and + (if ci.getResultType().(IntegralType).isSigned() then toSigned = true else toSigned = false) and ( if prior.getResultType().(IntegralType).isSigned() then fromSigned = true @@ -407,9 +494,7 @@ cached module SignAnalysisCached { or result = operandSign(i.(NegateInstruction).getAnOperand()).neg() or - exists(Sign s1, Sign s2 | - binaryOpSigns(i, s1, s2) - | + exists(Sign s1, Sign s2 | binaryOpSigns(i, s1, s2) | i instanceof AddInstruction and result = s1.add(s2) or i instanceof SubInstruction and result = s1.add(s2.neg()) @@ -480,6 +565,7 @@ predicate strictlyPositive(Operand op) { not operandSign(op) = TNeg() and not operandSign(op) = TZero() } + /** Holds if `i` is strictly negative. */ predicate strictlyNegativeInstruction(Instruction i) { instructionSign(i) = TNeg() and diff --git a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll index c0edeb7d59b..b7b646d5c8a 100644 --- a/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll @@ -41,6 +41,7 @@ * and negative overflow by looking for bounds that are outside the range * of the type. */ + import cpp private import RangeAnalysisUtils import RangeSSA @@ -57,8 +58,7 @@ private import NanAnalysis * bounds to the set if it helps on specific examples and does not make * performance dramatically worse on large codebases, such as libreoffice. */ -private -float wideningLowerBounds(ArithmeticType t) { +private float wideningLowerBounds(ArithmeticType t) { result = 2.0 or result = 1.0 or result = 0.0 or @@ -71,12 +71,11 @@ float wideningLowerBounds(ArithmeticType t) { result = -32768.0 or result = -65536.0 or result = typeLowerBound(t) or - result = -(1.0/0.0) // -Inf + result = -(1.0 / 0.0) // -Inf } /** See comment for `wideningLowerBounds`, above. */ -private -float wideningUpperBounds(ArithmeticType t) { +private float wideningUpperBounds(ArithmeticType t) { result = -2.0 or result = -1.0 or result = 0.0 or @@ -89,41 +88,40 @@ float wideningUpperBounds(ArithmeticType t) { result = 32767.0 or result = 65535.0 or result = typeUpperBound(t) or - result = 1.0/0.0 // +Inf + result = 1.0 / 0.0 // +Inf } /** Set of expressions which we know how to analyze. */ -private -predicate analyzableExpr(Expr e) { +private predicate analyzableExpr(Expr e) { // The type of the expression must be arithmetic. We reuse the logic in // `exprMinVal` to check this. - exists (exprMinVal(e)) and - ((exists (e.getValue().toFloat())) or - (e instanceof UnaryPlusExpr) or - (e instanceof UnaryMinusExpr) or - (e instanceof MinExpr) or - (e instanceof MaxExpr) or - (e instanceof ConditionalExpr) or - (e instanceof AddExpr) or - (e instanceof SubExpr) or - (e instanceof AssignExpr) or - (e instanceof AssignAddExpr) or - (e instanceof AssignSubExpr) or - (e instanceof CrementOperation) or - (e instanceof RemExpr) or - (e instanceof CommaExpr) or - (e instanceof StmtExpr) or - - // A conversion is analyzable, provided that its child has an arithmetic - // type. (Sometimes the child is a reference type, and so does not get - // any bounds.) Rather than checking whether the type of the child is - // arithmetic, we reuse the logic that is already encoded in - // `exprMinVal`. - exists(exprMinVal(e.(Conversion).getExpr())) or - - // Also allow variable accesses, provided that they have SSA - // information. - exists (RangeSsaDefinition def, LocalScopeVariable v | e = def.getAUse(v))) + exists(exprMinVal(e)) and + ( + exists(e.getValue().toFloat()) or + e instanceof UnaryPlusExpr or + e instanceof UnaryMinusExpr or + e instanceof MinExpr or + e instanceof MaxExpr or + e instanceof ConditionalExpr or + e instanceof AddExpr or + e instanceof SubExpr or + e instanceof AssignExpr or + e instanceof AssignAddExpr or + e instanceof AssignSubExpr or + e instanceof CrementOperation or + e instanceof RemExpr or + e instanceof CommaExpr or + e instanceof StmtExpr or + // A conversion is analyzable, provided that its child has an arithmetic + // type. (Sometimes the child is a reference type, and so does not get + // any bounds.) Rather than checking whether the type of the child is + // arithmetic, we reuse the logic that is already encoded in + // `exprMinVal`. + exists(exprMinVal(e.(Conversion).getExpr())) or + // Also allow variable accesses, provided that they have SSA + // information. + exists(RangeSsaDefinition def, LocalScopeVariable v | e = def.getAUse(v)) + ) } /** @@ -137,34 +135,33 @@ predicate analyzableExpr(Expr e) { * of the main analysis algorithm then matching changes need to be made * here. */ -private -predicate defDependsOnDef( - RangeSsaDefinition def, LocalScopeVariable v, - RangeSsaDefinition srcDef, LocalScopeVariable srcVar +private predicate defDependsOnDef( + RangeSsaDefinition def, LocalScopeVariable v, RangeSsaDefinition srcDef, LocalScopeVariable srcVar ) { // Definitions with a defining value. - exists (Expr expr - | assignmentDef(def, v, expr) - | exprDependsOnDef(expr, srcDef, srcVar)) + exists(Expr expr | assignmentDef(def, v, expr) | exprDependsOnDef(expr, srcDef, srcVar)) or - exists ( - AssignAddExpr assignAdd, RangeSsaDefinition nextDef - | def = assignAdd and + exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef | + def = assignAdd and assignAdd.getLValue() = nextDef.getAUse(v) - | defDependsOnDef(nextDef, v, srcDef, srcVar) or - exprDependsOnDef(assignAdd.getRValue(), srcDef, srcVar)) + | + defDependsOnDef(nextDef, v, srcDef, srcVar) or + exprDependsOnDef(assignAdd.getRValue(), srcDef, srcVar) + ) or - exists ( - AssignSubExpr assignSub, RangeSsaDefinition nextDef - | def = assignSub and + exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef | + def = assignSub and assignSub.getLValue() = nextDef.getAUse(v) - | defDependsOnDef(nextDef, v, srcDef, srcVar) or - exprDependsOnDef(assignSub.getRValue(), srcDef, srcVar)) + | + defDependsOnDef(nextDef, v, srcDef, srcVar) or + exprDependsOnDef(assignSub.getRValue(), srcDef, srcVar) + ) or - exists (CrementOperation crem - | def = crem and + exists(CrementOperation crem | + def = crem and crem.getOperand() = v.getAnAccess() and - exprDependsOnDef(crem.getOperand(), srcDef, srcVar)) + exprDependsOnDef(crem.getOperand(), srcDef, srcVar) + ) or // Phi nodes. phiDependsOnDef(def, v, srcDef, srcVar) @@ -174,69 +171,52 @@ predicate defDependsOnDef( * Helper predicate for `defDependsOnDef`. This predicate matches * the structure of `getLowerBoundsImpl` and `getUpperBoundsImpl`. */ -private -predicate exprDependsOnDef( - Expr e, RangeSsaDefinition srcDef, LocalScopeVariable srcVar -) { - exists (UnaryMinusExpr negateExpr - | e = negateExpr - | exprDependsOnDef(negateExpr.getOperand(), srcDef, srcVar)) +private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, LocalScopeVariable srcVar) { + exists(UnaryMinusExpr negateExpr | e = negateExpr | + exprDependsOnDef(negateExpr.getOperand(), srcDef, srcVar) + ) or - exists (UnaryPlusExpr plusExpr - | e = plusExpr - | exprDependsOnDef(plusExpr.getOperand(), srcDef, srcVar)) + exists(UnaryPlusExpr plusExpr | e = plusExpr | + exprDependsOnDef(plusExpr.getOperand(), srcDef, srcVar) + ) or - exists (MinExpr minExpr - | e = minExpr - | exprDependsOnDef(minExpr.getAnOperand(), srcDef, srcVar)) + exists(MinExpr minExpr | e = minExpr | exprDependsOnDef(minExpr.getAnOperand(), srcDef, srcVar)) or - exists (MaxExpr maxExpr - | e = maxExpr - | exprDependsOnDef(maxExpr.getAnOperand(), srcDef, srcVar)) + exists(MaxExpr maxExpr | e = maxExpr | exprDependsOnDef(maxExpr.getAnOperand(), srcDef, srcVar)) or - exists (ConditionalExpr condExpr - | e = condExpr - | exprDependsOnDef(condExpr.getAnOperand(), srcDef, srcVar)) + exists(ConditionalExpr condExpr | e = condExpr | + exprDependsOnDef(condExpr.getAnOperand(), srcDef, srcVar) + ) or - exists (AddExpr addExpr - | e = addExpr - | exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar)) + exists(AddExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar)) or - exists (SubExpr subExpr - | e = subExpr - | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) + exists(SubExpr subExpr | e = subExpr | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) or - exists (AssignExpr addExpr - | e = addExpr - | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar)) + exists(AssignExpr addExpr | e = addExpr | exprDependsOnDef(addExpr.getRValue(), srcDef, srcVar)) or - exists (AssignAddExpr addExpr - | e = addExpr - | exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar)) + exists(AssignAddExpr addExpr | e = addExpr | + exprDependsOnDef(addExpr.getAnOperand(), srcDef, srcVar) + ) or - exists (AssignSubExpr subExpr - | e = subExpr - | exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar)) + exists(AssignSubExpr subExpr | e = subExpr | + exprDependsOnDef(subExpr.getAnOperand(), srcDef, srcVar) + ) or - exists (CrementOperation crementExpr - | e = crementExpr - | exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar)) + exists(CrementOperation crementExpr | e = crementExpr | + exprDependsOnDef(crementExpr.getOperand(), srcDef, srcVar) + ) or - exists (RemExpr remExpr - | e = remExpr - | exprDependsOnDef(remExpr.getAnOperand(), srcDef, srcVar)) + exists(RemExpr remExpr | e = remExpr | exprDependsOnDef(remExpr.getAnOperand(), srcDef, srcVar)) or - exists (CommaExpr commaExpr - | e = commaExpr - | exprDependsOnDef(commaExpr.getRightOperand(), srcDef, srcVar)) + exists(CommaExpr commaExpr | e = commaExpr | + exprDependsOnDef(commaExpr.getRightOperand(), srcDef, srcVar) + ) or - exists (StmtExpr stmtExpr - | e = stmtExpr - | exprDependsOnDef(stmtExpr.getResultExpr(), srcDef, srcVar)) + exists(StmtExpr stmtExpr | e = stmtExpr | + exprDependsOnDef(stmtExpr.getResultExpr(), srcDef, srcVar) + ) or - exists (Conversion convExpr - | e = convExpr - | exprDependsOnDef(convExpr.getExpr(), srcDef, srcVar)) + exists(Conversion convExpr | e = convExpr | exprDependsOnDef(convExpr.getExpr(), srcDef, srcVar)) or e = srcDef.getAUse(srcVar) } @@ -245,35 +225,35 @@ predicate exprDependsOnDef( * Helper predicate for `defDependsOnDef`. This predicate matches * the structure of `getPhiLowerBounds` and `getPhiUpperBounds`. */ -private -predicate phiDependsOnDef( - RangeSsaDefinition phi, LocalScopeVariable v, - RangeSsaDefinition srcDef, LocalScopeVariable srcVar +private predicate phiDependsOnDef( + RangeSsaDefinition phi, LocalScopeVariable v, RangeSsaDefinition srcDef, LocalScopeVariable srcVar ) { - exists (VariableAccess access, ComparisonOperation guard - | access = v.getAnAccess() and + exists(VariableAccess access, ComparisonOperation guard | + access = v.getAnAccess() and phi.isGuardPhi(access, guard, _) - | exprDependsOnDef(guard.getAnOperand(), srcDef, srcVar) or - exprDependsOnDef(access, srcDef, srcVar)) + | + exprDependsOnDef(guard.getAnOperand(), srcDef, srcVar) or + exprDependsOnDef(access, srcDef, srcVar) + ) or - (srcDef = phi.getAPhiInput(v) and srcVar = v) + srcDef = phi.getAPhiInput(v) and srcVar = v } /** The transitive closure of `defDependsOnDef`. */ -private -predicate defDependsOnDefTransitively( - RangeSsaDefinition def, LocalScopeVariable v, - RangeSsaDefinition srcDef, LocalScopeVariable srcVar +private predicate defDependsOnDefTransitively( + RangeSsaDefinition def, LocalScopeVariable v, RangeSsaDefinition srcDef, LocalScopeVariable srcVar ) { - defDependsOnDef(def, v, srcDef, srcVar) or - exists (RangeSsaDefinition midDef, LocalScopeVariable midVar - | defDependsOnDef(def, v, midDef, midVar) - | defDependsOnDefTransitively(midDef, midVar, srcDef, srcVar)) + defDependsOnDef(def, v, srcDef, srcVar) + or + exists(RangeSsaDefinition midDef, LocalScopeVariable midVar | + defDependsOnDef(def, v, midDef, midVar) + | + defDependsOnDefTransitively(midDef, midVar, srcDef, srcVar) + ) } /** The set of definitions that depend recursively on themselves. */ -private -predicate isRecursiveDef(RangeSsaDefinition def, LocalScopeVariable v) { +private predicate isRecursiveDef(RangeSsaDefinition def, LocalScopeVariable v) { defDependsOnDefTransitively(def, v, def, v) } @@ -291,21 +271,21 @@ predicate isRecursiveDef(RangeSsaDefinition def, LocalScopeVariable v) { * * This predicate finds all the definitions in the first set. */ -private -predicate assignmentDef(RangeSsaDefinition def, LocalScopeVariable v, Expr expr) { - v.getUnspecifiedType() instanceof ArithmeticType - and - ((def = v.getInitializer().getExpr() and def = expr) - or - exists(AssignExpr assign - | def = assign and - assign.getLValue() = v.getAnAccess() and - expr = assign.getRValue())) +private predicate assignmentDef(RangeSsaDefinition def, LocalScopeVariable v, Expr expr) { + v.getUnspecifiedType() instanceof ArithmeticType and + ( + def = v.getInitializer().getExpr() and def = expr + or + exists(AssignExpr assign | + def = assign and + assign.getLValue() = v.getAnAccess() and + expr = assign.getRValue() + ) + ) } /** See comment above sourceDef. */ -private -predicate analyzableDef(RangeSsaDefinition def, LocalScopeVariable v) { +private predicate analyzableDef(RangeSsaDefinition def, LocalScopeVariable v) { assignmentDef(def, v, _) or defDependsOnDef(def, v, _, _) } @@ -316,9 +296,7 @@ predicate analyzableDef(RangeSsaDefinition def, LocalScopeVariable v) { * comparisons but instead defines -0.0 to be less than and distinct from 0.0. */ bindingset[x] -private float normalizeFloatUp(float x) { - result = x + 0.0 -} +private float normalizeFloatUp(float x) { result = x + 0.0 } /** * Computes `x + y`, rounded towards +Inf. This is the general case where both @@ -348,9 +326,7 @@ private float addRoundingDown(float x, float y) { */ bindingset[x, small] private float addRoundingUpSmall(float x, float small) { - if (x + small) - x < small - then result = (x + small).nextUp() - else result = (x + small) + if (x + small) - x < small then result = (x + small).nextUp() else result = (x + small) } /** @@ -359,16 +335,13 @@ private float addRoundingUpSmall(float x, float small) { */ bindingset[x, small] private float addRoundingDownSmall(float x, float small) { - if (x + small) - x > small - then result = (x + small).nextDown() - else result = (x + small) + if (x + small) - x > small then result = (x + small).nextDown() else result = (x + small) } /** * Gets the truncated lower bounds of the fully converted expression. */ -private -float getFullyConvertedLowerBounds(Expr expr) { +private float getFullyConvertedLowerBounds(Expr expr) { result = getTruncatedLowerBounds(expr.getFullyConverted()) } @@ -389,37 +362,39 @@ float getFullyConvertedLowerBounds(Expr expr) { * Note: most callers should use `getFullyConvertedLowerBounds` rather than * this predicate. */ -private -float getTruncatedLowerBounds(Expr expr) { +private float getTruncatedLowerBounds(Expr expr) { if analyzableExpr(expr) - then // If the expression evaluates to a constant, then there is no - // need to call getLowerBoundsImpl. - if exists(expr.getValue().toFloat()) - then result = expr.getValue().toFloat() - else (// Some of the bounds computed by getLowerBoundsImpl might - // overflow, so we replace invalid bounds with exprMinVal. - exists (float newLB - | newLB = getLowerBoundsImpl(expr) - | if exprMinVal(expr) <= newLB and newLB <= exprMaxVal(expr) - then result = newLB - else result = exprMinVal(expr)) - or - // The expression might overflow and wrap. If so, the - // lower bound is exprMinVal. - (exprMightOverflowPositively(expr) and - result = exprMinVal(expr))) - else // The expression is not analyzable, so its lower bound is - // unknown. Note that the call to exprMinVal restricts the - // expressions to just those with arithmetic types. There is no - // need to return results for non-arithmetic expressions. - result = exprMinVal(expr) + then + // If the expression evaluates to a constant, then there is no + // need to call getLowerBoundsImpl. + if exists(expr.getValue().toFloat()) + then result = expr.getValue().toFloat() + else ( + // Some of the bounds computed by getLowerBoundsImpl might + // overflow, so we replace invalid bounds with exprMinVal. + exists(float newLB | newLB = getLowerBoundsImpl(expr) | + if exprMinVal(expr) <= newLB and newLB <= exprMaxVal(expr) + then result = newLB + else result = exprMinVal(expr) + ) + or + // The expression might overflow and wrap. If so, the + // lower bound is exprMinVal. + exprMightOverflowPositively(expr) and + result = exprMinVal(expr) + ) + else + // The expression is not analyzable, so its lower bound is + // unknown. Note that the call to exprMinVal restricts the + // expressions to just those with arithmetic types. There is no + // need to return results for non-arithmetic expressions. + result = exprMinVal(expr) } /** * Gets the truncated upper bounds of the fully converted expression. */ -private -float getFullyConvertedUpperBounds(Expr expr) { +private float getFullyConvertedUpperBounds(Expr expr) { result = getTruncatedUpperBounds(expr.getFullyConverted()) } @@ -440,31 +415,34 @@ float getFullyConvertedUpperBounds(Expr expr) { * Note: most callers should use `getFullyConvertedUpperBounds` rather than * this predicate. */ -private -float getTruncatedUpperBounds(Expr expr) { +private float getTruncatedUpperBounds(Expr expr) { if analyzableExpr(expr) - then // If the expression evaluates to a constant, then there is no - // need to call getUpperBoundsImpl. - if exists(expr.getValue().toFloat()) - then result = expr.getValue().toFloat() - else (// Some of the bounds computed by `getUpperBoundsImpl` - // might overflow, so we replace invalid bounds with - // `exprMaxVal`. - exists (float newUB - | newUB = getUpperBoundsImpl(expr) - | if exprMinVal(expr) <= newUB and newUB <= exprMaxVal(expr) - then result = newUB - else result = exprMaxVal(expr)) - or - // The expression might overflow negatively and wrap. If so, - // the upper bound is `exprMaxVal`. - (exprMightOverflowNegatively(expr) and - result = exprMaxVal(expr))) - else // The expression is not analyzable, so its upper bound is - // unknown. Note that the call to exprMaxVal restricts the - // expressions to just those with arithmetic types. There is no - // need to return results for non-arithmetic expressions. - result = exprMaxVal(expr) + then + // If the expression evaluates to a constant, then there is no + // need to call getUpperBoundsImpl. + if exists(expr.getValue().toFloat()) + then result = expr.getValue().toFloat() + else ( + // Some of the bounds computed by `getUpperBoundsImpl` + // might overflow, so we replace invalid bounds with + // `exprMaxVal`. + exists(float newUB | newUB = getUpperBoundsImpl(expr) | + if exprMinVal(expr) <= newUB and newUB <= exprMaxVal(expr) + then result = newUB + else result = exprMaxVal(expr) + ) + or + // The expression might overflow negatively and wrap. If so, + // the upper bound is `exprMaxVal`. + exprMightOverflowNegatively(expr) and + result = exprMaxVal(expr) + ) + else + // The expression is not analyzable, so its upper bound is + // unknown. Note that the call to exprMaxVal restricts the + // expressions to just those with arithmetic types. There is no + // need to return results for non-arithmetic expressions. + result = exprMaxVal(expr) } /** @@ -474,10 +452,7 @@ float getTruncatedUpperBounds(Expr expr) { * * DEPRECATED: use `exprMightOverflowNegatively` instead. */ -deprecated predicate negative_overflow(Expr expr) { - exprMightOverflowNegatively(expr) -} - +deprecated predicate negative_overflow(Expr expr) { exprMightOverflowNegatively(expr) } /** * Holds if the expression might overflow positively. This predicate @@ -486,280 +461,314 @@ deprecated predicate negative_overflow(Expr expr) { * * DEPRECATED: use `exprMightOverflowPositively` instead. */ -deprecated predicate positive_overflow(Expr expr) { - exprMightOverflowPositively(expr) -} +deprecated predicate positive_overflow(Expr expr) { exprMightOverflowPositively(expr) } /** Only to be called by `getTruncatedLowerBounds`. */ -private -float getLowerBoundsImpl(Expr expr) { - exists (UnaryPlusExpr plusExpr - | expr = plusExpr and - result = getFullyConvertedLowerBounds(plusExpr.getOperand()) ) +private float getLowerBoundsImpl(Expr expr) { + exists(UnaryPlusExpr plusExpr | + expr = plusExpr and + result = getFullyConvertedLowerBounds(plusExpr.getOperand()) + ) or - exists (UnaryMinusExpr negateExpr, float xHigh - | expr = negateExpr and + exists(UnaryMinusExpr negateExpr, float xHigh | + expr = negateExpr and xHigh = getFullyConvertedUpperBounds(negateExpr.getOperand()) and - result = -xHigh) + result = -xHigh + ) or - exists (MinExpr minExpr - | expr = minExpr and + exists(MinExpr minExpr | + expr = minExpr and // Return the union of the lower bounds from both children. - result = getFullyConvertedLowerBounds(minExpr.getAnOperand())) + result = getFullyConvertedLowerBounds(minExpr.getAnOperand()) + ) or - exists (MaxExpr maxExpr - | expr = maxExpr and + exists(MaxExpr maxExpr | + expr = maxExpr and // Compute the cross product of the bounds from both children. We are // using this mathematical property: // // max (minimum{X}, minimum{Y}) // = minimum { max(x,y) | x in X, y in Y } - exists (float x, float y - | x = getFullyConvertedLowerBounds(maxExpr.getLeftOperand()) and + exists(float x, float y | + x = getFullyConvertedLowerBounds(maxExpr.getLeftOperand()) and y = getFullyConvertedLowerBounds(maxExpr.getRightOperand()) and - if x >= y - then result = x - else result = y)) + if x >= y then result = x else result = y + ) + ) or // ConditionalExpr (true branch) - exists (ConditionalExpr condExpr - | expr = condExpr and + exists(ConditionalExpr condExpr | + expr = condExpr and // Use `boolConversionUpperBound` to determine whether the condition // might evaluate to `true`. boolConversionUpperBound(condExpr.getCondition().getFullyConverted()) = 1 and - result = getFullyConvertedLowerBounds(condExpr.getThen())) + result = getFullyConvertedLowerBounds(condExpr.getThen()) + ) or // ConditionalExpr (false branch) - exists (ConditionalExpr condExpr - | expr = condExpr and + exists(ConditionalExpr condExpr | + expr = condExpr and // Use `boolConversionLowerBound` to determine whether the condition // might evaluate to `false`. boolConversionLowerBound(condExpr.getCondition().getFullyConverted()) = 0 and - result = getFullyConvertedLowerBounds(condExpr.getElse())) + result = getFullyConvertedLowerBounds(condExpr.getElse()) + ) or - exists (AddExpr addExpr, float xLow, float yLow - | expr = addExpr and + exists(AddExpr addExpr, float xLow, float yLow | + expr = addExpr and xLow = getFullyConvertedLowerBounds(addExpr.getLeftOperand()) and yLow = getFullyConvertedLowerBounds(addExpr.getRightOperand()) and - result = addRoundingDown(xLow, yLow)) + result = addRoundingDown(xLow, yLow) + ) or - exists (SubExpr subExpr, float xLow, float yHigh - | expr = subExpr and + exists(SubExpr subExpr, float xLow, float yHigh | + expr = subExpr and xLow = getFullyConvertedLowerBounds(subExpr.getLeftOperand()) and yHigh = getFullyConvertedUpperBounds(subExpr.getRightOperand()) and - result = addRoundingDown(xLow, -yHigh)) + result = addRoundingDown(xLow, -yHigh) + ) or - exists (AssignExpr assign - | expr = assign and - result = getFullyConvertedLowerBounds(assign.getRValue())) + exists(AssignExpr assign | + expr = assign and + result = getFullyConvertedLowerBounds(assign.getRValue()) + ) or - exists (AssignAddExpr addExpr, float xLow, float yLow - | expr = addExpr and + exists(AssignAddExpr addExpr, float xLow, float yLow | + expr = addExpr and xLow = getFullyConvertedLowerBounds(addExpr.getLValue()) and yLow = getFullyConvertedLowerBounds(addExpr.getRValue()) and - result = addRoundingDown(xLow, yLow)) + result = addRoundingDown(xLow, yLow) + ) or - exists (AssignSubExpr subExpr, float xLow, float yHigh - | expr = subExpr and + exists(AssignSubExpr subExpr, float xLow, float yHigh | + expr = subExpr and xLow = getFullyConvertedLowerBounds(subExpr.getLValue()) and yHigh = getFullyConvertedUpperBounds(subExpr.getRValue()) and - result = addRoundingDown(xLow, -yHigh)) + result = addRoundingDown(xLow, -yHigh) + ) or - exists (PrefixIncrExpr incrExpr, float xLow - | expr = incrExpr and + exists(PrefixIncrExpr incrExpr, float xLow | + expr = incrExpr and xLow = getFullyConvertedLowerBounds(incrExpr.getOperand()) and - result = xLow+1) + result = xLow + 1 + ) or - exists (PrefixDecrExpr decrExpr, float xLow - | expr = decrExpr and + exists(PrefixDecrExpr decrExpr, float xLow | + expr = decrExpr and xLow = getFullyConvertedLowerBounds(decrExpr.getOperand()) and - result = addRoundingDownSmall(xLow, -1)) + result = addRoundingDownSmall(xLow, -1) + ) or // `PostfixIncrExpr` and `PostfixDecrExpr` return the value of their // operand. The incrementing/decrementing behavior is handled in // `getDefLowerBoundsImpl`. - exists (PostfixIncrExpr incrExpr - | expr = incrExpr and - result = getFullyConvertedLowerBounds(incrExpr.getOperand())) + exists(PostfixIncrExpr incrExpr | + expr = incrExpr and + result = getFullyConvertedLowerBounds(incrExpr.getOperand()) + ) or - exists (PostfixDecrExpr decrExpr - | expr = decrExpr and - result = getFullyConvertedLowerBounds(decrExpr.getOperand())) + exists(PostfixDecrExpr decrExpr | + expr = decrExpr and + result = getFullyConvertedLowerBounds(decrExpr.getOperand()) + ) or - exists (RemExpr remExpr - | expr = remExpr - | // If both inputs are positive then the lower bound is zero. + exists(RemExpr remExpr | expr = remExpr | + // If both inputs are positive then the lower bound is zero. result = 0 or // If either input could be negative then the output could be // negative. If so, the lower bound of `x%y` is `-abs(y)`, which is // equal to `min(-y,y)`. - exists(float childLB - | childLB = getFullyConvertedLowerBounds(remExpr.getAnOperand()) and - not (childLB >= 0) - | result = getFullyConvertedLowerBounds(remExpr.getRightOperand()) + exists(float childLB | + childLB = getFullyConvertedLowerBounds(remExpr.getAnOperand()) and + not childLB >= 0 + | + result = getFullyConvertedLowerBounds(remExpr.getRightOperand()) or - exists(float rhsUB - | rhsUB = getFullyConvertedUpperBounds(remExpr.getRightOperand()) - | result = -rhsUB))) + exists(float rhsUB | rhsUB = getFullyConvertedUpperBounds(remExpr.getRightOperand()) | + result = -rhsUB + ) + ) + ) or - exists (CommaExpr commaExpr - | expr = commaExpr and - result = getFullyConvertedLowerBounds(commaExpr.getRightOperand())) + exists(CommaExpr commaExpr | + expr = commaExpr and + result = getFullyConvertedLowerBounds(commaExpr.getRightOperand()) + ) or - exists (StmtExpr stmtExpr - | expr = stmtExpr and - result = getFullyConvertedLowerBounds(stmtExpr.getResultExpr())) + exists(StmtExpr stmtExpr | + expr = stmtExpr and + result = getFullyConvertedLowerBounds(stmtExpr.getResultExpr()) + ) or // If the conversion is to an arithmetic type then we just return the // lower bound of the child. We do not need to handle truncation and // overflow here, because that is done in `getTruncatedLowerBounds`. // Conversions to `bool` need to be handled specially because they test // whether the value of the expression is equal to 0. - exists (Conversion convExpr - | expr = convExpr - | if convExpr.getUnspecifiedType() instanceof BoolType - then result = boolConversionLowerBound(convExpr.getExpr()) - else result = getTruncatedLowerBounds(convExpr.getExpr())) + exists(Conversion convExpr | expr = convExpr | + if convExpr.getUnspecifiedType() instanceof BoolType + then result = boolConversionLowerBound(convExpr.getExpr()) + else result = getTruncatedLowerBounds(convExpr.getExpr()) + ) or // Use SSA to get the lower bounds for a variable use. - exists (RangeSsaDefinition def, LocalScopeVariable v - | expr = def.getAUse(v) - | result = getDefLowerBounds(def, v)) + exists(RangeSsaDefinition def, LocalScopeVariable v | expr = def.getAUse(v) | + result = getDefLowerBounds(def, v) + ) } /** Only to be called by `getTruncatedUpperBounds`. */ -private -float getUpperBoundsImpl(Expr expr) { - exists (UnaryPlusExpr plusExpr - | expr = plusExpr and - result = getFullyConvertedUpperBounds(plusExpr.getOperand())) +private float getUpperBoundsImpl(Expr expr) { + exists(UnaryPlusExpr plusExpr | + expr = plusExpr and + result = getFullyConvertedUpperBounds(plusExpr.getOperand()) + ) or - exists (UnaryMinusExpr negateExpr, float xLow - | expr = negateExpr and + exists(UnaryMinusExpr negateExpr, float xLow | + expr = negateExpr and xLow = getFullyConvertedLowerBounds(negateExpr.getOperand()) and - result = -xLow) + result = -xLow + ) or - exists (MaxExpr maxExpr - | expr = maxExpr and + exists(MaxExpr maxExpr | + expr = maxExpr and // Return the union of the upper bounds from both children. - result = getFullyConvertedUpperBounds(maxExpr.getAnOperand())) + result = getFullyConvertedUpperBounds(maxExpr.getAnOperand()) + ) or - exists (MinExpr minExpr - | expr = minExpr and + exists(MinExpr minExpr | + expr = minExpr and // Compute the cross product of the bounds from both children. We are // using this mathematical property: // // min (maximum{X}, maximum{Y}) // = maximum { min(x,y) | x in X, y in Y } - exists (float x, float y - | x = getFullyConvertedUpperBounds(minExpr.getLeftOperand()) and + exists(float x, float y | + x = getFullyConvertedUpperBounds(minExpr.getLeftOperand()) and y = getFullyConvertedUpperBounds(minExpr.getRightOperand()) and - if x <= y - then result = x - else result = y)) + if x <= y then result = x else result = y + ) + ) or // ConditionalExpr (true branch) - exists (ConditionalExpr condExpr - | expr = condExpr and + exists(ConditionalExpr condExpr | + expr = condExpr and // Use `boolConversionUpperBound` to determine whether the condition // might evaluate to `true`. boolConversionUpperBound(condExpr.getCondition().getFullyConverted()) = 1 and - result = getFullyConvertedUpperBounds(condExpr.getThen())) + result = getFullyConvertedUpperBounds(condExpr.getThen()) + ) or // ConditionalExpr (false branch) - exists (ConditionalExpr condExpr - | expr = condExpr and + exists(ConditionalExpr condExpr | + expr = condExpr and // Use `boolConversionLowerBound` to determine whether the condition // might evaluate to `false`. boolConversionLowerBound(condExpr.getCondition().getFullyConverted()) = 0 and - result = getFullyConvertedUpperBounds(condExpr.getElse())) + result = getFullyConvertedUpperBounds(condExpr.getElse()) + ) or - exists (AddExpr addExpr, float xHigh, float yHigh - | expr = addExpr and + exists(AddExpr addExpr, float xHigh, float yHigh | + expr = addExpr and xHigh = getFullyConvertedUpperBounds(addExpr.getLeftOperand()) and yHigh = getFullyConvertedUpperBounds(addExpr.getRightOperand()) and - result = addRoundingUp(xHigh, yHigh)) + result = addRoundingUp(xHigh, yHigh) + ) or - exists (SubExpr subExpr, float xHigh, float yLow - | expr = subExpr and + exists(SubExpr subExpr, float xHigh, float yLow | + expr = subExpr and xHigh = getFullyConvertedUpperBounds(subExpr.getLeftOperand()) and yLow = getFullyConvertedLowerBounds(subExpr.getRightOperand()) and - result = addRoundingUp(xHigh, -yLow)) + result = addRoundingUp(xHigh, -yLow) + ) or - exists (AssignExpr assign - | expr = assign and - result = getFullyConvertedUpperBounds(assign.getRValue())) + exists(AssignExpr assign | + expr = assign and + result = getFullyConvertedUpperBounds(assign.getRValue()) + ) or - exists (AssignAddExpr addExpr, float xHigh, float yHigh - | expr = addExpr and + exists(AssignAddExpr addExpr, float xHigh, float yHigh | + expr = addExpr and xHigh = getFullyConvertedUpperBounds(addExpr.getLValue()) and yHigh = getFullyConvertedUpperBounds(addExpr.getRValue()) and - result = addRoundingUp(xHigh, yHigh)) + result = addRoundingUp(xHigh, yHigh) + ) or - exists (AssignSubExpr subExpr, float xHigh, float yLow - | expr = subExpr and + exists(AssignSubExpr subExpr, float xHigh, float yLow | + expr = subExpr and xHigh = getFullyConvertedUpperBounds(subExpr.getLValue()) and yLow = getFullyConvertedLowerBounds(subExpr.getRValue()) and - result = addRoundingUp(xHigh, -yLow)) + result = addRoundingUp(xHigh, -yLow) + ) or - exists (PrefixIncrExpr incrExpr, float xHigh - | expr = incrExpr and + exists(PrefixIncrExpr incrExpr, float xHigh | + expr = incrExpr and xHigh = getFullyConvertedUpperBounds(incrExpr.getOperand()) and - result = addRoundingUpSmall(xHigh, 1)) + result = addRoundingUpSmall(xHigh, 1) + ) or - exists (PrefixDecrExpr decrExpr, float xHigh - | expr = decrExpr and + exists(PrefixDecrExpr decrExpr, float xHigh | + expr = decrExpr and xHigh = getFullyConvertedUpperBounds(decrExpr.getOperand()) and - result = xHigh-1) + result = xHigh - 1 + ) or // `PostfixIncrExpr` and `PostfixDecrExpr` return the value of their operand. // The incrementing/decrementing behavior is handled in // `getDefUpperBoundsImpl`. - exists (PostfixIncrExpr incrExpr - | expr = incrExpr and - result = getFullyConvertedUpperBounds(incrExpr.getOperand())) + exists(PostfixIncrExpr incrExpr | + expr = incrExpr and + result = getFullyConvertedUpperBounds(incrExpr.getOperand()) + ) or - exists (PostfixDecrExpr decrExpr - | expr = decrExpr and - result = getFullyConvertedUpperBounds(decrExpr.getOperand())) + exists(PostfixDecrExpr decrExpr | + expr = decrExpr and + result = getFullyConvertedUpperBounds(decrExpr.getOperand()) + ) or - exists (RemExpr remExpr, float rhsUB - | expr = remExpr and + exists(RemExpr remExpr, float rhsUB | + expr = remExpr and rhsUB = getFullyConvertedUpperBounds(remExpr.getRightOperand()) - | result = rhsUB + | + result = rhsUB or // If the right hand side could be negative then we need to take its // absolute value. Since `abs(x) = max(-x,x)` this is equivalent to // adding `-rhsLB` to the set of upper bounds. - exists(float rhsLB - | rhsLB = getFullyConvertedLowerBounds(remExpr.getAnOperand()) and - not (rhsLB >= 0) - | result = -rhsLB)) + exists(float rhsLB | + rhsLB = getFullyConvertedLowerBounds(remExpr.getAnOperand()) and + not rhsLB >= 0 + | + result = -rhsLB + ) + ) or - exists (CommaExpr commaExpr - | expr = commaExpr and - result = getFullyConvertedUpperBounds(commaExpr.getRightOperand())) + exists(CommaExpr commaExpr | + expr = commaExpr and + result = getFullyConvertedUpperBounds(commaExpr.getRightOperand()) + ) or - exists (StmtExpr stmtExpr - | expr = stmtExpr and - result = getFullyConvertedUpperBounds(stmtExpr.getResultExpr())) + exists(StmtExpr stmtExpr | + expr = stmtExpr and + result = getFullyConvertedUpperBounds(stmtExpr.getResultExpr()) + ) or // If the conversion is to an arithmetic type then we just return the // upper bound of the child. We do not need to handle truncation and // overflow here, because that is done in `getTruncatedUpperBounds`. // Conversions to `bool` need to be handled specially because they test // whether the value of the expression is equal to 0. - exists (Conversion convExpr - | expr = convExpr - | if convExpr.getUnspecifiedType() instanceof BoolType - then result = boolConversionUpperBound(convExpr.getExpr()) - else result = getTruncatedUpperBounds(convExpr.getExpr())) + exists(Conversion convExpr | expr = convExpr | + if convExpr.getUnspecifiedType() instanceof BoolType + then result = boolConversionUpperBound(convExpr.getExpr()) + else result = getTruncatedUpperBounds(convExpr.getExpr()) + ) or // Use SSA to get the upper bounds for a variable use. - exists (RangeSsaDefinition def, LocalScopeVariable v - | expr = def.getAUse(v) - | result = getDefUpperBounds(def, v)) + exists(RangeSsaDefinition def, LocalScopeVariable v | expr = def.getAUse(v) | + result = getDefUpperBounds(def, v) + ) } /** @@ -773,12 +782,13 @@ float getUpperBoundsImpl(Expr expr) { * `boolConversionLowerBound` or `boolConversionUpperBound`. */ private predicate exprIsUsedAsBool(Expr expr) { - expr = any(BinaryLogicalOperation op).getAnOperand().getFullyConverted() or - expr = any(UnaryLogicalOperation op).getOperand().getFullyConverted() or - expr = any(ConditionalExpr c).getCondition().getFullyConverted() or - exists (Conversion cast - | cast.getUnspecifiedType() instanceof BoolType - | expr = cast.getExpr()) + expr = any(BinaryLogicalOperation op).getAnOperand().getFullyConverted() + or + expr = any(UnaryLogicalOperation op).getOperand().getFullyConverted() + or + expr = any(ConditionalExpr c).getCondition().getFullyConverted() + or + exists(Conversion cast | cast.getUnspecifiedType() instanceof BoolType | expr = cast.getExpr()) } /** @@ -788,22 +798,22 @@ private predicate exprIsUsedAsBool(Expr expr) { private float boolConversionLowerBound(Expr expr) { // Case 1: if the range for `expr` includes the value 0, // then `result = 0`. - (exprIsUsedAsBool(expr) and - exists (float lb | lb = getTruncatedLowerBounds(expr) and not (lb > 0)) and - exists (float ub | ub = getTruncatedUpperBounds(expr) and not (ub < 0)) and - result = 0) + exprIsUsedAsBool(expr) and + exists(float lb | lb = getTruncatedLowerBounds(expr) and not lb > 0) and + exists(float ub | ub = getTruncatedUpperBounds(expr) and not ub < 0) and + result = 0 or // Case 2a: if the range for `expr` does not include the value 0, // then `result = 1`. - (exprIsUsedAsBool(expr) and getTruncatedLowerBounds(expr) > 0 and result = 1) + exprIsUsedAsBool(expr) and getTruncatedLowerBounds(expr) > 0 and result = 1 or // Case 2b: if the range for `expr` does not include the value 0, // then `result = 1`. - (exprIsUsedAsBool(expr) and getTruncatedUpperBounds(expr) < 0 and result = 1) + exprIsUsedAsBool(expr) and getTruncatedUpperBounds(expr) < 0 and result = 1 or // Case 3: the type of `expr` is not arithmetic. For example, it might // be a pointer. - (exprIsUsedAsBool(expr) and not exists(exprMinVal(expr)) and result = 0) + exprIsUsedAsBool(expr) and not exists(exprMinVal(expr)) and result = 0 } /** @@ -813,27 +823,27 @@ private float boolConversionLowerBound(Expr expr) { private float boolConversionUpperBound(Expr expr) { // Case 1a: if the upper bound of the operand is <= 0, then the upper // bound might be 0. - (exprIsUsedAsBool(expr) and getTruncatedUpperBounds(expr) <= 0 and result = 0) + exprIsUsedAsBool(expr) and getTruncatedUpperBounds(expr) <= 0 and result = 0 or // Case 1b: if the upper bound of the operand is not <= 0, then the upper // bound is 1. - (exprIsUsedAsBool(expr) and - exists (float ub | ub = getTruncatedUpperBounds(expr) and not (ub <= 0)) and - result = 1) + exprIsUsedAsBool(expr) and + exists(float ub | ub = getTruncatedUpperBounds(expr) and not ub <= 0) and + result = 1 or // Case 2a: if the lower bound of the operand is >= 0, then the upper // bound might be 0. - (exprIsUsedAsBool(expr) and getTruncatedLowerBounds(expr) >= 0 and result = 0) + exprIsUsedAsBool(expr) and getTruncatedLowerBounds(expr) >= 0 and result = 0 or // Case 2b: if the lower bound of the operand is not >= 0, then the upper // bound is 1. - (exprIsUsedAsBool(expr) and - exists (float lb | lb = getTruncatedLowerBounds(expr) and not (lb >= 0)) and - result = 1) + exprIsUsedAsBool(expr) and + exists(float lb | lb = getTruncatedLowerBounds(expr) and not lb >= 0) and + result = 1 or // Case 3: the type of `expr` is not arithmetic. For example, it might // be a pointer. - (exprIsUsedAsBool(expr) and not exists(exprMaxVal(expr)) and result = 1) + exprIsUsedAsBool(expr) and not exists(exprMaxVal(expr)) and result = 1 } /** @@ -850,76 +860,73 @@ private float boolConversionUpperBound(Expr expr) { * In this example, the lower bound of x is 0, but we can * use the guard to deduce that the lower bound is 2 inside the block. */ -private -float getPhiLowerBounds(LocalScopeVariable v, RangeSsaDefinition phi) { - exists ( - VariableAccess access, ComparisonOperation guard, boolean branch, - float defLB, float guardLB - | access = v.getAnAccess() and +private float getPhiLowerBounds(LocalScopeVariable v, RangeSsaDefinition phi) { + exists( + VariableAccess access, ComparisonOperation guard, boolean branch, float defLB, float guardLB + | + access = v.getAnAccess() and phi.isGuardPhi(access, guard, branch) and lowerBoundFromGuard(guard, access, guardLB, branch) and defLB = getFullyConvertedLowerBounds(access) - | // Compute the maximum of `guardLB` and `defLB`. - if guardLB > defLB - then result = guardLB - else result = defLB) + | + // Compute the maximum of `guardLB` and `defLB`. + if guardLB > defLB then result = guardLB else result = defLB + ) or result = getDefLowerBounds(phi.getAPhiInput(v), v) } /** See comment for `getPhiLowerBounds`, above. */ -private -float getPhiUpperBounds(LocalScopeVariable v, RangeSsaDefinition phi) { - exists ( - VariableAccess access, ComparisonOperation guard, boolean branch, - float defUB, float guardUB - | access = v.getAnAccess() and +private float getPhiUpperBounds(LocalScopeVariable v, RangeSsaDefinition phi) { + exists( + VariableAccess access, ComparisonOperation guard, boolean branch, float defUB, float guardUB + | + access = v.getAnAccess() and phi.isGuardPhi(access, guard, branch) and upperBoundFromGuard(guard, access, guardUB, branch) and defUB = getFullyConvertedUpperBounds(access) - | // Compute the minimum of `guardUB` and `defUB`. - if guardUB < defUB - then result = guardUB - else result = defUB) + | + // Compute the minimum of `guardUB` and `defUB`. + if guardUB < defUB then result = guardUB else result = defUB + ) or result = getDefUpperBounds(phi.getAPhiInput(v), v) } /** Only to be called by `getDefLowerBounds`. */ -private -float getDefLowerBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) { +private float getDefLowerBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) { // Definitions with a defining value. - exists (Expr expr - | assignmentDef(def, v, expr) - | result = getFullyConvertedLowerBounds(expr)) + exists(Expr expr | assignmentDef(def, v, expr) | result = getFullyConvertedLowerBounds(expr)) or - exists ( - AssignAddExpr assignAdd, RangeSsaDefinition nextDef, float lhsLB, float rhsLB - | def = assignAdd and + exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef, float lhsLB, float rhsLB | + def = assignAdd and assignAdd.getLValue() = nextDef.getAUse(v) and lhsLB = getDefLowerBounds(nextDef, v) and rhsLB = getFullyConvertedLowerBounds(assignAdd.getRValue()) and - result = addRoundingDown(lhsLB, rhsLB)) + result = addRoundingDown(lhsLB, rhsLB) + ) or - exists ( - AssignSubExpr assignSub, RangeSsaDefinition nextDef, float lhsLB, float rhsUB - | def = assignSub and + exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef, float lhsLB, float rhsUB | + def = assignSub and assignSub.getLValue() = nextDef.getAUse(v) and lhsLB = getDefLowerBounds(nextDef, v) and rhsUB = getFullyConvertedUpperBounds(assignSub.getRValue()) and - result = addRoundingDown(lhsLB, -rhsUB)) + result = addRoundingDown(lhsLB, -rhsUB) + ) or - exists (IncrementOperation incr, float newLB - | def = incr and + exists(IncrementOperation incr, float newLB | + def = incr and incr.getOperand() = v.getAnAccess() and newLB = getFullyConvertedLowerBounds(incr.getOperand()) and - result = newLB+1) + result = newLB + 1 + ) or - exists (DecrementOperation decr, float newLB - | def = decr and + exists(DecrementOperation decr, float newLB | + def = decr and decr.getOperand() = v.getAnAccess() and newLB = getFullyConvertedLowerBounds(decr.getOperand()) and - result = addRoundingDownSmall(newLB, -1)) + result = addRoundingDownSmall(newLB, -1) + ) or // Phi nodes. result = getPhiLowerBounds(v, def) @@ -929,40 +936,39 @@ float getDefLowerBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) { } /** Only to be called by `getDefUpperBounds`. */ -private -float getDefUpperBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) { +private float getDefUpperBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) { // Definitions with a defining value. - exists (Expr expr - | assignmentDef(def, v, expr) - | result = getFullyConvertedUpperBounds(expr)) + exists(Expr expr | assignmentDef(def, v, expr) | result = getFullyConvertedUpperBounds(expr)) or - exists ( - AssignAddExpr assignAdd, RangeSsaDefinition nextDef, float lhsUB, float rhsUB - | def = assignAdd and + exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef, float lhsUB, float rhsUB | + def = assignAdd and assignAdd.getLValue() = nextDef.getAUse(v) and lhsUB = getDefUpperBounds(nextDef, v) and rhsUB = getFullyConvertedUpperBounds(assignAdd.getRValue()) and - result = addRoundingUp(lhsUB, rhsUB)) + result = addRoundingUp(lhsUB, rhsUB) + ) or - exists ( - AssignSubExpr assignSub, RangeSsaDefinition nextDef, float lhsUB, float rhsLB - | def = assignSub and + exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef, float lhsUB, float rhsLB | + def = assignSub and assignSub.getLValue() = nextDef.getAUse(v) and lhsUB = getDefUpperBounds(nextDef, v) and rhsLB = getFullyConvertedLowerBounds(assignSub.getRValue()) and - result = addRoundingUp(lhsUB, -rhsLB)) + result = addRoundingUp(lhsUB, -rhsLB) + ) or - exists (IncrementOperation incr, float newUB - | def = incr and + exists(IncrementOperation incr, float newUB | + def = incr and incr.getOperand() = v.getAnAccess() and newUB = getFullyConvertedUpperBounds(incr.getOperand()) and - result = addRoundingUpSmall(newUB, 1)) + result = addRoundingUpSmall(newUB, 1) + ) or - exists (DecrementOperation decr, float newUB - | def = decr and + exists(DecrementOperation decr, float newUB | + def = decr and decr.getOperand() = v.getAnAccess() and newUB = getFullyConvertedUpperBounds(decr.getOperand()) and - result = newUB-1) + result = newUB - 1 + ) or // Phi nodes. result = getPhiUpperBounds(v, def) @@ -976,55 +982,61 @@ float getDefUpperBoundsImpl(RangeSsaDefinition def, LocalScopeVariable v) { * done by `getDefLowerBoundsImpl`, but this is where widening is applied * to prevent the analysis from exploding due to a recursive definition. */ -private -float getDefLowerBounds(RangeSsaDefinition def, LocalScopeVariable v) { - exists (float newLB, float truncatedLB - | newLB = getDefLowerBoundsImpl(def, v) and +private float getDefLowerBounds(RangeSsaDefinition def, LocalScopeVariable v) { + exists(float newLB, float truncatedLB | + newLB = getDefLowerBoundsImpl(def, v) and if varMinVal(v) <= newLB and newLB <= varMaxVal(v) - then truncatedLB = newLB - else truncatedLB = varMinVal(v) - | // Widening: check whether the new lower bound is from a source which + then truncatedLB = newLB + else truncatedLB = varMinVal(v) + | + // Widening: check whether the new lower bound is from a source which // depends recursively on the current definition. if isRecursiveDef(def, v) - then // The new lower bound is from a recursive source, so we round - // down to one of a limited set of values to prevent the - // recursion from exploding. - result = - max (float widenLB - | widenLB = wideningLowerBounds(v.getUnspecifiedType()) and - not (widenLB > truncatedLB) - | widenLB) - else result = truncatedLB) + then + // The new lower bound is from a recursive source, so we round + // down to one of a limited set of values to prevent the + // recursion from exploding. + result = max(float widenLB | + widenLB = wideningLowerBounds(v.getUnspecifiedType()) and + not widenLB > truncatedLB + | + widenLB + ) + else result = truncatedLB + ) or // The definition might overflow positively and wrap. If so, the lower // bound is `typeLowerBound`. - (defMightOverflowPositively(def, v) and result = varMinVal(v)) + defMightOverflowPositively(def, v) and result = varMinVal(v) } /** See comment for `getDefLowerBounds`, above. */ -private -float getDefUpperBounds(RangeSsaDefinition def, LocalScopeVariable v) { - exists (float newUB, float truncatedUB - | newUB = getDefUpperBoundsImpl(def, v) and +private float getDefUpperBounds(RangeSsaDefinition def, LocalScopeVariable v) { + exists(float newUB, float truncatedUB | + newUB = getDefUpperBoundsImpl(def, v) and if varMinVal(v) <= newUB and newUB <= varMaxVal(v) - then truncatedUB = newUB - else truncatedUB = varMaxVal(v) - | // Widening: check whether the new upper bound is from a source which + then truncatedUB = newUB + else truncatedUB = varMaxVal(v) + | + // Widening: check whether the new upper bound is from a source which // depends recursively on the current definition. if isRecursiveDef(def, v) - then // The new upper bound is from a recursive source, so we round - // up to one of a fixed set of values to prevent the recursion - // from exploding. - result = - min (float widenUB - | widenUB = wideningUpperBounds(v.getUnspecifiedType()) and - not (widenUB < truncatedUB) - | widenUB) - else result = truncatedUB) + then + // The new upper bound is from a recursive source, so we round + // up to one of a fixed set of values to prevent the recursion + // from exploding. + result = min(float widenUB | + widenUB = wideningUpperBounds(v.getUnspecifiedType()) and + not widenUB < truncatedUB + | + widenUB + ) + else result = truncatedUB + ) or // The definition might overflow negatively and wrap. If so, the upper // bound is `typeUpperBound`. - (defMightOverflowNegatively(def, v) and result = varMaxVal(v)) + defMightOverflowNegatively(def, v) and result = varMaxVal(v) } /** @@ -1032,9 +1044,9 @@ float getDefUpperBounds(RangeSsaDefinition def, LocalScopeVariable v) { * unanalyzable definitions (such as function parameters) and make their * bounds unknown. */ -private -predicate unanalyzableDefBounds( - RangeSsaDefinition def, LocalScopeVariable v, float lb, float ub) { +private predicate unanalyzableDefBounds( + RangeSsaDefinition def, LocalScopeVariable v, float lb, float ub +) { v = def.getAVariable() and not analyzableDef(def, v) and lb = varMinVal(v) and @@ -1065,18 +1077,21 @@ predicate nonNanGuardedVariable(ComparisonOperation guard, VariableAccess v, boo * predicate uses the bounds information for `r` to compute a lower bound * for `v`. */ -private -predicate lowerBoundFromGuard( +private predicate lowerBoundFromGuard( ComparisonOperation guard, VariableAccess v, float lb, boolean branch ) { - exists (float childLB, RelationStrictness strictness - | boundFromGuard(guard, v, childLB, true, strictness, branch) - | if nonNanGuardedVariable(guard, v, branch) - then (if (strictness = Nonstrict() or - not (v.getUnspecifiedType() instanceof IntegralType)) - then lb = childLB - else lb = childLB+1) - else lb = varMinVal(v.getTarget())) + exists(float childLB, RelationStrictness strictness | + boundFromGuard(guard, v, childLB, true, strictness, branch) + | + if nonNanGuardedVariable(guard, v, branch) + then + if + strictness = Nonstrict() or + not v.getUnspecifiedType() instanceof IntegralType + then lb = childLB + else lb = childLB + 1 + else lb = varMinVal(v.getTarget()) + ) } /** @@ -1084,39 +1099,41 @@ predicate lowerBoundFromGuard( * predicate uses the bounds information for `r` to compute a upper bound * for `v`. */ -private -predicate upperBoundFromGuard( +private predicate upperBoundFromGuard( ComparisonOperation guard, VariableAccess v, float ub, boolean branch ) { - exists (float childUB, RelationStrictness strictness - | boundFromGuard(guard, v, childUB, false, strictness, branch) - | if nonNanGuardedVariable(guard, v, branch) - then (if (strictness = Nonstrict() or - not (v.getUnspecifiedType() instanceof IntegralType)) - then ub = childUB - else ub = childUB-1) - else ub = varMaxVal(v.getTarget())) + exists(float childUB, RelationStrictness strictness | + boundFromGuard(guard, v, childUB, false, strictness, branch) + | + if nonNanGuardedVariable(guard, v, branch) + then + if + strictness = Nonstrict() or + not v.getUnspecifiedType() instanceof IntegralType + then ub = childUB + else ub = childUB - 1 + else ub = varMaxVal(v.getTarget()) + ) } /** * This predicate simplifies the results returned by * `linearBoundFromGuard`. */ -private -predicate boundFromGuard( - ComparisonOperation guard, VariableAccess v, - float boundValue, - boolean isLowerBound, RelationStrictness strictness, boolean branch +private predicate boundFromGuard( + ComparisonOperation guard, VariableAccess v, float boundValue, boolean isLowerBound, + RelationStrictness strictness, boolean branch ) { - exists ( - float p, float q, float r, boolean isLB - | linearBoundFromGuard( - guard, v, p, q, r, isLB, strictness, branch) and - boundValue = (r - q)/p - | // If the multiplier is negative then the direction of the comparison + exists(float p, float q, float r, boolean isLB | + linearBoundFromGuard(guard, v, p, q, r, isLB, strictness, branch) and + boundValue = (r - q) / p + | + // If the multiplier is negative then the direction of the comparison // needs to be flipped. - (p > 0 and isLowerBound = isLB) or - (p < 0 and isLowerBound = isLB.booleanNot())) + p > 0 and isLowerBound = isLB + or + p < 0 and isLowerBound = isLB.booleanNot() + ) } /** @@ -1124,30 +1141,29 @@ predicate boundFromGuard( * and decomposes them into a tuple of values which can be used to deduce a * lower or upper bound for `v`. */ -private -predicate linearBoundFromGuard( - ComparisonOperation guard, VariableAccess v, - float p, float q, float boundValue, - boolean isLowerBound, // Is this a lower or an upper bound? - RelationStrictness strictness, - boolean branch // Which control-flow branch is this bound valid on? +private predicate linearBoundFromGuard( + ComparisonOperation guard, VariableAccess v, float p, float q, float boundValue, + boolean isLowerBound, // Is this a lower or an upper bound? + RelationStrictness strictness, boolean branch // Which control-flow branch is this bound valid on? ) { // For the comparison x < RHS, we create two bounds: // // 1. x < upperbound(RHS) // 2. x >= typeLowerBound(RHS.getUnspecifiedType()) // - exists (Expr lhs, Expr rhs, RelationDirection dir, RelationStrictness st - | linearAccess(lhs, v, p, q) and + exists(Expr lhs, Expr rhs, RelationDirection dir, RelationStrictness st | + linearAccess(lhs, v, p, q) and relOpWithSwapAndNegate(guard, lhs, rhs, dir, st, branch) - | (isLowerBound = directionIsGreater(dir) and - strictness = st and - getBounds(rhs, boundValue, isLowerBound)) + | + isLowerBound = directionIsGreater(dir) and + strictness = st and + getBounds(rhs, boundValue, isLowerBound) or - (isLowerBound = directionIsLesser(dir) and - strictness = Nonstrict() and - exprTypeBounds(rhs, boundValue, isLowerBound))) - + isLowerBound = directionIsLesser(dir) and + strictness = Nonstrict() and + exprTypeBounds(rhs, boundValue, isLowerBound) + ) + or // For x == RHS, we create the following bounds: // // 1. x <= upperbound(RHS) @@ -1158,34 +1174,36 @@ predicate linearBoundFromGuard( // 1. x <= typeUpperBound(RHS.getUnspecifiedType()) // 2. x >= typeLowerBound(RHS.getUnspecifiedType()) // - or - exists (Expr lhs, Expr rhs, boolean isEQ - | linearAccess(lhs, v, p, q) and + exists(Expr lhs, Expr rhs, boolean isEQ | + linearAccess(lhs, v, p, q) and eqOpWithSwapAndNegate(guard, lhs, rhs, isEQ, branch) and strictness = Nonstrict() - | // True branch - (isEQ = true and getBounds(rhs, boundValue, isLowerBound)) + | + // True branch + isEQ = true and getBounds(rhs, boundValue, isLowerBound) or // False branch: set the bounds to the min/max for the type. - (isEQ = false and exprTypeBounds(rhs, boundValue, isLowerBound))) + isEQ = false and exprTypeBounds(rhs, boundValue, isLowerBound) + ) } /** Utility for `linearBoundFromGuard`. */ -private -predicate getBounds(Expr expr, float boundValue, boolean isLowerBound) { - (isLowerBound = true and boundValue = getFullyConvertedLowerBounds(expr)) or - (isLowerBound = false and boundValue = getFullyConvertedUpperBounds(expr)) +private predicate getBounds(Expr expr, float boundValue, boolean isLowerBound) { + isLowerBound = true and boundValue = getFullyConvertedLowerBounds(expr) + or + isLowerBound = false and boundValue = getFullyConvertedUpperBounds(expr) } /** Utility for `linearBoundFromGuard`. */ -private -predicate exprTypeBounds(Expr expr, float boundValue, boolean isLowerBound) { - (isLowerBound = true and boundValue = exprMinVal(expr.getFullyConverted())) or - (isLowerBound = false and boundValue = exprMaxVal(expr.getFullyConverted())) +private predicate exprTypeBounds(Expr expr, float boundValue, boolean isLowerBound) { + isLowerBound = true and boundValue = exprMinVal(expr.getFullyConverted()) + or + isLowerBound = false and boundValue = exprMaxVal(expr.getFullyConverted()) } -private cached module SimpleRangeAnalysisCached { - /** +cached +private module SimpleRangeAnalysisCached { + /** * Gets the lower bound of the expression. * * Note: expressions in C/C++ are often implicitly or explicitly cast to a @@ -1241,9 +1259,11 @@ private cached module SimpleRangeAnalysisCached { cached predicate exprWithEmptyRange(Expr expr) { analyzableExpr(expr) and - (not exists(lowerBound(expr)) or - not exists(upperBound(expr)) or - lowerBound(expr) > upperBound(expr)) + ( + not exists(lowerBound(expr)) or + not exists(upperBound(expr)) or + lowerBound(expr) > upperBound(expr) + ) } /** Holds if the definition might overflow negatively. */ @@ -1275,8 +1295,8 @@ private cached module SimpleRangeAnalysisCached { */ cached predicate exprMightOverflowNegatively(Expr expr) { - getLowerBoundsImpl(expr) < exprMinVal(expr) or - + getLowerBoundsImpl(expr) < exprMinVal(expr) + or // The lower bound of the expression `x--` is the same as the lower // bound of `x`, so the standard logic (above) does not work for // detecting whether it might overflow. @@ -1295,15 +1315,15 @@ private cached module SimpleRangeAnalysisCached { convertedExprMightOverflowNegatively(expr.getConversion()) } - /** + /** * Holds if the expression might overflow positively. This predicate * does not consider the possibility that the expression might overflow * due to a conversion. */ cached predicate exprMightOverflowPositively(Expr expr) { - getUpperBoundsImpl(expr) > exprMaxVal(expr) or - + getUpperBoundsImpl(expr) > exprMaxVal(expr) + or // The upper bound of the expression `x++` is the same as the upper // bound of `x`, so the standard logic (above) does not work for // detecting whether it might overflow. diff --git a/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll b/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll index 53e9948d7e3..2023ab14721 100644 --- a/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll +++ b/cpp/ql/src/semmle/code/cpp/security/BufferAccess.qll @@ -1,21 +1,21 @@ import cpp /** - * Returns the size of the pointed-to type, counting void types as size 1. + * Returns the size of the pointed-to type, counting void types as size 1. */ -int getPointedSize(Type t) -{ +int getPointedSize(Type t) { result = t.getUnspecifiedType().(PointerType).getBaseType().getSize().maximum(1) } /** * An operation that reads data from or writes data to a buffer. - * + * * See the BufferWrite class for an explanation of how BufferAccess and * BufferWrite differ. */ abstract class BufferAccess extends Expr { abstract string getName(); + /** * Gets the expression that denotes the buffer, along with a textual label * for it and an access type. @@ -26,6 +26,7 @@ abstract class BufferAccess extends Expr { * - 3 = buffer is accessed at offset getSize - 1. */ abstract Expr getBuffer(string bufferDesc, int accessType); + abstract int getSize(); } @@ -49,27 +50,22 @@ class MemcpyBA extends BufferAccess { this.(FunctionCall).getTarget().getName() = "wmempcpy" or this.(FunctionCall).getTarget().getName() = "RtlCopyMemoryNonTemporal" } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { - ( - result = this.(FunctionCall).getArgument(0) and - bufferDesc = "destination buffer" and - accessType = 1 - ) or ( - result = this.(FunctionCall).getArgument(1) and - bufferDesc = "source buffer" and - accessType = 1 - ) + result = this.(FunctionCall).getArgument(0) and + bufferDesc = "destination buffer" and + accessType = 1 + or + result = this.(FunctionCall).getArgument(1) and + bufferDesc = "source buffer" and + accessType = 1 } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -78,30 +74,23 @@ class MemcpyBA extends BufferAccess { * bcopy(src, dest, num) */ class BCopyBA extends BufferAccess { - BCopyBA() { - this.(FunctionCall).getTarget().getName() = "bcopy" - } + BCopyBA() { this.(FunctionCall).getTarget().getName() = "bcopy" } - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { - ( - result = this.(FunctionCall).getArgument(0) and - bufferDesc = "source buffer" and - accessType = 1 - ) or ( - result = this.(FunctionCall).getArgument(1) and - bufferDesc = "destination buffer" and - accessType = 1 - ) + result = this.(FunctionCall).getArgument(0) and + bufferDesc = "source buffer" and + accessType = 1 + or + result = this.(FunctionCall).getArgument(1) and + bufferDesc = "destination buffer" and + accessType = 1 } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -110,30 +99,23 @@ class BCopyBA extends BufferAccess { * strncpy(dest, src, num) */ class StrncpyBA extends BufferAccess { - StrncpyBA() { - this.(FunctionCall).getTarget().getName() = "strncpy" - } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + StrncpyBA() { this.(FunctionCall).getTarget().getName() = "strncpy" } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { - ( - result = this.(FunctionCall).getArgument(0) and - bufferDesc = "destination buffer" and - accessType = 2 - ) or ( - result = this.(FunctionCall).getArgument(1) and - bufferDesc = "source buffer" and - accessType = 2 - ) + result = this.(FunctionCall).getArgument(0) and + bufferDesc = "destination buffer" and + accessType = 2 + or + result = this.(FunctionCall).getArgument(1) and + bufferDesc = "source buffer" and + accessType = 2 } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -142,30 +124,23 @@ class StrncpyBA extends BufferAccess { * memccpy(dest, src, c, n) */ class MemccpyBA extends BufferAccess { - MemccpyBA() { - this.(FunctionCall).getTarget().getName() = "memccpy" - } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + MemccpyBA() { this.(FunctionCall).getTarget().getName() = "memccpy" } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { - ( - result = this.(FunctionCall).getArgument(0) and - bufferDesc = "destination buffer" and - accessType = 2 - ) or ( - result = this.(FunctionCall).getArgument(1) and - bufferDesc = "source buffer" and - accessType = 2 - ) + result = this.(FunctionCall).getArgument(0) and + bufferDesc = "destination buffer" and + accessType = 2 + or + result = this.(FunctionCall).getArgument(1) and + bufferDesc = "source buffer" and + accessType = 2 } override int getSize() { - result = - this.(FunctionCall).getArgument(3).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(3).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -183,27 +158,22 @@ class MemcmpBA extends BufferAccess { this.(FunctionCall).getTarget().getName() = "_memicmp" or this.(FunctionCall).getTarget().getName() = "_memicmp_l" } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { - ( - result = this.(FunctionCall).getArgument(0) and - bufferDesc = "first buffer" and - accessType = 2 - ) or ( - result = this.(FunctionCall).getArgument(1) and - bufferDesc = "second buffer" and - accessType = 2 - ) + result = this.(FunctionCall).getArgument(0) and + bufferDesc = "first buffer" and + accessType = 2 + or + result = this.(FunctionCall).getArgument(1) and + bufferDesc = "second buffer" and + accessType = 2 } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -217,27 +187,22 @@ class SwabBA extends BufferAccess { this.(FunctionCall).getTarget().getName() = "swab" or this.(FunctionCall).getTarget().getName() = "_swab" } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { - ( - result = this.(FunctionCall).getArgument(0) and - bufferDesc = "source buffer" and - accessType = 1 - ) or ( - result = this.(FunctionCall).getArgument(1) and - bufferDesc = "destination buffer" and - accessType = 1 - ) + result = this.(FunctionCall).getArgument(0) and + bufferDesc = "source buffer" and + accessType = 1 + or + result = this.(FunctionCall).getArgument(1) and + bufferDesc = "destination buffer" and + accessType = 1 } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -251,10 +216,8 @@ class MemsetBA extends BufferAccess { this.(FunctionCall).getTarget().getName() = "memset" or this.(FunctionCall).getTarget().getName() = "wmemset" } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { result = this.(FunctionCall).getArgument(0) and @@ -263,9 +226,8 @@ class MemsetBA extends BufferAccess { } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -274,13 +236,9 @@ class MemsetBA extends BufferAccess { * RtlSecureZeroMemory(ptr, cnt) */ class ZeroMemoryBA extends BufferAccess { - ZeroMemoryBA() { - this.(FunctionCall).getTarget().getName() = "RtlSecureZeroMemory" - } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + ZeroMemoryBA() { this.(FunctionCall).getTarget().getName() = "RtlSecureZeroMemory" } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { result = this.(FunctionCall).getArgument(0) and @@ -288,9 +246,7 @@ class ZeroMemoryBA extends BufferAccess { accessType = 1 } - override int getSize() { - result = this.(FunctionCall).getArgument(1).getValue().toInt() - } + override int getSize() { result = this.(FunctionCall).getArgument(1).getValue().toInt() } } /** @@ -303,10 +259,8 @@ class MemchrBA extends BufferAccess { this.(FunctionCall).getTarget().getName() = "memchr" or this.(FunctionCall).getTarget().getName() = "wmemchr" } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { result = this.(FunctionCall).getArgument(0) and @@ -315,9 +269,8 @@ class MemchrBA extends BufferAccess { } override int getSize() { - result = - this.(FunctionCall).getArgument(2).getValue().toInt() * - getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) + result = this.(FunctionCall).getArgument(2).getValue().toInt() * + getPointedSize(this.(FunctionCall).getTarget().getParameter(0).getType()) } } @@ -326,13 +279,9 @@ class MemchrBA extends BufferAccess { * fread(buffer, size, number, file) */ class FreadBA extends BufferAccess { - FreadBA() { - this.(FunctionCall).getTarget().getName() = "fread" - } - - override string getName() { - result = this.(FunctionCall).getTarget().getName() - } + FreadBA() { this.(FunctionCall).getTarget().getName() = "fread" } + + override string getName() { result = this.(FunctionCall).getTarget().getName() } override Expr getBuffer(string bufferDesc, int accessType) { result = this.(FunctionCall).getArgument(0) and @@ -341,9 +290,8 @@ class FreadBA extends BufferAccess { } override int getSize() { - result = - this.(FunctionCall).getArgument(1).getValue().toInt() * - this.(FunctionCall).getArgument(2).getValue().toInt() + result = this.(FunctionCall).getArgument(1).getValue().toInt() * + this.(FunctionCall).getArgument(2).getValue().toInt() } } @@ -355,11 +303,8 @@ class FreadBA extends BufferAccess { */ class ArrayExprBA extends BufferAccess { ArrayExprBA() { - exists(this.(ArrayExpr).getArrayOffset().getValue().toInt()) - and - not exists(AddressOfExpr aoe | aoe.getAChild() = this) - and - + exists(this.(ArrayExpr).getArrayOffset().getValue().toInt()) and + not exists(AddressOfExpr aoe | aoe.getAChild() = this) and // exclude accesses in macro implementation of `strcmp`, // which are carefully controlled but can look dangerous. not exists(Macro m | @@ -368,9 +313,7 @@ class ArrayExprBA extends BufferAccess { ) } - override string getName() { - result = "array indexing" - } + override string getName() { result = "array indexing" } override Expr getBuffer(string bufferDesc, int accessType) { result = this.(ArrayExpr).getArrayBase() and @@ -381,8 +324,7 @@ class ArrayExprBA extends BufferAccess { override int getSize() { // byte size of the buffer that would be required to support this // access - result = - (1 + this.(ArrayExpr).getArrayOffset().getValue().toInt()) * - this.(ArrayExpr).getType().getSize() + result = (1 + this.(ArrayExpr).getArrayOffset().getValue().toInt()) * + this.(ArrayExpr).getType().getSize() } } diff --git a/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll b/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll index 7af1cf9095f..4c53f34c936 100644 --- a/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/BufferWrite.qll @@ -4,6 +4,7 @@ * @kind problem * @problem.severity recommendation */ + import cpp import semmle.code.cpp.commons.Alloc import semmle.code.cpp.commons.Buffer @@ -17,7 +18,7 @@ import semmle.code.cpp.models.implementations.Strcat /** * An operation that writes a variable amount of data to a buffer * (strcpy, strncat, sprintf etc). - * + * * Note that there are two related class frameworks: * - BufferWrite provides detailed coverage of null-terminated * buffer write operations. @@ -27,8 +28,7 @@ import semmle.code.cpp.models.implementations.Strcat * This design has some overlaps between the two classes, for example * the write of a 'strncpy'. */ -abstract class BufferWrite extends Expr -{ +abstract class BufferWrite extends Expr { /* * --- derived classes override these --- */ @@ -57,13 +57,13 @@ abstract class BufferWrite extends Expr * though it's value is unknown. */ predicate hasExplicitLimit() { none() } - + /** * Gets the explicit limit of bytes copied by this operation, if it exists * and it's value can be determined. */ int getExplicitLimit() { none() } - + /** * Gets an upper bound to the amount of data that's being written (if one * can be found). @@ -82,8 +82,7 @@ abstract class BufferWrite extends Expr * Gets the size of a single character of the type this * operation works with, in bytes. */ - int getCharSize() - { + int getCharSize() { result = getBufferType().(PointerType).getBaseType().getSize() or result = getBufferType().(ArrayType).getBaseType().getSize() } @@ -91,30 +90,23 @@ abstract class BufferWrite extends Expr /** * Gets a description of this buffer write. */ - string getBWDesc() - { - result = toString() - } + string getBWDesc() { result = toString() } } /** * A `BufferWrite` that is also a `FunctionCall` (most cases). */ -abstract class BufferWriteCall extends BufferWrite, FunctionCall -{ -} +abstract class BufferWriteCall extends BufferWrite, FunctionCall { } /* * --- BufferWrite classes --- */ /** - * A call to a variant of `strcpy`. + * A call to a variant of `strcpy`. */ -class StrCopyBW extends BufferWriteCall -{ - StrCopyBW() - { +class StrCopyBW extends BufferWriteCall { + StrCopyBW() { exists(TopLevelFunction fn, string name | fn = getTarget() and name = fn.getName() | // strcpy(dst, src) name = "strcpy" @@ -154,123 +146,82 @@ class StrCopyBW extends BufferWriteCall ) } - int getParamSize() - { - exists(TopLevelFunction fn, string name | (fn = getTarget()) and (name = fn.getName()) and ( - if (name.suffix(name.length() - 2) = "_s") then ( - result = 1 - ) else if exists(name.indexOf("ncpy")) then ( - result = 2 - ) else ( - none() + int getParamSize() { + exists(TopLevelFunction fn, string name | + fn = getTarget() and + name = fn.getName() and + ( + if name.suffix(name.length() - 2) = "_s" + then result = 1 + else + if exists(name.indexOf("ncpy")) + then result = 2 + else none() ) - )) - } - - int getParamSrc() - { - exists(TopLevelFunction fn, string name | (fn = getTarget()) and (name = fn.getName()) and ( - if (name.suffix(name.length() - 2) = "_s") then ( - result = 2 - ) else ( - result = 1 - ) - )) - } - - override Type getBufferType() - { - result = this.getTarget().getParameter(getParamSrc()).getUnspecifiedType() - } - - override Expr getASource() - { - result = getArgument(getParamSrc()) - } - - override Expr getDest() - { - result = getArgument(0) - } - - override predicate hasExplicitLimit() - { - exists(getParamSize()) - } - - override int getExplicitLimit() - { - result = getArgument(getParamSize()).getValue().toInt() * getCharSize() - } - - override int getMaxData() - { - result = getArgument(getParamSrc()).(AnalysedString).getMaxLength() * getCharSize() - } -} - -/** - * A call to a variant of `strcat`. - */ -class StrCatBW extends BufferWriteCall -{ - StrCatBW() - { - exists(TopLevelFunction fn | fn = getTarget() and fn instanceof StrcatFunction) - } - - int getParamSize() - { - if exists(getArgument(2)) then ( - result = 2 - ) else ( - none() ) } - - int getParamSrc() - { - result = 1 + + int getParamSrc() { + exists(TopLevelFunction fn, string name | + fn = getTarget() and + name = fn.getName() and + (if name.suffix(name.length() - 2) = "_s" then result = 2 else result = 1) + ) } - override Type getBufferType() - { + override Type getBufferType() { result = this.getTarget().getParameter(getParamSrc()).getUnspecifiedType() } - override Expr getASource() - { - result = getArgument(getParamSrc()) - } + override Expr getASource() { result = getArgument(getParamSrc()) } - override Expr getDest() - { - result = getArgument(0) - } + override Expr getDest() { result = getArgument(0) } - override predicate hasExplicitLimit() - { - exists(getParamSize()) - } + override predicate hasExplicitLimit() { exists(getParamSize()) } - override int getExplicitLimit() - { + override int getExplicitLimit() { result = getArgument(getParamSize()).getValue().toInt() * getCharSize() } - override int getMaxData() - { + override int getMaxData() { result = getArgument(getParamSrc()).(AnalysedString).getMaxLength() * getCharSize() } } /** - * A call to a variant of `sprintf`. + * A call to a variant of `strcat`. */ -class SprintfBW extends BufferWriteCall -{ - SprintfBW() - { +class StrCatBW extends BufferWriteCall { + StrCatBW() { exists(TopLevelFunction fn | fn = getTarget() and fn instanceof StrcatFunction) } + + int getParamSize() { if exists(getArgument(2)) then result = 2 else none() } + + int getParamSrc() { result = 1 } + + override Type getBufferType() { + result = this.getTarget().getParameter(getParamSrc()).getUnspecifiedType() + } + + override Expr getASource() { result = getArgument(getParamSrc()) } + + override Expr getDest() { result = getArgument(0) } + + override predicate hasExplicitLimit() { exists(getParamSize()) } + + override int getExplicitLimit() { + result = getArgument(getParamSize()).getValue().toInt() * getCharSize() + } + + override int getMaxData() { + result = getArgument(getParamSrc()).(AnalysedString).getMaxLength() * getCharSize() + } +} + +/** + * A call to a variant of `sprintf`. + */ +class SprintfBW extends BufferWriteCall { + SprintfBW() { exists(TopLevelFunction fn, string name | fn = getTarget() and name = fn.getName() | /* * C sprintf variants: @@ -306,50 +257,41 @@ class SprintfBW extends BufferWriteCall ) } - override Type getBufferType() - { + override Type getBufferType() { exists(FormattingFunction f | f = this.getTarget() and result = f.getParameter(f.getFormatParameterIndex()).getUnspecifiedType() ) } - override Expr getASource() - { - (result = this.(FormattingFunctionCall).getFormat()) + override Expr getASource() { + result = this.(FormattingFunctionCall).getFormat() or - (result = this.(FormattingFunctionCall).getFormatArgument(_)) + result = this.(FormattingFunctionCall).getFormatArgument(_) } - override Expr getDest() - { - result = getArgument(0) - } + override Expr getDest() { result = getArgument(0) } - override int getMaxData() - { + override int getMaxData() { exists(FormatLiteral fl | - (fl = this.(FormattingFunctionCall).getFormat()) - and (result = fl.getMaxConvertedLength() * getCharSize()) - ) + fl = this.(FormattingFunctionCall).getFormat() and + result = fl.getMaxConvertedLength() * getCharSize() + ) } - override int getMaxDataLimited() - { + override int getMaxDataLimited() { exists(FormatLiteral fl | - (fl = this.(FormattingFunctionCall).getFormat()) - and (result = fl.getMaxConvertedLengthLimited() * getCharSize()) + fl = this.(FormattingFunctionCall).getFormat() and + result = fl.getMaxConvertedLengthLimited() * getCharSize() ) } } /** - * A call to a variant of `snprintf`. + * A call to a variant of `snprintf`. */ -class SnprintfBW extends BufferWriteCall -{ - SnprintfBW() - { +class SnprintfBW extends BufferWriteCall { + SnprintfBW() { exists(TopLevelFunction fn, string name | fn = getTarget() and name = fn.getName() | /* * C snprintf variants: @@ -406,89 +348,62 @@ class SnprintfBW extends BufferWriteCall not this instanceof SprintfBW ) } - - int getParamSize() - { - result = 1 - } - override Type getBufferType() - { + int getParamSize() { result = 1 } + + override Type getBufferType() { exists(FormattingFunction f | f = this.getTarget() and result = f.getParameter(f.getFormatParameterIndex()).getUnspecifiedType() ) } - override Expr getASource() - { - (result = this.(FormattingFunctionCall).getFormat()) + override Expr getASource() { + result = this.(FormattingFunctionCall).getFormat() or - (result = this.(FormattingFunctionCall).getFormatArgument(_)) + result = this.(FormattingFunctionCall).getFormatArgument(_) } - override Expr getDest() - { - result = getArgument(0) - } + override Expr getDest() { result = getArgument(0) } - override predicate hasExplicitLimit() - { - exists(getParamSize()) - } + override predicate hasExplicitLimit() { exists(getParamSize()) } - override int getExplicitLimit() - { + override int getExplicitLimit() { result = getArgument(getParamSize()).getValue().toInt() * getCharSize() } - override int getMaxData() - { + override int getMaxData() { exists(FormatLiteral fl | - (fl = this.(FormattingFunctionCall).getFormat()) - and (result = fl.getMaxConvertedLength() * getCharSize()) + fl = this.(FormattingFunctionCall).getFormat() and + result = fl.getMaxConvertedLength() * getCharSize() ) } - override int getMaxDataLimited() - { + override int getMaxDataLimited() { exists(FormatLiteral fl | - (fl = this.(FormattingFunctionCall).getFormat()) - and (result = fl.getMaxConvertedLengthLimited() * getCharSize()) + fl = this.(FormattingFunctionCall).getFormat() and + result = fl.getMaxConvertedLengthLimited() * getCharSize() ) } } /** - * A call to a variant of `gets`. + * A call to a variant of `gets`. */ -class GetsBW extends BufferWriteCall -{ - GetsBW() - { +class GetsBW extends BufferWriteCall { + GetsBW() { exists(TopLevelFunction fn, string name | fn = getTarget() and name = fn.getName() | name = "gets" or // gets(dst) name = "fgets" or // fgets(dst, max_amount, src_stream) - name = "fgetws" // fgetws(dst, max_amount, src_stream) + name = "fgetws" // fgetws(dst, max_amount, src_stream) ) } - int getParamSize() - { - if exists(getArgument(1)) then ( - result = 1 - ) else ( - none() - ) - } + int getParamSize() { if exists(getArgument(1)) then result = 1 else none() } - override Type getBufferType() - { - result = this.getTarget().getParameter(0).getUnspecifiedType() - } + override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() } - override Expr getASource() - { + override Expr getASource() { if exists(getArgument(2)) then result = getArgument(2) else @@ -496,18 +411,11 @@ class GetsBW extends BufferWriteCall result = this } - override Expr getDest() - { - result = getArgument(0) - } + override Expr getDest() { result = getArgument(0) } - override predicate hasExplicitLimit() - { - exists(getParamSize()) - } + override predicate hasExplicitLimit() { exists(getParamSize()) } - override int getExplicitLimit() - { + override int getExplicitLimit() { result = getArgument(getParamSize()).getValue().toInt() * getCharSize() } } @@ -515,28 +423,25 @@ class GetsBW extends BufferWriteCall /** * A string that is written by a `scanf`-like function. */ -class ScanfBW extends BufferWrite -{ - ScanfBW() - { +class ScanfBW extends BufferWrite { + ScanfBW() { exists(ScanfFunctionCall fc, ScanfFormatLiteral fl, int arg, int args_pos | - (this = fc.getArgument(arg)) - and (args_pos = fc.getTarget().getNumberOfParameters()) - and (arg >= args_pos) - and (fl = fc.getFormat()) - and (fl.getConversionChar(arg - args_pos) = "s") + this = fc.getArgument(arg) and + args_pos = fc.getTarget().getNumberOfParameters() and + arg >= args_pos and + fl = fc.getFormat() and + fl.getConversionChar(arg - args_pos) = "s" ) } - int getParamArgs() - { - exists(FunctionCall fc | this = fc.getArgument(_) - and (result = fc.getTarget().getNumberOfParameters()) + int getParamArgs() { + exists(FunctionCall fc | + this = fc.getArgument(_) and + result = fc.getTarget().getNumberOfParameters() ) } - override Type getBufferType() - { + override Type getBufferType() { exists(ScanfFunction f, ScanfFunctionCall fc | this = fc.getArgument(_) and f = fc.getTarget() and @@ -544,36 +449,34 @@ class ScanfBW extends BufferWrite ) } - override Expr getASource() - { + override Expr getASource() { exists(ScanfFunctionCall fc | - (this = fc.getArgument(_)) and ( - // inputs are: the format string, input or the argument itself (if there's no explicit input) - (result = fc.getFormat()) or - (result = fc.getArgument(fc.getInputParameterIndex())) or - (not exists(fc.getInputParameterIndex()) and (result = this)) + this = fc.getArgument(_) and + ( + // inputs are: the format string, input or the argument itself (if there's no explicit input) + result = fc.getFormat() + or + result = fc.getArgument(fc.getInputParameterIndex()) + or + not exists(fc.getInputParameterIndex()) and result = this ) ) } - override Expr getDest() - { - result = this - } + override Expr getDest() { result = this } - override int getMaxData() - { + override int getMaxData() { exists(ScanfFunctionCall fc, ScanfFormatLiteral fl, int arg | - (this = fc.getArgument(arg)) - and (fl = fc.getFormat()) - and (result = (fl.getMaxConvertedLength(arg - getParamArgs()) + 1) * getCharSize()) // +1 is for the terminating null + this = fc.getArgument(arg) and + fl = fc.getFormat() and + result = (fl.getMaxConvertedLength(arg - getParamArgs()) + 1) * getCharSize() // +1 is for the terminating null ) } - override string getBWDesc() - { - exists(FunctionCall fc | (this = fc.getArgument(_)) - and (result = fc.getTarget().getName() + " string argument") + override string getBWDesc() { + exists(FunctionCall fc | + this = fc.getArgument(_) and + result = fc.getTarget().getName() + " string argument" ) } } @@ -582,13 +485,11 @@ class ScanfBW extends BufferWrite * A detected definition of PATH_MAX */ private int path_max() { - result = max(Macro macro | - macro.getName() = "PATH_MAX" - | macro.getBody().toInt()) + result = max(Macro macro | macro.getName() = "PATH_MAX" | macro.getBody().toInt()) } /** - * A call to `realpath`. + * A call to `realpath`. */ class RealpathBW extends BufferWriteCall { RealpathBW() { @@ -596,16 +497,14 @@ class RealpathBW extends BufferWriteCall { getTarget().hasGlobalName("realpath") // realpath(path, resolved_path); } - override Type getBufferType() - { - result = this.getTarget().getParameter(0).getUnspecifiedType() - } - + override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() } + override Expr getDest() { result = getArgument(1) } + override Expr getASource() { result = getArgument(0) } - + override int getMaxData() { - result = path_max() - and this = this // Suppress a compiler warning + result = path_max() and + this = this // Suppress a compiler warning } } diff --git a/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll b/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll index f4881f373ff..9988e20290c 100644 --- a/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll +++ b/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll @@ -1,7 +1,6 @@ /** Provides definitions related to execution of commands */ import cpp - import semmle.code.cpp.security.FunctionWithWrappers /** @@ -9,21 +8,17 @@ import semmle.code.cpp.security.FunctionWithWrappers */ class SystemFunction extends FunctionWithWrappers { SystemFunction() { - hasGlobalName("system") - or hasGlobalName("popen") - + hasGlobalName("system") or + hasGlobalName("popen") or // Windows variants - or hasGlobalName("_popen") - or hasGlobalName("_wpopen") - or hasGlobalName("_wsystem") + hasGlobalName("_popen") or + hasGlobalName("_wpopen") or + hasGlobalName("_wsystem") } - override predicate interestingArg(int arg) { - arg = 0 - } + override predicate interestingArg(int arg) { arg = 0 } } - /** * A function for running a command via varargs. Note that, at the time * of writing, FunctionWithWrappers doesn't really support varargs @@ -31,68 +26,69 @@ class SystemFunction extends FunctionWithWrappers { */ class VarargsExecFunctionCall extends FunctionCall { VarargsExecFunctionCall() { - getTarget().hasGlobalName("execl") - or getTarget().hasGlobalName("execle") - or getTarget().hasGlobalName("execlp") - + getTarget().hasGlobalName("execl") or + getTarget().hasGlobalName("execle") or + getTarget().hasGlobalName("execlp") or // Windows - or getTarget().hasGlobalName("_execl") - or getTarget().hasGlobalName("_execle") - or getTarget().hasGlobalName("_execlp") - or getTarget().hasGlobalName("_execlpe") - or getTarget().hasGlobalName("_spawnl") - or getTarget().hasGlobalName("_spawnle") - or getTarget().hasGlobalName("_spawnlp") - or getTarget().hasGlobalName("_spawnlpe") - or getTarget().hasGlobalName("_wexecl") - or getTarget().hasGlobalName("_wexecle") - or getTarget().hasGlobalName("_wexeclp") - or getTarget().hasGlobalName("_wexeclpe") - or getTarget().hasGlobalName("_wspawnl") - or getTarget().hasGlobalName("_wspawnle") - or getTarget().hasGlobalName("_wspawnlp") - or getTarget().hasGlobalName("_wspawnlpe") + getTarget().hasGlobalName("_execl") or + getTarget().hasGlobalName("_execle") or + getTarget().hasGlobalName("_execlp") or + getTarget().hasGlobalName("_execlpe") or + getTarget().hasGlobalName("_spawnl") or + getTarget().hasGlobalName("_spawnle") or + getTarget().hasGlobalName("_spawnlp") or + getTarget().hasGlobalName("_spawnlpe") or + getTarget().hasGlobalName("_wexecl") or + getTarget().hasGlobalName("_wexecle") or + getTarget().hasGlobalName("_wexeclp") or + getTarget().hasGlobalName("_wexeclpe") or + getTarget().hasGlobalName("_wspawnl") or + getTarget().hasGlobalName("_wspawnle") or + getTarget().hasGlobalName("_wspawnlp") or + getTarget().hasGlobalName("_wspawnlpe") } /** Whether the last argument to the function is an environment pointer */ predicate hasEnvironmentArgument() { - getTarget().hasGlobalName("execle") - or getTarget().hasGlobalName("_execle") - or getTarget().hasGlobalName("_execlpe") - or getTarget().hasGlobalName("_wexecle") - or getTarget().hasGlobalName("_wexeclpe") + getTarget().hasGlobalName("execle") or + getTarget().hasGlobalName("_execle") or + getTarget().hasGlobalName("_execlpe") or + getTarget().hasGlobalName("_wexecle") or + getTarget().hasGlobalName("_wexeclpe") } - /** The arguments passed to the command. The 0th such argument is conventionally - * the name of the command. */ + /** + * The arguments passed to the command. The 0th such argument is conventionally + * the name of the command. + */ Expr getCommandArgument(int idx) { - exists (int underlyingIdx | - result = getArgument(underlyingIdx) - and underlyingIdx > getCommandIdx() - and ( - underlyingIdx < getNumberOfArguments() - 1 - or not hasEnvironmentArgument() - ) - and idx = underlyingIdx - getCommandIdx() - 1) + exists(int underlyingIdx | + result = getArgument(underlyingIdx) and + underlyingIdx > getCommandIdx() and + ( + underlyingIdx < getNumberOfArguments() - 1 or + not hasEnvironmentArgument() + ) and + idx = underlyingIdx - getCommandIdx() - 1 + ) } /** The expression denoting the program to execute */ - Expr getCommand() { - result = getArgument(getCommandIdx()) - } - - /** The index of the command. The spawn variants start with a mode, whereas - * all the other ones start with the command. */ + Expr getCommand() { result = getArgument(getCommandIdx()) } + + /** + * The index of the command. The spawn variants start with a mode, whereas + * all the other ones start with the command. + */ private int getCommandIdx() { - if ( - getTarget().getName().matches("\\_spawn%") - or getTarget().getName().matches("\\_wspawn%")) + if + getTarget().getName().matches("\\_spawn%") or + getTarget().getName().matches("\\_wspawn%") then result = 1 else result = 0 } } - /** * A function for running a command using an array of arguments. Note that * FunctionWithWrappers does not support tracking multiple interesting @@ -100,63 +96,63 @@ class VarargsExecFunctionCall extends FunctionCall { */ class ArrayExecFunctionCall extends FunctionCall { ArrayExecFunctionCall() { - getTarget().hasGlobalName("execv") - or getTarget().hasGlobalName("execvp") - or getTarget().hasGlobalName("execvpe") - + getTarget().hasGlobalName("execv") or + getTarget().hasGlobalName("execvp") or + getTarget().hasGlobalName("execvpe") or // Windows variants - or getTarget().hasGlobalName("_execv") - or getTarget().hasGlobalName("_execve") - or getTarget().hasGlobalName("_execvp") - or getTarget().hasGlobalName("_execvpe") - or getTarget().hasGlobalName("_spawnv") - or getTarget().hasGlobalName("_spawnve") - or getTarget().hasGlobalName("_spawnvp") - or getTarget().hasGlobalName("_spawnvpe") - or getTarget().hasGlobalName("_wexecv") - or getTarget().hasGlobalName("_wexecve") - or getTarget().hasGlobalName("_wexecvp") - or getTarget().hasGlobalName("_wexecvpe") - or getTarget().hasGlobalName("_wspawnv") - or getTarget().hasGlobalName("_wspawnve") - or getTarget().hasGlobalName("_wspawnvp") - or getTarget().hasGlobalName("_wspawnvpe") + getTarget().hasGlobalName("_execv") or + getTarget().hasGlobalName("_execve") or + getTarget().hasGlobalName("_execvp") or + getTarget().hasGlobalName("_execvpe") or + getTarget().hasGlobalName("_spawnv") or + getTarget().hasGlobalName("_spawnve") or + getTarget().hasGlobalName("_spawnvp") or + getTarget().hasGlobalName("_spawnvpe") or + getTarget().hasGlobalName("_wexecv") or + getTarget().hasGlobalName("_wexecve") or + getTarget().hasGlobalName("_wexecvp") or + getTarget().hasGlobalName("_wexecvpe") or + getTarget().hasGlobalName("_wspawnv") or + getTarget().hasGlobalName("_wspawnve") or + getTarget().hasGlobalName("_wspawnvp") or + getTarget().hasGlobalName("_wspawnvpe") } - + /** The argument with the array of command arguments */ - Expr getArrayArgument() { - result = getArgument(getCommandIdx() + 1) - } + Expr getArrayArgument() { result = getArgument(getCommandIdx() + 1) } /** The expression denoting the program to execute */ - Expr getCommand() { - result = getArgument(getCommandIdx()) - } - - /** The index of the command. The spawn variants start with a mode, whereas - * all the other ones start with the command. */ + Expr getCommand() { result = getArgument(getCommandIdx()) } + + /** + * The index of the command. The spawn variants start with a mode, whereas + * all the other ones start with the command. + */ private int getCommandIdx() { - if ( - getTarget().getName().matches("\\_spawn%") - or getTarget().getName().matches("\\_wspawn%")) + if + getTarget().getName().matches("\\_spawn%") or + getTarget().getName().matches("\\_wspawn%") then result = 1 else result = 0 } } - -/** The name of a shell and the flag used to preface a command that should be parsed. Public - * for testing purposes. */ +/** + * The name of a shell and the flag used to preface a command that should be parsed. Public + * for testing purposes. + */ predicate shellCommandPreface(string cmd, string flag) { + (cmd = "sh" or cmd = "/bin/sh" or cmd = "bash" or cmd = "/bin/bash") and + flag = "-c" + or ( - (cmd = "sh" or cmd = "/bin/sh" or cmd = "bash" or cmd = "/bin/bash") - and (flag = "-c") - ) or ( - (cmd = "cmd" or cmd = "cmd.exe" or cmd = "CMD" or cmd = "CMD.EXE" - or cmd = "%WINDIR%\\system32\\cmd.exe" // used in Juliet tests - ) - and (flag = "/c" or flag = "/C") - ) + cmd = "cmd" or + cmd = "cmd.exe" or + cmd = "CMD" or + cmd = "CMD.EXE" or + cmd = "%WINDIR%\\system32\\cmd.exe" // used in Juliet tests + ) and + (flag = "/c" or flag = "/C") } /** @@ -166,31 +162,36 @@ predicate shellCommandPreface(string cmd, string flag) { */ predicate shellCommand(Expr command, string callChain) { // A call to a function like system() - exists (SystemFunction systemFunction | - systemFunction.outermostWrapperFunctionCall(command, callChain)) - + exists(SystemFunction systemFunction | + systemFunction.outermostWrapperFunctionCall(command, callChain) + ) + or // A call to a function like execl(), passing "sh", then "-c", and then a command. - or exists (VarargsExecFunctionCall execCall, StringLiteral commandInterpreter, StringLiteral flag, int commandIdx | - callChain = execCall.getTarget().getName() - and execCall.getCommand() = commandInterpreter - and execCall.getCommandArgument(1) = flag - and execCall.getCommandArgument(commandIdx) = command - and commandIdx > 1 - and shellCommandPreface(commandInterpreter.getValue(), flag.getValue())) - + exists( + VarargsExecFunctionCall execCall, StringLiteral commandInterpreter, StringLiteral flag, + int commandIdx + | + callChain = execCall.getTarget().getName() and + execCall.getCommand() = commandInterpreter and + execCall.getCommandArgument(1) = flag and + execCall.getCommandArgument(commandIdx) = command and + commandIdx > 1 and + shellCommandPreface(commandInterpreter.getValue(), flag.getValue()) + ) + or // A call to a function like execv(), where the array being passed is // initialized to an array literal - or exists( + exists( ArrayExecFunctionCall execCall, StringLiteral commandInterpreter, Variable arrayVariable, AggregateLiteral arrayInitializer, StringLiteral flag, int idx | - callChain = execCall.getTarget().getName() - and execCall.getCommand() = commandInterpreter - and execCall.getArrayArgument() = arrayVariable.getAnAccess() - and arrayVariable.getInitializer().getExpr() = arrayInitializer - and arrayInitializer.getChild(1) = flag - and arrayInitializer.getChild(idx) = command - and shellCommandPreface(commandInterpreter.getValue(), flag.getValue()) - and idx > 1) + callChain = execCall.getTarget().getName() and + execCall.getCommand() = commandInterpreter and + execCall.getArrayArgument() = arrayVariable.getAnAccess() and + arrayVariable.getInitializer().getExpr() = arrayInitializer and + arrayInitializer.getChild(1) = flag and + arrayInitializer.getChild(idx) = command and + shellCommandPreface(commandInterpreter.getValue(), flag.getValue()) and + idx > 1 + ) } - diff --git a/cpp/ql/src/semmle/code/cpp/security/Encryption.qll b/cpp/ql/src/semmle/code/cpp/security/Encryption.qll index 173438be3ec..61d64673314 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Encryption.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Encryption.qll @@ -1,12 +1,11 @@ // Common predicates relating to encryption in C and C++ - import cpp /** A blacklist of algorithms that are known to be insecure */ string algorithmBlacklist() { result = "DES" or result = "RC2" or - result = "RC4" or + result = "RC4" or result = "RC5" or result = "ARCFOUR" // a variant of RC4 } @@ -24,13 +23,12 @@ string algorithmBlacklistRegex() { // algorithms usually appear in names surrounded by characters that are not // alphabetical characters in the same case. This handles the upper and lower // case cases - "(^|.*[^A-Z])(" + strictconcat(algorithmBlacklist(), "|") + ")([^A-Z].*|$)" + - "|" + - // for lowercase, we want to be careful to avoid being confused by camelCase - // hence we require two preceding uppercase letters to be sure of a case switch, - // or a preceding non-alphabetic character - "(^|.*[A-Z]{2}|.*[^a-zA-Z])(" + strictconcat(algorithmBlacklist().toLowerCase(), "|") + - ")([^a-z].*|$)" + "(^|.*[^A-Z])(" + strictconcat(algorithmBlacklist(), "|") + ")([^A-Z].*|$)" + "|" + + // for lowercase, we want to be careful to avoid being confused by camelCase + // hence we require two preceding uppercase letters to be sure of a case switch, + // or a preceding non-alphabetic character + "(^|.*[A-Z]{2}|.*[^a-zA-Z])(" + strictconcat(algorithmBlacklist().toLowerCase(), "|") + + ")([^a-z].*|$)" } /** A whitelist of algorithms that are known to be secure */ @@ -46,15 +44,15 @@ string algorithmWhitelist() { /** A regex for matching strings that look like they contain a whitelisted algorithm */ string algorithmWhitelistRegex() { - // The implementation of this is a duplicate of algorithmBlacklistRegex, as it isn't + // The implementation of this is a duplicate of algorithmBlacklistRegex, as it isn't // possible to have string -> string functions at the moment - // algorithms usually appear in names surrounded by characters that are not // alphabetical characters in the same case. This handles the upper and lower // case cases result = "(^|.*[^A-Z])" + algorithmWhitelist() + "([^A-Z].*|$)" + or // for lowercase, we want to be careful to avoid being confused by camelCase // hence we require two preceding uppercase letters to be sure of a case switch, // or a preceding non-alphabetic character - or result = "(^|.*[A-Z]{2}|.*[^a-zA-Z])" + algorithmWhitelist().toLowerCase() + "([^a-z].*|$)" + result = "(^|.*[A-Z]{2}|.*[^a-zA-Z])" + algorithmWhitelist().toLowerCase() + "([^a-z].*|$)" } diff --git a/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll b/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll index 9a2070fe111..6363e3a5d14 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll @@ -4,17 +4,11 @@ import cpp * A function call that writes to a file */ class FileWrite extends Expr { - FileWrite() { - fileWrite(this, _ ,_) - } - - Expr getASource() { - fileWrite(this, result, _) - } - - Expr getDest() { - fileWrite(this, _, result) - } + FileWrite() { fileWrite(this, _, _) } + + Expr getASource() { fileWrite(this, result, _) } + + Expr getDest() { fileWrite(this, _, result) } } /** @@ -23,32 +17,28 @@ class FileWrite extends Expr { */ class BasicOStreamClass extends Type { BasicOStreamClass() { - ( - this.(Class).getName().matches("basic\\_ostream%") - ) or ( - this.getUnspecifiedType() instanceof BasicOStreamClass - ) or ( - this.(Class).getABaseClass() instanceof BasicOStreamClass - ) or ( - this.(ReferenceType).getBaseType() instanceof BasicOStreamClass - ) + this.(Class).getName().matches("basic\\_ostream%") + or + this.getUnspecifiedType() instanceof BasicOStreamClass + or + this.(Class).getABaseClass() instanceof BasicOStreamClass + or + this.(ReferenceType).getBaseType() instanceof BasicOStreamClass } } /** * A call to a member of `std::basic_ostream`, or something related, - * or a call with one of those objects as the first parameter. + * or a call with one of those objects as the first parameter. */ class BasicOStreamCall extends FunctionCall { BasicOStreamCall() { - if (getTarget() instanceof MemberFunction) then ( - getQualifier().getType() instanceof BasicOStreamClass - ) else ( - getArgument(0).getType() instanceof BasicOStreamClass - ) + if getTarget() instanceof MemberFunction + then getQualifier().getType() instanceof BasicOStreamClass + else getArgument(0).getType() instanceof BasicOStreamClass } } - + /** * Output by a function that can be chained, such as `operator<<`. */ @@ -66,16 +56,13 @@ abstract class ChainedOutputCall extends BasicOStreamCall { /** * The destination at the far left-hand end of the output chain. */ - Expr getEndDest() - { - ( - // recurse into the destination - result = getDest().(ChainedOutputCall).getEndDest() - ) or ( - // or return something other than a ChainedOutputCall - result = getDest() and - not result instanceof ChainedOutputCall - ) + Expr getEndDest() { + // recurse into the destination + result = getDest().(ChainedOutputCall).getEndDest() + or + // or return something other than a ChainedOutputCall + result = getDest() and + not result instanceof ChainedOutputCall } } @@ -83,24 +70,18 @@ abstract class ChainedOutputCall extends BasicOStreamCall { * A call to `operator<<` on an output stream. */ class OperatorLShiftCall extends ChainedOutputCall { - OperatorLShiftCall() { - getTarget().(Operator).hasName("operator<<") - } + OperatorLShiftCall() { getTarget().(Operator).hasName("operator<<") } override Expr getSource() { - if (getTarget() instanceof MemberFunction) then ( - result = getArgument(0) - ) else ( - result = getArgument(1) - ) + if getTarget() instanceof MemberFunction + then result = getArgument(0) + else result = getArgument(1) } override Expr getDest() { - if (getTarget() instanceof MemberFunction) then ( - result = getQualifier() - ) else ( - result = getArgument(0) - ) + if getTarget() instanceof MemberFunction + then result = getQualifier() + else result = getArgument(0) } } @@ -108,34 +89,22 @@ class OperatorLShiftCall extends ChainedOutputCall { * A call to 'put'. */ class PutFunctionCall extends ChainedOutputCall { - PutFunctionCall() { - getTarget().(MemberFunction).hasName("put") - } + PutFunctionCall() { getTarget().(MemberFunction).hasName("put") } - override Expr getSource() { - result = getArgument(0) - } + override Expr getSource() { result = getArgument(0) } - override Expr getDest() { - result = getQualifier() - } + override Expr getDest() { result = getQualifier() } } /** * A call to 'write'. */ class WriteFunctionCall extends ChainedOutputCall { - WriteFunctionCall() { - getTarget().(MemberFunction).hasName("write") - } + WriteFunctionCall() { getTarget().(MemberFunction).hasName("write") } - override Expr getSource() { - result = getArgument(0) - } + override Expr getSource() { result = getArgument(0) } - override Expr getDest() { - result = getQualifier() - } + override Expr getDest() { result = getQualifier() } } /** @@ -153,10 +122,13 @@ private predicate fileStreamChain(ChainedOutputCall out, Expr source, Expr dest) * Whether the function call is a write to file 'dest' from 'source'. */ private predicate fileWrite(Call write, Expr source, Expr dest) { - exists(Function f, int s, int d | f = write.getTarget() and source = write.getArgument(s) and dest = write.getArgument(d) | - exists(string name | f.hasGlobalName(name) | + exists(Function f, int s, int d | + f = write.getTarget() and source = write.getArgument(s) and dest = write.getArgument(d) + | + exists(string name | f.hasGlobalName(name) | // named functions - name = "fwrite" and s = 0 and d = 3 or + name = "fwrite" and s = 0 and d = 3 + or ( name = "fputs" or name = "fputws" or @@ -165,13 +137,16 @@ private predicate fileWrite(Call write, Expr source, Expr dest) { name = "putc" or name = "putwc" or name = "putw" - ) and s = 0 and d = 1 - ) or ( - // fprintf - s >= f.(Fprintf).getFormatParameterIndex() and - d = f.(Fprintf).getOutputParameterIndex() + ) and + s = 0 and + d = 1 ) - ) or + or + // fprintf + s >= f.(Fprintf).getFormatParameterIndex() and + d = f.(Fprintf).getOutputParameterIndex() + ) + or // file stream using '<<', 'put' or 'write' fileStreamChain(write, source, dest) } diff --git a/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll b/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll index 5ccb8aa9ad0..68974b29a09 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll @@ -2,36 +2,30 @@ import cpp import PrintfLike private import TaintTracking -private bindingset[index] -string toCause(Function func, int index) -{ - result = func.getQualifiedName() + "(" + func.getParameter(index).getName() + ")" or - ( - not exists(func.getParameter(index).getName()) and - result = func.getQualifiedName() + "(arg " + index + ")" - ) +private string toCause(Function func, int index) { + result = func.getQualifiedName() + "(" + func.getParameter(index).getName() + ")" + or + not exists(func.getParameter(index).getName()) and + result = func.getQualifiedName() + "(arg " + index + ")" } /** * Whether the parameter at index 'sourceParamIndex' of function 'source' is passed * (without any evident changes) to the parameter at index 'targetParamIndex' of function 'target'. */ -private -predicate wrapperFunctionStep(Function source, int sourceParamIndex, Function target, int targetParamIndex) -{ +private predicate wrapperFunctionStep( + Function source, int sourceParamIndex, Function target, int targetParamIndex +) { not target.isVirtual() and not source.isVirtual() and source.isDefined() and - exists(Call call, Expr arg, Parameter sourceParam | // there is a 'call' to 'target' with argument 'arg' at index 'targetParamIndex' target = resolveCall(call) and arg = call.getArgument(targetParamIndex) and - // 'call' is enclosed in 'source' source = call.getEnclosingFunction() and - // 'arg' is an access to the parameter at index 'sourceParamIndex' of function 'source' sourceParam = source.getParameter(sourceParamIndex) and not exists(sourceParam.getAnAssignedValue()) and @@ -51,40 +45,35 @@ predicate wrapperFunctionStep(Function source, int sourceParamIndex, Function ta * Subclasses should override the characteristic predicate and 'interestingArg'. */ abstract class FunctionWithWrappers extends Function { - /** * Which argument indices are relevant for wrapper function detection. */ - predicate interestingArg(int arg) { - none() - } - + predicate interestingArg(int arg) { none() } + /** * Whether 'func' is a (possibly nested) wrapper function that feeds a parameter at the given index * through to an interesting parameter of 'this' function at the given call chain 'depth'. * The call chain depth is limited to 4. */ - private - predicate wrapperFunctionLimitedDepth(Function func, int paramIndex, string callChain, int depth) - { + private predicate wrapperFunctionLimitedDepth( + Function func, int paramIndex, string callChain, int depth + ) { // base case - ( - func = this and - interestingArg(paramIndex) and - callChain = toCause(func, paramIndex) and - depth = 0 - ) - // recursive step + func = this and + interestingArg(paramIndex) and + callChain = toCause(func, paramIndex) and + depth = 0 or + // recursive step exists(Function target, int targetParamIndex, string targetCause, int targetDepth | - this.wrapperFunctionLimitedDepth(target, targetParamIndex, targetCause, targetDepth) - and targetDepth < 4 - and wrapperFunctionStep(func, paramIndex, target, targetParamIndex) - and callChain = toCause(func, paramIndex) + ", which calls " + targetCause - and depth = targetDepth + 1 + this.wrapperFunctionLimitedDepth(target, targetParamIndex, targetCause, targetDepth) and + targetDepth < 4 and + wrapperFunctionStep(func, paramIndex, target, targetParamIndex) and + callChain = toCause(func, paramIndex) + ", which calls " + targetCause and + depth = targetDepth + 1 ) } - + /** * Whether 'func' is a (possibly nested) wrapper function that feeds a parameter at the given index * through to an interesting parameter of 'this' function. @@ -92,23 +81,19 @@ abstract class FunctionWithWrappers extends Function { * The 'cause' gives the name of 'this' interesting function and its relevant parameter * at the end of the call chain. */ - private - predicate wrapperFunctionAnyDepth(Function func, int paramIndex, string cause) - { + private predicate wrapperFunctionAnyDepth(Function func, int paramIndex, string cause) { // base case - ( - func = this and - interestingArg(paramIndex) and - cause = toCause(func, paramIndex) - ) - // recursive step + func = this and + interestingArg(paramIndex) and + cause = toCause(func, paramIndex) or + // recursive step exists(Function target, int targetParamIndex | - this.wrapperFunctionAnyDepth(target, targetParamIndex, cause) - and wrapperFunctionStep(func, paramIndex, target, targetParamIndex) + this.wrapperFunctionAnyDepth(target, targetParamIndex, cause) and + wrapperFunctionStep(func, paramIndex, target, targetParamIndex) ) } - + /** * Whether 'func' is a (possibly nested) wrapper function that feeds a parameter at the given index * through to an interesting parameter of 'this' function. @@ -119,52 +104,44 @@ abstract class FunctionWithWrappers extends Function { * * If there is more than one possible 'cause', a unique one is picked (by lexicographic order). */ - predicate wrapperFunction(Function func, int paramIndex, string cause) - { - ( - cause = min(string callChain, int depth | + predicate wrapperFunction(Function func, int paramIndex, string cause) { + cause = min(string callChain, int depth | this.wrapperFunctionLimitedDepth(func, paramIndex, callChain, depth) and depth = min(int d | this.wrapperFunctionLimitedDepth(func, paramIndex, _, d) | d) - | callChain + | + callChain ) - ) or - ( - not this.wrapperFunctionLimitedDepth(func, paramIndex, _, _) and - cause = min(string targetCause, string possibleCause | + not this.wrapperFunctionLimitedDepth(func, paramIndex, _, _) and + cause = min(string targetCause, string possibleCause | this.wrapperFunctionAnyDepth(func, paramIndex, targetCause) and possibleCause = toCause(func, paramIndex) + ", which ends up calling " + targetCause - | possibleCause + | + possibleCause ) - ) } - + /** * Whether 'arg' is an argument in a call to an outermost wrapper function of 'this' function. */ - predicate outermostWrapperFunctionCall(Expr arg, string callChain) - { + predicate outermostWrapperFunctionCall(Expr arg, string callChain) { exists(Function targetFunc, Call call, int argIndex | - targetFunc = resolveCall(call) - and this.wrapperFunction(targetFunc, argIndex, callChain) - and ( + targetFunc = resolveCall(call) and + this.wrapperFunction(targetFunc, argIndex, callChain) and + ( exists(Function sourceFunc | sourceFunc = call.getEnclosingFunction() | not wrapperFunctionStep(sourceFunc, _, targetFunc, argIndex) - ) or not exists(call.getEnclosingFunction()) - ) - and arg = call.getArgument(argIndex) + ) + or + not exists(call.getEnclosingFunction()) + ) and + arg = call.getArgument(argIndex) ) } - } - class PrintfLikeFunction extends FunctionWithWrappers { - PrintfLikeFunction() { - printfLikeFunction(this, _) - } + PrintfLikeFunction() { printfLikeFunction(this, _) } - override predicate interestingArg(int arg) { - printfLikeFunction(this, arg) - } + override predicate interestingArg(int arg) { printfLikeFunction(this, arg) } } diff --git a/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll b/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll index 47ed3f4f45e..751a7a71ec7 100644 --- a/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll @@ -5,13 +5,9 @@ import FileWrite * A function call that writes to standard output or standard error */ class OutputWrite extends Expr { - OutputWrite() { - outputWrite(this, _) - } + OutputWrite() { outputWrite(this, _) } - Expr getASource() { - outputWrite(this, result) - } + Expr getASource() { outputWrite(this, result) } } /** @@ -21,7 +17,6 @@ private predicate outputVariable(Variable v) { // standard output v.hasName("cout") or v.hasName("wcout") or - // standard error v.hasName("cerr") or v.hasName("clog") or @@ -45,7 +40,8 @@ private predicate outputFile(Expr e) { ( name = e.(VariableAccess).getTarget().(GlobalVariable).toString() or name = e.findRootCause().(Macro).getName() - ) and ( + ) and + ( name = "stdout" or name = "stderr" ) @@ -56,30 +52,35 @@ private predicate outputFile(Expr e) { * is the function call a write to standard output or standard error from 'source' */ private predicate outputWrite(Expr write, Expr source) { - exists(Function f, int arg | f = write.(Call).getTarget() and source = write.(Call).getArgument(arg) | + exists(Function f, int arg | + f = write.(Call).getTarget() and source = write.(Call).getArgument(arg) + | + // printf + arg >= f.(Printf).getFormatParameterIndex() + or + // syslog + arg >= f.(Syslog).getFormatParameterIndex() + or + // puts, putchar ( - // printf - arg >= f.(Printf).getFormatParameterIndex() - ) or ( - // syslog - arg >= f.(Syslog).getFormatParameterIndex() - ) or ( - // puts, putchar - ( - f.hasGlobalName("puts") or - f.hasGlobalName("putchar") - ) and arg = 0 - ) or exists(Call wrappedCall, Expr wrappedSource | + f.hasGlobalName("puts") or + f.hasGlobalName("putchar") + ) and + arg = 0 + or + exists(Call wrappedCall, Expr wrappedSource | // wrapped output call (recursive case) outputWrite(wrappedCall, wrappedSource) and wrappedCall.getEnclosingFunction() = f and parameterUsePair(f.getParameter(arg), wrappedSource) ) - ) or ( - // output to standard output / standard error using operator<<, put or write - outputExpr(write) and - source = write.(ChainedOutputCall).getSource() - ) or exists(FileWrite fileWrite | + ) + or + // output to standard output / standard error using operator<<, put or write + outputExpr(write) and + source = write.(ChainedOutputCall).getSource() + or + exists(FileWrite fileWrite | // output to stdout, stderr as a file (using FileWrite.qll logic) write = fileWrite and outputFile(fileWrite.getDest()) and diff --git a/cpp/ql/src/semmle/code/cpp/security/Overflow.qll b/cpp/ql/src/semmle/code/cpp/security/Overflow.qll index 7a1dd19e712..ba98f42d096 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Overflow.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Overflow.qll @@ -7,10 +7,9 @@ import semmle.code.cpp.controlflow.Dominance /** is the size of this use guarded using 'abs'? */ predicate guardedAbs(Operation e, Expr use) { - exists(FunctionCall fc | - fc.getTarget().getName() = "abs" | - fc.getArgument(0).getAChild*() = use - and guardedLesser(e, fc) + exists(FunctionCall fc | fc.getTarget().getName() = "abs" | + fc.getArgument(0).getAChild*() = use and + guardedLesser(e, fc) ) } @@ -22,17 +21,20 @@ predicate guardedLesser(Operation e, Expr use) { guard = c.getControllingExpr().getAChild*() and iDominates*(c.getThen(), e.getEnclosingStmt()) ) - or exists(Loop c, RelationalOperation guard | + or + exists(Loop c, RelationalOperation guard | use = guard.getLesserOperand().getAChild*() and guard = c.getControllingExpr().getAChild*() and iDominates*(c.getStmt(), e.getEnclosingStmt()) ) - or exists(ConditionalExpr c, RelationalOperation guard | + or + exists(ConditionalExpr c, RelationalOperation guard | use = guard.getLesserOperand().getAChild*() and guard = c.getCondition().getAChild*() and c.getThen().getAChild*() = e ) - or guardedAbs(e, use) + or + guardedAbs(e, use) } /** is the size of this use guarded to be greater than something? */ @@ -43,35 +45,41 @@ predicate guardedGreater(Operation e, Expr use) { guard = c.getControllingExpr().getAChild*() and iDominates*(c.getThen(), e.getEnclosingStmt()) ) - or exists(Loop c, RelationalOperation guard | + or + exists(Loop c, RelationalOperation guard | use = guard.getGreaterOperand().getAChild*() and guard = c.getControllingExpr().getAChild*() and iDominates*(c.getStmt(), e.getEnclosingStmt()) ) - or exists(ConditionalExpr c, RelationalOperation guard | + or + exists(ConditionalExpr c, RelationalOperation guard | use = guard.getGreaterOperand().getAChild*() and guard = c.getCondition().getAChild*() and c.getThen().getAChild*() = e ) - or guardedAbs(e, use) + or + guardedAbs(e, use) } /** a use of a given variable */ -VariableAccess varUse(LocalScopeVariable v) { - result = v.getAnAccess() -} +VariableAccess varUse(LocalScopeVariable v) { result = v.getAnAccess() } /** is e not guarded against overflow by use? */ predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) { use = e.getAnOperand() and exists(LocalScopeVariable v | use.getTarget() = v | // overflow possible if large - (e instanceof AddExpr and not guardedLesser(e, varUse(v))) or - (e instanceof AssignAddExpr and not guardedLesser(e, varUse(v))) or - (e instanceof IncrementOperation and not guardedLesser(e, varUse(v)) and v.getUnspecifiedType() instanceof IntegralType) or + e instanceof AddExpr and not guardedLesser(e, varUse(v)) + or + e instanceof AssignAddExpr and not guardedLesser(e, varUse(v)) + or + e instanceof IncrementOperation and + not guardedLesser(e, varUse(v)) and + v.getUnspecifiedType() instanceof IntegralType + or // overflow possible if large or small - (e instanceof MulExpr and - not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v)))) + e instanceof MulExpr and + not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v))) ) } @@ -80,12 +88,17 @@ predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) { use = e.getAnOperand() and exists(LocalScopeVariable v | use.getTarget() = v | // underflow possible if use is left operand and small - (use = e.(SubExpr).getLeftOperand() and not guardedGreater(e, varUse(v))) or - (use = e.(AssignSubExpr).getLValue() and not guardedGreater(e, varUse(v))) or + use = e.(SubExpr).getLeftOperand() and not guardedGreater(e, varUse(v)) + or + use = e.(AssignSubExpr).getLValue() and not guardedGreater(e, varUse(v)) + or // underflow possible if small - (e instanceof DecrementOperation and not guardedGreater(e, varUse(v)) and v.getUnspecifiedType() instanceof IntegralType) or + e instanceof DecrementOperation and + not guardedGreater(e, varUse(v)) and + v.getUnspecifiedType() instanceof IntegralType + or // underflow possible if large or small - (e instanceof MulExpr and - not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v)))) + e instanceof MulExpr and + not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v))) ) } diff --git a/cpp/ql/src/semmle/code/cpp/security/PrintfLike.qll b/cpp/ql/src/semmle/code/cpp/security/PrintfLike.qll index cbb35217eae..47d0ca3aa93 100644 --- a/cpp/ql/src/semmle/code/cpp/security/PrintfLike.qll +++ b/cpp/ql/src/semmle/code/cpp/security/PrintfLike.qll @@ -2,14 +2,15 @@ import semmle.code.cpp.commons.Printf import external.ExternalArtifact predicate printfLikeFunction(Function func, int formatArg) { - (formatArg = func.(FormattingFunction).getFormatParameterIndex() and not func instanceof UserDefinedFormattingFunction) + formatArg = func.(FormattingFunction).getFormatParameterIndex() and + not func instanceof UserDefinedFormattingFunction or primitiveVariadicFormatter(func, formatArg) or exists(ExternalData data | // TODO Do this \ to / conversion in the toolchain? - data.getDataPath().replaceAll("\\", "/") = "cert/formatingFunction.csv" - and func.getName() = data.getField(0) - and formatArg = data.getFieldAsInt(1) + data.getDataPath().replaceAll("\\", "/") = "cert/formatingFunction.csv" and + func.getName() = data.getField(0) and + formatArg = data.getFieldAsInt(1) ) } diff --git a/cpp/ql/src/semmle/code/cpp/security/Security.qll b/cpp/ql/src/semmle/code/cpp/security/Security.qll index aad3b34e957..1a1c1d61ce8 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Security.qll @@ -7,116 +7,120 @@ import semmle.code.cpp.exprs.Expr import semmle.code.cpp.commons.Environment import semmle.code.cpp.security.SecurityOptions - /** * Extend this class to customize the security queries for * a particular code base. Provide no constructor in the * subclass, and override any methods that need customizing. */ class SecurityOptions extends string { - SecurityOptions() { - this = "SecurityOptions" - } - + SecurityOptions() { this = "SecurityOptions" } + /** * This predicate should hold if the function with the given * name is a pure function of its arguments. */ predicate isPureFunction(string name) { - name = "abs" - or name = "atof" - or name = "atoi" - or name = "atol" - or name = "atoll" - or name = "labs" - or name = "strcasestr" - or name = "strcat" - or name = "strchnul" - or name = "strchr" - or name = "strchrnul" - or name = "strcmp" - or name = "strcpy" - or name = "strcspn" - or name = "strdup" - or name = "strlen" - or name = "strncat" - or name = "strncmp" - or name = "strncpy" - or name = "strndup" - or name = "strnlen" - or name = "strrchr" - or name = "strspn" - or name = "strstr" - or name = "strtod" - or name = "strtof" - or name = "strtol" - or name = "strtoll" - or name = "strtoq" - or name = "strtoul" + name = "abs" or + name = "atof" or + name = "atoi" or + name = "atol" or + name = "atoll" or + name = "labs" or + name = "strcasestr" or + name = "strcat" or + name = "strchnul" or + name = "strchr" or + name = "strchrnul" or + name = "strcmp" or + name = "strcpy" or + name = "strcspn" or + name = "strdup" or + name = "strlen" or + name = "strncat" or + name = "strncmp" or + name = "strncpy" or + name = "strndup" or + name = "strnlen" or + name = "strrchr" or + name = "strspn" or + name = "strstr" or + name = "strtod" or + name = "strtof" or + name = "strtol" or + name = "strtoll" or + name = "strtoq" or + name = "strtoul" } - + /** * An argument to a function that is passed to a SQL server. */ predicate sqlArgument(string function, int arg) { // MySQL C API - (function = "mysql_query" and arg = 1) or - (function = "mysql_real_query" and arg = 1) or - + function = "mysql_query" and arg = 1 + or + function = "mysql_real_query" and arg = 1 + or // SQLite3 C API - (function = "sqlite3_exec" and arg = 1) + function = "sqlite3_exec" and arg = 1 } /** * The argument of the given function is filled in from user input. */ - predicate userInputArgument(FunctionCall functionCall, int arg) - { + predicate userInputArgument(FunctionCall functionCall, int arg) { exists(string fname | functionCall.getTarget().hasGlobalName(fname) and exists(functionCall.getArgument(arg)) and ( - (fname = "read" and arg = 1) or - (fname = "fread" and arg = 0) or - (fname = "fgets" and arg = 0) or - (fname = "fgetws" and arg = 0) or - (fname = "gets" and arg = 0) or - (fname = "getaddrinfo" and arg = 3) or - (fname = "recv" and arg = 1) or - (fname = "recvfrom" and (arg = 1 or arg = 4 or arg = 5)) or - (fname = "recvmsg" and arg = 1) or - (fname = "scanf" and arg >= 1) or - (fname = "fscanf" and arg >= 2) + fname = "read" and arg = 1 + or + fname = "fread" and arg = 0 + or + fname = "fgets" and arg = 0 + or + fname = "fgetws" and arg = 0 + or + fname = "gets" and arg = 0 + or + fname = "getaddrinfo" and arg = 3 + or + fname = "recv" and arg = 1 + or + fname = "recvfrom" and + (arg = 1 or arg = 4 or arg = 5) + or + fname = "recvmsg" and arg = 1 + or + fname = "scanf" and arg >= 1 + or + fname = "fscanf" and arg >= 2 ) ) } - + /** * The return value of the given function is filled in from user input. */ - predicate userInputReturned(FunctionCall functionCall) - { + predicate userInputReturned(FunctionCall functionCall) { exists(string fname | functionCall.getTarget().getName() = fname and - ( + ( fname = "fgets" or fname = "gets" or userInputReturn(fname) ) ) } - + /** * DEPRECATED: Users should override `userInputReturned()` instead. - * + * * note: this function is not formally tagged as `deprecated` since the * new `userInputReturned` uses it to provide compatibility with older * custom SecurityOptions.qll files. */ - predicate userInputReturn(string function) - { - none() - } + predicate userInputReturn(string function) { none() } /** * The argument of the given function is used for running a process or loading @@ -124,20 +128,30 @@ class SecurityOptions extends string { */ predicate isProcessOperationArgument(string function, int arg) { // POSIX - (function = "system" and arg = 0) - or (function = "popen" and arg = 0) - or (function = "execl" and arg = 0) - or (function = "execlp" and arg = 0) - or (function = "execle" and arg = 0) - or (function = "execv" and arg = 0) - or (function = "execvp" and arg = 0) - or (function = "execvpe" and arg = 0) - or (function = "dlopen" and arg = 0) - + function = "system" and arg = 0 + or + function = "popen" and arg = 0 + or + function = "execl" and arg = 0 + or + function = "execlp" and arg = 0 + or + function = "execle" and arg = 0 + or + function = "execv" and arg = 0 + or + function = "execvp" and arg = 0 + or + function = "execvpe" and arg = 0 + or + function = "dlopen" and arg = 0 + or // Windows - or (function = "LoadLibrary" and arg = 0) - or (function = "LoadLibraryA" and arg = 0) - or (function = "LoadLibraryW" and arg = 0) + function = "LoadLibrary" and arg = 0 + or + function = "LoadLibraryA" and arg = 0 + or + function = "LoadLibraryW" and arg = 0 } /** @@ -147,17 +161,22 @@ class SecurityOptions extends string { */ predicate isUserInput(Expr expr, string cause) { exists(FunctionCall fc, int i | - this.userInputArgument(fc, i) - and expr = fc.getArgument(i) - and cause = fc.getTarget().getName()) - or exists(FunctionCall fc | - this.userInputReturned(fc) - and expr = fc - and cause = fc.getTarget().getName()) - or (commandLineArg(expr) and cause = "argv") - or expr.(EnvironmentRead).getSourceDescription() = cause + this.userInputArgument(fc, i) and + expr = fc.getArgument(i) and + cause = fc.getTarget().getName() + ) + or + exists(FunctionCall fc | + this.userInputReturned(fc) and + expr = fc and + cause = fc.getTarget().getName() + ) + or + commandLineArg(expr) and cause = "argv" + or + expr.(EnvironmentRead).getSourceDescription() = cause } - + /** * This predicate should hold if the expression raises privilege for the * current session. The default definition only holds true for some @@ -165,66 +184,65 @@ class SecurityOptions extends string { * a particular code base to be useful. */ predicate raisesPrivilege(Expr expr) { - exists (ReturnStmt ret | ret.getExpr() = expr | - ret.getEnclosingFunction().getName() = "checkPinCode" - and ret.getExpr().getValue() = "1") - or exists (AssignExpr assign, Variable adminPrivileges | - assign = expr - and adminPrivileges.hasName("adminPrivileges") - and assign.getLValue().(Access).getTarget() = adminPrivileges - and not (assign.getRValue().(Literal).getValue() = "0")) + exists(ReturnStmt ret | ret.getExpr() = expr | + ret.getEnclosingFunction().getName() = "checkPinCode" and + ret.getExpr().getValue() = "1" + ) + or + exists(AssignExpr assign, Variable adminPrivileges | + assign = expr and + adminPrivileges.hasName("adminPrivileges") and + assign.getLValue().(Access).getTarget() = adminPrivileges and + not assign.getRValue().(Literal).getValue() = "0" + ) } } /** * An access to the argv argument to main(). */ -private predicate commandLineArg(Expr e) -{ +private predicate commandLineArg(Expr e) { exists(Parameter argv | argv(argv) and - argv.getAnAccess() = e) + argv.getAnAccess() = e + ) } /** The argv parameter to the main function */ -predicate argv(Parameter argv) -{ +predicate argv(Parameter argv) { exists(Function f | - f.hasGlobalName("main") - and f.getParameter(1) = argv) + f.hasGlobalName("main") and + f.getParameter(1) = argv + ) } /** Convenience accessor for SecurityOptions.isPureFunction */ -predicate isPureFunction(string name) { - exists (SecurityOptions opts | opts.isPureFunction(name)) -} +predicate isPureFunction(string name) { exists(SecurityOptions opts | opts.isPureFunction(name)) } /** Convenience accessor for SecurityOptions.userInputArgument */ predicate userInputArgument(FunctionCall functionCall, int arg) { - exists (SecurityOptions opts | opts.userInputArgument(functionCall, arg)) + exists(SecurityOptions opts | opts.userInputArgument(functionCall, arg)) } /** Convenience accessor for SecurityOptions.userInputReturn */ predicate userInputReturned(FunctionCall functionCall) { - exists (SecurityOptions opts | opts.userInputReturned(functionCall)) + exists(SecurityOptions opts | opts.userInputReturned(functionCall)) } /** Convenience accessor for SecurityOptions.isUserInput */ predicate isUserInput(Expr expr, string cause) { - exists (SecurityOptions opts | opts.isUserInput(expr, cause)) + exists(SecurityOptions opts | opts.isUserInput(expr, cause)) } /** Convenience accessor for SecurityOptions.isProcessOperationArgument */ predicate isProcessOperationArgument(string function, int arg) { - exists (SecurityOptions opts | opts.isProcessOperationArgument(function, arg)) + exists(SecurityOptions opts | opts.isProcessOperationArgument(function, arg)) } /** Convenient accessor for SecurityOptions.raisesPrivilege */ -predicate raisesPrivilege(Expr expr) { - exists (SecurityOptions opts | opts.raisesPrivilege(expr)) -} +predicate raisesPrivilege(Expr expr) { exists(SecurityOptions opts | opts.raisesPrivilege(expr)) } /** Convenience accessor for SecurityOptions.sqlArgument */ predicate sqlArgument(string function, int arg) { - exists (SecurityOptions opts | opts.sqlArgument(function, arg)) + exists(SecurityOptions opts | opts.sqlArgument(function, arg)) } diff --git a/cpp/ql/src/semmle/code/cpp/security/SecurityOptions.qll b/cpp/ql/src/semmle/code/cpp/security/SecurityOptions.qll index 47889a1f42e..8d35d80e613 100644 --- a/cpp/ql/src/semmle/code/cpp/security/SecurityOptions.qll +++ b/cpp/ql/src/semmle/code/cpp/security/SecurityOptions.qll @@ -11,37 +11,35 @@ import semmle.code.cpp.security.Security class CustomSecurityOptions extends SecurityOptions { override predicate sqlArgument(string function, int arg) { - SecurityOptions.super.sqlArgument(function, arg) or + SecurityOptions.super.sqlArgument(function, arg) + or // --- custom functions that access SQL code via one of their arguments: // 'arg' is the 0-based index of the argument that contains an SQL string // for example: (function = "MySpecialSqlFunction" and arg = 0) none() // rules to match custom functions replace this line } - override predicate userInputArgument(FunctionCall functionCall, int arg) - { - SecurityOptions.super.userInputArgument(functionCall, arg) or + override predicate userInputArgument(FunctionCall functionCall, int arg) { + SecurityOptions.super.userInputArgument(functionCall, arg) + or exists(string fname | functionCall.getTarget().hasGlobalName(fname) and - exists(functionCall.getArgument(arg)) and ( - // --- custom functions that return user input via one of their arguments: - // 'arg' is the 0-based index of the argument that is used to return user input - // for example: (fname = "readXmlInto" and arg = 1) - none() // rules to match custom functions replace this line - ) + exists(functionCall.getArgument(arg)) and + // --- custom functions that return user input via one of their arguments: + // 'arg' is the 0-based index of the argument that is used to return user input + // for example: (fname = "readXmlInto" and arg = 1) + none() // rules to match custom functions replace this line ) } - override predicate userInputReturned(FunctionCall functionCall) - { - SecurityOptions.super.userInputReturned(functionCall) or + override predicate userInputReturned(FunctionCall functionCall) { + SecurityOptions.super.userInputReturned(functionCall) + or exists(string fname | functionCall.getTarget().hasGlobalName(fname) and - ( - // --- custom functions that return user input via their return value: - // for example: fname = "xmlReadAttribute" - none() // rules to match custom functions replace this line - ) + // --- custom functions that return user input via their return value: + // for example: fname = "xmlReadAttribute" + none() // rules to match custom functions replace this line ) } } diff --git a/cpp/ql/src/semmle/code/cpp/security/SensitiveExprs.qll b/cpp/ql/src/semmle/code/cpp/security/SensitiveExprs.qll index c19cfd4f090..41cf1e814e7 100644 --- a/cpp/ql/src/semmle/code/cpp/security/SensitiveExprs.qll +++ b/cpp/ql/src/semmle/code/cpp/security/SensitiveExprs.qll @@ -14,13 +14,13 @@ private string nonSuspicious() { result = "%crypt%" } -abstract class SensitiveExpr extends Expr {} +abstract class SensitiveExpr extends Expr { } class SensitiveVarAccess extends SensitiveExpr { SensitiveVarAccess() { this instanceof VariableAccess and exists(string s | this.toString().toLowerCase() = s | - s.matches(suspicious())and + s.matches(suspicious()) and not s.matches(nonSuspicious()) ) } @@ -30,8 +30,8 @@ class SensitiveCall extends SensitiveExpr { SensitiveCall() { this instanceof FunctionCall and exists(string s | this.toString().toLowerCase() = s | - s.matches(suspicious())and + s.matches(suspicious()) and not s.matches(nonSuspicious()) ) - } + } } diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll index 3cb563ccd58..21dffb03244 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll @@ -6,50 +6,44 @@ import cpp import Security /** Expressions that change the value of a variable */ -private -predicate valueSource(Expr expr) -{ +private predicate valueSource(Expr expr) { exists(AssignExpr ae | expr = ae.getLValue()) or exists(FunctionCall fc, int i | - userInputArgument(fc, i) - and expr = fc.getArgument(i)) + userInputArgument(fc, i) and + expr = fc.getArgument(i) + ) or exists(FunctionCall c, int arg | copyValueBetweenArguments(c.getTarget(), _, arg) and - expr = c.getArgument(arg)) + expr = c.getArgument(arg) + ) or exists(FunctionCall c, int arg | c.getTarget().getParameter(arg).getType() instanceof ReferenceType and - expr = c.getArgument(arg)) -} - -/** Expressions that are inside an expression that changes the value of a variable */ -private -predicate insideValueSource(Expr expr) -{ - valueSource(expr) or - ( - insideValueSource(expr.getParent()) and - - // A modification of array[offset] does not modify offset - not expr.getParent().(ArrayExpr).getArrayOffset() = expr + expr = c.getArgument(arg) ) } -private -predicate isPointer(Type type) -{ - type instanceof PointerType - or isPointer(type.(ReferenceType).getBaseType()) +/** Expressions that are inside an expression that changes the value of a variable */ +private predicate insideValueSource(Expr expr) { + valueSource(expr) + or + insideValueSource(expr.getParent()) and + // A modification of array[offset] does not modify offset + not expr.getParent().(ArrayExpr).getArrayOffset() = expr +} + +private predicate isPointer(Type type) { + type instanceof PointerType or + isPointer(type.(ReferenceType).getBaseType()) } /** * Tracks data flow from src to dest. * If this is used in the left side of an assignment src and dest should be swapped */ -private -predicate moveToDependingOnSide(Expr src, Expr dest) { +private predicate moveToDependingOnSide(Expr src, Expr dest) { exists(ParenthesisExpr e | src = e.getAChild() and dest = e @@ -69,36 +63,48 @@ predicate moveToDependingOnSide(Expr src, Expr dest) { src = e.getOperand() and dest = e ) + or // if var+offset is tainted, then so is var - or exists (VariableAccess base, BinaryOperation binop | - dest = binop - and (base = binop.getLeftOperand() or base = binop.getRightOperand()) - and isPointer(base.getType()) - and base.getTarget() instanceof LocalScopeVariable - and src = base - + exists(VariableAccess base, BinaryOperation binop | + dest = binop and + (base = binop.getLeftOperand() or base = binop.getRightOperand()) and + isPointer(base.getType()) and + base.getTarget() instanceof LocalScopeVariable and + src = base and // flow through pointer-pointer subtraction is dubious, the result should be // a number bounded by the size of the pointed-to thing. - and not binop instanceof PointerDiffExpr) - or exists (UnaryOperation unop | - dest = unop - and unop.getAnOperand() = src) - or (exists (BinaryOperation binop | - dest = binop - and binop.getLeftOperand() = src - and predictable(binop.getRightOperand()))) - or (exists (BinaryOperation binop | - dest = binop - and binop.getRightOperand() = src - and predictable(binop.getLeftOperand()))) - or exists (Cast cast | - dest = cast - and src = cast.getExpr()) - or exists (ConditionalExpr cond | - cond = dest - and ( - cond.getThen() = src - or cond.getElse() = src)) + not binop instanceof PointerDiffExpr + ) + or + exists(UnaryOperation unop | + dest = unop and + unop.getAnOperand() = src + ) + or + exists(BinaryOperation binop | + dest = binop and + binop.getLeftOperand() = src and + predictable(binop.getRightOperand()) + ) + or + exists(BinaryOperation binop | + dest = binop and + binop.getRightOperand() = src and + predictable(binop.getLeftOperand()) + ) + or + exists(Cast cast | + dest = cast and + src = cast.getExpr() + ) + or + exists(ConditionalExpr cond | + cond = dest and + ( + cond.getThen() = src or + cond.getElse() = src + ) + ) } /** @@ -110,46 +116,49 @@ predicate moveToDependingOnSide(Expr src, Expr dest) { * (this is done to avoid false positives). Because of this we need to track if the tainted element came from an argument * or not, and for that we use destFromArg */ -private -predicate betweenFunctionsValueMoveTo(Element src, Element dest, boolean destFromArg) -{ - not unreachable(src) - and not unreachable(dest) - and ( +private predicate betweenFunctionsValueMoveTo(Element src, Element dest, boolean destFromArg) { + not unreachable(src) and + not unreachable(dest) and + ( exists(Call call, Function called, int i | - src = call.getArgument(i) - and resolveCallWithParam(call, called, i, dest) - and destFromArg = true) - + src = call.getArgument(i) and + resolveCallWithParam(call, called, i, dest) and + destFromArg = true + ) + or // Only move the return of the function to the function itself if the value didn't came from an // argument, or else we would taint all the calls to one function if one argument is tainted // somewhere - or exists(Function f, ReturnStmt ret | - ret.getEnclosingFunction() = f - and src = ret.getExpr() - and destFromArg = false - and dest = f) - or exists(Call call, Function f | - f = resolveCall(call) - and src = f - and dest = call - and destFromArg = false) - + exists(Function f, ReturnStmt ret | + ret.getEnclosingFunction() = f and + src = ret.getExpr() and + destFromArg = false and + dest = f + ) + or + exists(Call call, Function f | + f = resolveCall(call) and + src = f and + dest = call and + destFromArg = false + ) + or // If a parameter of type reference is tainted inside a function, taint the argument too - or exists(Call call, Function f, int pi, Parameter p | - resolveCallWithParam(call, f, pi, p) - and p.getType() instanceof ReferenceType - and src = p - and dest = call.getArgument(pi) - and destFromArg = false) + exists(Call call, Function f, int pi, Parameter p | + resolveCallWithParam(call, f, pi, p) and + p.getType() instanceof ReferenceType and + src = p and + dest = call.getArgument(pi) and + destFromArg = false + ) ) } // predicate folding for proper join-order -pragma [nomagic] // bad magic: pushes down predicate that ruins join-order +// bad magic: pushes down predicate that ruins join-order +pragma[nomagic] private predicate resolveCallWithParam(Call call, Function called, int i, Parameter p) { - called = resolveCall(call) - and + called = resolveCall(call) and p = called.getParameter(i) } @@ -157,112 +166,128 @@ private predicate resolveCallWithParam(Call call, Function called, int i, Parame library class FlowVariable extends Variable { FlowVariable() { ( - this instanceof LocalScopeVariable - or this instanceof GlobalOrNamespaceVariable - ) - and not argv(this) + this instanceof LocalScopeVariable or + this instanceof GlobalOrNamespaceVariable + ) and + not argv(this) } } /** A local scope variable for which flow through is allowed. */ library class FlowLocalScopeVariable extends Variable { - FlowLocalScopeVariable() { - this instanceof LocalScopeVariable - } + FlowLocalScopeVariable() { this instanceof LocalScopeVariable } } -private -predicate insideFunctionValueMoveTo(Element src, Element dest) -{ - not unreachable(src) - and not unreachable(dest) - and ( +private predicate insideFunctionValueMoveTo(Element src, Element dest) { + not unreachable(src) and + not unreachable(dest) and + ( // Taint all variable usages when one is tainted // This function taints global variables but doesn't taint from a global variable (see globalVariableValueMoveTo) exists(FlowLocalScopeVariable v | - src = v - and dest = v.getAnAccess() - and not insideValueSource(dest)) - or exists(FlowVariable v | - src = v.getAnAccess() - and dest = v - and insideValueSource(src)) - + src = v and + dest = v.getAnAccess() and + not insideValueSource(dest) + ) + or + exists(FlowVariable v | + src = v.getAnAccess() and + dest = v and + insideValueSource(src) + ) + or // Taint all union usages when one is tainted // This function taints global variables but doesn't taint from a global variable (see globalVariableValueMoveTo) - or exists(FlowLocalScopeVariable v, FieldAccess a | - unionAccess(v, _, a) - and src = v - and dest = a - and not insideValueSource(dest)) - or exists(FlowVariable v, FieldAccess a | - unionAccess(v, _, a) - and src = a - and dest = v - and insideValueSource(src)) - + exists(FlowLocalScopeVariable v, FieldAccess a | + unionAccess(v, _, a) and + src = v and + dest = a and + not insideValueSource(dest) + ) + or + exists(FlowVariable v, FieldAccess a | + unionAccess(v, _, a) and + src = a and + dest = v and + insideValueSource(src) + ) + or // If a pointer is tainted, taint the original variable - or exists(FlowVariable p, FlowVariable v, AddressOfExpr e | - p.getAnAssignedValue() = e - and e.getOperand() = v.getAnAccess() - and src = p - and dest = v) + exists(FlowVariable p, FlowVariable v, AddressOfExpr e | + p.getAnAssignedValue() = e and + e.getOperand() = v.getAnAccess() and + src = p and + dest = v + ) + or // If a reference is tainted, taint the original variable - or exists(FlowVariable r, FlowVariable v | - r.getType() instanceof ReferenceType - and r.getInitializer().getExpr() = v.getAnAccess() - and src = r - and dest = v) - - or exists (Variable var | - var = dest - and var.getInitializer().getExpr() = src) - or exists(AssignExpr ae | - src = ae.getRValue() - and dest = ae.getLValue()) - or exists (CommaExpr comma | - comma = dest - and comma.getRightOperand() = src) - or exists(FunctionCall c, int sourceArg, int destArg | - copyValueBetweenArguments(c.getTarget(), sourceArg, destArg) + exists(FlowVariable r, FlowVariable v | + r.getType() instanceof ReferenceType and + r.getInitializer().getExpr() = v.getAnAccess() and + src = r and + dest = v + ) + or + exists(Variable var | + var = dest and + var.getInitializer().getExpr() = src + ) + or + exists(AssignExpr ae | + src = ae.getRValue() and + dest = ae.getLValue() + ) + or + exists(CommaExpr comma | + comma = dest and + comma.getRightOperand() = src + ) + or + exists(FunctionCall c, int sourceArg, int destArg | + copyValueBetweenArguments(c.getTarget(), sourceArg, destArg) and // Only consider copies from `printf`-like functions if the format is a string - and ( + ( exists(FormattingFunctionCall ffc, FormatLiteral format, string argFormat | - ffc = c - and format = ffc.getFormat() - and format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = argFormat - and (argFormat = "s" or argFormat = "S") + ffc = c and + format = ffc.getFormat() and + format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = argFormat and + (argFormat = "s" or argFormat = "S") ) - or not exists(FormatLiteral fl | fl = c.(FormattingFunctionCall).getFormat()) - or not c instanceof FormattingFunctionCall - ) - and src = c.getArgument(sourceArg) - and dest = c.getArgument(destArg)) - or exists(FunctionCall c, int sourceArg | - returnArgument(c.getTarget(), sourceArg) - and src = c.getArgument(sourceArg) - and dest = c) - or exists(FormattingFunctionCall formattingSend, int arg, FormatLiteral format, string argFormat | - dest = formattingSend - and formattingSend.getArgument(arg) = src - and format = formattingSend.getFormat() - and format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = argFormat - and (argFormat = "s" or argFormat = "S" or argFormat = "@")) + or + not exists(FormatLiteral fl | fl = c.(FormattingFunctionCall).getFormat()) + or + not c instanceof FormattingFunctionCall + ) and + src = c.getArgument(sourceArg) and + dest = c.getArgument(destArg) + ) + or + exists(FunctionCall c, int sourceArg | + returnArgument(c.getTarget(), sourceArg) and + src = c.getArgument(sourceArg) and + dest = c + ) + or + exists(FormattingFunctionCall formattingSend, int arg, FormatLiteral format, string argFormat | + dest = formattingSend and + formattingSend.getArgument(arg) = src and + format = formattingSend.getFormat() and + format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = argFormat and + (argFormat = "s" or argFormat = "S" or argFormat = "@") + ) + or // Expressions computed from tainted data are also tainted - or exists(FunctionCall call | dest = call and isPureFunction(call.getTarget().getName()) | + exists(FunctionCall call | dest = call and isPureFunction(call.getTarget().getName()) | call.getAnArgument() = src and forall(Expr arg | arg = call.getAnArgument() | arg = src or predictable(arg)) and - // flow through `strlen` tends to cause dubious results, if the length is // bounded. not call.getTarget().getName() = "strlen" ) - or exists(Element a, Element b | + or + exists(Element a, Element b | moveToDependingOnSide(a, b) and - if insideValueSource(a) then - (src = b and dest = a) - else - (src = a and dest = b) + if insideValueSource(a) then (src = b and dest = a) else (src = a and dest = b) ) ) } @@ -271,86 +296,84 @@ predicate insideFunctionValueMoveTo(Element src, Element dest) * Handles data flow from global variables to its usages. * The tainting for the global variable itself is done at insideFunctionValueMoveTo. */ -private -predicate globalVariableValueMoveTo(GlobalOrNamespaceVariable src, Expr dest) -{ - not unreachable(dest) - and ( +private predicate globalVariableValueMoveTo(GlobalOrNamespaceVariable src, Expr dest) { + not unreachable(dest) and + ( exists(GlobalOrNamespaceVariable v | - src = v - and dest = v.getAnAccess() - and not insideValueSource(dest)) - or exists(GlobalOrNamespaceVariable v, FieldAccess a | - unionAccess(v, _, a) - and src = v - and dest = a - and not insideValueSource(dest)) + src = v and + dest = v.getAnAccess() and + not insideValueSource(dest) + ) + or + exists(GlobalOrNamespaceVariable v, FieldAccess a | + unionAccess(v, _, a) and + src = v and + dest = a and + not insideValueSource(dest) + ) ) } -private -predicate unionAccess(Variable v, Field f, FieldAccess a) -{ - f.getDeclaringType() instanceof Union - and a.getTarget() = f - and a.getQualifier() = v.getAnAccess() +private predicate unionAccess(Variable v, Field f, FieldAccess a) { + f.getDeclaringType() instanceof Union and + a.getTarget() = f and + a.getQualifier() = v.getAnAccess() } GlobalOrNamespaceVariable globalVarFromId(string id) { - if result instanceof NamespaceVariable then - id = result.getNamespace() + "::" + result.getName() - else - id = result.getName() + if result instanceof NamespaceVariable + then id = result.getNamespace() + "::" + result.getName() + else id = result.getName() } - /** * A variable that has any kind of upper-bound check anywhere in the program */ -private -predicate hasUpperBoundsCheck(Variable var) { - exists (BinaryOperation oper, VariableAccess access | - (oper.getOperator() = "<" or oper.getOperator() = "<=" or oper.getOperator() = ">" or oper.getOperator() = ">=") - and oper.getLeftOperand() = access - and access.getTarget() = var - +private predicate hasUpperBoundsCheck(Variable var) { + exists(BinaryOperation oper, VariableAccess access | + ( + oper.getOperator() = "<" or + oper.getOperator() = "<=" or + oper.getOperator() = ">" or + oper.getOperator() = ">=" + ) and + oper.getLeftOperand() = access and + access.getTarget() = var and // Comparing to 0 is not an upper bound check - and not oper.getRightOperand().getValue() = "0") + not oper.getRightOperand().getValue() = "0" + ) } -private cached -predicate taintedWithArgsAndGlobalVars(Element src, Element dest, boolean destFromArg, string globalVar) -{ - ( - isUserInput(src, _) - and not unreachable(src) - and dest = src - and destFromArg = false - and globalVar = "" - ) - or exists (Element other, boolean otherFromArg, string otherGlobalVar | taintedWithArgsAndGlobalVars(src, other, otherFromArg, otherGlobalVar) | - not unreachable(dest) - and not hasUpperBoundsCheck(dest) - and ( +private predicate taintedWithArgsAndGlobalVars( + Element src, Element dest, boolean destFromArg, string globalVar +) { + isUserInput(src, _) and + not unreachable(src) and + dest = src and + destFromArg = false and + globalVar = "" + or + exists(Element other, boolean otherFromArg, string otherGlobalVar | + taintedWithArgsAndGlobalVars(src, other, otherFromArg, otherGlobalVar) + | + not unreachable(dest) and + not hasUpperBoundsCheck(dest) and + ( // Direct flow from one expression to another. - ( - betweenFunctionsValueMoveTo(other, dest, destFromArg) - and (destFromArg = true or otherFromArg = false) - and globalVar = otherGlobalVar - ) + betweenFunctionsValueMoveTo(other, dest, destFromArg) and + (destFromArg = true or otherFromArg = false) and + globalVar = otherGlobalVar or - ( - insideFunctionValueMoveTo(other, dest) - and destFromArg = otherFromArg - and globalVar = otherGlobalVar - ) + insideFunctionValueMoveTo(other, dest) and + destFromArg = otherFromArg and + globalVar = otherGlobalVar or exists(GlobalOrNamespaceVariable v | - v = other - and globalVariableValueMoveTo(v, dest) - and destFromArg = false - and v = globalVarFromId(globalVar) + v = other and + globalVariableValueMoveTo(v, dest) and + destFromArg = false and + v = globalVarFromId(globalVar) ) ) ) @@ -389,72 +412,117 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global * predictable. */ private predicate predictable(Expr expr) { - (expr instanceof Literal) - or exists (BinaryOperation binop | binop = expr | - predictable(binop.getLeftOperand()) and predictable(binop.getRightOperand())) - or exists (UnaryOperation unop | unop = expr | - predictable(unop.getOperand())) + expr instanceof Literal + or + exists(BinaryOperation binop | binop = expr | + predictable(binop.getLeftOperand()) and predictable(binop.getRightOperand()) + ) + or + exists(UnaryOperation unop | unop = expr | predictable(unop.getOperand())) } -private int maxArgIndex(Function f) -{ - result = max(FunctionCall fc, int toMax | (fc.getTarget() = f) and (toMax = fc.getNumberOfArguments() - 1) | toMax) +private int maxArgIndex(Function f) { + result = max(FunctionCall fc, int toMax | + fc.getTarget() = f and toMax = fc.getNumberOfArguments() - 1 + | + toMax + ) } /** Functions that copy the value of one argument to another */ -private predicate copyValueBetweenArguments(Function f, int sourceArg, int destArg) -{ - (f.hasGlobalName("memcpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("__builtin___memcpy_chk") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("memmove") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("strcat") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("_mbscat") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("wcsncat") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("strncat") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("_mbsncat") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("wcsncat") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("strcpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("_mbscpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("wcscpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("strncpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("_mbsncpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("wcsncpy") and sourceArg = 1 and destArg = 0) - or (f.hasGlobalName("inet_aton") and sourceArg = 0 and destArg = 1) - or (f.hasGlobalName("inet_pton") and sourceArg = 1 and destArg = 2) - or (f.hasGlobalName("strftime") and sourceArg in [2 .. maxArgIndex(f)] and destArg = 0) - or exists(FormattingFunction ff | ff = f | - sourceArg in [ff.getFormatParameterIndex() .. maxArgIndex(f)] - and destArg = ff.getOutputParameterIndex() +private predicate copyValueBetweenArguments(Function f, int sourceArg, int destArg) { + f.hasGlobalName("memcpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("__builtin___memcpy_chk") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("memmove") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("strcat") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("_mbscat") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("wcsncat") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("strncat") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("_mbsncat") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("wcsncat") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("strcpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("_mbscpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("wcscpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("strncpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("_mbsncpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("wcsncpy") and sourceArg = 1 and destArg = 0 + or + f.hasGlobalName("inet_aton") and sourceArg = 0 and destArg = 1 + or + f.hasGlobalName("inet_pton") and sourceArg = 1 and destArg = 2 + or + f.hasGlobalName("strftime") and sourceArg in [2 .. maxArgIndex(f)] and destArg = 0 + or + exists(FormattingFunction ff | ff = f | + sourceArg in [ff.getFormatParameterIndex() .. maxArgIndex(f)] and + destArg = ff.getOutputParameterIndex() ) } /** Functions where if one of the arguments is tainted, the result should be tainted */ -private predicate returnArgument(Function f, int sourceArg) -{ - (f.hasGlobalName("memcpy") and sourceArg = 0) - or (f.hasGlobalName("__builtin___memcpy_chk") and sourceArg = 0) - or (f.hasGlobalName("memmove") and sourceArg = 0) - or (f.hasGlobalName("strcat") and sourceArg = 0) - or (f.hasGlobalName("_mbscat") and sourceArg = 0) - or (f.hasGlobalName("wcsncat") and sourceArg = 0) - or (f.hasGlobalName("strncat") and sourceArg = 0) - or (f.hasGlobalName("_mbsncat") and sourceArg = 0) - or (f.hasGlobalName("wcsncat") and sourceArg = 0) - or (f.hasGlobalName("strcpy") and sourceArg = 0) - or (f.hasGlobalName("_mbscpy") and sourceArg = 0) - or (f.hasGlobalName("wcscpy") and sourceArg = 0) - or (f.hasGlobalName("strncpy") and sourceArg = 0) - or (f.hasGlobalName("_mbsncpy") and sourceArg = 0) - or (f.hasGlobalName("wcsncpy") and sourceArg = 0) - or (f.hasGlobalName("inet_ntoa") and sourceArg = 0) - or (f.hasGlobalName("inet_addr") and sourceArg = 0) - or (f.hasGlobalName("inet_network") and sourceArg = 0) - or (f.hasGlobalName("inet_ntoa") and sourceArg = 0) - or (f.hasGlobalName("inet_makeaddr") and (sourceArg = 0 or sourceArg = 1)) - or (f.hasGlobalName("inet_lnaof") and sourceArg = 0) - or (f.hasGlobalName("inet_netof") and sourceArg = 0) - or (f.hasGlobalName("gethostbyname") and sourceArg = 0) - or (f.hasGlobalName("gethostbyaddr") and sourceArg = 0) +private predicate returnArgument(Function f, int sourceArg) { + f.hasGlobalName("memcpy") and sourceArg = 0 + or + f.hasGlobalName("__builtin___memcpy_chk") and sourceArg = 0 + or + f.hasGlobalName("memmove") and sourceArg = 0 + or + f.hasGlobalName("strcat") and sourceArg = 0 + or + f.hasGlobalName("_mbscat") and sourceArg = 0 + or + f.hasGlobalName("wcsncat") and sourceArg = 0 + or + f.hasGlobalName("strncat") and sourceArg = 0 + or + f.hasGlobalName("_mbsncat") and sourceArg = 0 + or + f.hasGlobalName("wcsncat") and sourceArg = 0 + or + f.hasGlobalName("strcpy") and sourceArg = 0 + or + f.hasGlobalName("_mbscpy") and sourceArg = 0 + or + f.hasGlobalName("wcscpy") and sourceArg = 0 + or + f.hasGlobalName("strncpy") and sourceArg = 0 + or + f.hasGlobalName("_mbsncpy") and sourceArg = 0 + or + f.hasGlobalName("wcsncpy") and sourceArg = 0 + or + f.hasGlobalName("inet_ntoa") and sourceArg = 0 + or + f.hasGlobalName("inet_addr") and sourceArg = 0 + or + f.hasGlobalName("inet_network") and sourceArg = 0 + or + f.hasGlobalName("inet_ntoa") and sourceArg = 0 + or + f.hasGlobalName("inet_makeaddr") and + (sourceArg = 0 or sourceArg = 1) + or + f.hasGlobalName("inet_lnaof") and sourceArg = 0 + or + f.hasGlobalName("inet_netof") and sourceArg = 0 + or + f.hasGlobalName("gethostbyname") and sourceArg = 0 + or + f.hasGlobalName("gethostbyaddr") and sourceArg = 0 } /** @@ -471,11 +539,13 @@ Function resolveCall(Call call) { } /** A data sensitive call expression. */ -library abstract class DataSensitiveCallExpr extends Expr { +abstract library class DataSensitiveCallExpr extends Expr { DataSensitiveCallExpr() { not unreachable(this) } abstract Expr getSrc(); - cached abstract Function resolve(); + + cached + abstract Function resolve(); /** * Whether `src` can flow to this call expression. @@ -486,8 +556,7 @@ library abstract class DataSensitiveCallExpr extends Expr { src = getSrc() and allowFromArg = true or exists(Element other, boolean allowOtherFromArg | flowsFrom(other, allowOtherFromArg) | - exists(boolean otherFromArg | - betweenFunctionsValueMoveToStatic(src, other, otherFromArg) | + exists(boolean otherFromArg | betweenFunctionsValueMoveToStatic(src, other, otherFromArg) | otherFromArg = true and allowOtherFromArg = true and allowFromArg = true or otherFromArg = false and allowFromArg = false @@ -519,10 +588,8 @@ library class DataSensitiveOverriddenFunctionCall extends DataSensitiveCallExpr, override MemberFunction resolve() { exists(NewExpr new | - flowsFrom(new, true) - and - memberFunctionFromNewExpr(new, result) - and + flowsFrom(new, true) and + memberFunctionFromNewExpr(new, result) and result.overrides*(getTarget().(VirtualFunction)) ) } @@ -533,39 +600,42 @@ private predicate memberFunctionFromNewExpr(NewExpr new, MemberFunction f) { } /** Same as `betweenFunctionsValueMoveTo`, but calls are resolved to their static target. */ -private -predicate betweenFunctionsValueMoveToStatic(Element src, Element dest, boolean destFromArg) -{ - not unreachable(src) - and not unreachable(dest) - and ( - exists (FunctionCall call, Function called, int i | - src = call.getArgument(i) - and called = call.getTarget() - and dest = called.getParameter(i) - and destFromArg = true) - +private predicate betweenFunctionsValueMoveToStatic(Element src, Element dest, boolean destFromArg) { + not unreachable(src) and + not unreachable(dest) and + ( + exists(FunctionCall call, Function called, int i | + src = call.getArgument(i) and + called = call.getTarget() and + dest = called.getParameter(i) and + destFromArg = true + ) + or // Only move the return of the function to the function itself if the value didn't came from an // argument, or else we would taint all the calls to one function if one argument is tainted // somewhere - or exists(Function f, ReturnStmt ret | - ret.getEnclosingFunction() = f - and src = ret.getExpr() - and destFromArg = false - and dest = f) - or exists(FunctionCall call, Function f | - call.getTarget() = f - and src = f - and dest = call - and destFromArg = false) - + exists(Function f, ReturnStmt ret | + ret.getEnclosingFunction() = f and + src = ret.getExpr() and + destFromArg = false and + dest = f + ) + or + exists(FunctionCall call, Function f | + call.getTarget() = f and + src = f and + dest = call and + destFromArg = false + ) + or // If a parameter of type reference is tainted inside a function, taint the argument too - or exists(FunctionCall call, Function f, int pi, Parameter p | - call.getTarget() = f - and f.getParameter(pi) = p - and p.getType() instanceof ReferenceType - and src = p - and dest = call.getArgument(pi) - and destFromArg = false) + exists(FunctionCall call, Function f, int pi, Parameter p | + call.getTarget() = f and + f.getParameter(pi) = p and + p.getType() instanceof ReferenceType and + src = p and + dest = call.getArgument(pi) and + destFromArg = false + ) ) } diff --git a/cpp/ql/src/semmle/code/cpp/stmts/Block.qll b/cpp/ql/src/semmle/code/cpp/stmts/Block.qll index 3cfc78c1d1d..4f69f52caf4 100644 --- a/cpp/ql/src/semmle/code/cpp/stmts/Block.qll +++ b/cpp/ql/src/semmle/code/cpp/stmts/Block.qll @@ -2,7 +2,7 @@ import semmle.code.cpp.Element import semmle.code.cpp.stmts.Stmt /** - * A C/C++ block statement. + * A C/C++ block statement. * * For example, the block from `{` to `}` in the following code: * ``` @@ -14,7 +14,6 @@ import semmle.code.cpp.stmts.Stmt * ``` */ class Block extends Stmt, @stmt_block { - override string getCanonicalQLClass() { result = "Block" } /** @@ -26,9 +25,7 @@ class Block extends Stmt, @stmt_block { * ``` * it would have 2 results, for the declarations of `a` and `b`. */ - Declaration getADeclaration() { - result = this.getAStmt().(DeclStmt).getADeclaration() - } + Declaration getADeclaration() { result = this.getAStmt().(DeclStmt).getADeclaration() } /** * Gets a body statement of this block. @@ -52,7 +49,7 @@ class Block extends Stmt, @stmt_block { * `getStmt(2)`'s result is the expression statement `a = b`. */ Stmt getStmt(int n) { result = this.getChild(n) } - + /** * Gets the last body statement of this block. * @@ -62,7 +59,7 @@ class Block extends Stmt, @stmt_block { * ``` * the result is the expression statement `a = b`. */ - Stmt getLastStmt() { result = this.getStmt(this.getNumStmt()-1) } + Stmt getLastStmt() { result = this.getStmt(this.getNumStmt() - 1) } /** * Gets the last body statement of this block. If this last statement @@ -75,11 +72,9 @@ class Block extends Stmt, @stmt_block { * the result is the expression statement `a = b`. */ Stmt getLastStmtIn() { - if getLastStmt() instanceof Block then ( - result = getLastStmt().(Block).getLastStmtIn() - ) else ( - result = getLastStmt() - ) + if getLastStmt() instanceof Block + then result = getLastStmt().(Block).getLastStmtIn() + else result = getLastStmt() } /** @@ -92,15 +87,15 @@ class Block extends Stmt, @stmt_block { * the result is 3. */ int getNumStmt() { result = count(this.getAStmt()) } - + /** * Holds if the block has no statements. - * - * For example, the block + * + * For example, the block * ``` * { } * ``` - * is empty, as is the block + * is empty, as is the block * ``` * { * // a comment @@ -123,12 +118,7 @@ class Block extends Stmt, @stmt_block { override string toString() { result = "{ ... }" } - override predicate mayBeImpure() { - this.getAStmt().mayBeImpure() - } - - override predicate mayBeGloballyImpure() { - this.getAStmt().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getAStmt().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getAStmt().mayBeGloballyImpure() } } diff --git a/cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll b/cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll index cf8328a6bf2..73d54c678b0 100644 --- a/cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll +++ b/cpp/ql/src/semmle/code/cpp/stmts/Stmt.qll @@ -6,11 +6,10 @@ private import semmle.code.cpp.internal.ResolveClass * A C/C++ statement. */ class Stmt extends StmtParent, @stmt { - /** Gets the `n`th child of this statement. */ Element getChild(int n) { - stmtparents(unresolveElement(result),n,underlyingElement(this)) or - exprparents(unresolveElement(result),n,underlyingElement(this)) + stmtparents(unresolveElement(result), n, underlyingElement(this)) or + exprparents(unresolveElement(result), n, underlyingElement(this)) } /** Holds if `e` is the `n`th child of this statement. */ @@ -23,22 +22,21 @@ class Stmt extends StmtParent, @stmt { * Gets the nearest enclosing block of this statement in the source, if any. */ Block getEnclosingBlock() { - if getParentStmt() instanceof Block and - not (getParentStmt().(Block).getLocation() instanceof UnknownLocation) - then - result = getParentStmt() - else - result = getParentStmt().getEnclosingBlock() + if + getParentStmt() instanceof Block and + not getParentStmt().(Block).getLocation() instanceof UnknownLocation + then result = getParentStmt() + else result = getParentStmt().getEnclosingBlock() } /** Gets a child of this statement. */ - Element getAChild() { exists (int n | result = this.getChild(n)) } + Element getAChild() { exists(int n | result = this.getChild(n)) } /** Gets the parent of this statement, if any. */ - StmtParent getParent() { stmtparents(underlyingElement(this),_,unresolveElement(result)) } + StmtParent getParent() { stmtparents(underlyingElement(this), _, unresolveElement(result)) } /** Gets the parent statement of this statement, if any. */ - Stmt getParentStmt() { stmtparents(underlyingElement(this),_,unresolveElement(result)) } + Stmt getParentStmt() { stmtparents(underlyingElement(this), _, unresolveElement(result)) } /** Gets a child statement of this statement. */ Stmt getChildStmt() { result.getParentStmt() = this } @@ -51,28 +49,26 @@ class Stmt extends StmtParent, @stmt { * to trace the flow of control instead. */ Stmt getFollowingStmt() { - exists(Block b, int i | this = b.getStmt(i) and - result = b.getStmt(i+1)) + exists(Block b, int i | + this = b.getStmt(i) and + result = b.getStmt(i + 1) + ) } - override Location getLocation() { stmts(underlyingElement(this),_,result) } + override Location getLocation() { stmts(underlyingElement(this), _, result) } /** * Gets an int indicating the type of statement that this represents. * * DEPRECATED: use the subclasses of `Stmt` rather than relying on this predicate. */ - deprecated int getKind() { stmts(underlyingElement(this),result,_) } + deprecated int getKind() { stmts(underlyingElement(this), result, _) } override string toString() { none() } - override Function getControlFlowScope() { - result = this.getEnclosingFunction() - } + override Function getControlFlowScope() { result = this.getEnclosingFunction() } - override Stmt getEnclosingStmt() { - result = this - } + override Stmt getEnclosingStmt() { result = this } /** * Holds if this statement is side-effect free (a conservative @@ -87,16 +83,14 @@ class Stmt extends StmtParent, @stmt { * statement may be impure in the sense that its behavior is affected * by external factors, such as the contents of global variables. */ - final predicate isPure() { - not this.mayBeImpure() - } + final predicate isPure() { not this.mayBeImpure() } + /** * Holds if it is possible that this statement is impure. If we are not * sure, then it holds. */ - predicate mayBeImpure() { - any() - } + predicate mayBeImpure() { any() } + /** * Holds if it is possible that this statement is globally impure. * @@ -107,17 +101,13 @@ class Stmt extends StmtParent, @stmt { * function as a whole will have no side-effects, even if it mutates * its own fresh stack variables. */ - predicate mayBeGloballyImpure() { - any() - } + predicate mayBeGloballyImpure() { any() } /** * Gets an attribute of this statement, for example * `[[clang::fallthrough]]`. */ - Attribute getAnAttribute() { - stmtattributes(underlyingElement(this), unresolveElement(result)) - } + Attribute getAnAttribute() { stmtattributes(underlyingElement(this), unresolveElement(result)) } /** * Gets a macro invocation that generates this entire statement. @@ -137,15 +127,10 @@ class Stmt extends StmtParent, @stmt { * Note that, unlike `isInMacroExpansion()` it is not necessary for * the macro to generate the terminating semi-colon. */ - MacroInvocation getGeneratingMacro() { - result.getAnExpandedElement() = this - } + MacroInvocation getGeneratingMacro() { result.getAnExpandedElement() = this } /** Holds if this statement was generated by the compiler. */ - predicate isCompilerGenerated() { - compgenerated(underlyingElement(this)) - } - + predicate isCompilerGenerated() { compgenerated(underlyingElement(this)) } } /** @@ -153,8 +138,7 @@ class Stmt extends StmtParent, @stmt { * * This is normally a statement, but may be a `StmtExpr`. */ -abstract class StmtParent extends ControlFlowNode { -} +abstract class StmtParent extends ControlFlowNode { } /** * A C/C++ 'expression' statement. @@ -167,7 +151,7 @@ abstract class StmtParent extends ControlFlowNode { */ class ExprStmt extends Stmt, @stmt_expr { override string getCanonicalQLClass() { result = "ExprStmt" } - + /** * Gets the expression of this 'expression' statement. * @@ -182,9 +166,8 @@ class ExprStmt extends Stmt, @stmt_expr { override string toString() { result = "ExprStmt" } override predicate mayBeImpure() { this.getExpr().mayBeImpure() } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } override MacroInvocation getGeneratingMacro() { // We only need the expression to be in the macro, not the semicolon. @@ -201,7 +184,8 @@ abstract class ControlStructure extends Stmt { * Gets the controlling expression of this control structure. * * This is the condition of 'if' statements and loops, and the - * switched expression for 'switch' statements. */ + * switched expression for 'switch' statements. + */ abstract Expr getControllingExpr(); /** Gets a child declaration of this scope. */ @@ -212,8 +196,7 @@ abstract class ControlStructure extends Stmt { * A C/C++ conditional statement, that is, either an 'if' statement or a * 'switch' statement. */ -abstract class ConditionalStmt extends ControlStructure { -} +abstract class ConditionalStmt extends ControlStructure { } /** * A C/C++ 'if' statement. For example, the `if` statement in the following @@ -287,6 +270,7 @@ class IfStmt extends ConditionalStmt, @stmt_if { this.getThen().mayBeImpure() or this.getElse().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getCondition().mayBeGloballyImpure() or this.getThen().mayBeGloballyImpure() or @@ -310,7 +294,6 @@ class IfStmt extends ConditionalStmt, @stmt_if { * ``` */ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if { - /** * Gets the condition expression of this 'constexpr if' statement. * @@ -371,6 +354,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if { this.getThen().mayBeImpure() or this.getElse().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getCondition().mayBeGloballyImpure() or this.getThen().mayBeGloballyImpure() or @@ -391,6 +375,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if { abstract class Loop extends ControlStructure { /** Gets the condition expression of this loop. */ abstract Expr getCondition(); + /** Gets the body statement of this loop. */ abstract Stmt getStmt(); } @@ -409,7 +394,9 @@ class WhileStmt extends Loop, @stmt_while { override string getCanonicalQLClass() { result = "WhileStmt" } override Expr getCondition() { result = this.getChild(0) } + override Expr getControllingExpr() { result = this.getCondition() } + override Stmt getStmt() { while_body(underlyingElement(this), unresolveElement(result)) } override string toString() { result = "while (...) ..." } @@ -418,6 +405,7 @@ class WhileStmt extends Loop, @stmt_while { this.getCondition().mayBeImpure() or this.getStmt().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getCondition().mayBeGloballyImpure() or this.getStmt().mayBeGloballyImpure() @@ -436,20 +424,17 @@ class WhileStmt extends Loop, @stmt_while { * while(1) { ...; if(b) break; ...; } * ``` */ - predicate conditionAlwaysTrue() { - conditionAlwaysTrue(getCondition()) - } + predicate conditionAlwaysTrue() { conditionAlwaysTrue(getCondition()) } - /** Holds if the loop condition is provably `false`. + /** + * Holds if the loop condition is provably `false`. * * For example, this holds for * ``` * while(0) { ...; } * ``` */ - predicate conditionAlwaysFalse() { - conditionAlwaysFalse(getCondition()) - } + predicate conditionAlwaysFalse() { conditionAlwaysFalse(getCondition()) } /** * Holds if the loop condition is provably `true` upon entry, @@ -464,9 +449,7 @@ class WhileStmt extends Loop, @stmt_while { * `done = false`, but the condition may evaluate to `false` after * some iterations. */ - predicate conditionAlwaysTrueUponEntry() { - loopConditionAlwaysTrueUponEntry(this, _) - } + predicate conditionAlwaysTrueUponEntry() { loopConditionAlwaysTrueUponEntry(this, _) } } /** @@ -474,9 +457,9 @@ class WhileStmt extends Loop, @stmt_while { */ abstract class JumpStmt extends Stmt, @jump { override string getCanonicalQLClass() { result = "JumpStmt" } - + /** Gets the target of this jump statement. */ - Stmt getTarget() { jumpinfo(underlyingElement(this),_,unresolveElement(result)) } + Stmt getTarget() { jumpinfo(underlyingElement(this), _, unresolveElement(result)) } } /** @@ -501,10 +484,10 @@ class GotoStmt extends JumpStmt, @stmt_goto { * ``` * the result is `"someLabel"`. */ - string getName() { jumpinfo(underlyingElement(this),result,_) and result != "" } + string getName() { jumpinfo(underlyingElement(this), result, _) and result != "" } /** Holds if this 'goto' statement refers to a label. */ - predicate hasName() { exists(string s | jumpinfo(underlyingElement(this),s,_) and s != "") } + predicate hasName() { exists(string s | jumpinfo(underlyingElement(this), s, _) and s != "") } override string toString() { result = "goto ..." } @@ -530,10 +513,12 @@ class GotoStmt extends JumpStmt, @stmt_goto { exists(Loop l1, Loop l2 | this.getParentStmt+() = l1 and l1.getParentStmt+() = l2 and - l2.getParentStmt+() = this.getASuccessor().(Stmt).getParentStmt()) + l2.getParentStmt+() = this.getASuccessor().(Stmt).getParentStmt() + ) } override predicate mayBeImpure() { none() } + override predicate mayBeGloballyImpure() { none() } } @@ -547,7 +532,6 @@ class GotoStmt extends JumpStmt, @stmt_goto { * ``` */ class ComputedGotoStmt extends Stmt, @stmt_assigned_goto { - /** * Gets the expression used to compute the target of this 'goto' * statement. @@ -563,9 +547,8 @@ class ComputedGotoStmt extends Stmt, @stmt_assigned_goto { override string toString() { result = "computed goto ..." } override predicate mayBeImpure() { this.getExpr().mayBeImpure() } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } override MacroInvocation getGeneratingMacro() { // We only need the expression to be in the macro, not the semicolon. @@ -590,14 +573,13 @@ class ContinueStmt extends JumpStmt, @stmt_continue { override string toString() { result = "continue;" } override predicate mayBeImpure() { none() } + override predicate mayBeGloballyImpure() { none() } - + /** * Gets the loop that this continue statement will jump to the beginning of. */ - Stmt getContinuable() { - result = getEnclosingContinuable(this) - } + Stmt getContinuable() { result = getEnclosingContinuable(this) } } private Stmt getEnclosingContinuable(Stmt s) { @@ -623,18 +605,19 @@ class BreakStmt extends JumpStmt, @stmt_break { override string toString() { result = "break;" } override predicate mayBeImpure() { none() } + override predicate mayBeGloballyImpure() { none() } /** * Gets the loop or switch statement that this break statement will exit. */ - Stmt getBreakable() { - result = getEnclosingBreakable(this) - } + Stmt getBreakable() { result = getEnclosingBreakable(this) } } private Stmt getEnclosingBreakable(Stmt s) { - if s.getParent().getEnclosingStmt() instanceof Loop or s.getParent().getEnclosingStmt() instanceof SwitchStmt + if + s.getParent().getEnclosingStmt() instanceof Loop or + s.getParent().getEnclosingStmt() instanceof SwitchStmt then result = s.getParent().getEnclosingStmt() else result = getEnclosingBreakable(s.getParent().getEnclosingStmt()) } @@ -651,9 +634,9 @@ private Stmt getEnclosingBreakable(Stmt s) { */ class LabelStmt extends Stmt, @stmt_label { override string getCanonicalQLClass() { result = "LabelStmt" } - + /** Gets the name of this 'label' statement. */ - string getName() { jumpinfo(underlyingElement(this),result,_) and result != "" } + string getName() { jumpinfo(underlyingElement(this), result, _) and result != "" } /** Holds if this 'label' statement is named. */ predicate isNamed() { exists(this.getName()) } @@ -661,6 +644,7 @@ class LabelStmt extends Stmt, @stmt_label { override string toString() { result = "label ...:" } override predicate mayBeImpure() { none() } + override predicate mayBeGloballyImpure() { none() } } @@ -709,12 +693,9 @@ class ReturnStmt extends Stmt, @stmt_return { override string toString() { result = "return ..." } - override predicate mayBeImpure() { - this.getExpr().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getExpr().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } } /** @@ -731,7 +712,9 @@ class DoStmt extends Loop, @stmt_end_test_while { override string getCanonicalQLClass() { result = "DoStmt" } override Expr getCondition() { result = this.getChild(0) } + override Expr getControllingExpr() { result = this.getCondition() } + override Stmt getStmt() { do_body(underlyingElement(this), unresolveElement(result)) } override string toString() { result = "do (...) ..." } @@ -740,6 +723,7 @@ class DoStmt extends Loop, @stmt_end_test_while { this.getCondition().mayBeImpure() or this.getStmt().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getCondition().mayBeGloballyImpure() or this.getStmt().mayBeGloballyImpure() @@ -812,9 +796,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { Expr getRange() { result = getRangeVariable().getInitializer().getExpr() } /** Gets the compiler-generated `__range` variable after desugaring. */ - LocalVariable getRangeVariable() { - result = getChild(0).(DeclStmt).getADeclaration() - } + LocalVariable getRangeVariable() { result = getChild(0).(DeclStmt).getADeclaration() } /** * Gets the compiler-generated `__begin != __end` which is the @@ -823,6 +805,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { * `operator!=`. */ override Expr getCondition() { result = this.getChild(2) } + override Expr getControllingExpr() { result = this.getCondition() } /** @@ -833,14 +816,10 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { DeclStmt getBeginEndDeclaration() { result = this.getChild(1) } /** Gets the compiler-generated `__begin` variable after desugaring. */ - LocalVariable getBeginVariable() { - result = getBeginEndDeclaration().getDeclaration(0) - } + LocalVariable getBeginVariable() { result = getBeginEndDeclaration().getDeclaration(0) } /** Gets the compiler-generated `__end` variable after desugaring. */ - LocalVariable getEndVariable() { - result = getBeginEndDeclaration().getDeclaration(1) - } + LocalVariable getEndVariable() { result = getBeginEndDeclaration().getDeclaration(1) } /** * Gets the compiler-generated `++__begin` which is the update @@ -851,9 +830,7 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for { Expr getUpdate() { result = this.getChild(3) } /** Gets the compiler-generated `__begin` variable after desugaring. */ - LocalVariable getAnIterationVariable() { - result = getBeginVariable() - } + LocalVariable getAnIterationVariable() { result = getBeginVariable() } } /** @@ -901,6 +878,7 @@ class ForStmt extends Loop, @stmt_for { * ``` */ override Expr getCondition() { for_condition(underlyingElement(this), unresolveElement(result)) } + override Expr getControllingExpr() { result = this.getCondition() } /** @@ -940,11 +918,11 @@ class ForStmt extends Loop, @stmt_for { pragma[noopt] Variable getAnIterationVariable() { this instanceof ForStmt and - // check that it is assigned to, incremented or decremented in the update exists(Expr updateOpRoot, Expr updateOp | - updateOpRoot = this.getUpdate() and - inForUpdate(updateOpRoot, updateOp) | + updateOpRoot = this.getUpdate() and + inForUpdate(updateOpRoot, updateOp) + | exists(CrementOperation op, VariableAccess va | op = updateOp and op instanceof CrementOperation and @@ -953,10 +931,8 @@ class ForStmt extends Loop, @stmt_for { ) or updateOp = result.getAnAssignedValue() - ) - and - result instanceof Variable - and + ) and + result instanceof Variable and // checked or used in the condition exists(Expr e, VariableAccess va | va = result.getAnAccess() and @@ -989,6 +965,7 @@ class ForStmt extends Loop, @stmt_for { this.getUpdate().mayBeImpure() or this.getStmt().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getInitialization().mayBeGloballyImpure() or this.getCondition().mayBeGloballyImpure() or @@ -997,7 +974,11 @@ class ForStmt extends Loop, @stmt_for { } override MacroInvocation getGeneratingMacro() { - (exists(this.getInitialization()) implies result = this.getInitialization().getGeneratingMacro()) and + ( + exists(this.getInitialization()) + implies + result = this.getInitialization().getGeneratingMacro() + ) and (exists(this.getCondition()) implies this.getCondition() = result.getAnExpandedElement()) and (exists(this.getUpdate()) implies this.getUpdate() = result.getAnExpandedElement()) and this.getStmt().getGeneratingMacro() = result @@ -1011,9 +992,7 @@ class ForStmt extends Loop, @stmt_for { * for(x = 0; 1; ++x) { sum += x; } * ``` */ - predicate conditionAlwaysTrue() { - conditionAlwaysTrue(getCondition()) - } + predicate conditionAlwaysTrue() { conditionAlwaysTrue(getCondition()) } /** * Holds if the loop condition is provably `false`. @@ -1023,9 +1002,7 @@ class ForStmt extends Loop, @stmt_for { * for(x = 0; 0; ++x) { sum += x; } * ``` */ - predicate conditionAlwaysFalse() { - conditionAlwaysFalse(getCondition()) - } + predicate conditionAlwaysFalse() { conditionAlwaysFalse(getCondition()) } /** * Holds if the loop condition is provably `true` upon entry, @@ -1039,9 +1016,7 @@ class ForStmt extends Loop, @stmt_for { * `i = 0`, but the condition will evaluate to `false` after 10 * iterations. */ - predicate conditionAlwaysTrueUponEntry() { - loopConditionAlwaysTrueUponEntry(this, _) - } + predicate conditionAlwaysTrueUponEntry() { loopConditionAlwaysTrueUponEntry(this, _) } } /** @@ -1057,12 +1032,16 @@ class ForStmt extends Loop, @stmt_for { */ pragma[noopt] private predicate inForCondition(Expr forCondition, Expr child) { - exists (ForStmt for | forCondition = for.getCondition() and - child = forCondition and - for instanceof ForStmt) - or - exists (Expr mid | inForCondition(forCondition, mid) and - child.getParent() = mid) + exists(ForStmt for | + forCondition = for.getCondition() and + child = forCondition and + for instanceof ForStmt + ) + or + exists(Expr mid | + inForCondition(forCondition, mid) and + child.getParent() = mid + ) } /** @@ -1077,9 +1056,9 @@ private predicate inForCondition(Expr forCondition, Expr child) { */ pragma[noopt] private predicate inForUpdate(Expr forUpdate, Expr child) { - exists (ForStmt for | forUpdate = for.getUpdate() and child = forUpdate) - or - exists (Expr mid | inForUpdate(forUpdate, mid) and child.getParent() = mid) + exists(ForStmt for | forUpdate = for.getUpdate() and child = forUpdate) + or + exists(Expr mid | inForUpdate(forUpdate, mid) and child.getParent() = mid) } /** @@ -1169,9 +1148,7 @@ class SwitchCase extends Stmt, @stmt_switch_case { * the `case 5:` has result 0, `case 6:` has result 1, and `default:` * has result 2. */ - int getChildNum() { - switch_case(_, result, underlyingElement(this)) - } + int getChildNum() { switch_case(_, result, underlyingElement(this)) } /** * DEPRECATED: use `SwitchCase.getAStmt` or `ControlFlowNode.getASuccessor` @@ -1199,10 +1176,11 @@ class SwitchCase extends Stmt, @stmt_switch_case { * `{ x = 3; }`, and the others have no result. */ deprecated Block getLabelledStmt() { - exists(int i, Stmt parent | - this = parent.getChild(i) and - result = parent.getChild(i+1)) - } + exists(int i, Stmt parent | + this = parent.getChild(i) and + result = parent.getChild(i + 1) + ) + } /** * Gets the next `SwitchCase` belonging to the same 'switch' @@ -1227,8 +1205,8 @@ class SwitchCase extends Stmt, @stmt_switch_case { * which has result `default:`, which has no result. */ SwitchCase getNextSwitchCase() { - result.getSwitchStmt() = this.getSwitchStmt() and - result.getChildNum() = this.getChildNum() + 1 + result.getSwitchStmt() = this.getSwitchStmt() and + result.getChildNum() = this.getChildNum() + 1 } /** @@ -1253,9 +1231,7 @@ class SwitchCase extends Stmt, @stmt_switch_case { * the `default:` has result `case 7:`, which has result `case 6:`, * which has result `case 5:`, which has no result. */ - SwitchCase getPreviousSwitchCase() { - result.getNextSwitchCase() = this - } + SwitchCase getPreviousSwitchCase() { result.getNextSwitchCase() = this } /** * Gets a statement belonging under this 'switch case' statement. @@ -1281,14 +1257,16 @@ class SwitchCase extends Stmt, @stmt_switch_case { */ Stmt getAStmt() { exists(Block b, int i, int j | - b.getStmt(i) = this and - b.getStmt(j) = result and - i < j and - not result instanceof SwitchCase and - not exists(SwitchCase sc, int k | - b.getStmt(k) = sc and - i < k and - j > k)) + b.getStmt(i) = this and + b.getStmt(j) = result and + i < j and + not result instanceof SwitchCase and + not exists(SwitchCase sc, int k | + b.getStmt(k) = sc and + i < k and + j > k + ) + ) } /** @@ -1317,10 +1295,9 @@ class SwitchCase extends Stmt, @stmt_switch_case { exists(Stmt lastStmt | lastStmt = this.getAStmt() and not lastStmt.getFollowingStmt() = this.getAStmt() and - if lastStmt instanceof Block then - result = lastStmt.(Block).getLastStmtIn() - else - result = lastStmt + if lastStmt instanceof Block + then result = lastStmt.(Block).getLastStmtIn() + else result = lastStmt ) } @@ -1343,9 +1320,7 @@ class SwitchCase extends Stmt, @stmt_switch_case { * ``` * this holds for `case 5:`, `case 7:` and `default:`, but not for `case 6:`. */ - predicate terminatesInBreakStmt() { - this.getLastStmt() instanceof BreakStmt - } + predicate terminatesInBreakStmt() { this.getLastStmt() instanceof BreakStmt } /** * Holds if the last statement, as determined by `getLastStmt`, under @@ -1366,9 +1341,7 @@ class SwitchCase extends Stmt, @stmt_switch_case { * ``` * this holds for `case 5:`, `case 7:` and `default:`, but not for `case 6:`. */ - predicate terminatesInReturnStmt() { - this.getLastStmt() instanceof ReturnStmt - } + predicate terminatesInReturnStmt() { this.getLastStmt() instanceof ReturnStmt } /** * Holds if the last statement, as determined by `getLastStmt`, under @@ -1408,18 +1381,13 @@ class SwitchCase extends Stmt, @stmt_switch_case { * this holds for `default:`, but not for `case 5:`, `case 6:`, * or `case 7:`. */ - predicate isDefault() { - this instanceof DefaultCase - } + predicate isDefault() { this instanceof DefaultCase } override string toString() { result = "case ...:" } - override predicate mayBeImpure() { - this.getExpr().mayBeImpure() - } - override predicate mayBeGloballyImpure() { - this.getExpr().mayBeGloballyImpure() - } + override predicate mayBeImpure() { this.getExpr().mayBeImpure() } + + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } } /** @@ -1437,17 +1405,13 @@ class SwitchCase extends Stmt, @stmt_switch_case { * ``` */ class DefaultCase extends SwitchCase { - DefaultCase() { not exists(this.getExpr()) } override string toString() { result = "default: " } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -1483,6 +1447,7 @@ class SwitchStmt extends ConditionalStmt, @stmt_switch { * the result is `i`. */ Expr getExpr() { result = this.getChild(0) } + override Expr getControllingExpr() { result = this.getExpr() } /** @@ -1586,6 +1551,7 @@ class SwitchStmt extends ConditionalStmt, @stmt_switch { this.getExpr().mayBeImpure() or this.getStmt().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() or this.getStmt().mayBeGloballyImpure() @@ -1593,8 +1559,7 @@ class SwitchStmt extends ConditionalStmt, @stmt_switch { override MacroInvocation getGeneratingMacro() { result.getAnExpandedElement() = this.getExpr() and - forall(SwitchCase c | c = this.getASwitchCase() - | exists(c.getGeneratingMacro())) + forall(SwitchCase c | c = this.getASwitchCase() | exists(c.getGeneratingMacro())) } } @@ -1618,9 +1583,7 @@ class SwitchStmt extends ConditionalStmt, @stmt_switch { * ``` */ class EnumSwitch extends SwitchStmt { - EnumSwitch() { - this.getExpr().getType().getUnderlyingType() instanceof Enum - } + EnumSwitch() { this.getExpr().getType().getUnderlyingType() instanceof Enum } /** * Gets a constant from the enum type that does not have a case in this @@ -1650,13 +1613,16 @@ class EnumSwitch extends SwitchStmt { ) and result = et.getAnEnumConstant() and not exists(string value | - exists(SwitchCase sc, Expr e | sc = this.getASwitchCase() and - e = sc.getExpr() and - value = e.getValue()) - and - exists(Initializer init, Expr e | init = result.getInitializer() and - e = init.getExpr() and - e.getValue() = value) + exists(SwitchCase sc, Expr e | + sc = this.getASwitchCase() and + e = sc.getExpr() and + value = e.getValue() + ) and + exists(Initializer init, Expr e | + init = result.getInitializer() and + e = init.getExpr() and + e.getValue() = value + ) ) ) } @@ -1683,7 +1649,6 @@ class EnumSwitch extends SwitchStmt { * entry to it. */ class Handler extends Stmt, @stmt_handler { - override string toString() { result = "" } override string getCanonicalQLClass() { result = "Handler" } @@ -1704,12 +1669,9 @@ class Handler extends Stmt, @stmt_handler { */ Parameter getParameter() { result = getBlock().getParameter() } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -1724,12 +1686,9 @@ deprecated class FinallyEnd extends Stmt { override string toString() { result = "" } - override predicate mayBeImpure() { - none() - } - override predicate mayBeGloballyImpure() { - none() - } + override predicate mayBeImpure() { none() } + + override predicate mayBeGloballyImpure() { none() } } /** @@ -1769,9 +1728,7 @@ class TryStmt extends Stmt, @stmt_try_block { * ``` * the result of `getCatchClause(0)` is `{ g(); }`. */ - CatchBlock getCatchClause(int n) { - result = this.getChild(n + 1).(Handler).getBlock() - } + CatchBlock getCatchClause(int n) { result = this.getChild(n + 1).(Handler).getBlock() } /** * Gets a 'catch block' of this 'try' statement. @@ -1793,14 +1750,13 @@ class TryStmt extends Stmt, @stmt_try_block { * ``` * the result is 1. */ - int getNumberOfCatchClauses() { - result = count(this.getACatchClause()) - } + int getNumberOfCatchClauses() { result = count(this.getACatchClause()) } override predicate mayBeImpure() { this.getStmt().mayBeImpure() or this.getACatchClause().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getStmt().mayBeGloballyImpure() or this.getACatchClause().mayBeGloballyImpure() @@ -1821,9 +1777,7 @@ class TryStmt extends Stmt, @stmt_try_block { * ``` */ class FunctionTryStmt extends TryStmt { - FunctionTryStmt() { - not exists(this.getEnclosingBlock()) - } + FunctionTryStmt() { not exists(this.getEnclosingBlock()) } override string getCanonicalQLClass() { result = "FunctionTryStmt" } } @@ -1842,7 +1796,6 @@ class FunctionTryStmt extends TryStmt { * ``` */ class CatchBlock extends Block { - override string getCanonicalQLClass() { result = "CatchBlock" } CatchBlock() { ishandler(underlyingElement(this)) } @@ -1856,9 +1809,7 @@ class CatchBlock extends Block { Parameter getParameter() { result.getCatchBlock() = this } /** Gets the try statement corresponding to this 'catch block'. */ - TryStmt getTryStmt() { - result.getACatchClause() = this - } + TryStmt getTryStmt() { result.getACatchClause() = this } } /** @@ -1874,9 +1825,7 @@ class CatchBlock extends Block { * ``` */ class CatchAnyBlock extends CatchBlock { - CatchAnyBlock() { - not exists(this.getParameter()) - } + CatchAnyBlock() { not exists(this.getParameter()) } override string getCanonicalQLClass() { result = "CatchAnyBlock" } } @@ -1905,13 +1854,9 @@ class MicrosoftTryStmt extends Stmt, @stmt_microsoft_try { * This is a Microsoft C/C++ extension. */ class MicrosoftTryExceptStmt extends MicrosoftTryStmt { - MicrosoftTryExceptStmt() { - getChild(1) instanceof Expr - } + MicrosoftTryExceptStmt() { getChild(1) instanceof Expr } - override string toString() { - result = "__try { ... } __except( ... ) { ... }" - } + override string toString() { result = "__try { ... } __except( ... ) { ... }" } /** Gets the expression guarding the `__except` statement. */ Expr getCondition() { result = getChild(1) } @@ -1936,9 +1881,7 @@ class MicrosoftTryExceptStmt extends MicrosoftTryStmt { * This is a Microsoft C/C++ extension. */ class MicrosoftTryFinallyStmt extends MicrosoftTryStmt { - MicrosoftTryFinallyStmt() { - not getChild(1) instanceof Expr - } + MicrosoftTryFinallyStmt() { not getChild(1) instanceof Expr } override string toString() { result = "__try { ... } __finally { ... }" } @@ -1957,7 +1900,6 @@ class MicrosoftTryFinallyStmt extends MicrosoftTryStmt { * ``` */ class DeclStmt extends Stmt, @stmt_decl { - override string getCanonicalQLClass() { result = "DeclStmt" } /** @@ -1982,9 +1924,7 @@ class DeclStmt extends Stmt, @stmt_decl { * ``` * the results are `i` and `j`. */ - DeclarationEntry getADeclarationEntry() { - result = this.getDeclarationEntry(_) - } + DeclarationEntry getADeclarationEntry() { result = this.getDeclarationEntry(_) } /** * Gets the number of declarations declared by this 'declaration' statement. @@ -2006,7 +1946,9 @@ class DeclStmt extends Stmt, @stmt_decl { * ``` * the result of `getDeclaration(0)` is `i`. */ - Declaration getDeclaration(int i) { stmt_decl_bind(underlyingElement(this), i, unresolveElement(result)) } + Declaration getDeclaration(int i) { + stmt_decl_bind(underlyingElement(this), i, unresolveElement(result)) + } /** * Gets a declaration declared by this 'declaration' statement. @@ -2024,6 +1966,7 @@ class DeclStmt extends Stmt, @stmt_decl { override predicate mayBeImpure() { this.getADeclaration().(LocalVariable).getInitializer().getExpr().mayBeImpure() } + override predicate mayBeGloballyImpure() { this.getADeclaration().(LocalVariable).getInitializer().getExpr().mayBeGloballyImpure() } @@ -2038,12 +1981,12 @@ class DeclStmt extends Stmt, @stmt_decl { * ``` */ class EmptyStmt extends Stmt, @stmt_empty { - override string getCanonicalQLClass() { result = "EmptyStmt" } override string toString() { result = ";" } override predicate mayBeImpure() { none() } + override predicate mayBeGloballyImpure() { none() } } @@ -2056,10 +1999,8 @@ class EmptyStmt extends Stmt, @stmt_empty { * ``` */ class AsmStmt extends Stmt, @stmt_asm { - override string toString() { - result = "asm statement" - } - + override string toString() { result = "asm statement" } + override string getCanonicalQLClass() { result = "AsmStmt" } } @@ -2076,7 +2017,7 @@ class AsmStmt extends Stmt, @stmt_asm { */ class VlaDimensionStmt extends Stmt, @stmt_set_vla_size { override string toString() { result = "VLA dimension size" } - + override string getCanonicalQLClass() { result = "VlaDimensionStmt" } /** Gets the expression which gives the size. */ @@ -2095,7 +2036,7 @@ class VlaDimensionStmt extends Stmt, @stmt_set_vla_size { */ class VlaDeclStmt extends Stmt, @stmt_vla_decl { override string toString() { result = "VLA declaration" } - + override string getCanonicalQLClass() { result = "VlaDeclStmt" } /** @@ -2104,10 +2045,13 @@ class VlaDeclStmt extends Stmt, @stmt_vla_decl { */ int getNumberOfVlaDimensionStmts() { exists(Block b, int j | - this = b.getStmt(j) and - result = j - 1 - max(int i | - i in [0 .. j - 1] and - not b.getStmt(i) instanceof VlaDimensionStmt)) + this = b.getStmt(j) and + result = j - 1 - + max(int i | + i in [0 .. j - 1] and + not b.getStmt(i) instanceof VlaDimensionStmt + ) + ) } /** @@ -2117,8 +2061,9 @@ class VlaDeclStmt extends Stmt, @stmt_vla_decl { VlaDimensionStmt getVlaDimensionStmt(int i) { i in [0 .. this.getNumberOfVlaDimensionStmts() - 1] and exists(Block b, int j | - this = b.getStmt(j) and - result = b.getStmt(j - this.getNumberOfVlaDimensionStmts() + i)) + this = b.getStmt(j) and + result = b.getStmt(j - this.getNumberOfVlaDimensionStmts() + i) + ) } /** diff --git a/cpp/ql/src/semmle/code/cpp/valuenumbering/GlobalValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/valuenumbering/GlobalValueNumbering.qll index ee318354534..5c8196c15e0 100644 --- a/cpp/ql/src/semmle/code/cpp/valuenumbering/GlobalValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/valuenumbering/GlobalValueNumbering.qll @@ -61,12 +61,13 @@ private ControlFlowNode nodeWithPossibleSideEffect() { or // If the lhs of an assignment is not analyzable by SSA, then // we need to treat the assignment as having a possible side-effect. - (result instanceof Assignment and not result instanceof SsaDefinition) + result instanceof Assignment and not result instanceof SsaDefinition or - (result instanceof CrementOperation and not result instanceof SsaDefinition) + result instanceof CrementOperation and not result instanceof SsaDefinition or - exists (LocalVariable v - | result = v.getInitializer().getExpr() and not result instanceof SsaDefinition) + exists(LocalVariable v | + result = v.getInitializer().getExpr() and not result instanceof SsaDefinition + ) or result instanceof AsmStmt } @@ -75,7 +76,8 @@ private ControlFlowNode nodeWithPossibleSideEffect() { * Gets the entry node of the control flow graph of which `node` is a * member. */ -private cached ControlFlowNode getControlFlowEntry(ControlFlowNode node) { +cached +private ControlFlowNode getControlFlowEntry(ControlFlowNode node) { result = node.getControlFlowScope().getEntryPoint() and result.getASuccessor*() = node } @@ -92,8 +94,8 @@ private predicate sideEffectCFG(ControlFlowNode src, ControlFlowNode dst) { or // Add an edge from the entry point to any node that might have a side // effect. - (dst = nodeWithPossibleSideEffect() and - src = getControlFlowEntry(dst)) + dst = nodeWithPossibleSideEffect() and + src = getControlFlowEntry(dst) } /** @@ -101,7 +103,7 @@ private predicate sideEffectCFG(ControlFlowNode src, ControlFlowNode dst) { * the side-effect CFG. */ private predicate iDomEffect(ControlFlowNode dominator, ControlFlowNode node) = - idominance(functionEntry/1,sideEffectCFG/2)(_, dominator, node) + idominance(functionEntry/1, sideEffectCFG/2)(_, dominator, node) /** * Gets the most recent side effect. To be more precise, `result` is a @@ -152,67 +154,53 @@ private predicate iDomEffect(ControlFlowNode dominator, ControlFlowNode node) = * The immediate dominator path to line 015 is 000 - 009 - 012 - 015. * Therefore, the most recent side effect for line 015 is line 009. */ -private cached ControlFlowNode mostRecentSideEffect(ControlFlowNode node) { - exists (ControlFlowNode entry - | functionEntry(entry) and +cached +private ControlFlowNode mostRecentSideEffect(ControlFlowNode node) { + exists(ControlFlowNode entry | + functionEntry(entry) and iDomEffect(entry, result) and - iDomEffect*(result, node)) + iDomEffect*(result, node) + ) } /** Used to represent the "global value number" of an expression. */ -private cached newtype GVNBase = - GVN_IntConst(int val, Type t) { mk_IntConst(val,t,_) } - or - GVN_FloatConst(float val, Type t) { mk_FloatConst(val,t,_) } - or +cached +private newtype GVNBase = + GVN_IntConst(int val, Type t) { mk_IntConst(val, t, _) } or + GVN_FloatConst(float val, Type t) { mk_FloatConst(val, t, _) } or // If the local variable does not have a defining value, then // we use the SsaDefinition as its global value number. GVN_UndefinedLocalScopeVariable(LocalScopeVariable x, SsaDefinition def) { mk_UndefinedLocalScopeVariable(x, def, _) - } - or + } or // Variables with no SSA information. As a crude (but safe) // approximation, we use `mostRecentSideEffect` to compute a definition // location for the variable. This ensures that two instances of the same // global variable will only get the same value number if they are // guaranteed to have the same value. - GVN_OtherVariable(Variable x, ControlFlowNode dominator) { - mk_OtherVariable(x, dominator, _) - } - or + GVN_OtherVariable(Variable x, ControlFlowNode dominator) { mk_OtherVariable(x, dominator, _) } or GVN_FieldAccess(GVN s, Field f) { - mk_DotFieldAccess(s,f,_) or - mk_PointerFieldAccess_with_deref(s,f,_) or - mk_ImplicitThisFieldAccess_with_deref(s,f,_) - } - or + mk_DotFieldAccess(s, f, _) or + mk_PointerFieldAccess_with_deref(s, f, _) or + mk_ImplicitThisFieldAccess_with_deref(s, f, _) + } or // Dereference a pointer. The value might have changed since the last // time the pointer was dereferenced, so we need to include a definition // location. As a crude (but safe) approximation, we use // `mostRecentSideEffect` to compute a definition location. GVN_Deref(GVN p, ControlFlowNode dominator) { - mk_Deref(p,dominator,_) or - mk_PointerFieldAccess(p,_,dominator,_) or - mk_ImplicitThisFieldAccess_with_qualifier(p,_,dominator,_) - } - or + mk_Deref(p, dominator, _) or + mk_PointerFieldAccess(p, _, dominator, _) or + mk_ImplicitThisFieldAccess_with_qualifier(p, _, dominator, _) + } or GVN_ThisExpr(Function fcn) { - mk_ThisExpr(fcn,_) or - mk_ImplicitThisFieldAccess(fcn,_,_,_) - } - or - GVN_Conversion(Type t, GVN child) { mk_Conversion(t, child, _) } - or - GVN_BinaryOp(GVN lhs, GVN rhs, string opname) { - mk_BinaryOp(lhs, rhs, opname, _) - } - or - GVN_UnaryOp(GVN child, string opname) { mk_UnaryOp(child, opname, _) } - or - GVN_ArrayAccess(GVN x, GVN i, ControlFlowNode dominator) { - mk_ArrayAccess(x,i,dominator,_) - } - or + mk_ThisExpr(fcn, _) or + mk_ImplicitThisFieldAccess(fcn, _, _, _) + } or + GVN_Conversion(Type t, GVN child) { mk_Conversion(t, child, _) } or + GVN_BinaryOp(GVN lhs, GVN rhs, string opname) { mk_BinaryOp(lhs, rhs, opname, _) } or + GVN_UnaryOp(GVN child, string opname) { mk_UnaryOp(child, opname, _) } or + GVN_ArrayAccess(GVN x, GVN i, ControlFlowNode dominator) { mk_ArrayAccess(x, i, dominator, _) } or // Any expression that is not handled by the cases above is // given a unique number based on the expression itself. GVN_Unanalyzable(Expr e) { not analyzableExpr(e) } @@ -237,26 +225,46 @@ class GVN extends GVNBase { GVN() { this instanceof GVNBase } /** Gets an expression that has this GVN. */ - Expr getAnExpr() { - this = globalValueNumber(result) - } + Expr getAnExpr() { this = globalValueNumber(result) } /** Gets the kind of the GVN. This can be useful for debugging. */ string getKind() { - if this instanceof GVN_IntConst then result = "IntConst" else - if this instanceof GVN_FloatConst then result = "FloatConst" else - if this instanceof GVN_UndefinedLocalScopeVariable then - result = "UndefinedLocalScopeVariable" else - if this instanceof GVN_OtherVariable then result = "OtherVariable" else - if this instanceof GVN_FieldAccess then result = "FieldAccess" else - if this instanceof GVN_Deref then result = "Deref" else - if this instanceof GVN_ThisExpr then result = "ThisExpr" else - if this instanceof GVN_Conversion then result = "Conversion" else - if this instanceof GVN_BinaryOp then result = "BinaryOp" else - if this instanceof GVN_UnaryOp then result = "UnaryOp" else - if this instanceof GVN_ArrayAccess then result = "ArrayAccess" else - if this instanceof GVN_Unanalyzable then result = "Unanalyzable" else - result = "error" + if this instanceof GVN_IntConst + then result = "IntConst" + else + if this instanceof GVN_FloatConst + then result = "FloatConst" + else + if this instanceof GVN_UndefinedLocalScopeVariable + then result = "UndefinedLocalScopeVariable" + else + if this instanceof GVN_OtherVariable + then result = "OtherVariable" + else + if this instanceof GVN_FieldAccess + then result = "FieldAccess" + else + if this instanceof GVN_Deref + then result = "Deref" + else + if this instanceof GVN_ThisExpr + then result = "ThisExpr" + else + if this instanceof GVN_Conversion + then result = "Conversion" + else + if this instanceof GVN_BinaryOp + then result = "BinaryOp" + else + if this instanceof GVN_UnaryOp + then result = "UnaryOp" + else + if this instanceof GVN_ArrayAccess + then result = "ArrayAccess" + else + if this instanceof GVN_Unanalyzable + then result = "Unanalyzable" + else result = "error" } /** @@ -266,26 +274,19 @@ class GVN extends GVNBase { private Expr exampleExpr() { // Pick the expression with the minimum source location string. This is // just an arbitrary way to pick an expression with this `GVN`. - result = - min(Expr e - | this = globalValueNumber(e) - | e order by e.getLocation().toString()) + result = min(Expr e | this = globalValueNumber(e) | e order by e.getLocation().toString()) } /** Gets a textual representation of this element. */ - string toString() { - result = exampleExpr().toString() - } + string toString() { result = exampleExpr().toString() } /** Gets the primary location of this element. */ - Location getLocation() { - result = exampleExpr().getLocation() - } + Location getLocation() { result = exampleExpr().getLocation() } } private predicate analyzableIntConst(Expr e) { - strictcount (e.getValue().toInt()) = 1 and - strictcount (e.getUnspecifiedType()) = 1 + strictcount(e.getValue().toInt()) = 1 and + strictcount(e.getUnspecifiedType()) = 1 } private predicate mk_IntConst(int val, Type t, Expr e) { @@ -295,8 +296,8 @@ private predicate mk_IntConst(int val, Type t, Expr e) { } private predicate analyzableFloatConst(Expr e) { - strictcount (e.getValue().toFloat()) = 1 and - strictcount (e.getUnspecifiedType()) = 1 and + strictcount(e.getValue().toFloat()) = 1 and + strictcount(e.getUnspecifiedType()) = 1 and not analyzableIntConst(e) } @@ -306,13 +307,14 @@ private predicate mk_FloatConst(float val, Type t, Expr e) { t = e.getUnspecifiedType() } - private predicate analyzableLocalScopeVariable(VariableAccess access) { - strictcount (SsaDefinition def | def.getAUse(_) = access | def) = 1 and - strictcount (SsaDefinition def, Variable v | def.getAUse(v) = access | v) = 1 and - count (SsaDefinition def, Variable v - | def.getAUse(v) = access - | def.getDefiningValue(v).getFullyConverted()) <= 1 and + strictcount(SsaDefinition def | def.getAUse(_) = access | def) = 1 and + strictcount(SsaDefinition def, Variable v | def.getAUse(v) = access | v) = 1 and + count(SsaDefinition def, Variable v | + def.getAUse(v) = access + | + def.getDefiningValue(v).getFullyConverted() + ) <= 1 and not analyzableConst(access) } @@ -321,36 +323,36 @@ private predicate analyzableLocalScopeVariable(VariableAccess access) { // need to generate a fresh `GVN` for the access because `globalValueNumber` // will follow the chain and use the GVN of the defining value. private predicate mk_UndefinedLocalScopeVariable( - LocalScopeVariable x, SsaDefinition def, VariableAccess access) { + LocalScopeVariable x, SsaDefinition def, VariableAccess access +) { analyzableLocalScopeVariable(access) and access = def.getAUse(x) and - not exists (def.getDefiningValue(x)) + not exists(def.getDefiningValue(x)) } private predicate analyzableDotFieldAccess(DotFieldAccess access) { - strictcount (access.getTarget()) = 1 and - strictcount (access.getQualifier().getFullyConverted()) = 1 and + strictcount(access.getTarget()) = 1 and + strictcount(access.getQualifier().getFullyConverted()) = 1 and not analyzableConst(access) } -private predicate mk_DotFieldAccess( - GVN qualifier, Field target, DotFieldAccess access) { +private predicate mk_DotFieldAccess(GVN qualifier, Field target, DotFieldAccess access) { analyzableDotFieldAccess(access) and target = access.getTarget() and qualifier = globalValueNumber(access.getQualifier().getFullyConverted()) } private predicate analyzablePointerFieldAccess(PointerFieldAccess access) { - strictcount (mostRecentSideEffect(access)) = 1 and - strictcount (access.getTarget()) = 1 and - strictcount (access.getQualifier().getFullyConverted()) = 1 and + strictcount(mostRecentSideEffect(access)) = 1 and + strictcount(access.getTarget()) = 1 and + strictcount(access.getQualifier().getFullyConverted()) = 1 and not analyzableConst(access) } private predicate mk_PointerFieldAccess( - GVN qualifier, Field target, ControlFlowNode dominator, - PointerFieldAccess access) { - analyzablePointerFieldAccess(access) and + GVN qualifier, Field target, ControlFlowNode dominator, PointerFieldAccess access +) { + analyzablePointerFieldAccess(access) and dominator = mostRecentSideEffect(access) and target = access.getTarget() and qualifier = globalValueNumber(access.getQualifier().getFullyConverted()) @@ -361,23 +363,24 @@ private predicate mk_PointerFieldAccess( * extra `GVN_Deref` around the qualifier. */ private predicate mk_PointerFieldAccess_with_deref( - GVN new_qualifier, Field target, PointerFieldAccess access) { - exists (GVN qualifier, ControlFlowNode dominator - | mk_PointerFieldAccess(qualifier, target, dominator, access) and - new_qualifier = GVN_Deref(qualifier, dominator)) + GVN new_qualifier, Field target, PointerFieldAccess access +) { + exists(GVN qualifier, ControlFlowNode dominator | + mk_PointerFieldAccess(qualifier, target, dominator, access) and + new_qualifier = GVN_Deref(qualifier, dominator) + ) } -private predicate analyzableImplicitThisFieldAccess( - ImplicitThisFieldAccess access) { - strictcount (mostRecentSideEffect(access)) = 1 and - strictcount (access.getTarget()) = 1 and - strictcount (access.getEnclosingFunction()) = 1 and +private predicate analyzableImplicitThisFieldAccess(ImplicitThisFieldAccess access) { + strictcount(mostRecentSideEffect(access)) = 1 and + strictcount(access.getTarget()) = 1 and + strictcount(access.getEnclosingFunction()) = 1 and not analyzableConst(access) } private predicate mk_ImplicitThisFieldAccess( - Function fcn, Field target, ControlFlowNode dominator, - ImplicitThisFieldAccess access) { + Function fcn, Field target, ControlFlowNode dominator, ImplicitThisFieldAccess access +) { analyzableImplicitThisFieldAccess(access) and dominator = mostRecentSideEffect(access) and target = access.getTarget() and @@ -385,19 +388,21 @@ private predicate mk_ImplicitThisFieldAccess( } private predicate mk_ImplicitThisFieldAccess_with_qualifier( - GVN qualifier, Field target, ControlFlowNode dominator, - ImplicitThisFieldAccess access) { - exists (Function fcn - | mk_ImplicitThisFieldAccess(fcn, target, dominator, access) and - qualifier = GVN_ThisExpr(fcn)) + GVN qualifier, Field target, ControlFlowNode dominator, ImplicitThisFieldAccess access +) { + exists(Function fcn | + mk_ImplicitThisFieldAccess(fcn, target, dominator, access) and + qualifier = GVN_ThisExpr(fcn) + ) } private predicate mk_ImplicitThisFieldAccess_with_deref( - GVN new_qualifier, Field target, ImplicitThisFieldAccess access) { - exists (GVN qualifier, ControlFlowNode dominator - | mk_ImplicitThisFieldAccess_with_qualifier( - qualifier, target, dominator, access) and - new_qualifier = GVN_Deref(qualifier, dominator)) + GVN new_qualifier, Field target, ImplicitThisFieldAccess access +) { + exists(GVN qualifier, ControlFlowNode dominator | + mk_ImplicitThisFieldAccess_with_qualifier(qualifier, target, dominator, access) and + new_qualifier = GVN_Deref(qualifier, dominator) + ) } /** @@ -406,23 +411,22 @@ private predicate mk_ImplicitThisFieldAccess_with_deref( * is global.) */ private predicate analyzableOtherVariable(VariableAccess access) { - not (access instanceof FieldAccess) and - not exists (SsaDefinition def | access = def.getAUse(_)) and - strictcount (access.getTarget()) = 1 and - strictcount (mostRecentSideEffect(access)) = 1 and + not access instanceof FieldAccess and + not exists(SsaDefinition def | access = def.getAUse(_)) and + strictcount(access.getTarget()) = 1 and + strictcount(mostRecentSideEffect(access)) = 1 and not analyzableConst(access) } -private predicate mk_OtherVariable( - Variable x, ControlFlowNode dominator, VariableAccess access) { +private predicate mk_OtherVariable(Variable x, ControlFlowNode dominator, VariableAccess access) { analyzableOtherVariable(access) and x = access.getTarget() and dominator = mostRecentSideEffect(access) } private predicate analyzableConversion(Conversion conv) { - strictcount (conv.getUnspecifiedType()) = 1 and - strictcount (conv.getExpr()) = 1 and + strictcount(conv.getUnspecifiedType()) = 1 and + strictcount(conv.getExpr()) = 1 and not analyzableConst(conv) } @@ -434,14 +438,13 @@ private predicate mk_Conversion(Type t, GVN child, Conversion conv) { private predicate analyzableBinaryOp(BinaryOperation op) { op.isPure() and - strictcount (op.getLeftOperand().getFullyConverted()) = 1 and - strictcount (op.getRightOperand().getFullyConverted()) = 1 and - strictcount (op.getOperator()) = 1 and + strictcount(op.getLeftOperand().getFullyConverted()) = 1 and + strictcount(op.getRightOperand().getFullyConverted()) = 1 and + strictcount(op.getOperator()) = 1 and not analyzableConst(op) } -private predicate mk_BinaryOp( - GVN lhs, GVN rhs, string opname, BinaryOperation op) { +private predicate mk_BinaryOp(GVN lhs, GVN rhs, string opname, BinaryOperation op) { analyzableBinaryOp(op) and lhs = globalValueNumber(op.getLeftOperand().getFullyConverted()) and rhs = globalValueNumber(op.getRightOperand().getFullyConverted()) and @@ -449,10 +452,10 @@ private predicate mk_BinaryOp( } private predicate analyzableUnaryOp(UnaryOperation op) { - not (op instanceof PointerDereferenceExpr) and + not op instanceof PointerDereferenceExpr and op.isPure() and - strictcount (op.getOperand().getFullyConverted()) = 1 and - strictcount (op.getOperator()) = 1 and + strictcount(op.getOperand().getFullyConverted()) = 1 and + strictcount(op.getOperator()) = 1 and not analyzableConst(op) } @@ -473,97 +476,109 @@ private predicate mk_ThisExpr(Function fcn, ThisExpr thisExpr) { } private predicate analyzableArrayAccess(ArrayExpr ae) { - strictcount (ae.getArrayBase().getFullyConverted()) = 1 and - strictcount (ae.getArrayOffset().getFullyConverted()) = 1 and - strictcount (mostRecentSideEffect(ae)) = 1 and + strictcount(ae.getArrayBase().getFullyConverted()) = 1 and + strictcount(ae.getArrayOffset().getFullyConverted()) = 1 and + strictcount(mostRecentSideEffect(ae)) = 1 and not analyzableConst(ae) } -private predicate mk_ArrayAccess( - GVN base, GVN offset, ControlFlowNode dominator, ArrayExpr ae) { +private predicate mk_ArrayAccess(GVN base, GVN offset, ControlFlowNode dominator, ArrayExpr ae) { analyzableArrayAccess(ae) and base = globalValueNumber(ae.getArrayBase().getFullyConverted()) and offset = globalValueNumber(ae.getArrayOffset().getFullyConverted()) and dominator = mostRecentSideEffect(ae) } -private predicate analyzablePointerDereferenceExpr( - PointerDereferenceExpr deref) { - strictcount (deref.getOperand().getFullyConverted()) = 1 and - strictcount (mostRecentSideEffect(deref)) = 1 and +private predicate analyzablePointerDereferenceExpr(PointerDereferenceExpr deref) { + strictcount(deref.getOperand().getFullyConverted()) = 1 and + strictcount(mostRecentSideEffect(deref)) = 1 and not analyzableConst(deref) } -private predicate mk_Deref( - GVN p, ControlFlowNode dominator, PointerDereferenceExpr deref) { +private predicate mk_Deref(GVN p, ControlFlowNode dominator, PointerDereferenceExpr deref) { analyzablePointerDereferenceExpr(deref) and p = globalValueNumber(deref.getOperand().getFullyConverted()) and dominator = mostRecentSideEffect(deref) } /** Gets the global value number of expression `e`. */ -cached GVN globalValueNumber(Expr e) { - exists (int val, Type t - | mk_IntConst(val, t, e) and - result = GVN_IntConst(val, t)) +cached +GVN globalValueNumber(Expr e) { + exists(int val, Type t | + mk_IntConst(val, t, e) and + result = GVN_IntConst(val, t) + ) or - exists (float val, Type t - | mk_FloatConst(val, t, e) and - result = GVN_FloatConst(val, t)) + exists(float val, Type t | + mk_FloatConst(val, t, e) and + result = GVN_FloatConst(val, t) + ) or // Local variable with a defining value. - exists (LocalScopeVariable x, SsaDefinition def - | analyzableLocalScopeVariable(e) and + exists(LocalScopeVariable x, SsaDefinition def | + analyzableLocalScopeVariable(e) and e = def.getAUse(x) and - result = globalValueNumber(def.getDefiningValue(x).getFullyConverted())) + result = globalValueNumber(def.getDefiningValue(x).getFullyConverted()) + ) or // Local variable without a defining value. - exists (LocalScopeVariable x, SsaDefinition def - | mk_UndefinedLocalScopeVariable(x, def, e) and - result = GVN_UndefinedLocalScopeVariable(x, def)) + exists(LocalScopeVariable x, SsaDefinition def | + mk_UndefinedLocalScopeVariable(x, def, e) and + result = GVN_UndefinedLocalScopeVariable(x, def) + ) or // Variable with no SSA information. - exists (Variable x, ControlFlowNode dominator - | mk_OtherVariable(x, dominator, e) and - result = GVN_OtherVariable(x, dominator)) + exists(Variable x, ControlFlowNode dominator | + mk_OtherVariable(x, dominator, e) and + result = GVN_OtherVariable(x, dominator) + ) or - exists (GVN qualifier, Field target - | mk_DotFieldAccess(qualifier, target, e) and - result = GVN_FieldAccess(qualifier, target)) + exists(GVN qualifier, Field target | + mk_DotFieldAccess(qualifier, target, e) and + result = GVN_FieldAccess(qualifier, target) + ) or - exists (GVN qualifier, Field target - | mk_PointerFieldAccess_with_deref(qualifier, target, e) and - result = GVN_FieldAccess(qualifier, target)) + exists(GVN qualifier, Field target | + mk_PointerFieldAccess_with_deref(qualifier, target, e) and + result = GVN_FieldAccess(qualifier, target) + ) or - exists (GVN qualifier, Field target - | mk_ImplicitThisFieldAccess_with_deref(qualifier, target, e) and - result = GVN_FieldAccess(qualifier, target)) + exists(GVN qualifier, Field target | + mk_ImplicitThisFieldAccess_with_deref(qualifier, target, e) and + result = GVN_FieldAccess(qualifier, target) + ) or - exists (Function fcn - | mk_ThisExpr(fcn, e) and - result = GVN_ThisExpr(fcn)) + exists(Function fcn | + mk_ThisExpr(fcn, e) and + result = GVN_ThisExpr(fcn) + ) or - exists (Type t, GVN child - | mk_Conversion(t, child, e) and - result = GVN_Conversion(t, child)) + exists(Type t, GVN child | + mk_Conversion(t, child, e) and + result = GVN_Conversion(t, child) + ) or - exists (GVN lhs, GVN rhs, string opname - | mk_BinaryOp(lhs, rhs, opname, e) and - result = GVN_BinaryOp(lhs, rhs, opname)) + exists(GVN lhs, GVN rhs, string opname | + mk_BinaryOp(lhs, rhs, opname, e) and + result = GVN_BinaryOp(lhs, rhs, opname) + ) or - exists (GVN child, string opname - | mk_UnaryOp(child, opname, e) and - result = GVN_UnaryOp(child, opname)) + exists(GVN child, string opname | + mk_UnaryOp(child, opname, e) and + result = GVN_UnaryOp(child, opname) + ) or - exists (GVN x, GVN i, ControlFlowNode dominator - | mk_ArrayAccess(x, i, dominator, e) and - result = GVN_ArrayAccess(x, i, dominator)) + exists(GVN x, GVN i, ControlFlowNode dominator | + mk_ArrayAccess(x, i, dominator, e) and + result = GVN_ArrayAccess(x, i, dominator) + ) or - exists (GVN p, ControlFlowNode dominator - | mk_Deref(p, dominator, e) and - result = GVN_Deref(p, dominator)) + exists(GVN p, ControlFlowNode dominator | + mk_Deref(p, dominator, e) and + result = GVN_Deref(p, dominator) + ) or - (not analyzableExpr(e) and result = GVN_Unanalyzable(e)) + not analyzableExpr(e) and result = GVN_Unanalyzable(e) } private predicate analyzableConst(Expr e) { diff --git a/cpp/ql/src/semmle/code/cpp/valuenumbering/HashCons.qll b/cpp/ql/src/semmle/code/cpp/valuenumbering/HashCons.qll index b51f0c6ce7a..aa41af86f97 100644 --- a/cpp/ql/src/semmle/code/cpp/valuenumbering/HashCons.qll +++ b/cpp/ql/src/semmle/code/cpp/valuenumbering/HashCons.qll @@ -40,173 +40,94 @@ import cpp /** Used to represent the hash-cons of an expression. */ -private cached newtype HCBase = - HC_IntLiteral(int val, Type t) { mk_IntLiteral(val,t,_) } - or - HC_EnumConstantAccess(EnumConstant val, Type t) { mk_EnumConstantAccess(val,t,_) } - or - HC_FloatLiteral(float val, Type t) { mk_FloatLiteral(val,t,_) } - or - HC_StringLiteral(string val, Type t) {mk_StringLiteral(val,t,_)} - or - HC_Nullptr() {mk_Nullptr(_)} - or - HC_Variable(Variable x) { - mk_Variable(x, _) - } - or - HC_FieldAccess(HashCons s, Field f) { - mk_DotFieldAccess(s,f,_) - } - or - HC_Deref(HashCons p) { - mk_Deref(p,_) - } - or - HC_PointerFieldAccess(HashCons qual, Field target) { - mk_PointerFieldAccess(qual, target, _) - } - or - HC_ThisExpr(Function fcn) { - mk_ThisExpr(fcn,_) - } - or - HC_ImplicitThisFieldAccess (Function fcn, Field target){ +cached +private newtype HCBase = + HC_IntLiteral(int val, Type t) { mk_IntLiteral(val, t, _) } or + HC_EnumConstantAccess(EnumConstant val, Type t) { mk_EnumConstantAccess(val, t, _) } or + HC_FloatLiteral(float val, Type t) { mk_FloatLiteral(val, t, _) } or + HC_StringLiteral(string val, Type t) { mk_StringLiteral(val, t, _) } or + HC_Nullptr() { mk_Nullptr(_) } or + HC_Variable(Variable x) { mk_Variable(x, _) } or + HC_FieldAccess(HashCons s, Field f) { mk_DotFieldAccess(s, f, _) } or + HC_Deref(HashCons p) { mk_Deref(p, _) } or + HC_PointerFieldAccess(HashCons qual, Field target) { mk_PointerFieldAccess(qual, target, _) } or + HC_ThisExpr(Function fcn) { mk_ThisExpr(fcn, _) } or + HC_ImplicitThisFieldAccess(Function fcn, Field target) { mk_ImplicitThisFieldAccess(fcn, target, _) - } - or - HC_Conversion(Type t, HashCons child) { mk_Conversion(t, child, _) } - or - HC_BinaryOp(HashCons lhs, HashCons rhs, string opname) { - mk_BinaryOp(lhs, rhs, opname, _) - } - or - HC_UnaryOp(HashCons child, string opname) { mk_UnaryOp(child, opname, _) } - or - HC_ArrayAccess(HashCons x, HashCons i) { - mk_ArrayAccess(x,i,_) - } - or - HC_NonmemberFunctionCall(Function fcn, HC_Args args) { - mk_NonmemberFunctionCall(fcn, args, _) - } - or HC_ExprCall(HashCons hc, HC_Args args) { - mk_ExprCall(hc, args, _) - } - or + } or + HC_Conversion(Type t, HashCons child) { mk_Conversion(t, child, _) } or + HC_BinaryOp(HashCons lhs, HashCons rhs, string opname) { mk_BinaryOp(lhs, rhs, opname, _) } or + HC_UnaryOp(HashCons child, string opname) { mk_UnaryOp(child, opname, _) } or + HC_ArrayAccess(HashCons x, HashCons i) { mk_ArrayAccess(x, i, _) } or + HC_NonmemberFunctionCall(Function fcn, HC_Args args) { mk_NonmemberFunctionCall(fcn, args, _) } or + HC_ExprCall(HashCons hc, HC_Args args) { mk_ExprCall(hc, args, _) } or HC_MemberFunctionCall(Function trg, HashCons qual, HC_Args args) { mk_MemberFunctionCall(trg, qual, args, _) - } - or + } or // Hack to get around argument 0 of allocator calls being an error expression - HC_AllocatorArgZero(Type t) { - mk_AllocatorArgZero(t, _) - } - or - HC_NewExpr(Type t, HC_Alloc alloc, HC_Init init) { - mk_NewExpr(t, alloc, init, _) - } - or + HC_AllocatorArgZero(Type t) { mk_AllocatorArgZero(t, _) } or + HC_NewExpr(Type t, HC_Alloc alloc, HC_Init init) { mk_NewExpr(t, alloc, init, _) } or HC_NewArrayExpr(Type t, HC_Alloc alloc, HC_Extent extent, HC_Init init) { mk_NewArrayExpr(t, alloc, extent, init, _) - } - or - HC_SizeofType(Type t) {mk_SizeofType(t, _)} - or - HC_SizeofExpr(HashCons child) {mk_SizeofExpr(child, _)} - or - HC_AlignofType(Type t) {mk_AlignofType(t, _)} - or - HC_AlignofExpr(HashCons child) {mk_AlignofExpr(child, _)} - or - HC_UuidofOperator(Type t) {mk_UuidofOperator(t, _)} - or - HC_TypeidType(Type t) {mk_TypeidType(t, _)} - or - HC_TypeidExpr(HashCons child) {mk_TypeidExpr(child, _)} - or - HC_ClassAggregateLiteral(Class c, HC_Fields hcf) { - mk_ClassAggregateLiteral(c, hcf, _) - } - or - HC_ArrayAggregateLiteral(Type t, HC_Array hca) { - mk_ArrayAggregateLiteral(t, hca, _) - } - or - HC_DeleteExpr(HashCons child) {mk_DeleteExpr(child, _)} - or - HC_DeleteArrayExpr(HashCons child) {mk_DeleteArrayExpr(child, _)} - or - HC_ThrowExpr(HashCons child) {mk_ThrowExpr(child, _)} - or - HC_ReThrowExpr() - or + } or + HC_SizeofType(Type t) { mk_SizeofType(t, _) } or + HC_SizeofExpr(HashCons child) { mk_SizeofExpr(child, _) } or + HC_AlignofType(Type t) { mk_AlignofType(t, _) } or + HC_AlignofExpr(HashCons child) { mk_AlignofExpr(child, _) } or + HC_UuidofOperator(Type t) { mk_UuidofOperator(t, _) } or + HC_TypeidType(Type t) { mk_TypeidType(t, _) } or + HC_TypeidExpr(HashCons child) { mk_TypeidExpr(child, _) } or + HC_ClassAggregateLiteral(Class c, HC_Fields hcf) { mk_ClassAggregateLiteral(c, hcf, _) } or + HC_ArrayAggregateLiteral(Type t, HC_Array hca) { mk_ArrayAggregateLiteral(t, hca, _) } or + HC_DeleteExpr(HashCons child) { mk_DeleteExpr(child, _) } or + HC_DeleteArrayExpr(HashCons child) { mk_DeleteArrayExpr(child, _) } or + HC_ThrowExpr(HashCons child) { mk_ThrowExpr(child, _) } or + HC_ReThrowExpr() or HC_ConditionalExpr(HashCons cond, HashCons trueHC, HashCons falseHC) { mk_ConditionalExpr(cond, trueHC, falseHC, _) - } - or - HC_NoExceptExpr(HashCons child) { - mk_NoExceptExpr(child, _) - } - or + } or + HC_NoExceptExpr(HashCons child) { mk_NoExceptExpr(child, _) } or // Any expression that is not handled by the cases above is // given a unique number based on the expression itself. - HC_Unanalyzable(Expr e) { not analyzableExpr(e,_) } + HC_Unanalyzable(Expr e) { not analyzableExpr(e, _) } /** Used to implement optional init on `new` expressions */ private newtype HC_Init = - HC_NoInit() - or - HC_HasInit(HashCons hc) {mk_HasInit(hc, _)} + HC_NoInit() or + HC_HasInit(HashCons hc) { mk_HasInit(hc, _) } /** * Used to implement optional allocator call on `new` expressions */ private newtype HC_Alloc = - HC_NoAlloc() - or - HC_HasAlloc(HashCons hc) {mk_HasAlloc(hc, _)} - + HC_NoAlloc() or + HC_HasAlloc(HashCons hc) { mk_HasAlloc(hc, _) } + /** * Used to implement optional extent expression on `new[]` exprtessions */ private newtype HC_Extent = - HC_NoExtent() - or - HC_HasExtent(HashCons hc) {mk_HasExtent(hc, _)} -/** Used to implement hash-consing of argument lists */ + HC_NoExtent() or + HC_HasExtent(HashCons hc) { mk_HasExtent(hc, _) } + +/** Used to implement hash-consing of argument lists */ private newtype HC_Args = - HC_EmptyArgs() { - any() - } - or HC_ArgCons(HashCons hc, int i, HC_Args list) { - mk_ArgCons(hc, i, list, _) - } + HC_EmptyArgs() { any() } or + HC_ArgCons(HashCons hc, int i, HC_Args list) { mk_ArgCons(hc, i, list, _) } /** * Used to implement hash-consing of struct initizializers. */ private newtype HC_Fields = - HC_EmptyFields(Class c) { - exists(ClassAggregateLiteral cal | - c = cal.getUnspecifiedType() - ) - } - or + HC_EmptyFields(Class c) { exists(ClassAggregateLiteral cal | c = cal.getUnspecifiedType()) } or HC_FieldCons(Class c, int i, Field f, HashCons hc, HC_Fields hcf) { - mk_FieldCons(c, i, f, hc, hcf, _) + mk_FieldCons(c, i, f, hc, hcf, _) } private newtype HC_Array = - HC_EmptyArray(Type t) { - exists(ArrayAggregateLiteral aal | - aal.getUnspecifiedType() = t - ) - } - or - HC_ArrayCons(Type t, int i, HashCons hc, HC_Array hca) { - mk_ArrayCons(t, i, hc, hca, _) - } + HC_EmptyArray(Type t) { exists(ArrayAggregateLiteral aal | aal.getUnspecifiedType() = t) } or + HC_ArrayCons(Type t, int i, HashCons hc, HC_Array hca) { mk_ArrayCons(t, i, hc, hca, _) } + /** * HashCons is the hash-cons of an expression. The relationship between `Expr` * and `HC` is many-to-one: every `Expr` has exactly one `HC`, but multiple @@ -223,48 +144,122 @@ private newtype HC_Array = */ class HashCons extends HCBase { /** Gets an expression that has this HC. */ - Expr getAnExpr() { - this = hashCons(result) - } + Expr getAnExpr() { this = hashCons(result) } /** Gets the kind of the HC. This can be useful for debugging. */ string getKind() { - if this instanceof HC_IntLiteral then result = "IntLiteral" else - if this instanceof HC_EnumConstantAccess then result = "EnumConstantAccess" else - if this instanceof HC_FloatLiteral then result = "FloatLiteral" else - if this instanceof HC_StringLiteral then result = "StringLiteral" else - if this instanceof HC_Nullptr then result = "Nullptr" else - if this instanceof HC_Variable then result = "Variable" else - if this instanceof HC_FieldAccess then result = "FieldAccess" else - if this instanceof HC_Deref then result = "Deref" else - if this instanceof HC_ThisExpr then result = "ThisExpr" else - if this instanceof HC_Conversion then result = "Conversion" else - if this instanceof HC_BinaryOp then result = "BinaryOp" else - if this instanceof HC_UnaryOp then result = "UnaryOp" else - if this instanceof HC_ArrayAccess then result = "ArrayAccess" else - if this instanceof HC_Unanalyzable then result = "Unanalyzable" else - if this instanceof HC_NonmemberFunctionCall then result = "NonmemberFunctionCall" else - if this instanceof HC_MemberFunctionCall then result = "MemberFunctionCall" else - if this instanceof HC_NewExpr then result = "NewExpr" else - if this instanceof HC_NewArrayExpr then result = "NewArrayExpr" else - if this instanceof HC_SizeofType then result = "SizeofTypeOperator" else - if this instanceof HC_SizeofExpr then result = "SizeofExprOperator" else - if this instanceof HC_AlignofType then result = "AlignofTypeOperator" else - if this instanceof HC_AlignofExpr then result = "AlignofExprOperator" else - if this instanceof HC_UuidofOperator then result = "UuidofOperator" else - if this instanceof HC_TypeidType then result = "TypeidType" else - if this instanceof HC_TypeidExpr then result = "TypeidExpr" else - if this instanceof HC_ArrayAggregateLiteral then result = "ArrayAggregateLiteral" else - if this instanceof HC_ClassAggregateLiteral then result = "ClassAggregateLiteral" else - if this instanceof HC_DeleteExpr then result = "DeleteExpr" else - if this instanceof HC_DeleteArrayExpr then result = "DeleteArrayExpr" else - if this instanceof HC_ThrowExpr then result = "ThrowExpr" else - if this instanceof HC_ReThrowExpr then result = "ReThrowExpr" else - if this instanceof HC_ExprCall then result = "ExprCall" else - if this instanceof HC_ConditionalExpr then result = "ConditionalExpr" else - if this instanceof HC_NoExceptExpr then result = "NoExceptExpr" else - if this instanceof HC_AllocatorArgZero then result = "AllocatorArgZero" else - result = "error" + if this instanceof HC_IntLiteral + then result = "IntLiteral" + else + if this instanceof HC_EnumConstantAccess + then result = "EnumConstantAccess" + else + if this instanceof HC_FloatLiteral + then result = "FloatLiteral" + else + if this instanceof HC_StringLiteral + then result = "StringLiteral" + else + if this instanceof HC_Nullptr + then result = "Nullptr" + else + if this instanceof HC_Variable + then result = "Variable" + else + if this instanceof HC_FieldAccess + then result = "FieldAccess" + else + if this instanceof HC_Deref + then result = "Deref" + else + if this instanceof HC_ThisExpr + then result = "ThisExpr" + else + if this instanceof HC_Conversion + then result = "Conversion" + else + if this instanceof HC_BinaryOp + then result = "BinaryOp" + else + if this instanceof HC_UnaryOp + then result = "UnaryOp" + else + if this instanceof HC_ArrayAccess + then result = "ArrayAccess" + else + if this instanceof HC_Unanalyzable + then result = "Unanalyzable" + else + if this instanceof HC_NonmemberFunctionCall + then result = "NonmemberFunctionCall" + else + if this instanceof HC_MemberFunctionCall + then result = "MemberFunctionCall" + else + if this instanceof HC_NewExpr + then result = "NewExpr" + else + if this instanceof HC_NewArrayExpr + then result = "NewArrayExpr" + else + if this instanceof HC_SizeofType + then result = "SizeofTypeOperator" + else + if this instanceof HC_SizeofExpr + then result = "SizeofExprOperator" + else + if this instanceof HC_AlignofType + then result = "AlignofTypeOperator" + else + if this instanceof HC_AlignofExpr + then result = "AlignofExprOperator" + else + if this instanceof HC_UuidofOperator + then result = "UuidofOperator" + else + if this instanceof HC_TypeidType + then result = "TypeidType" + else + if this instanceof HC_TypeidExpr + then result = "TypeidExpr" + else + if this instanceof HC_ArrayAggregateLiteral + then result = "ArrayAggregateLiteral" + else + if this instanceof HC_ClassAggregateLiteral + then result = "ClassAggregateLiteral" + else + if this instanceof HC_DeleteExpr + then result = "DeleteExpr" + else + if this instanceof HC_DeleteArrayExpr + then result = "DeleteArrayExpr" + else + if this instanceof HC_ThrowExpr + then result = "ThrowExpr" + else + if this instanceof HC_ReThrowExpr + then result = "ReThrowExpr" + else + if this instanceof HC_ExprCall + then result = "ExprCall" + else + if + this instanceof + HC_ConditionalExpr + then result = "ConditionalExpr" + else + if + this instanceof + HC_NoExceptExpr + then result = "NoExceptExpr" + else + if + this instanceof + HC_AllocatorArgZero + then + result = "AllocatorArgZero" + else result = "error" } /** @@ -274,22 +269,21 @@ class HashCons extends HCBase { private Expr exampleExpr() { // Pick the expression with the minimum source location string. This is // just an arbitrary way to pick an expression with this `HC`. - result = - min(Expr e - | this = hashCons(e) - | e order by exampleLocationString(e.getLocation()), e.getLocation().getStartColumn(), - e.getLocation().getEndLine(), e.getLocation().getEndColumn()) + result = min(Expr e | + this = hashCons(e) + | + e + order by + exampleLocationString(e.getLocation()), e.getLocation().getStartColumn(), + e.getLocation().getEndLine(), e.getLocation().getEndColumn() + ) } /** Gets a textual representation of this element. */ - string toString() { - result = exampleExpr().toString() - } + string toString() { result = exampleExpr().toString() } /** Gets the primary location of this element. */ - Location getLocation() { - result = exampleExpr().getLocation() - } + Location getLocation() { result = exampleExpr().getLocation() } } /** @@ -298,14 +292,12 @@ class HashCons extends HCBase { * selecting an example expression for a HashCons value. */ private string exampleLocationString(Location l) { - if l instanceof UnknownLocation - then result = "~" - else result = l.getFile().getAbsolutePath() + if l instanceof UnknownLocation then result = "~" else result = l.getFile().getAbsolutePath() } private predicate analyzableIntLiteral(Literal e) { - strictcount (e.getValue().toInt()) = 1 and - strictcount (e.getUnspecifiedType()) = 1 and + strictcount(e.getValue().toInt()) = 1 and + strictcount(e.getUnspecifiedType()) = 1 and e.getUnspecifiedType() instanceof IntegralType } @@ -316,8 +308,8 @@ private predicate mk_IntLiteral(int val, Type t, Expr e) { } private predicate analyzableEnumConstantAccess(EnumConstantAccess e) { - strictcount (e.getValue().toInt()) = 1 and - strictcount (e.getUnspecifiedType()) = 1 and + strictcount(e.getValue().toInt()) = 1 and + strictcount(e.getUnspecifiedType()) = 1 and e.getUnspecifiedType() instanceof Enum } @@ -328,8 +320,8 @@ private predicate mk_EnumConstantAccess(EnumConstant val, Type t, Expr e) { } private predicate analyzableFloatLiteral(Literal e) { - strictcount (e.getValue().toFloat()) = 1 and - strictcount (e.getUnspecifiedType()) = 1 and + strictcount(e.getValue().toFloat()) = 1 and + strictcount(e.getUnspecifiedType()) = 1 and e.getUnspecifiedType() instanceof FloatingPointType } @@ -340,13 +332,11 @@ private predicate mk_FloatLiteral(float val, Type t, Expr e) { } private predicate analyzableNullptr(NullValue e) { - strictcount (e.getUnspecifiedType()) = 1 and + strictcount(e.getUnspecifiedType()) = 1 and e.getType() instanceof NullPointerType } -private predicate mk_Nullptr(Expr e) { - analyzableNullptr(e) -} +private predicate mk_Nullptr(Expr e) { analyzableNullptr(e) } private predicate analyzableStringLiteral(Literal e) { strictcount(e.getValue()) = 1 and @@ -359,49 +349,46 @@ private predicate mk_StringLiteral(string val, Type t, Expr e) { val = e.getValue() and t = e.getUnspecifiedType() and t.(ArrayType).getBaseType() instanceof CharType - } private predicate analyzableDotFieldAccess(DotFieldAccess access) { - strictcount (access.getTarget()) = 1 and - strictcount (access.getQualifier().getFullyConverted()) = 1 + strictcount(access.getTarget()) = 1 and + strictcount(access.getQualifier().getFullyConverted()) = 1 } -private predicate mk_DotFieldAccess( - HashCons qualifier, Field target, DotFieldAccess access) { +private predicate mk_DotFieldAccess(HashCons qualifier, Field target, DotFieldAccess access) { analyzableDotFieldAccess(access) and target = access.getTarget() and qualifier = hashCons(access.getQualifier().getFullyConverted()) } private predicate analyzablePointerFieldAccess(PointerFieldAccess access) { - strictcount (access.getTarget()) = 1 and - strictcount (access.getQualifier().getFullyConverted()) = 1 + strictcount(access.getTarget()) = 1 and + strictcount(access.getQualifier().getFullyConverted()) = 1 } -private predicate mk_PointerFieldAccess( - HashCons qualifier, Field target, - PointerFieldAccess access) { +private predicate mk_PointerFieldAccess(HashCons qualifier, Field target, PointerFieldAccess access) { analyzablePointerFieldAccess(access) and target = access.getTarget() and qualifier = hashCons(access.getQualifier().getFullyConverted()) } private predicate analyzableImplicitThisFieldAccess(ImplicitThisFieldAccess access) { - strictcount (access.getTarget()) = 1 and - strictcount (access.getEnclosingFunction()) = 1 + strictcount(access.getTarget()) = 1 and + strictcount(access.getEnclosingFunction()) = 1 } -private predicate mk_ImplicitThisFieldAccess(Function fcn, Field target, - ImplicitThisFieldAccess access) { +private predicate mk_ImplicitThisFieldAccess( + Function fcn, Field target, ImplicitThisFieldAccess access +) { analyzableImplicitThisFieldAccess(access) and target = access.getTarget() and fcn = access.getEnclosingFunction() } private predicate analyzableVariable(VariableAccess access) { - not (access instanceof FieldAccess) and - strictcount (access.getTarget()) = 1 + not access instanceof FieldAccess and + strictcount(access.getTarget()) = 1 } private predicate mk_Variable(Variable x, VariableAccess access) { @@ -410,8 +397,8 @@ private predicate mk_Variable(Variable x, VariableAccess access) { } private predicate analyzableConversion(Conversion conv) { - strictcount (conv.getUnspecifiedType()) = 1 and - strictcount (conv.getExpr()) = 1 + strictcount(conv.getUnspecifiedType()) = 1 and + strictcount(conv.getExpr()) = 1 } private predicate mk_Conversion(Type t, HashCons child, Conversion conv) { @@ -421,9 +408,9 @@ private predicate mk_Conversion(Type t, HashCons child, Conversion conv) { } private predicate analyzableBinaryOp(BinaryOperation op) { - strictcount (op.getLeftOperand().getFullyConverted()) = 1 and - strictcount (op.getRightOperand().getFullyConverted()) = 1 and - strictcount (op.getOperator()) = 1 + strictcount(op.getLeftOperand().getFullyConverted()) = 1 and + strictcount(op.getRightOperand().getFullyConverted()) = 1 and + strictcount(op.getOperator()) = 1 } private predicate mk_BinaryOp(HashCons lhs, HashCons rhs, string opname, BinaryOperation op) { @@ -434,9 +421,9 @@ private predicate mk_BinaryOp(HashCons lhs, HashCons rhs, string opname, BinaryO } private predicate analyzableUnaryOp(UnaryOperation op) { - not (op instanceof PointerDereferenceExpr) and - strictcount (op.getOperand().getFullyConverted()) = 1 and - strictcount (op.getOperator()) = 1 + not op instanceof PointerDereferenceExpr and + strictcount(op.getOperand().getFullyConverted()) = 1 and + strictcount(op.getOperator()) = 1 } private predicate mk_UnaryOp(HashCons child, string opname, UnaryOperation op) { @@ -455,8 +442,8 @@ private predicate mk_ThisExpr(Function fcn, ThisExpr thisExpr) { } private predicate analyzableArrayAccess(ArrayExpr ae) { - strictcount (ae.getArrayBase().getFullyConverted()) = 1 and - strictcount (ae.getArrayOffset().getFullyConverted()) = 1 + strictcount(ae.getArrayBase().getFullyConverted()) = 1 and + strictcount(ae.getArrayOffset().getFullyConverted()) = 1 } private predicate mk_ArrayAccess(HashCons base, HashCons offset, ArrayExpr ae) { @@ -466,7 +453,7 @@ private predicate mk_ArrayAccess(HashCons base, HashCons offset, ArrayExpr ae) { } private predicate analyzablePointerDereferenceExpr(PointerDereferenceExpr deref) { - strictcount (deref.getOperand().getFullyConverted()) = 1 + strictcount(deref.getOperand().getFullyConverted()) = 1 } private predicate mk_Deref(HashCons p, PointerDereferenceExpr deref) { @@ -475,16 +462,14 @@ private predicate mk_Deref(HashCons p, PointerDereferenceExpr deref) { } private predicate analyzableNonmemberFunctionCall(FunctionCall fc) { - forall(int i | - i in [0..fc.getNumberOfArguments()-1] | + forall(int i | i in [0 .. fc.getNumberOfArguments() - 1] | strictcount(fc.getArgument(i).getFullyConverted()) = 1 ) and strictcount(fc.getTarget()) = 1 and not exists(fc.getQualifier()) } -private predicate mk_NonmemberFunctionCall(Function fcn, HC_Args args, FunctionCall fc -) { +private predicate mk_NonmemberFunctionCall(Function fcn, HC_Args args, FunctionCall fc) { fc.getTarget() = fcn and analyzableNonmemberFunctionCall(fc) and ( @@ -498,8 +483,7 @@ private predicate mk_NonmemberFunctionCall(Function fcn, HC_Args args, FunctionC } private predicate analyzableExprCall(ExprCall ec) { - forall(int i | - i in [0..ec.getNumberOfArguments()-1] | + forall(int i | i in [0 .. ec.getNumberOfArguments() - 1] | strictcount(ec.getArgument(i).getFullyConverted()) = 1 ) and strictcount(ec.getExpr().getFullyConverted()) = 1 @@ -517,22 +501,15 @@ private predicate mk_ExprCall(HashCons hc, HC_Args args, ExprCall ec) { ) } -private predicate analyzableMemberFunctionCall( - FunctionCall fc) { - forall(int i | - i in [0..fc.getNumberOfArguments()-1] | +private predicate analyzableMemberFunctionCall(FunctionCall fc) { + forall(int i | i in [0 .. fc.getNumberOfArguments() - 1] | strictcount(fc.getArgument(i).getFullyConverted()) = 1 ) and strictcount(fc.getTarget()) = 1 and strictcount(fc.getQualifier().getFullyConverted()) = 1 } -private predicate mk_MemberFunctionCall( - Function fcn, - HashCons qual, - HC_Args args, - FunctionCall fc -) { +private predicate mk_MemberFunctionCall(Function fcn, HashCons qual, HC_Args args, FunctionCall fc) { fc.getTarget() = fcn and analyzableMemberFunctionCall(fc) and hashCons(fc.getQualifier().getFullyConverted()) = qual and @@ -563,7 +540,7 @@ private predicate mk_ArgCons(HashCons hc, int i, HC_Args list, Call c) { hc = hashCons(c.getArgument(i).getFullyConverted()) and ( exists(HashCons head, HC_Args tail | - mk_ArgConsInner(head, tail, i-1, list, c) and + mk_ArgConsInner(head, tail, i - 1, list, c) and i > 0 ) or @@ -581,14 +558,13 @@ private predicate mk_ArgConsInner(HashCons head, HC_Args tail, int i, HC_Args li /** * The 0th argument of an allocator call in a new expression is always an error expression; - * this works around it + * this works around it */ private predicate analyzableAllocatorArgZero(ErrorExpr e) { exists(NewOrNewArrayExpr new | new.getAllocatorCall().getChild(0) = e and strictcount(new.getUnspecifiedType()) = 1 - ) - and + ) and strictcount(NewOrNewArrayExpr new | new.getAllocatorCall().getChild(0) = e) = 1 } @@ -628,8 +604,7 @@ private predicate mk_NewExpr(Type t, HC_Alloc alloc, HC_Init init, NewExpr new) or not exists(new.getAllocatorCall().getFullyConverted()) and alloc = HC_NoAlloc() - ) - and + ) and ( init = HC_HasInit(hashCons(new.getInitializer().getFullyConverted())) or @@ -645,25 +620,23 @@ private predicate analyzableNewArrayExpr(NewArrayExpr new) { count(new.(NewArrayExpr).getExtent().getFullyConverted()) <= 1 } -private predicate mk_NewArrayExpr(Type t, HC_Alloc alloc, HC_Extent extent, HC_Init init, NewArrayExpr new) { +private predicate mk_NewArrayExpr( + Type t, HC_Alloc alloc, HC_Extent extent, HC_Init init, NewArrayExpr new +) { analyzableNewArrayExpr(new) and t = new.getAllocatedType() and - ( alloc = HC_HasAlloc(hashCons(new.getAllocatorCall().getFullyConverted())) or not exists(new.getAllocatorCall().getFullyConverted()) and alloc = HC_NoAlloc() - ) - and + ) and ( init = HC_HasInit(hashCons(new.getInitializer().getFullyConverted())) or not exists(new.getInitializer().getFullyConverted()) and init = HC_NoInit() - ) - and - + ) and ( extent = HC_HasExtent(hashCons(new.getExtent().getFullyConverted())) or @@ -710,9 +683,7 @@ private predicate mk_SizeofExpr(HashCons child, SizeofExprOperator e) { child = hashCons(e.getAChild()) } -private predicate analyzableUuidofOperator(UuidofOperator e) { - strictcount(e.getTypeOperand()) = 1 -} +private predicate analyzableUuidofOperator(UuidofOperator e) { strictcount(e.getTypeOperand()) = 1 } private predicate mk_UuidofOperator(Type t, UuidofOperator e) { analyzableUuidofOperator(e) and @@ -758,8 +729,9 @@ private predicate mk_AlignofExpr(HashCons child, AlignofExprOperator e) { child = hashCons(e.getAChild()) } -private predicate mk_FieldCons(Class c, int i, Field f, HashCons hc, HC_Fields hcf, - ClassAggregateLiteral cal) { +private predicate mk_FieldCons( + Class c, int i, Field f, HashCons hc, HC_Fields hcf, ClassAggregateLiteral cal +) { analyzableClassAggregateLiteral(cal) and cal.getUnspecifiedType() = c and exists(Expr e | @@ -768,9 +740,9 @@ private predicate mk_FieldCons(Class c, int i, Field f, HashCons hc, HC_Fields h hc = hashCons(e) and ( exists(HashCons head, Field f2, HC_Fields tail | - hcf = HC_FieldCons(c, i-1, f2, head, tail) and - f2.getInitializationOrder() = i-1 and - mk_FieldCons(c, i-1, f2, head, tail, cal) + hcf = HC_FieldCons(c, i - 1, f2, head, tail) and + f2.getInitializationOrder() = i - 1 and + mk_FieldCons(c, i - 1, f2, head, tail, cal) ) or i = 0 and @@ -780,12 +752,12 @@ private predicate mk_FieldCons(Class c, int i, Field f, HashCons hc, HC_Fields h } private predicate analyzableClassAggregateLiteral(ClassAggregateLiteral cal) { - forall(int i | - exists(cal.getChild(i)) | + forall(int i | exists(cal.getChild(i)) | strictcount(cal.getChild(i).getFullyConverted()) = 1 and strictcount(Field f | cal.getChild(i) = cal.getFieldExpr(f)) = 1 and strictcount(Field f, int j | - cal.getFieldExpr(f) = cal.getChild(i) and j = f.getInitializationOrder()) = 1 + cal.getFieldExpr(f) = cal.getChild(i) and j = f.getInitializationOrder() + ) = 1 ) } @@ -806,10 +778,7 @@ private predicate mk_ClassAggregateLiteral(Class c, HC_Fields hcf, ClassAggregat } private predicate analyzableArrayAggregateLiteral(ArrayAggregateLiteral aal) { - forall(int i | - exists(aal.getChild(i)) | - strictcount(aal.getChild(i).getFullyConverted()) = 1 - ) and + forall(int i | exists(aal.getChild(i)) | strictcount(aal.getChild(i).getFullyConverted()) = 1) and strictcount(aal.getUnspecifiedType()) = 1 } @@ -820,7 +789,7 @@ private predicate mk_ArrayCons(Type t, int i, HashCons hc, HC_Array hca, ArrayAg ( exists(HC_Array tail, HashCons head | hca = HC_ArrayCons(t, i - 1, head, tail) and - mk_ArrayCons(t, i-1, head, tail, aal) + mk_ArrayCons(t, i - 1, head, tail, aal) ) or i = 0 and @@ -850,13 +819,9 @@ private predicate mk_ThrowExpr(HashCons hc, ThrowExpr te) { hc.getAnExpr() = te.getExpr().getFullyConverted() } -private predicate analyzableReThrowExpr(ReThrowExpr rte) { - any() -} +private predicate analyzableReThrowExpr(ReThrowExpr rte) { any() } -private predicate mk_ReThrowExpr(ReThrowExpr te) { - any() -} +private predicate mk_ReThrowExpr(ReThrowExpr te) { any() } private predicate analyzableConditionalExpr(ConditionalExpr ce) { strictcount(ce.getCondition().getFullyConverted()) = 1 and @@ -864,8 +829,9 @@ private predicate analyzableConditionalExpr(ConditionalExpr ce) { strictcount(ce.getElse().getFullyConverted()) = 1 } -private predicate mk_ConditionalExpr(HashCons cond, HashCons trueHc, HashCons falseHc, - ConditionalExpr ce) { +private predicate mk_ConditionalExpr( + HashCons cond, HashCons trueHc, HashCons falseHc, ConditionalExpr ce +) { analyzableConditionalExpr(ce) and cond.getAnExpr() = ce.getCondition() and trueHc.getAnExpr() = ce.getThen() and @@ -881,174 +847,184 @@ private predicate mk_NoExceptExpr(HashCons child, NoExceptExpr nee) { nee.getExpr().getFullyConverted() = child.getAnExpr() } - /** Gets the hash-cons of expression `e`. */ -cached HashCons hashCons(Expr e) { - exists (int val, Type t - | mk_IntLiteral(val, t, e) and - result = HC_IntLiteral(val, t)) +cached +HashCons hashCons(Expr e) { + exists(int val, Type t | + mk_IntLiteral(val, t, e) and + result = HC_IntLiteral(val, t) + ) or - exists (EnumConstant val, Type t - | mk_EnumConstantAccess(val, t, e) and - result = HC_EnumConstantAccess(val, t)) + exists(EnumConstant val, Type t | + mk_EnumConstantAccess(val, t, e) and + result = HC_EnumConstantAccess(val, t) + ) or - exists (float val, Type t - | mk_FloatLiteral(val, t, e) and - result = HC_FloatLiteral(val, t)) + exists(float val, Type t | + mk_FloatLiteral(val, t, e) and + result = HC_FloatLiteral(val, t) + ) or - exists (string val, Type t - | mk_StringLiteral(val, t, e) and - result = HC_StringLiteral(val, t)) + exists(string val, Type t | + mk_StringLiteral(val, t, e) and + result = HC_StringLiteral(val, t) + ) or - exists (Variable x - | mk_Variable(x, e) and - result = HC_Variable(x)) + exists(Variable x | + mk_Variable(x, e) and + result = HC_Variable(x) + ) or - exists (HashCons qualifier, Field target - | mk_DotFieldAccess(qualifier, target, e) and - result = HC_FieldAccess(qualifier, target)) + exists(HashCons qualifier, Field target | + mk_DotFieldAccess(qualifier, target, e) and + result = HC_FieldAccess(qualifier, target) + ) or - exists (HashCons qualifier, Field target - | mk_PointerFieldAccess(qualifier, target, e) and - result = HC_PointerFieldAccess(qualifier, target)) + exists(HashCons qualifier, Field target | + mk_PointerFieldAccess(qualifier, target, e) and + result = HC_PointerFieldAccess(qualifier, target) + ) or - exists (Function fcn, Field target - | mk_ImplicitThisFieldAccess(fcn, target, e) and - result = HC_ImplicitThisFieldAccess(fcn, target)) + exists(Function fcn, Field target | + mk_ImplicitThisFieldAccess(fcn, target, e) and + result = HC_ImplicitThisFieldAccess(fcn, target) + ) or - exists (Function fcn - | mk_ThisExpr(fcn, e) and - result = HC_ThisExpr(fcn)) + exists(Function fcn | + mk_ThisExpr(fcn, e) and + result = HC_ThisExpr(fcn) + ) or - exists (Type t, HashCons child - | mk_Conversion(t, child, e) and - result = HC_Conversion(t, child)) + exists(Type t, HashCons child | + mk_Conversion(t, child, e) and + result = HC_Conversion(t, child) + ) or - exists (HashCons lhs, HashCons rhs, string opname - | mk_BinaryOp(lhs, rhs, opname, e) and - result = HC_BinaryOp(lhs, rhs, opname)) + exists(HashCons lhs, HashCons rhs, string opname | + mk_BinaryOp(lhs, rhs, opname, e) and + result = HC_BinaryOp(lhs, rhs, opname) + ) or - exists (HashCons child, string opname - | mk_UnaryOp(child, opname, e) and - result = HC_UnaryOp(child, opname)) + exists(HashCons child, string opname | + mk_UnaryOp(child, opname, e) and + result = HC_UnaryOp(child, opname) + ) or - exists (HashCons x, HashCons i - | mk_ArrayAccess(x, i, e) and - result = HC_ArrayAccess(x, i)) + exists(HashCons x, HashCons i | + mk_ArrayAccess(x, i, e) and + result = HC_ArrayAccess(x, i) + ) or - exists (HashCons p - | mk_Deref(p, e) and - result = HC_Deref(p)) + exists(HashCons p | + mk_Deref(p, e) and + result = HC_Deref(p) + ) or - exists(Function fcn, HC_Args args - | mk_NonmemberFunctionCall(fcn, args, e) and + exists(Function fcn, HC_Args args | + mk_NonmemberFunctionCall(fcn, args, e) and result = HC_NonmemberFunctionCall(fcn, args) ) or - exists(HashCons hc, HC_Args args - | mk_ExprCall(hc, args, e) and + exists(HashCons hc, HC_Args args | + mk_ExprCall(hc, args, e) and result = HC_ExprCall(hc, args) ) or - exists(Function fcn, HashCons qual, HC_Args args - | mk_MemberFunctionCall(fcn, qual, args, e) and + exists(Function fcn, HashCons qual, HC_Args args | + mk_MemberFunctionCall(fcn, qual, args, e) and result = HC_MemberFunctionCall(fcn, qual, args) ) or // works around an extractor issue - exists(Type t - | mk_AllocatorArgZero(t, e) and + exists(Type t | + mk_AllocatorArgZero(t, e) and result = HC_AllocatorArgZero(t) ) or - exists(Type t, HC_Alloc alloc, HC_Init init - | mk_NewExpr(t, alloc, init, e) and + exists(Type t, HC_Alloc alloc, HC_Init init | + mk_NewExpr(t, alloc, init, e) and result = HC_NewExpr(t, alloc, init) ) or - exists(Type t, HC_Alloc alloc, HC_Extent extent, HC_Init init - | mk_NewArrayExpr(t, alloc, extent, init, e) and + exists(Type t, HC_Alloc alloc, HC_Extent extent, HC_Init init | + mk_NewArrayExpr(t, alloc, extent, init, e) and result = HC_NewArrayExpr(t, alloc, extent, init) ) or - exists(Type t - | mk_SizeofType(t, e) and + exists(Type t | + mk_SizeofType(t, e) and result = HC_SizeofType(t) ) or - exists(HashCons child - | mk_SizeofExpr(child, e) and + exists(HashCons child | + mk_SizeofExpr(child, e) and result = HC_SizeofExpr(child) ) or - exists(Type t - | mk_TypeidType(t, e) and + exists(Type t | + mk_TypeidType(t, e) and result = HC_TypeidType(t) ) or - exists(HashCons child - | mk_TypeidExpr(child, e) and + exists(HashCons child | + mk_TypeidExpr(child, e) and result = HC_TypeidExpr(child) ) or - exists(Type t - | mk_UuidofOperator(t, e) and + exists(Type t | + mk_UuidofOperator(t, e) and result = HC_UuidofOperator(t) ) or - exists(Type t - | mk_AlignofType(t, e) and + exists(Type t | + mk_AlignofType(t, e) and result = HC_AlignofType(t) ) or - exists(HashCons child - | mk_AlignofExpr(child, e) and + exists(HashCons child | + mk_AlignofExpr(child, e) and result = HC_AlignofExpr(child) ) or - exists(Class c, HC_Fields hfc - | mk_ClassAggregateLiteral(c, hfc, e) and + exists(Class c, HC_Fields hfc | + mk_ClassAggregateLiteral(c, hfc, e) and result = HC_ClassAggregateLiteral(c, hfc) ) or - exists(Type t, HC_Array hca - | mk_ArrayAggregateLiteral(t, hca, e) and + exists(Type t, HC_Array hca | + mk_ArrayAggregateLiteral(t, hca, e) and result = HC_ArrayAggregateLiteral(t, hca) ) or - exists(HashCons child - | mk_DeleteExpr(child, e) and + exists(HashCons child | + mk_DeleteExpr(child, e) and result = HC_DeleteExpr(child) ) or - exists(HashCons child - | mk_DeleteArrayExpr(child, e) and + exists(HashCons child | + mk_DeleteArrayExpr(child, e) and result = HC_DeleteArrayExpr(child) ) or - exists(HashCons child - | mk_ThrowExpr(child, e) and + exists(HashCons child | + mk_ThrowExpr(child, e) and result = HC_ThrowExpr(child) ) or - ( - mk_ReThrowExpr(e) and - result = HC_ReThrowExpr() - ) + mk_ReThrowExpr(e) and + result = HC_ReThrowExpr() or - exists(HashCons cond, HashCons thenHC, HashCons elseHC - | mk_ConditionalExpr(cond, thenHC, elseHC, e) and + exists(HashCons cond, HashCons thenHC, HashCons elseHC | + mk_ConditionalExpr(cond, thenHC, elseHC, e) and result = HC_ConditionalExpr(cond, thenHC, elseHC) ) or - ( - mk_Nullptr(e) and - result = HC_Nullptr() - ) - + mk_Nullptr(e) and + result = HC_Nullptr() or - (not analyzableExpr(e,_) and result = HC_Unanalyzable(e)) + not analyzableExpr(e, _) and result = HC_Unanalyzable(e) } + /** * Holds if the expression is explicitly handled by `hashCons`. * Unanalyzable expressions still need to be given a hash-cons, @@ -1056,40 +1032,75 @@ cached HashCons hashCons(Expr e) { * expression. */ predicate analyzableExpr(Expr e, string kind) { - (analyzableIntLiteral(e) and kind = "IntLiteral") or - (analyzableEnumConstantAccess(e) and kind = "EnumConstantAccess") or - (analyzableFloatLiteral(e) and kind = "FloatLiteral") or - (analyzableStringLiteral(e) and kind = "StringLiteral") or - (analyzableNullptr(e) and kind = "Nullptr") or - (analyzableDotFieldAccess(e) and kind = "DotFieldAccess") or - (analyzablePointerFieldAccess(e) and kind = "PointerFieldAccess") or - (analyzableImplicitThisFieldAccess(e) and kind = "ImplicitThisFieldAccess") or - (analyzableVariable(e) and kind = "Variable") or - (analyzableConversion(e) and kind = "Conversion") or - (analyzableBinaryOp(e) and kind = "BinaryOp") or - (analyzableUnaryOp(e) and kind = "UnaryOp") or - (analyzableThisExpr(e) and kind = "ThisExpr") or - (analyzableArrayAccess(e) and kind = "ArrayAccess") or - (analyzablePointerDereferenceExpr(e) and kind = "PointerDereferenceExpr") or - (analyzableNonmemberFunctionCall(e) and kind = "NonmemberFunctionCall") or - (analyzableMemberFunctionCall(e) and kind = "MemberFunctionCall") or - (analyzableExprCall(e) and kind = "ExprCall") or - (analyzableNewExpr(e) and kind = "NewExpr") or - (analyzableNewArrayExpr(e) and kind = "NewArrayExpr") or - (analyzableSizeofType(e) and kind = "SizeofTypeOperator") or - (analyzableSizeofExpr(e) and kind = "SizeofExprOperator") or - (analyzableAlignofType(e) and kind = "AlignofTypeOperator") or - (analyzableAlignofExpr(e) and kind = "AlignofExprOperator") or - (analyzableUuidofOperator(e) and kind = "UuidofOperator") or - (analyzableTypeidType(e) and kind = "TypeidType") or - (analyzableTypeidExpr(e) and kind = "TypeidExpr") or - (analyzableClassAggregateLiteral(e) and kind = "ClassAggregateLiteral") or - (analyzableArrayAggregateLiteral(e) and kind = "ArrayAggregateLiteral") or - (analyzableDeleteExpr(e) and kind = "DeleteExpr") or - (analyzableDeleteArrayExpr(e) and kind = "DeleteArrayExpr") or - (analyzableThrowExpr(e) and kind = "ThrowExpr") or - (analyzableReThrowExpr(e) and kind = "ReThrowExpr") or - (analyzableConditionalExpr(e) and kind = "ConditionalExpr") or - (analyzableNoExceptExpr(e) and kind = "NoExceptExpr") or - (analyzableAllocatorArgZero(e) and kind = "AllocatorArgZero") + analyzableIntLiteral(e) and kind = "IntLiteral" + or + analyzableEnumConstantAccess(e) and kind = "EnumConstantAccess" + or + analyzableFloatLiteral(e) and kind = "FloatLiteral" + or + analyzableStringLiteral(e) and kind = "StringLiteral" + or + analyzableNullptr(e) and kind = "Nullptr" + or + analyzableDotFieldAccess(e) and kind = "DotFieldAccess" + or + analyzablePointerFieldAccess(e) and kind = "PointerFieldAccess" + or + analyzableImplicitThisFieldAccess(e) and kind = "ImplicitThisFieldAccess" + or + analyzableVariable(e) and kind = "Variable" + or + analyzableConversion(e) and kind = "Conversion" + or + analyzableBinaryOp(e) and kind = "BinaryOp" + or + analyzableUnaryOp(e) and kind = "UnaryOp" + or + analyzableThisExpr(e) and kind = "ThisExpr" + or + analyzableArrayAccess(e) and kind = "ArrayAccess" + or + analyzablePointerDereferenceExpr(e) and kind = "PointerDereferenceExpr" + or + analyzableNonmemberFunctionCall(e) and kind = "NonmemberFunctionCall" + or + analyzableMemberFunctionCall(e) and kind = "MemberFunctionCall" + or + analyzableExprCall(e) and kind = "ExprCall" + or + analyzableNewExpr(e) and kind = "NewExpr" + or + analyzableNewArrayExpr(e) and kind = "NewArrayExpr" + or + analyzableSizeofType(e) and kind = "SizeofTypeOperator" + or + analyzableSizeofExpr(e) and kind = "SizeofExprOperator" + or + analyzableAlignofType(e) and kind = "AlignofTypeOperator" + or + analyzableAlignofExpr(e) and kind = "AlignofExprOperator" + or + analyzableUuidofOperator(e) and kind = "UuidofOperator" + or + analyzableTypeidType(e) and kind = "TypeidType" + or + analyzableTypeidExpr(e) and kind = "TypeidExpr" + or + analyzableClassAggregateLiteral(e) and kind = "ClassAggregateLiteral" + or + analyzableArrayAggregateLiteral(e) and kind = "ArrayAggregateLiteral" + or + analyzableDeleteExpr(e) and kind = "DeleteExpr" + or + analyzableDeleteArrayExpr(e) and kind = "DeleteArrayExpr" + or + analyzableThrowExpr(e) and kind = "ThrowExpr" + or + analyzableReThrowExpr(e) and kind = "ReThrowExpr" + or + analyzableConditionalExpr(e) and kind = "ConditionalExpr" + or + analyzableNoExceptExpr(e) and kind = "NoExceptExpr" + or + analyzableAllocatorArgZero(e) and kind = "AllocatorArgZero" } diff --git a/cpp/ql/src/semmle/uml/MagicDraw.qll b/cpp/ql/src/semmle/uml/MagicDraw.qll index 9dcd497d9f3..6192af3e021 100644 --- a/cpp/ql/src/semmle/uml/MagicDraw.qll +++ b/cpp/ql/src/semmle/uml/MagicDraw.qll @@ -25,9 +25,7 @@ class UMLElement extends XMLElement { * `idref` attribute whose value is the same as the value of this * element's `id` attribute. */ - UMLElement getUMLReference() { - result.getAttributeValue("idref") = this.getAttributeValue("id") - } + UMLElement getUMLReference() { result.getAttributeValue("idref") = this.getAttributeValue("id") } /** * Gets the name of a stereotype that applies to this element. @@ -49,15 +47,14 @@ class UMLElement extends XMLElement { constrained.getName() = "Constraint.constrainedElement" and constraint.getAChild() = constrained and constrained.getAChild() = this.getUMLReference() and - constraint.getAttribute("name").getValue() = result) + constraint.getAttribute("name").getValue() = result + ) } /** * Gets the name of this element, that is, the value of its `name` attribute. */ - string getUMLName() { - result = this.getAttribute("name").getValue() - } + string getUMLName() { result = this.getAttribute("name").getValue() } } /** @@ -71,61 +68,51 @@ class UMLType extends UMLElement { exists(string type | this.getName() = "packagedElement" and this.getAttribute("type").getValue() = type and - (type = "uml:Class" or - type = "uml:Interface" or - type = "uml:PrimitiveType")) + ( + type = "uml:Class" or + type = "uml:Interface" or + type = "uml:PrimitiveType" + ) + ) } /** * Gets the package that contains this type. */ - UMLPackage getUMLPackage() { - result.getAClass() = this - } + UMLPackage getUMLPackage() { result.getAClass() = this } /** * Gets a property directly contained in this type. */ - UMLProperty getUMLProperty() { - this.getAChild() = result - } + UMLProperty getUMLProperty() { this.getAChild() = result } /** * Gets an operation directly contained in this type. */ - UMLOperation getUMLOperation() { - this.getAChild() = result - } + UMLOperation getUMLOperation() { this.getAChild() = result } /** * Holds if this is an enum type, that is, if `enum` is one of its * stereotypes. */ - predicate isEnum() { - this.getAStereotype() = "enum" - } + predicate isEnum() { this.getAStereotype() = "enum" } /** * Gets the C class, struct or union type corresponding to this UML type. */ - Class getCType() { - result.getQualifiedName() = this.getUMLQualifiedName() - } + Class getCType() { result.getQualifiedName() = this.getUMLQualifiedName() } /** * Gets the qualified name of this type. If this type is in a package * then this is `package.name`; otherwise it is just `name`. */ string getUMLQualifiedName() { - if exists(this.getUMLPackage()) then - result = this.getUMLPackage().getUMLQualifiedName() + "." + this.getUMLName() - else - result = this.getUMLName() + if exists(this.getUMLPackage()) + then result = this.getUMLPackage().getUMLQualifiedName() + "." + this.getUMLName() + else result = this.getUMLName() } - string toString() { - result = this.getUMLName() - } + string toString() { result = this.getUMLName() } } /** @@ -160,17 +147,13 @@ class UMLProperty extends UMLElement { /** * Gets the type that contains this property. */ - UMLType getUMLType() { - result.getUMLProperty() = this - } + UMLType getUMLType() { result.getUMLProperty() = this } /** * Holds if this property represents an enum constant, that is, if it * has a stereotype with name `enum+constant`. */ - predicate isEnumConstant() { - this.getAStereotype() = "enum+constant" - } + predicate isEnumConstant() { this.getAStereotype() = "enum+constant" } /** * Gets the C field corresponding to this property, if any. @@ -181,10 +164,9 @@ class UMLProperty extends UMLElement { } string toString() { - if this.isEnumConstant() then - result = "- <> " + this.getUMLName() - else - result = "- " + this.getUMLName() + if this.isEnumConstant() + then result = "- <> " + this.getUMLName() + else result = "- " + this.getUMLName() } } @@ -204,9 +186,7 @@ class UMLOperation extends UMLElement { /** * Gets the type that contains this operation. */ - UMLType getUMLType() { - result.getUMLOperation() = this - } + UMLType getUMLType() { result.getUMLOperation() = this } /** * Gets the C function corresponding to this operation, if any. @@ -216,33 +196,27 @@ class UMLOperation extends UMLElement { result.getDeclaringType() = this.getUMLType().getCType() } - string toString() { - result = "+ " + this.getUMLName() - } + string toString() { result = "+ " + this.getUMLName() } } /** * A UML property that has an association. */ class UMLAssociation extends UMLProperty { - UMLAssociation() { - this.hasAttribute("association") - } + UMLAssociation() { this.hasAttribute("association") } /** * Gets the property that this property is associated with. */ UMLAssociation getConverse() { - this.getAttribute("association").getValue() = result.getAttribute("association").getValue() and - this != result + this.getAttribute("association").getValue() = result.getAttribute("association").getValue() and + this != result } /** * Gets the name of this property. */ - string getLabel() { - result = this.getAttribute("name").getValue() - } + string getLabel() { result = this.getAttribute("name").getValue() } /** * Gets the C field corresponding to this property, if any. @@ -255,16 +229,12 @@ class UMLAssociation extends UMLProperty { /** * Gets the class that this association is contained in. */ - UMLClass getSource() { - result = this.getParent() - } + UMLClass getSource() { result = this.getParent() } /** * Gets the class that this association is associated with. */ - UMLClass getDest() { - result = this.getConverse().getParent() - } + UMLClass getDest() { result = this.getConverse().getParent() } } /** @@ -286,7 +256,8 @@ class UMLInheritance extends UMLElement { exists(UMLElement e | e.getName() = "supplier" and result.getUMLReference() = e and - e = this.getAChild()) + e = this.getAChild() + ) } /** @@ -296,7 +267,8 @@ class UMLInheritance extends UMLElement { exists(UMLElement e | e.getName() = "client" and result.getUMLReference() = e and - e = this.getAChild()) + e = this.getAChild() + ) } string toString() { @@ -308,23 +280,17 @@ class UMLInheritance extends UMLElement { * A UML element representing a package. */ class UMLPackage extends UMLElement { - UMLPackage() { - this.getName() = "Package" - } + UMLPackage() { this.getName() = "Package" } /** * Gets a class in this package. */ - UMLClass getAClass() { - result.getAChild().getAChild() = this.getUMLReference() - } + UMLClass getAClass() { result.getAChild().getAChild() = this.getUMLReference() } /** * Gets the parent package of this package, if any. */ - UMLPackage parentPackage() { - result.getAChild().getAChild() = this - } + UMLPackage parentPackage() { result.getAChild().getAChild() = this } /** * Gets the qualified name of this package. If this package is in a @@ -332,13 +298,10 @@ class UMLPackage extends UMLElement { * `package`. */ string getUMLQualifiedName() { - if exists(this.parentPackage()) then - result = this.parentPackage().getUMLQualifiedName() + "." + this.getUMLName() - else - result = this.getUMLName() + if exists(this.parentPackage()) + then result = this.parentPackage().getUMLQualifiedName() + "." + this.getUMLName() + else result = this.getUMLName() } - string toString() { - result = this.getUMLQualifiedName() - } + string toString() { result = this.getUMLQualifiedName() } } diff --git a/cpp/ql/test/duplication-tests/tokenising/duplications.ql b/cpp/ql/test/duplication-tests/tokenising/duplications.ql index fd142954d48..ea0b688a82c 100644 --- a/cpp/ql/test/duplication-tests/tokenising/duplications.ql +++ b/cpp/ql/test/duplication-tests/tokenising/duplications.ql @@ -3,4 +3,3 @@ import cpp // Provided tokenisation succeeded, we ought to have some // @duplication rows. select count(@duplication d) - diff --git a/cpp/ql/test/examples/BadLocking/DeclStmts.ql b/cpp/ql/test/examples/BadLocking/DeclStmts.ql index 772daa66f46..2a743f6904d 100644 --- a/cpp/ql/test/examples/BadLocking/DeclStmts.ql +++ b/cpp/ql/test/examples/BadLocking/DeclStmts.ql @@ -1,18 +1,13 @@ import cpp -string describe(Declaration d) -{ - ( - d instanceof Variable and - result = "Variable" - ) or ( - d instanceof Function and - result = "Function" - ) +string describe(Declaration d) { + d instanceof Variable and + result = "Variable" + or + d instanceof Function and + result = "Function" } from DeclStmt ds, Declaration d -where - ds.getADeclaration() = d -select - ds, concat(d.getName(), ", "), concat(describe(d), ", ") +where ds.getADeclaration() = d +select ds, concat(d.getName(), ", "), concat(describe(d), ", ") diff --git a/cpp/ql/test/examples/lgtm-query-examples/assignment_to_parameter.ql b/cpp/ql/test/examples/lgtm-query-examples/assignment_to_parameter.ql index 0fea6596948..a885a98c4ac 100644 --- a/cpp/ql/test/examples/lgtm-query-examples/assignment_to_parameter.ql +++ b/cpp/ql/test/examples/lgtm-query-examples/assignment_to_parameter.ql @@ -9,9 +9,9 @@ import cpp from Parameter p, Assignment assign -where assign = p.getAnAssignment() - and not assign.getASuccessor+() = p.getAnAccess() - and not p.getType() instanceof ReferenceType -select assign, "Assignment of '"+ assign.getRValue() + - "' to parameter '$@' has no effect.", - p, p.getName() +where + assign = p.getAnAssignment() and + not assign.getASuccessor+() = p.getAnAccess() and + not p.getType() instanceof ReferenceType +select assign, "Assignment of '" + assign.getRValue() + "' to parameter '$@' has no effect.", p, + p.getName() diff --git a/cpp/ql/test/examples/lgtm-query-examples/equality_test_on_boolean.ql b/cpp/ql/test/examples/lgtm-query-examples/equality_test_on_boolean.ql index 083c4bc1c68..9377bb46df8 100644 --- a/cpp/ql/test/examples/lgtm-query-examples/equality_test_on_boolean.ql +++ b/cpp/ql/test/examples/lgtm-query-examples/equality_test_on_boolean.ql @@ -5,6 +5,7 @@ * @kind problem * @problem.severity warning */ + import cpp from EqualityOperation eq, Expr trueExpr diff --git a/cpp/ql/test/examples/lgtm-query-examples/non_literal_format_string.ql b/cpp/ql/test/examples/lgtm-query-examples/non_literal_format_string.ql index 9c1eb974d68..fe1ddfffb93 100644 --- a/cpp/ql/test/examples/lgtm-query-examples/non_literal_format_string.ql +++ b/cpp/ql/test/examples/lgtm-query-examples/non_literal_format_string.ql @@ -8,9 +8,11 @@ * @kind problem * @problem.severity warning */ + import cpp from FunctionCall fc -where fc.getTarget().getQualifiedName() = "sprintf" -and not fc.getArgument(1) instanceof StringLiteral +where + fc.getTarget().getQualifiedName() = "sprintf" and + not fc.getArgument(1) instanceof StringLiteral select fc, "sprintf called with variable format string." diff --git a/cpp/ql/test/header-variant-tests/deduplication/functions.ql b/cpp/ql/test/header-variant-tests/deduplication/functions.ql index 8265e5dfab5..2671a26fb55 100644 --- a/cpp/ql/test/header-variant-tests/deduplication/functions.ql +++ b/cpp/ql/test/header-variant-tests/deduplication/functions.ql @@ -1,9 +1,11 @@ import cpp from Function f, string d, string c -where if f instanceof MemberFunction then ( - d = "MemberFunction" and c = ((MemberFunction)f).getDeclaringType().getName() -) else ( - d = "Function" and c = "" -) +where + if f instanceof MemberFunction + then ( + d = "MemberFunction" and c = f.(MemberFunction).getDeclaringType().getName() + ) else ( + d = "Function" and c = "" + ) select f, d, count(f.getBlock()), c diff --git a/cpp/ql/test/header-variant-tests/deduplication/variables.ql b/cpp/ql/test/header-variant-tests/deduplication/variables.ql index 1dc60d84615..a0525cd2b38 100644 --- a/cpp/ql/test/header-variant-tests/deduplication/variables.ql +++ b/cpp/ql/test/header-variant-tests/deduplication/variables.ql @@ -1,9 +1,11 @@ import cpp from Variable v, string d, string c -where if v instanceof MemberVariable then ( - d = "MemberVariable" and c = ((MemberVariable)v).getDeclaringType().getName() -) else ( - d = "Variable" and c = "" -) +where + if v instanceof MemberVariable + then ( + d = "MemberVariable" and c = v.(MemberVariable).getDeclaringType().getName() + ) else ( + d = "Variable" and c = "" + ) select v, v.getType(), d, c diff --git a/cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.ql b/cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.ql index d29ab57cf7b..d21d641a49d 100644 --- a/cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.ql +++ b/cpp/ql/test/header-variant-tests/microsoft-pch/microsoft-pch.ql @@ -1,4 +1,4 @@ import cpp from ReturnStmt rs -select rs.getEnclosingFunction().getName(), ((Literal)rs.getExpr()).getValue() +select rs.getEnclosingFunction().getName(), rs.getExpr().(Literal).getValue() diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/arrays.ql b/cpp/ql/test/header-variant-tests/multi-target-includes/arrays.ql index b70e83993ad..a191bc5c5bf 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/arrays.ql +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/arrays.ql @@ -2,4 +2,4 @@ import cpp from Variable v, ArrayType t where v.getType() = t -select v, t.toString() \ No newline at end of file +select v, t.toString() diff --git a/cpp/ql/test/library-tests/CPP-205/elements.ql b/cpp/ql/test/library-tests/CPP-205/elements.ql index eb21ae77793..4aaeafb30eb 100644 --- a/cpp/ql/test/library-tests/CPP-205/elements.ql +++ b/cpp/ql/test/library-tests/CPP-205/elements.ql @@ -3,14 +3,17 @@ import cpp string describe(Element e) { result = "function " + e.(Function).getFullSignature() or - result = "function declaration entry for " + e.(FunctionDeclarationEntry).getFunction().getFullSignature() + result = "function declaration entry for " + + e.(FunctionDeclarationEntry).getFunction().getFullSignature() or result = "parameter for " + e.(Parameter).getFunction().getFullSignature() or - result = "parameter declaration entry for " + e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction().getFullSignature() + result = "parameter declaration entry for " + + e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction().getFullSignature() } from Element e -where not e.getLocation() instanceof UnknownLocation - and not e instanceof Folder +where + not e.getLocation() instanceof UnknownLocation and + not e instanceof Folder select e, concat(describe(e), ", ") diff --git a/cpp/ql/test/library-tests/access/DerivationAccess/actual_member.ql b/cpp/ql/test/library-tests/access/DerivationAccess/actual_member.ql index ef4d021671f..eff7489a7bb 100644 --- a/cpp/ql/test/library-tests/access/DerivationAccess/actual_member.ql +++ b/cpp/ql/test/library-tests/access/DerivationAccess/actual_member.ql @@ -2,6 +2,4 @@ import cpp from Class c, Declaration member where not member.(Function).isCompilerGenerated() -select c.getQualifiedName(), - member.getQualifiedName(), - c.accessOfBaseMember(member).getName() +select c.getQualifiedName(), member.getQualifiedName(), c.accessOfBaseMember(member).getName() diff --git a/cpp/ql/test/library-tests/access/DerivationAccess/hypothetical_member.ql b/cpp/ql/test/library-tests/access/DerivationAccess/hypothetical_member.ql index 20bc19bd85a..d1bdd15a258 100644 --- a/cpp/ql/test/library-tests/access/DerivationAccess/hypothetical_member.ql +++ b/cpp/ql/test/library-tests/access/DerivationAccess/hypothetical_member.ql @@ -1,9 +1,9 @@ import cpp from Class base, Class derived, AccessSpecifier public -where public.hasName("public") - and // filter out compiler-generated junk - not derived.getNamespace() instanceof GlobalNamespace -select derived.getQualifiedName(), - base.getQualifiedName(), - derived.accessOfBaseMember(base, public).getName() +where + public.hasName("public") and + // filter out compiler-generated junk + not derived.getNamespace() instanceof GlobalNamespace +select derived.getQualifiedName(), base.getQualifiedName(), + derived.accessOfBaseMember(base, public).getName() diff --git a/cpp/ql/test/library-tests/access/FieldAccess/FieldAccess.ql b/cpp/ql/test/library-tests/access/FieldAccess/FieldAccess.ql index 32af8bd6bde..c39e510f146 100644 --- a/cpp/ql/test/library-tests/access/FieldAccess/FieldAccess.ql +++ b/cpp/ql/test/library-tests/access/FieldAccess/FieldAccess.ql @@ -1,13 +1,13 @@ import cpp string describeAccess(FieldAccess access) { - (access instanceof PointerFieldAccess and result = "ptr") + access instanceof PointerFieldAccess and result = "ptr" or - (access instanceof ReferenceFieldAccess and result = "ref") + access instanceof ReferenceFieldAccess and result = "ref" or - (access instanceof ValueFieldAccess and result = "val") + access instanceof ValueFieldAccess and result = "val" or - (access instanceof ImplicitThisFieldAccess and result = "this") + access instanceof ImplicitThisFieldAccess and result = "this" } from FieldAccess access diff --git a/cpp/ql/test/library-tests/access/MemberOrFriend/MemberOrFriend.ql b/cpp/ql/test/library-tests/access/MemberOrFriend/MemberOrFriend.ql index 670030e24c6..e41bb025f0d 100644 --- a/cpp/ql/test/library-tests/access/MemberOrFriend/MemberOrFriend.ql +++ b/cpp/ql/test/library-tests/access/MemberOrFriend/MemberOrFriend.ql @@ -1,12 +1,15 @@ import cpp string functionName(Function f) { - result = f.getQualifiedName() +"("+ f.getParameterString() +")" or + result = f.getQualifiedName() + "(" + f.getParameterString() + ")" + or not exists(f.getQualifiedName()) and - result = f.getName() +"("+ f.getParameterString() +")" + result = f.getName() + "(" + f.getParameterString() + ")" } from Class c, Function f -where c.getName() = "C" and f.inMemberOrFriendOf(c) - and not f.isCompilerGenerated() +where + c.getName() = "C" and + f.inMemberOrFriendOf(c) and + not f.isCompilerGenerated() select c, f, functionName(f) diff --git a/cpp/ql/test/library-tests/access/canAccessClass/canAccessClass.ql b/cpp/ql/test/library-tests/access/canAccessClass/canAccessClass.ql index 58a91c59751..899758537ef 100644 --- a/cpp/ql/test/library-tests/access/canAccessClass/canAccessClass.ql +++ b/cpp/ql/test/library-tests/access/canAccessClass/canAccessClass.ql @@ -1,11 +1,11 @@ import cpp from Function f, Class namingClass, Class base -where f.canAccessClass(base, namingClass) - and // filter out compiler-generated junk - not namingClass.getNamespace() instanceof GlobalNamespace - and // only in same namespace - f.getNamespace() = namingClass.getNamespace() - and not f.isCompilerGenerated() -select f.getQualifiedName(), - "Can convert "+ namingClass.getName() +" -> "+ base.getName() +where + f.canAccessClass(base, namingClass) and + // filter out compiler-generated junk + not namingClass.getNamespace() instanceof GlobalNamespace and + // only in same namespace + f.getNamespace() = namingClass.getNamespace() and + not f.isCompilerGenerated() +select f.getQualifiedName(), "Can convert " + namingClass.getName() + " -> " + base.getName() diff --git a/cpp/ql/test/library-tests/access/canAccessMember/canAccessMember.ql b/cpp/ql/test/library-tests/access/canAccessMember/canAccessMember.ql index ecd0f803158..5fd0a02fb90 100644 --- a/cpp/ql/test/library-tests/access/canAccessMember/canAccessMember.ql +++ b/cpp/ql/test/library-tests/access/canAccessMember/canAccessMember.ql @@ -1,9 +1,9 @@ import cpp from Function f, Class namingClass, Declaration member -where f.canAccessMember(member, namingClass) - and // only in same namespace - f.getNamespace() = namingClass.getNamespace() - and not f.isCompilerGenerated() -select f.getQualifiedName(), - "Can access "+ namingClass.getName() +"::"+ member.getName() +where + f.canAccessMember(member, namingClass) and + // only in same namespace + f.getNamespace() = namingClass.getNamespace() and + not f.isCompilerGenerated() +select f.getQualifiedName(), "Can access " + namingClass.getName() + "::" + member.getName() diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 4c0cceb23be..9cc7444739f 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -12,7 +12,9 @@ query predicate newExprs(NewExpr expr, string type, string sig, int size, int al ) } -query predicate newArrayExprs(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate newArrayExprs( + NewArrayExpr expr, string type, string sig, int size, int alignment, string form +) { exists(Function allocator, Type elementType | expr.getAllocator() = allocator and sig = allocator.getFullSignature() and @@ -24,7 +26,9 @@ query predicate newArrayExprs(NewArrayExpr expr, string type, string sig, int si ) } -query predicate newExprDeallocators(NewExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate newExprDeallocators( + NewExpr expr, string type, string sig, int size, int alignment, string form +) { exists(Function deallocator, Type allocatedType | expr.getDeallocator() = deallocator and sig = deallocator.getFullSignature() and @@ -40,7 +44,9 @@ query predicate newExprDeallocators(NewExpr expr, string type, string sig, int s ) } -query predicate newArrayExprDeallocators(NewArrayExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate newArrayExprDeallocators( + NewArrayExpr expr, string type, string sig, int size, int alignment, string form +) { exists(Function deallocator, Type elementType | expr.getDeallocator() = deallocator and sig = deallocator.getFullSignature() and @@ -56,7 +62,9 @@ query predicate newArrayExprDeallocators(NewArrayExpr expr, string type, string ) } -query predicate deleteExprs(DeleteExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate deleteExprs( + DeleteExpr expr, string type, string sig, int size, int alignment, string form +) { exists(Function deallocator, Type deletedType | expr.getDeallocator() = deallocator and sig = deallocator.getFullSignature() and @@ -72,7 +80,9 @@ query predicate deleteExprs(DeleteExpr expr, string type, string sig, int size, ) } -query predicate deleteArrayExprs(DeleteArrayExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate deleteArrayExprs( + DeleteArrayExpr expr, string type, string sig, int size, int alignment, string form +) { exists(Function deallocator, Type elementType | expr.getDeallocator() = deallocator and sig = deallocator.getFullSignature() and diff --git a/cpp/ql/test/library-tests/arguments/arguments.ql b/cpp/ql/test/library-tests/arguments/arguments.ql index 2680fd90d18..ad9e04c2668 100644 --- a/cpp/ql/test/library-tests/arguments/arguments.ql +++ b/cpp/ql/test/library-tests/arguments/arguments.ql @@ -2,9 +2,10 @@ import cpp from Compilation c, int i, string s // Skip the extractor name; it'll vary depending on platform -where i > 0 - and s = c.getArgument(i).replaceAll("\\", "/") - .regexpReplaceAll(".*(tools/qltest/predefined_macros)", "/$1") -select c.getAFileCompiled().toString(), - i, s - +where + i > 0 and + s = c + .getArgument(i) + .replaceAll("\\", "/") + .regexpReplaceAll(".*(tools/qltest/predefined_macros)", "/$1") +select c.getAFileCompiled().toString(), i, s diff --git a/cpp/ql/test/library-tests/array_expr/parts.ql b/cpp/ql/test/library-tests/array_expr/parts.ql index ed627e12210..f77104833bb 100644 --- a/cpp/ql/test/library-tests/array_expr/parts.ql +++ b/cpp/ql/test/library-tests/array_expr/parts.ql @@ -1,6 +1,8 @@ import cpp from ArrayExpr ae, string meth, Expr expr -where (meth = "getArrayBase" and expr = ae.getArrayBase()) - or (meth = "getArrayOffset" and expr = ae.getArrayOffset()) +where + meth = "getArrayBase" and expr = ae.getArrayBase() + or + meth = "getArrayOffset" and expr = ae.getArrayOffset() select meth, expr diff --git a/cpp/ql/test/library-tests/array_sizes/arr1.ql b/cpp/ql/test/library-tests/array_sizes/arr1.ql index 66bfbaeb949..618ab7d60a3 100644 --- a/cpp/ql/test/library-tests/array_sizes/arr1.ql +++ b/cpp/ql/test/library-tests/array_sizes/arr1.ql @@ -1,6 +1,7 @@ import cpp from EnumConstant ec, Access ac -where ec.getName().matches("sizeof\\_arr%") -and ac = ec.getAnAccess() +where + ec.getName().matches("sizeof\\_arr%") and + ac = ec.getAnAccess() select ac diff --git a/cpp/ql/test/library-tests/attributes/alignment/alignment.ql b/cpp/ql/test/library-tests/attributes/alignment/alignment.ql index 2f81e786b19..62ff499a24f 100644 --- a/cpp/ql/test/library-tests/attributes/alignment/alignment.ql +++ b/cpp/ql/test/library-tests/attributes/alignment/alignment.ql @@ -1,6 +1,10 @@ import cpp from Struct s, Attribute a, string alignment -where a = s.getAnAttribute() - and (alignment = a.getAnArgument().getValueInt().toString() or alignment = ((Struct)a.getAnArgument().getValueType()).getQualifiedName()) +where + a = s.getAnAttribute() and + ( + alignment = a.getAnArgument().getValueInt().toString() or + alignment = a.getAnArgument().getValueType().(Struct).getQualifiedName() + ) select a.getLocation().toString(), s.getQualifiedName(), alignment diff --git a/cpp/ql/test/library-tests/attributes/availability/availability.ql b/cpp/ql/test/library-tests/attributes/availability/availability.ql index 2894df522c7..26370e3c6c8 100644 --- a/cpp/ql/test/library-tests/attributes/availability/availability.ql +++ b/cpp/ql/test/library-tests/attributes/availability/availability.ql @@ -1,6 +1,7 @@ import cpp from Function f, Attribute a, int i -where a = f.getAnAttribute() - and a.hasName("availability") +where + a = f.getAnAttribute() and + a.hasName("availability") select f.getName(), i, a.getArgument(i) diff --git a/cpp/ql/test/library-tests/attributes/exclusive_locks_required/attributes.ql b/cpp/ql/test/library-tests/attributes/exclusive_locks_required/attributes.ql index 628006311be..c1dfd33d75e 100644 --- a/cpp/ql/test/library-tests/attributes/exclusive_locks_required/attributes.ql +++ b/cpp/ql/test/library-tests/attributes/exclusive_locks_required/attributes.ql @@ -1,11 +1,8 @@ import cpp string attribute(Function f) { - if exists(f.getAnAttribute()) - then result = f.getAnAttribute().toString() - else result = "" + if exists(f.getAnAttribute()) then result = f.getAnAttribute().toString() else result = "" } from Function f select f, attribute(f) - diff --git a/cpp/ql/test/library-tests/attributes/gnu_visibility/visibility.ql b/cpp/ql/test/library-tests/attributes/gnu_visibility/visibility.ql index 566d9992726..1c902406cd7 100644 --- a/cpp/ql/test/library-tests/attributes/gnu_visibility/visibility.ql +++ b/cpp/ql/test/library-tests/attributes/gnu_visibility/visibility.ql @@ -1,7 +1,8 @@ import cpp from Element e, Attribute a -where a = ((Variable)e).getAnAttribute() - or a = ((Function)e).getAnAttribute() - or a = ((Struct )e).getAnAttribute() +where + a = e.(Variable).getAnAttribute() or + a = e.(Function).getAnAttribute() or + a = e.(Struct).getAnAttribute() select e, a, a.getAnArgument() diff --git a/cpp/ql/test/library-tests/attributes/nonnull/attrs.ql b/cpp/ql/test/library-tests/attributes/nonnull/attrs.ql index 847264af9e9..f7d3c85a42e 100644 --- a/cpp/ql/test/library-tests/attributes/nonnull/attrs.ql +++ b/cpp/ql/test/library-tests/attributes/nonnull/attrs.ql @@ -1,9 +1,7 @@ import cpp string attributeArg(Attribute a) { - if exists(a.getAnArgument()) - then result = a.getAnArgument().toString() - else result = "" + if exists(a.getAnArgument()) then result = a.getAnArgument().toString() else result = "" } from Attribute a diff --git a/cpp/ql/test/library-tests/attributes/routine_attributes/arguments.ql b/cpp/ql/test/library-tests/attributes/routine_attributes/arguments.ql index f9bac5b82be..400133d861e 100644 --- a/cpp/ql/test/library-tests/attributes/routine_attributes/arguments.ql +++ b/cpp/ql/test/library-tests/attributes/routine_attributes/arguments.ql @@ -1,6 +1,7 @@ import cpp from Function f, Attribute a, AttributeArgument arg -where a = f.getAnAttribute() - and arg = a.getAnArgument() +where + a = f.getAnAttribute() and + arg = a.getAnArgument() select arg, f, a, arg.getValueText() diff --git a/cpp/ql/test/library-tests/attributes/sal/sal.ql b/cpp/ql/test/library-tests/attributes/sal/sal.ql index e4e41a796dc..c1dc9a6bffc 100644 --- a/cpp/ql/test/library-tests/attributes/sal/sal.ql +++ b/cpp/ql/test/library-tests/attributes/sal/sal.ql @@ -1,23 +1,24 @@ import cpp predicate argsOrPlaceholder(Attribute a, int index, int start_line, string name, string value) { - if exists(a.getAnArgument()) then + if exists(a.getAnArgument()) + then exists(AttributeArgument arg | arg = a.getAnArgument() | index = arg.getIndex() and start_line = arg.getLocation().getStartLine() and name = arg.getName() and value = arg.getValueText() ) - else - ( - index = -1 and - start_line = a.getLocation().getStartLine() and - name = "" and - value = "" - ) + else ( + index = -1 and + start_line = a.getLocation().getStartLine() and + name = "" and + value = "" + ) } from Parameter p, Attribute a, int arg_index, int arg_line, string arg_name, string arg_value -where a = p.getAnAttribute() - and argsOrPlaceholder(a, arg_index, arg_line, arg_name, arg_value) +where + a = p.getAnAttribute() and + argsOrPlaceholder(a, arg_index, arg_line, arg_name, arg_value) select arg_line, p, a, arg_index, arg_name, arg_value diff --git a/cpp/ql/test/library-tests/attributes/stmt_attributes/clang_fallthrough.ql b/cpp/ql/test/library-tests/attributes/stmt_attributes/clang_fallthrough.ql index cb4dbdb7bf7..6036d118e39 100644 --- a/cpp/ql/test/library-tests/attributes/stmt_attributes/clang_fallthrough.ql +++ b/cpp/ql/test/library-tests/attributes/stmt_attributes/clang_fallthrough.ql @@ -1,7 +1,8 @@ import cpp from Stmt s, StdAttribute a -where s.getASuccessor() instanceof SwitchCase - and a = s.getAnAttribute() - and a.hasQualifiedName("clang", "fallthrough") +where + s.getASuccessor() instanceof SwitchCase and + a = s.getAnAttribute() and + a.hasQualifiedName("clang", "fallthrough") select s, a.getLocation().toString() diff --git a/cpp/ql/test/library-tests/attributes/type_attributes/arguments.ql b/cpp/ql/test/library-tests/attributes/type_attributes/arguments.ql index c17576c9747..07ac0928655 100644 --- a/cpp/ql/test/library-tests/attributes/type_attributes/arguments.ql +++ b/cpp/ql/test/library-tests/attributes/type_attributes/arguments.ql @@ -1,6 +1,7 @@ import cpp from Type t, Attribute a, AttributeArgument arg -where a = t.getAnAttribute() - and arg = a.getAnArgument() +where + a = t.getAnAttribute() and + arg = a.getAnArgument() select t, a, arg diff --git a/cpp/ql/test/library-tests/basic_blocks/bb_cfg.ql b/cpp/ql/test/library-tests/basic_blocks/bb_cfg.ql index a80c1d3d3ae..79d62603164 100644 --- a/cpp/ql/test/library-tests/basic_blocks/bb_cfg.ql +++ b/cpp/ql/test/library-tests/basic_blocks/bb_cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,21 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, BasicBlock x, BasicBlock y, string label) { - isEdge = false and x = y and label = x.getStart().toString() + " [" + x.getStart().getLocation().toString() + "]" + isEdge = false and + x = y and + label = x.getStart().toString() + " [" + x.getStart().getLocation().toString() + "]" } predicate isSuccessor(boolean isEdge, BasicBlock x, BasicBlock y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, BasicBlock x, BasicBlock y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(mkElement(x)), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/basic_blocks/cfg.ql b/cpp/ql/test/library-tests/basic_blocks/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/basic_blocks/cfg.ql +++ b/cpp/ql/test/library-tests/basic_blocks/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/blocks/c/blocks.ql b/cpp/ql/test/library-tests/blocks/c/blocks.ql index 68320137506..fe2afd844db 100644 --- a/cpp/ql/test/library-tests/blocks/c/blocks.ql +++ b/cpp/ql/test/library-tests/blocks/c/blocks.ql @@ -1,7 +1,4 @@ import cpp from Variable v -select v, - v.getType().toString(), - v.getType().explain() - +select v, v.getType().toString(), v.getType().explain() diff --git a/cpp/ql/test/library-tests/blocks/c/code_blocks.ql b/cpp/ql/test/library-tests/blocks/c/code_blocks.ql index 842832fadb6..1662525cae6 100644 --- a/cpp/ql/test/library-tests/blocks/c/code_blocks.ql +++ b/cpp/ql/test/library-tests/blocks/c/code_blocks.ql @@ -1,25 +1,20 @@ import cpp predicate paramsString(Function f, int n, string res) { - if n = -1 then res = "" - else exists(string sep | - if n = 0 then sep = "" else sep = ", " - and - exists(string prefixRes | - paramsString(f, n - 1, prefixRes) - and - res = prefixRes + sep + f.getParameter(n) - + "(" + f.getParameter(n).getType() + ")")) + if n = -1 + then res = "" + else + exists(string sep | + (if n = 0 then sep = "" else sep = ", ") and + exists(string prefixRes | + paramsString(f, n - 1, prefixRes) and + res = prefixRes + sep + f.getParameter(n) + "(" + f.getParameter(n).getType() + ")" + ) + ) } from BlockExpr e, Function f, string params -where f = e.getFunction() - and paramsString(f, f.getNumberOfParameters() - 1, params) -select e, - e.getType() as te, - te.explain(), - e.getFunction(), - f.getType() as tf, - tf.explain(), - params - +where + f = e.getFunction() and + paramsString(f, f.getNumberOfParameters() - 1, params) +select e, e.getType() as te, te.explain(), e.getFunction(), f.getType() as tf, tf.explain(), params diff --git a/cpp/ql/test/library-tests/blocks/c/exprs.ql b/cpp/ql/test/library-tests/blocks/c/exprs.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/blocks/c/exprs.ql +++ b/cpp/ql/test/library-tests/blocks/c/exprs.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/blocks/capture/capture.ql b/cpp/ql/test/library-tests/blocks/capture/capture.ql index 7b40e737757..8cf764547e9 100644 --- a/cpp/ql/test/library-tests/blocks/capture/capture.ql +++ b/cpp/ql/test/library-tests/blocks/capture/capture.ql @@ -2,8 +2,4 @@ import cpp from VariableAccess a, BlockExpr b where a.getEnclosingFunction() = b.getFunction() -select b, - a, - a.getTarget(), - a.getEnclosingFunction() - +select b, a, a.getTarget(), a.getEnclosingFunction() diff --git a/cpp/ql/test/library-tests/blocks/capture/quals.ql b/cpp/ql/test/library-tests/blocks/capture/quals.ql index 61004e4d61d..77431c278e7 100644 --- a/cpp/ql/test/library-tests/blocks/capture/quals.ql +++ b/cpp/ql/test/library-tests/blocks/capture/quals.ql @@ -1,6 +1,4 @@ import cpp from Variable v -select v, - v.getASpecifier() - +select v, v.getASpecifier() diff --git a/cpp/ql/test/library-tests/blocks/cpp/blocks.ql b/cpp/ql/test/library-tests/blocks/cpp/blocks.ql index d437dd74f97..5847854f24d 100644 --- a/cpp/ql/test/library-tests/blocks/cpp/blocks.ql +++ b/cpp/ql/test/library-tests/blocks/cpp/blocks.ql @@ -1,7 +1,4 @@ import cpp from Variable v -select v, - v.getType(), - v.getType().explain() - +select v, v.getType(), v.getType().explain() diff --git a/cpp/ql/test/library-tests/blocks/cpp/code_blocks.ql b/cpp/ql/test/library-tests/blocks/cpp/code_blocks.ql index 842832fadb6..1662525cae6 100644 --- a/cpp/ql/test/library-tests/blocks/cpp/code_blocks.ql +++ b/cpp/ql/test/library-tests/blocks/cpp/code_blocks.ql @@ -1,25 +1,20 @@ import cpp predicate paramsString(Function f, int n, string res) { - if n = -1 then res = "" - else exists(string sep | - if n = 0 then sep = "" else sep = ", " - and - exists(string prefixRes | - paramsString(f, n - 1, prefixRes) - and - res = prefixRes + sep + f.getParameter(n) - + "(" + f.getParameter(n).getType() + ")")) + if n = -1 + then res = "" + else + exists(string sep | + (if n = 0 then sep = "" else sep = ", ") and + exists(string prefixRes | + paramsString(f, n - 1, prefixRes) and + res = prefixRes + sep + f.getParameter(n) + "(" + f.getParameter(n).getType() + ")" + ) + ) } from BlockExpr e, Function f, string params -where f = e.getFunction() - and paramsString(f, f.getNumberOfParameters() - 1, params) -select e, - e.getType() as te, - te.explain(), - e.getFunction(), - f.getType() as tf, - tf.explain(), - params - +where + f = e.getFunction() and + paramsString(f, f.getNumberOfParameters() - 1, params) +select e, e.getType() as te, te.explain(), e.getFunction(), f.getType() as tf, tf.explain(), params diff --git a/cpp/ql/test/library-tests/blocks/cpp/exprs.ql b/cpp/ql/test/library-tests/blocks/cpp/exprs.ql index 1403942f5a1..bfc312e00ea 100644 --- a/cpp/ql/test/library-tests/blocks/cpp/exprs.ql +++ b/cpp/ql/test/library-tests/blocks/cpp/exprs.ql @@ -4,10 +4,10 @@ import cpp * Plainer output for CStyleCast, that does not reference the (potentially platform * dependent) type of the cast. */ + class CStyleCastPlain extends CStyleCast { override string toString() { result = "Conversion of " + getExpr().toString() } } from Expr e select e - diff --git a/cpp/ql/test/library-tests/blocks/deduplication/deduplication.ql b/cpp/ql/test/library-tests/blocks/deduplication/deduplication.ql index 4bf5f2d5ce1..8dc3d0660a4 100644 --- a/cpp/ql/test/library-tests/blocks/deduplication/deduplication.ql +++ b/cpp/ql/test/library-tests/blocks/deduplication/deduplication.ql @@ -1,5 +1,3 @@ import cpp -select count(BlockExpr be), - count(ReturnStmt rs | rs.getExpr().getValue() = "0") - +select count(BlockExpr be), count(ReturnStmt rs | rs.getExpr().getValue() = "0") diff --git a/cpp/ql/test/library-tests/builtins/builtins/builtins.ql b/cpp/ql/test/library-tests/builtins/builtins/builtins.ql index 6406da42c24..eb225fef989 100644 --- a/cpp/ql/test/library-tests/builtins/builtins/builtins.ql +++ b/cpp/ql/test/library-tests/builtins/builtins/builtins.ql @@ -2,4 +2,3 @@ import cpp from BuiltInOperation op select op - diff --git a/cpp/ql/test/library-tests/builtins/edg/expr.ql b/cpp/ql/test/library-tests/builtins/edg/expr.ql index e11a9b9f39a..4a5a2ee0bb0 100644 --- a/cpp/ql/test/library-tests/builtins/edg/expr.ql +++ b/cpp/ql/test/library-tests/builtins/edg/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e, count(e.getAPredecessor()), count(e.getASuccessor()) - diff --git a/cpp/ql/test/library-tests/builtins/edg/intaddr.ql b/cpp/ql/test/library-tests/builtins/edg/intaddr.ql index 64effcd1ba6..c17c7249793 100644 --- a/cpp/ql/test/library-tests/builtins/edg/intaddr.ql +++ b/cpp/ql/test/library-tests/builtins/edg/intaddr.ql @@ -1,4 +1,3 @@ import cpp select count(@intaddrexpr e) - diff --git a/cpp/ql/test/library-tests/builtins/type_traits/expr.ql b/cpp/ql/test/library-tests/builtins/type_traits/expr.ql index 6a84fd6b619..a7d2b436ebd 100644 --- a/cpp/ql/test/library-tests/builtins/type_traits/expr.ql +++ b/cpp/ql/test/library-tests/builtins/type_traits/expr.ql @@ -1,15 +1,15 @@ import cpp string childrenFrom(Expr e, int i) { - (if i = 0 - then result = e.getChild(i).toString() + childrenFrom(e, i + 1) - else result = "," + e.getChild(i).toString() + childrenFrom(e, i + 1)) - or - (i = e.getNumChild() and result = "") + ( + if i = 0 + then result = e.getChild(i).toString() + childrenFrom(e, i + 1) + else result = "," + e.getChild(i).toString() + childrenFrom(e, i + 1) + ) + or + i = e.getNumChild() and result = "" } from Expr e, string value -where if exists(e.getValue()) then value = e.getValue().toString() - else value = "" +where if exists(e.getValue()) then value = e.getValue().toString() else value = "" select e, childrenFrom(e, 0), value - diff --git a/cpp/ql/test/library-tests/builtins/types/types.ql b/cpp/ql/test/library-tests/builtins/types/types.ql index ff3df9a5653..560d1a66fb1 100644 --- a/cpp/ql/test/library-tests/builtins/types/types.ql +++ b/cpp/ql/test/library-tests/builtins/types/types.ql @@ -3,4 +3,3 @@ import cpp from Variable v, Type t where t = v.getType() select v, t - diff --git a/cpp/ql/test/library-tests/c++_exceptions/graphable.ql b/cpp/ql/test/library-tests/c++_exceptions/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/c++_exceptions/graphable.ql +++ b/cpp/ql/test/library-tests/c++_exceptions/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/c++_exceptions/handler.ql b/cpp/ql/test/library-tests/c++_exceptions/handler.ql index e7a534da2a9..82be3d62431 100644 --- a/cpp/ql/test/library-tests/c++_exceptions/handler.ql +++ b/cpp/ql/test/library-tests/c++_exceptions/handler.ql @@ -2,8 +2,11 @@ import cpp from Handler h, string property, Element value where - (property = "getParameter" and value = h.getParameter()) or - (property = "getBlock" and value = h.getBlock()) or - (property = "getTryStmt" and value = h.getTryStmt()) or - (property = "getTryStmt.getACatchClause()" and value = h.getTryStmt().getACatchClause()) + property = "getParameter" and value = h.getParameter() + or + property = "getBlock" and value = h.getBlock() + or + property = "getTryStmt" and value = h.getTryStmt() + or + property = "getTryStmt.getACatchClause()" and value = h.getTryStmt().getACatchClause() select h, property, value diff --git a/cpp/ql/test/library-tests/c++_exceptions/unreachable.ql b/cpp/ql/test/library-tests/c++_exceptions/unreachable.ql index 891b4d062ec..32c7f9c95f2 100644 --- a/cpp/ql/test/library-tests/c++_exceptions/unreachable.ql +++ b/cpp/ql/test/library-tests/c++_exceptions/unreachable.ql @@ -3,4 +3,3 @@ import cpp from BasicBlock b where not b.isReachable() select b - diff --git a/cpp/ql/test/library-tests/c11_generic/test.ql b/cpp/ql/test/library-tests/c11_generic/test.ql index 65fc28181dc..314377d4095 100644 --- a/cpp/ql/test/library-tests/c11_generic/test.ql +++ b/cpp/ql/test/library-tests/c11_generic/test.ql @@ -1,6 +1,5 @@ import cpp from FunctionCall fc -where - fc.getTarget().getName() = "printf" +where fc.getTarget().getName() = "printf" select fc.getArgument(1) diff --git a/cpp/ql/test/library-tests/calls/Calls1.ql b/cpp/ql/test/library-tests/calls/Calls1.ql index 145022dd940..533422826f9 100644 --- a/cpp/ql/test/library-tests/calls/Calls1.ql +++ b/cpp/ql/test/library-tests/calls/Calls1.ql @@ -2,9 +2,12 @@ * @name Calls1 * @kind table */ + import cpp from Function a, string rel, Function b -where (a.accesses(b) and rel = "accesses") or - (a.calls(b) and rel = "calls") +where + a.accesses(b) and rel = "accesses" + or + a.calls(b) and rel = "calls" select a.getName(), rel, b.getName() diff --git a/cpp/ql/test/library-tests/calls/Calls3.ql b/cpp/ql/test/library-tests/calls/Calls3.ql index 6204ac03a89..c046461a5c0 100644 --- a/cpp/ql/test/library-tests/calls/Calls3.ql +++ b/cpp/ql/test/library-tests/calls/Calls3.ql @@ -2,6 +2,7 @@ * @name Calls3 * @kind table */ + import cpp from FunctionCall c, CppFile f diff --git a/cpp/ql/test/library-tests/calls/args.ql b/cpp/ql/test/library-tests/calls/args.ql index 1112dc5a7e3..83ea622b20b 100644 --- a/cpp/ql/test/library-tests/calls/args.ql +++ b/cpp/ql/test/library-tests/calls/args.ql @@ -2,4 +2,3 @@ import cpp from Call c, int i select c, i, c.getArgument(i) - diff --git a/cpp/ql/test/library-tests/cast_specifiers/cast_specifiers.ql b/cpp/ql/test/library-tests/cast_specifiers/cast_specifiers.ql index af588809d4e..0133d662f2e 100644 --- a/cpp/ql/test/library-tests/cast_specifiers/cast_specifiers.ql +++ b/cpp/ql/test/library-tests/cast_specifiers/cast_specifiers.ql @@ -1,23 +1,12 @@ import cpp -from Cast c, string cs, string ts, - string volatile, string const, string explicit, string padding -where if c.getType().isVolatile() - then volatile = "Volatile" - else volatile = "--------" - and if c.getType().isConst() - then const = "Const" - else const = "-----" - and if c.isImplicit() - then explicit = "implicit" - else explicit = "explicit" - and padding = " " - and cs = c.toString() - and ts = c.getType().toString() -select c.getLocation().getStartLine(), - (cs + padding).prefix(cs.length().maximum(23)), - (ts + padding).prefix(ts.length().maximum(18)), - explicit, - volatile, - const - +from Cast c, string cs, string ts, string volatile, string const, string explicit, string padding +where + (if c.getType().isVolatile() then volatile = "Volatile" else volatile = "--------") and + (if c.getType().isConst() then const = "Const" else const = "-----") and + (if c.isImplicit() then explicit = "implicit" else explicit = "explicit") and + padding = " " and + cs = c.toString() and + ts = c.getType().toString() +select c.getLocation().getStartLine(), (cs + padding).prefix(cs.length().maximum(23)), + (ts + padding).prefix(ts.length().maximum(18)), explicit, volatile, const diff --git a/cpp/ql/test/library-tests/clang_builtin_macros/values.ql b/cpp/ql/test/library-tests/clang_builtin_macros/values.ql index 70fba76eb39..80cfa4d450c 100644 --- a/cpp/ql/test/library-tests/clang_builtin_macros/values.ql +++ b/cpp/ql/test/library-tests/clang_builtin_macros/values.ql @@ -1,9 +1,9 @@ import cpp string varInit(Variable v) { - if exists(v.getInitializer().getExpr()) - then result = v.getInitializer().getExpr().toString() - else result = "" + if exists(v.getInitializer().getExpr()) + then result = v.getInitializer().getExpr().toString() + else result = "" } from Variable v diff --git a/cpp/ql/test/library-tests/clang_c99_default/clang_c99_default.ql b/cpp/ql/test/library-tests/clang_c99_default/clang_c99_default.ql index c7be0c02925..52a67ac4b91 100644 --- a/cpp/ql/test/library-tests/clang_c99_default/clang_c99_default.ql +++ b/cpp/ql/test/library-tests/clang_c99_default/clang_c99_default.ql @@ -1,3 +1,4 @@ import cpp -from Variable v select v, v.getName() +from Variable v +select v, v.getName() diff --git a/cpp/ql/test/library-tests/clang_ms/declspec.ql b/cpp/ql/test/library-tests/clang_ms/declspec.ql index 06576211d94..5beb98a2184 100644 --- a/cpp/ql/test/library-tests/clang_ms/declspec.ql +++ b/cpp/ql/test/library-tests/clang_ms/declspec.ql @@ -2,4 +2,3 @@ import cpp from Declspec ds select ds - diff --git a/cpp/ql/test/library-tests/classes/base_classes/base_classes.ql b/cpp/ql/test/library-tests/classes/base_classes/base_classes.ql index d9c228e768c..f75aece14b2 100644 --- a/cpp/ql/test/library-tests/classes/base_classes/base_classes.ql +++ b/cpp/ql/test/library-tests/classes/base_classes/base_classes.ql @@ -1,7 +1,5 @@ import cpp from Class c, string s -where if exists(c.getABaseClass()) - then s = c.getABaseClass().toString() - else s = "" +where if exists(c.getABaseClass()) then s = c.getABaseClass().toString() else s = "" select c, s diff --git a/cpp/ql/test/library-tests/classes/classes/Classes1.ql b/cpp/ql/test/library-tests/classes/classes/Classes1.ql index 7ca760f9dcc..0641cf21722 100644 --- a/cpp/ql/test/library-tests/classes/classes/Classes1.ql +++ b/cpp/ql/test/library-tests/classes/classes/Classes1.ql @@ -1,7 +1,7 @@ import cpp from Class c, string isFinal -where c.getName() != "__va_list_tag" - and if c.isFinal() then isFinal = "final" else isFinal = "-----" +where + c.getName() != "__va_list_tag" and + if c.isFinal() then isFinal = "final" else isFinal = "-----" select c, isFinal - diff --git a/cpp/ql/test/library-tests/classes/classes/Classes2.ql b/cpp/ql/test/library-tests/classes/classes/Classes2.ql index f11a7b3375f..24387c5bd3c 100644 --- a/cpp/ql/test/library-tests/classes/classes/Classes2.ql +++ b/cpp/ql/test/library-tests/classes/classes/Classes2.ql @@ -2,4 +2,3 @@ import cpp from NestedClass c select c - diff --git a/cpp/ql/test/library-tests/classes/classes/Classes3.ql b/cpp/ql/test/library-tests/classes/classes/Classes3.ql index 10e6f109d4f..ce1dd9aaa93 100644 --- a/cpp/ql/test/library-tests/classes/classes/Classes3.ql +++ b/cpp/ql/test/library-tests/classes/classes/Classes3.ql @@ -1,9 +1,10 @@ import cpp from Class d, NestedClass e, NestedClass f -where not d instanceof NestedClass and d.isTopLevel() - and e.getDeclaringType() = d - and f.getDeclaringType() = e - and f.hasName("F") +where + not d instanceof NestedClass and + d.isTopLevel() and + e.getDeclaringType() = d and + f.getDeclaringType() = e and + f.hasName("F") select d, e, f - diff --git a/cpp/ql/test/library-tests/classes/classes/Classes4.ql b/cpp/ql/test/library-tests/classes/classes/Classes4.ql index 896ed1f15cf..920d59c11e0 100644 --- a/cpp/ql/test/library-tests/classes/classes/Classes4.ql +++ b/cpp/ql/test/library-tests/classes/classes/Classes4.ql @@ -1,7 +1,8 @@ import cpp from NestedClass f, NestedClass g -where f.hasName("F") - and g.hasName("G") - and f.getABaseClass() = g +where + f.hasName("F") and + g.hasName("G") and + f.getABaseClass() = g select f, g diff --git a/cpp/ql/test/library-tests/classes/classes/Classes6.ql b/cpp/ql/test/library-tests/classes/classes/Classes6.ql index 2c016fa5955..8d87845a272 100644 --- a/cpp/ql/test/library-tests/classes/classes/Classes6.ql +++ b/cpp/ql/test/library-tests/classes/classes/Classes6.ql @@ -1,6 +1,7 @@ import cpp from NestedClass f, NestedClass g -where g.getADerivedClass() = f - and g.getDeclaringType().getAMember() = f +where + g.getADerivedClass() = f and + g.getDeclaringType().getAMember() = f select f, g diff --git a/cpp/ql/test/library-tests/classes/classes/MetricClasses1.ql b/cpp/ql/test/library-tests/classes/classes/MetricClasses1.ql index 70f8a5dfdd4..1e76f512bc3 100644 --- a/cpp/ql/test/library-tests/classes/classes/MetricClasses1.ql +++ b/cpp/ql/test/library-tests/classes/classes/MetricClasses1.ql @@ -3,4 +3,3 @@ import cpp from Class c where c.getName() != "__va_list_tag" select c, c.getMetrics().getNestingLevel() - diff --git a/cpp/ql/test/library-tests/classes/classes/MetricClasses2.ql b/cpp/ql/test/library-tests/classes/classes/MetricClasses2.ql index 0753bab39b6..f400119988d 100644 --- a/cpp/ql/test/library-tests/classes/classes/MetricClasses2.ql +++ b/cpp/ql/test/library-tests/classes/classes/MetricClasses2.ql @@ -3,4 +3,3 @@ import cpp from Class c where c.getName() != "__va_list_tag" select c, c.getMetrics().getInheritanceDepth() - diff --git a/cpp/ql/test/library-tests/classes/derivations/derivations/derivations.ql b/cpp/ql/test/library-tests/classes/derivations/derivations/derivations.ql index 1ae00d09f8c..6ef14d4dffc 100644 --- a/cpp/ql/test/library-tests/classes/derivations/derivations/derivations.ql +++ b/cpp/ql/test/library-tests/classes/derivations/derivations/derivations.ql @@ -1,4 +1,5 @@ import cpp from ClassDerivation cd -select cd, cd.getLocation().getStartLine(), cd.getDerivedClass(), cd.getASpecifier(), cd.getBaseClass() +select cd, cd.getLocation().getStartLine(), cd.getDerivedClass(), cd.getASpecifier(), + cd.getBaseClass() diff --git a/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.ql b/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.ql index ba15b608e72..23224e35a5e 100644 --- a/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.ql +++ b/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.ql @@ -1,4 +1,5 @@ import cpp from ClassDerivation cd -select cd.getLocation().getStartLine(), cd.getDerivedClass().toString(), cd.getBaseClass().toString(), cd.getByteOffset() +select cd.getLocation().getStartLine(), cd.getDerivedClass().toString(), + cd.getBaseClass().toString(), cd.getByteOffset() diff --git a/cpp/ql/test/library-tests/classes/structlikeclass/StructLikeClass.ql b/cpp/ql/test/library-tests/classes/structlikeclass/StructLikeClass.ql index 27b04c5d04d..bb723136d53 100644 --- a/cpp/ql/test/library-tests/classes/structlikeclass/StructLikeClass.ql +++ b/cpp/ql/test/library-tests/classes/structlikeclass/StructLikeClass.ql @@ -2,11 +2,9 @@ import cpp from StructLikeClass slc, string relation, Function f, Variable v where - ( - slc.getASetter(v) = f and - relation = "getASetter" - ) or ( - slc.getAGetter(v) = f and - relation = "getAGetter" - ) + slc.getASetter(v) = f and + relation = "getASetter" + or + slc.getAGetter(v) = f and + relation = "getAGetter" select slc, relation, f, v diff --git a/cpp/ql/test/library-tests/classes/variadic/expr.ql b/cpp/ql/test/library-tests/classes/variadic/expr.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/classes/variadic/expr.ql +++ b/cpp/ql/test/library-tests/classes/variadic/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/comments/binding/commentBinding.ql b/cpp/ql/test/library-tests/comments/binding/commentBinding.ql index 79ec5435735..4cf54c01ed0 100644 --- a/cpp/ql/test/library-tests/comments/binding/commentBinding.ql +++ b/cpp/ql/test/library-tests/comments/binding/commentBinding.ql @@ -1,8 +1,6 @@ import cpp from Comment c, string s -where if exists(c.getCommentedElement()) - then s = c.getCommentedElement().toString() - else s = "" +where + if exists(c.getCommentedElement()) then s = c.getCommentedElement().toString() else s = "" select c, s - diff --git a/cpp/ql/test/library-tests/compiler_generated/compilerGenerated.ql b/cpp/ql/test/library-tests/compiler_generated/compilerGenerated.ql index 4676849ecfd..0eb620f0c79 100644 --- a/cpp/ql/test/library-tests/compiler_generated/compilerGenerated.ql +++ b/cpp/ql/test/library-tests/compiler_generated/compilerGenerated.ql @@ -1,9 +1,12 @@ import cpp from Element e, string type -where ((Function)e).isCompilerGenerated() and type = "Function" - or ((Expr) e).isCompilerGenerated() and type = "Expr" - or ((Variable)e).isCompilerGenerated() and type = "Variable" - or ((Stmt) e).isCompilerGenerated() and type = "Stmt" +where + e.(Function).isCompilerGenerated() and type = "Function" + or + e.(Expr).isCompilerGenerated() and type = "Expr" + or + e.(Variable).isCompilerGenerated() and type = "Variable" + or + e.(Stmt).isCompilerGenerated() and type = "Stmt" select e, type - diff --git a/cpp/ql/test/library-tests/complex_numbers/expr.ql b/cpp/ql/test/library-tests/complex_numbers/expr.ql index 00335eb188d..903359f5f72 100644 --- a/cpp/ql/test/library-tests/complex_numbers/expr.ql +++ b/cpp/ql/test/library-tests/complex_numbers/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e, e.getAQlClass() - diff --git a/cpp/ql/test/library-tests/conditions/vars.ql b/cpp/ql/test/library-tests/conditions/vars.ql index 14c3aed68dd..d00bf751145 100644 --- a/cpp/ql/test/library-tests/conditions/vars.ql +++ b/cpp/ql/test/library-tests/conditions/vars.ql @@ -2,4 +2,3 @@ import cpp from Variable v select v - diff --git a/cpp/ql/test/library-tests/constants/constants/chars.ql b/cpp/ql/test/library-tests/constants/constants/chars.ql index 0e4f220fe6d..842c63f7eba 100644 --- a/cpp/ql/test/library-tests/constants/constants/chars.ql +++ b/cpp/ql/test/library-tests/constants/constants/chars.ql @@ -1,6 +1,4 @@ import cpp from CharLiteral cl -select cl.getValue(), - cl.getValueText(), - cl.getCharacter() +select cl.getValue(), cl.getValueText(), cl.getCharacter() diff --git a/cpp/ql/test/library-tests/constants/constants/ints.ql b/cpp/ql/test/library-tests/constants/constants/ints.ql index 853e1feadc4..aaa00f0e684 100644 --- a/cpp/ql/test/library-tests/constants/constants/ints.ql +++ b/cpp/ql/test/library-tests/constants/constants/ints.ql @@ -1,8 +1,9 @@ import cpp from LocalVariable v, Literal l, string clazz -where l = v.getInitializer().getExpr() - and v.getFunction().hasName("integers") - and clazz = l.getAQlClass() - and (clazz.matches("%Literal") or clazz = "Zero") +where + l = v.getInitializer().getExpr() and + v.getFunction().hasName("integers") and + clazz = l.getAQlClass() and + (clazz.matches("%Literal") or clazz = "Zero") select v, l.getValue(), l.getValueText(), clazz diff --git a/cpp/ql/test/library-tests/constants/constants/strings.ql b/cpp/ql/test/library-tests/constants/constants/strings.ql index a412155cee7..6276e897a65 100644 --- a/cpp/ql/test/library-tests/constants/constants/strings.ql +++ b/cpp/ql/test/library-tests/constants/constants/strings.ql @@ -2,4 +2,4 @@ import cpp from StringLiteral sl select sl.getValue().regexpReplaceAll("\\\\x00+", "\\\\x0"), // Normalise for different sizeof(wchar_t) - sl.getValueText() + sl.getValueText() diff --git a/cpp/ql/test/library-tests/constants/initializerexpr/initializerexpr.ql b/cpp/ql/test/library-tests/constants/initializerexpr/initializerexpr.ql index d09a91f81be..11f4d6c7e1a 100644 --- a/cpp/ql/test/library-tests/constants/initializerexpr/initializerexpr.ql +++ b/cpp/ql/test/library-tests/constants/initializerexpr/initializerexpr.ql @@ -1,10 +1,17 @@ import cpp Declaration initializedDecl(Expr e) { - exists(Initializer i | i.getExpr() = e and i.getDeclaration() = result) + exists(Initializer i | i.getExpr() = e and i.getDeclaration() = result) } from Expr e, string enclosedBy, string initializes -where if exists(e.getEnclosingFunction()) then enclosedBy = e.getEnclosingFunction().toString() else enclosedBy = "" -and if exists(initializedDecl(e)) then initializes = initializedDecl(e).toString() else initializes = "" +where + ( + if exists(e.getEnclosingFunction()) + then enclosedBy = e.getEnclosingFunction().toString() + else enclosedBy = "" + ) and + if exists(initializedDecl(e)) + then initializes = initializedDecl(e).toString() + else initializes = "" select e, initializes, enclosedBy diff --git a/cpp/ql/test/library-tests/constants/initializers/initializers.ql b/cpp/ql/test/library-tests/constants/initializers/initializers.ql index 0086631eefd..858dc11cbe9 100644 --- a/cpp/ql/test/library-tests/constants/initializers/initializers.ql +++ b/cpp/ql/test/library-tests/constants/initializers/initializers.ql @@ -4,4 +4,3 @@ import Best_Practices.Magic_Constants.MagicConstants from Literal l, Variable v where literalIsConstantInitializer(l, v) select l, v - diff --git a/cpp/ql/test/library-tests/constants/strlen/expr.ql b/cpp/ql/test/library-tests/constants/strlen/expr.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/constants/strlen/expr.ql +++ b/cpp/ql/test/library-tests/constants/strlen/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/constexpr_if/cfg.ql b/cpp/ql/test/library-tests/constexpr_if/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/constexpr_if/cfg.ql +++ b/cpp/ql/test/library-tests/constexpr_if/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/controlflow/assume/cfg.ql b/cpp/ql/test/library-tests/controlflow/assume/cfg.ql index 521231b4958..726f6dcd073 100644 --- a/cpp/ql/test/library-tests/controlflow/assume/cfg.ql +++ b/cpp/ql/test/library-tests/controlflow/assume/cfg.ql @@ -1,22 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope().toString(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope().toString(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/library-tests/controlflow/assume/interesting.ql b/cpp/ql/test/library-tests/controlflow/assume/interesting.ql index 95e499b2f81..2bb2732d039 100644 --- a/cpp/ql/test/library-tests/controlflow/assume/interesting.ql +++ b/cpp/ql/test/library-tests/controlflow/assume/interesting.ql @@ -1,25 +1,25 @@ import cpp predicate interesting(ControlFlowNode n) { - n instanceof AssumeExpr or - n instanceof FunctionCall + n instanceof AssumeExpr or + n instanceof FunctionCall } predicate ptrUnassigned(ControlFlowNode n) { - // declaration of `ptr` - n.(DeclStmt).getADeclaration().getName() = "ptr" or - - // flow - exists(ControlFlowNode pred | - ptrUnassigned(pred) and - pred.getASuccessor() = n and - not pred.(AssignExpr).getLValue().(Access).getTarget().getName() = "ptr" - ) + // declaration of `ptr` + n.(DeclStmt).getADeclaration().getName() = "ptr" + or + // flow + exists(ControlFlowNode pred | + ptrUnassigned(pred) and + pred.getASuccessor() = n and + not pred.(AssignExpr).getLValue().(Access).getTarget().getName() = "ptr" + ) } from ControlFlowNode n, string r, string p where - interesting(n) and - if reachable(n) then r = "reachable" else r = "" and - if ptrUnassigned(n) then p = "unassigned ptr" else p = "" + interesting(n) and + (if reachable(n) then r = "reachable" else r = "") and + if ptrUnassigned(n) then p = "unassigned ptr" else p = "" select n, count(n.getAPredecessor()), count(n.getASuccessor()), r, p diff --git a/cpp/ql/test/library-tests/controlflow/controlflow/SsaCompleteness.ql b/cpp/ql/test/library-tests/controlflow/controlflow/SsaCompleteness.ql index 8cce68940c9..7af147f73d6 100644 --- a/cpp/ql/test/library-tests/controlflow/controlflow/SsaCompleteness.ql +++ b/cpp/ql/test/library-tests/controlflow/controlflow/SsaCompleteness.ql @@ -8,14 +8,17 @@ import cpp import semmle.code.cpp.controlflow.SSA -/* Count of number of uses of a LocalScopeVariable where no corresponding SSA definition exists, - but at least one SSA definition for that variable can reach that use. - Should always be zero *regardless* of the input */ -select -count(LocalScopeVariable v, Expr use | - exists(SsaDefinition def, BasicBlock db, BasicBlock ub | - def.getAUse(v) = use and db.contains(def.getDefinition()) and ub.contains(use) | - db.getASuccessor+() = ub - ) - and not exists(SsaDefinition def | def.getAUse(v) = use) -) \ No newline at end of file +/* + * Count of number of uses of a LocalScopeVariable where no corresponding SSA definition exists, + * but at least one SSA definition for that variable can reach that use. + * Should always be zero *regardless* of the input + */ + +select count(LocalScopeVariable v, Expr use | + exists(SsaDefinition def, BasicBlock db, BasicBlock ub | + def.getAUse(v) = use and db.contains(def.getDefinition()) and ub.contains(use) + | + db.getASuccessor+() = ub + ) and + not exists(SsaDefinition def | def.getAUse(v) = use) + ) diff --git a/cpp/ql/test/library-tests/controlflow/controlflow/SsaCorrespondence.ql b/cpp/ql/test/library-tests/controlflow/controlflow/SsaCorrespondence.ql index 8eec528ddff..07aba34237d 100644 --- a/cpp/ql/test/library-tests/controlflow/controlflow/SsaCorrespondence.ql +++ b/cpp/ql/test/library-tests/controlflow/controlflow/SsaCorrespondence.ql @@ -8,16 +8,19 @@ import cpp import semmle.code.cpp.controlflow.SSA import semmle.code.cpp.controlflow.SSAUtils -/* Count of number of reachable definitions or parameters where the no corresponding SSA definition exists. - Should always be zero *regardless* of the input */ +/* + * Count of number of reachable definitions or parameters where the no corresponding SSA definition exists. + * Should always be zero *regardless* of the input + */ -select -count(Variable v, ControlFlowNode def | var_definition(v, def) and not unreachable(def) and +select count(Variable v, ControlFlowNode def | + var_definition(v, def) and + not unreachable(def) and not exists(SsaDefinition d | d.getAVariable() = v and d.getDefinition() = def) -) -+ -count(Parameter p | - exists(p.getAnAccess()) - and - not exists(SsaDefinition d | d.getAVariable() = p and d.getDefinition() = p.getFunction().getEntryPoint()) -) \ No newline at end of file + ) + + count(Parameter p | + exists(p.getAnAccess()) and + not exists(SsaDefinition d | + d.getAVariable() = p and d.getDefinition() = p.getFunction().getEntryPoint() + ) + ) diff --git a/cpp/ql/test/library-tests/controlflow/controlflow/SsaDominance.ql b/cpp/ql/test/library-tests/controlflow/controlflow/SsaDominance.ql index a30edf640f9..2bbf7c7707d 100644 --- a/cpp/ql/test/library-tests/controlflow/controlflow/SsaDominance.ql +++ b/cpp/ql/test/library-tests/controlflow/controlflow/SsaDominance.ql @@ -1,21 +1,26 @@ /** * @name SSA dominance property test - * @description SSA dominance property test. SSA definitions *must* dominate all uses + * @description SSA dominance property test. SSA definitions *must* dominate all uses * @kind test */ import cpp import semmle.code.cpp.controlflow.SSA -/* Count of number of SSA def-use pairs where the defn does not dominate the use. - Should always be zero *regardless* of the input */ +/* + * Count of number of SSA def-use pairs where the defn does not dominate the use. + * Should always be zero *regardless* of the input + */ -select -count(SsaDefinition d, LocalScopeVariable v, Expr u | - d.getAUse(v) = u and - not exists(BasicBlock bd, BasicBlock bu | bd.contains(mkElement(d).(ControlFlowNode)) and bu.contains(u) | - bbStrictlyDominates(bd, bu) - or - exists(int i, int j | bd = bu and bd.getNode(i) = mkElement(d) and bu.getNode(j) = u and i <= j) - ) -) +select count(SsaDefinition d, LocalScopeVariable v, Expr u | + d.getAUse(v) = u and + not exists(BasicBlock bd, BasicBlock bu | + bd.contains(mkElement(d).(ControlFlowNode)) and bu.contains(u) + | + bbStrictlyDominates(bd, bu) + or + exists(int i, int j | + bd = bu and bd.getNode(i) = mkElement(d) and bu.getNode(j) = u and i <= j + ) + ) + ) diff --git a/cpp/ql/test/library-tests/controlflow/controlflow/SsaLt.ql b/cpp/ql/test/library-tests/controlflow/controlflow/SsaLt.ql index 7b3cc49c682..ef422265b61 100644 --- a/cpp/ql/test/library-tests/controlflow/controlflow/SsaLt.ql +++ b/cpp/ql/test/library-tests/controlflow/controlflow/SsaLt.ql @@ -10,11 +10,11 @@ import semmle.code.cpp.controlflow.Guards from GuardedSsa def, LocalScopeVariable var, Expr other, int k, int start, int end, string op where -exists(BasicBlock block | + exists(BasicBlock block | def.isLt(var, other, k, block, true) and op = "<" or - def.isLt(var, other, k, block, false) and op = ">" | + def.isLt(var, other, k, block, false) and op = ">" + | block.hasLocationInfo(_, start, _, end, _) -) - + ) select def, var, op, other, start, end diff --git a/cpp/ql/test/library-tests/controlflow/controlflow/SsaPhiInputs.ql b/cpp/ql/test/library-tests/controlflow/controlflow/SsaPhiInputs.ql index 981db4ebb64..353b6cd279c 100644 --- a/cpp/ql/test/library-tests/controlflow/controlflow/SsaPhiInputs.ql +++ b/cpp/ql/test/library-tests/controlflow/controlflow/SsaPhiInputs.ql @@ -7,9 +7,12 @@ import cpp import semmle.code.cpp.controlflow.SSA -from File file, SsaDefinition phi, LocalScopeVariable var, SsaDefinition input, int philine, int inputline -where phi.getAPhiInput(var) = input and -file = phi.getLocation().getFile() and -philine = phi.getLocation().getStartLine() and -inputline = input.getLocation().getStartLine() +from + File file, SsaDefinition phi, LocalScopeVariable var, SsaDefinition input, int philine, + int inputline +where + phi.getAPhiInput(var) = input and + file = phi.getLocation().getFile() and + philine = phi.getLocation().getStartLine() and + inputline = input.getLocation().getStartLine() select file.getAbsolutePath(), philine, phi.toString(var), inputline, input.toString(var) diff --git a/cpp/ql/test/library-tests/controlflow/controlflow/SsaUniqueness.ql b/cpp/ql/test/library-tests/controlflow/controlflow/SsaUniqueness.ql index f7938c8e30c..bff4301287f 100644 --- a/cpp/ql/test/library-tests/controlflow/controlflow/SsaUniqueness.ql +++ b/cpp/ql/test/library-tests/controlflow/controlflow/SsaUniqueness.ql @@ -7,11 +7,13 @@ import cpp import semmle.code.cpp.controlflow.SSA -/* Count of number of uses where the number of SSA definitions exceeds one. - Should always be zero *regardless* of the input */ +/* + * Count of number of uses where the number of SSA definitions exceeds one. + * Should always be zero *regardless* of the input + */ -select -count(SsaDefinition d1, SsaDefinition d2, Expr u, LocalScopeVariable v | - d1.getAUse(v) = u and - d2.getAUse(v) = u and not d1 = d2 -) +select count(SsaDefinition d1, SsaDefinition d2, Expr u, LocalScopeVariable v | + d1.getAUse(v) = u and + d2.getAUse(v) = u and + not d1 = d2 + ) diff --git a/cpp/ql/test/library-tests/controlflow/dominance/bbIDominates.ql b/cpp/ql/test/library-tests/controlflow/dominance/bbIDominates.ql index e4428117b6e..53e467c8055 100644 --- a/cpp/ql/test/library-tests/controlflow/dominance/bbIDominates.ql +++ b/cpp/ql/test/library-tests/controlflow/dominance/bbIDominates.ql @@ -3,11 +3,8 @@ import semmle.code.cpp.controlflow.Dominance from Function func, BasicBlock dominator, BasicBlock node where - bbIDominates(dominator, node) - and dominator.getNode(0).getControlFlowScope() = func -select - func.getName(), - dominator.getNode(0).getLocation().getStartLine(), dominator.getNode(0).toString(), - node.getNode(0).getLocation().getStartLine(), node.getNode(0).toString() - - \ No newline at end of file + bbIDominates(dominator, node) and + dominator.getNode(0).getControlFlowScope() = func +select func.getName(), dominator.getNode(0).getLocation().getStartLine(), + dominator.getNode(0).toString(), node.getNode(0).getLocation().getStartLine(), + node.getNode(0).toString() diff --git a/cpp/ql/test/library-tests/controlflow/dominance/dominatedByStart.ql b/cpp/ql/test/library-tests/controlflow/dominance/dominatedByStart.ql index b6a4ef8d159..92ca16a189c 100644 --- a/cpp/ql/test/library-tests/controlflow/dominance/dominatedByStart.ql +++ b/cpp/ql/test/library-tests/controlflow/dominance/dominatedByStart.ql @@ -1,25 +1,25 @@ // All nodes should be dominated by their associated start node - import cpp import semmle.code.cpp.controlflow.Dominance ControlFlowNode reachableIn(Function func) { - result = func.getEntryPoint() - or result = reachableIn(func).getASuccessor() + result = func.getEntryPoint() or + result = reachableIn(func).getASuccessor() } predicate dominatedByStart(Function func, ControlFlowNode node) { iDominates(func.getEntryPoint(), node) - or exists (ControlFlowNode dom | - dominatedByStart(func, dom) - and iDominates(dom, node)) + or + exists(ControlFlowNode dom | + dominatedByStart(func, dom) and + iDominates(dom, node) + ) } - from Function func, ControlFlowNode entry, ControlFlowNode node where - func.getEntryPoint() = entry - and reachableIn(func) = node - and entry != node - and not dominatedByStart(func, node) + func.getEntryPoint() = entry and + reachableIn(func) = node and + entry != node and + not dominatedByStart(func, node) select func, node diff --git a/cpp/ql/test/library-tests/controlflow/dominance/dominator.ql b/cpp/ql/test/library-tests/controlflow/dominance/dominator.ql index 10f185da477..22cc0a8054d 100644 --- a/cpp/ql/test/library-tests/controlflow/dominance/dominator.ql +++ b/cpp/ql/test/library-tests/controlflow/dominance/dominator.ql @@ -3,9 +3,7 @@ import semmle.code.cpp.controlflow.Dominance from Function func, ControlFlowNode dominator, ControlFlowNode node where - iDominates(dominator, node) - and dominator.getControlFlowScope() = func -select - func.getName(), - dominator.getLocation().getStartLine(), dominator.toString(), + iDominates(dominator, node) and + dominator.getControlFlowScope() = func +select func.getName(), dominator.getLocation().getStartLine(), dominator.toString(), node.getLocation().getStartLine(), node.toString() diff --git a/cpp/ql/test/library-tests/controlflow/dominance/dominatorExists.ql b/cpp/ql/test/library-tests/controlflow/dominance/dominatorExists.ql index 12a58c044d5..2163221b6c4 100644 --- a/cpp/ql/test/library-tests/controlflow/dominance/dominatorExists.ql +++ b/cpp/ql/test/library-tests/controlflow/dominance/dominatorExists.ql @@ -1,17 +1,15 @@ // Every reachable node has a dominator - import cpp import semmle.code.cpp.controlflow.Dominance ControlFlowNode reachableIn(Function func) { - result = func.getEntryPoint() - or result = reachableIn(func).getASuccessor() + result = func.getEntryPoint() or + result = reachableIn(func).getASuccessor() } - from Function func, ControlFlowNode node where - node = reachableIn(func) - and node != func.getEntryPoint() - and not iDominates(_, node) + node = reachableIn(func) and + node != func.getEntryPoint() and + not iDominates(_, node) select func, node diff --git a/cpp/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql b/cpp/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql index 5911d2d0cb4..1f07d881400 100644 --- a/cpp/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql +++ b/cpp/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql @@ -1,12 +1,11 @@ // Every reachable node has a dominator - import cpp import semmle.code.cpp.controlflow.Dominance from Function func, ControlFlowNode dom1, ControlFlowNode dom2, ControlFlowNode node where - iDominates(dom1, node) - and iDominates(dom2, node) - and dom1 != dom2 - and node.getControlFlowScope() = func + iDominates(dom1, node) and + iDominates(dom2, node) and + dom1 != dom2 and + node.getControlFlowScope() = func select func, node, dom1, dom2 diff --git a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql index 019f5a121d9..96bdf080308 100644 --- a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql +++ b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.ql @@ -1,73 +1,75 @@ import cpp import semmle.code.cpp.controlflow.IRGuards -query predicate astGuards(GuardCondition guard) { - any() -} +query predicate astGuards(GuardCondition guard) { any() } query predicate astGuardsCompare(int startLine, string msg) { exists(GuardCondition guard, Expr left, Expr right, int k, string which, string op | exists(boolean sense | sense = true and which = "true" - or sense = false and which = "false" - | + or + sense = false and which = "false" + | guard.comparesLt(left, right, k, true, sense) and op = " < " or guard.comparesLt(left, right, k, false, sense) and op = " >= " or guard.comparesEq(left, right, k, true, sense) and op = " == " - or - guard.comparesEq(left, right, k, false, sense) and op = " != " - ) - and startLine = guard.getLocation().getStartLine() - and msg = left + op + right + "+" + k + " when " + guard + " is " + which + or + guard.comparesEq(left, right, k, false, sense) and op = " != " + ) and + startLine = guard.getLocation().getStartLine() and + msg = left + op + right + "+" + k + " when " + guard + " is " + which ) } query predicate astGuardsControl(GuardCondition guard, boolean sense, int start, int end) { exists(BasicBlock block | - guard.controls(block, sense) and - block.hasLocationInfo(_, start, _, end, _) + guard.controls(block, sense) and + block.hasLocationInfo(_, start, _, end, _) ) } -query predicate astGuardsEnsure(GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end) -{ +query predicate astGuardsEnsure( + GuardCondition guard, Expr left, string op, Expr right, int k, int start, int end +) { exists(BasicBlock block | - guard.ensuresLt(left, right, k, block, true) and op = "<" - or - guard.ensuresLt(left, right, k, block, false) and op = ">=" - or - guard.ensuresEq(left, right, k, block, true) and op = "==" - or - guard.ensuresEq(left, right, k, block, false) and op = "!=" - | - block.hasLocationInfo(_, start, _, end, _) + guard.ensuresLt(left, right, k, block, true) and op = "<" + or + guard.ensuresLt(left, right, k, block, false) and op = ">=" + or + guard.ensuresEq(left, right, k, block, true) and op = "==" + or + guard.ensuresEq(left, right, k, block, false) and op = "!=" + | + block.hasLocationInfo(_, start, _, end, _) ) } -query predicate irGuards(IRGuardCondition guard) { - any() -} +query predicate irGuards(IRGuardCondition guard) { any() } query predicate irGuardsCompare(int startLine, string msg) { exists(IRGuardCondition guard, Operand left, Operand right, int k, string which, string op | exists(boolean sense | sense = true and which = "true" - or sense = false and which = "false" - | + or + sense = false and which = "false" + | guard.comparesLt(left, right, k, true, sense) and op = " < " or guard.comparesLt(left, right, k, false, sense) and op = " >= " or guard.comparesEq(left, right, k, true, sense) and op = " == " - or - guard.comparesEq(left, right, k, false, sense) and op = " != " - ) - and startLine = guard.getLocation().getStartLine() - and msg = left.getAnyDef().getUnconvertedResultExpression() + op + right.getAnyDef().getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + which + or + guard.comparesEq(left, right, k, false, sense) and op = " != " + ) and + startLine = guard.getLocation().getStartLine() and + msg = left.getAnyDef().getUnconvertedResultExpression() + op + + right.getAnyDef().getUnconvertedResultExpression() + "+" + k + " when " + guard + " is " + + which ) } + query predicate irGuardsControl(IRGuardCondition guard, boolean sense, int start, int end) { exists(IRBlock block | guard.controls(block, sense) and @@ -75,18 +77,18 @@ query predicate irGuardsControl(IRGuardCondition guard, boolean sense, int start ) } -query predicate irGuardsEnsure(IRGuardCondition guard, Instruction left, string op, Instruction right, int k, int start, int end) -{ - +query predicate irGuardsEnsure( + IRGuardCondition guard, Instruction left, string op, Instruction right, int k, int start, int end +) { exists(IRBlock block, Operand leftOp, Operand rightOp | guard.ensuresLt(leftOp, rightOp, k, block, true) and op = "<" or - guard.ensuresLt(leftOp, rightOp, k, block, false) and op = ">=" + guard.ensuresLt(leftOp, rightOp, k, block, false) and op = ">=" or guard.ensuresEq(leftOp, rightOp, k, block, true) and op = "==" or guard.ensuresEq(leftOp, rightOp, k, block, false) and op = "!=" - | + | leftOp = left.getAUse() and rightOp = right.getAUse() and block.getLocation().hasLocationInfo(_, start, _, end, _) diff --git a/cpp/ql/test/library-tests/controlflow/guards/Guards.ql b/cpp/ql/test/library-tests/controlflow/guards/Guards.ql index b205a16034b..6580c2acf58 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/Guards.ql +++ b/cpp/ql/test/library-tests/controlflow/guards/Guards.ql @@ -2,4 +2,4 @@ import cpp import semmle.code.cpp.controlflow.Guards from GuardCondition guard -select guard \ No newline at end of file +select guard diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.ql b/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.ql index 6adc9db4610..a1373b2923b 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.ql +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.ql @@ -7,19 +7,20 @@ import cpp import semmle.code.cpp.controlflow.Guards - from GuardCondition guard, Expr left, Expr right, int k, string which, string op, string msg -where -(exists(boolean sense | sense = true and which = "true" or sense = false and which = "false" | +where + exists(boolean sense | + sense = true and which = "true" + or + sense = false and which = "false" + | guard.comparesLt(left, right, k, true, sense) and op = " < " or guard.comparesLt(left, right, k, false, sense) and op = " >= " or guard.comparesEq(left, right, k, true, sense) and op = " == " - or - guard.comparesEq(left, right, k, false, sense) and op = " != " - ) -) -and msg = left + op + right + "+" + k + " when " + guard + " is " + which - -select guard.getLocation().getStartLine(), msg \ No newline at end of file + or + guard.comparesEq(left, right, k, false, sense) and op = " != " + ) and + msg = left + op + right + "+" + k + " when " + guard + " is " + which +select guard.getLocation().getStartLine(), msg diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.ql b/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.ql index fecfe8f7d61..5101f64a2c5 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.ql +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.ql @@ -7,11 +7,10 @@ import cpp import semmle.code.cpp.controlflow.Guards - from GuardCondition guard, boolean sense, int start, int end -where -exists(BasicBlock block | - guard.controls(block, sense) and - block.hasLocationInfo(_, start, _, end, _) -) +where + exists(BasicBlock block | + guard.controls(block, sense) and + block.hasLocationInfo(_, start, _, end, _) + ) select guard, sense, start, end diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql index 67e0cf698a1..94aaade03ed 100644 --- a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql +++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.ql @@ -7,17 +7,17 @@ import cpp import semmle.code.cpp.controlflow.Guards - from GuardCondition guard, Expr left, Expr right, int k, int start, int end, string op -where -exists(BasicBlock block | - guard.ensuresLt(left, right, k, block, true) and op = "<" - or - guard.ensuresLt(left, right, k, block, false) and op = ">=" - or - guard.ensuresEq(left, right, k, block, true) and op = "==" - or - guard.ensuresEq(left, right, k, block, false) and op = "!=" | - block.hasLocationInfo(_, start, _, end, _) -) +where + exists(BasicBlock block | + guard.ensuresLt(left, right, k, block, true) and op = "<" + or + guard.ensuresLt(left, right, k, block, false) and op = ">=" + or + guard.ensuresEq(left, right, k, block, true) and op = "==" + or + guard.ensuresEq(left, right, k, block, false) and op = "!=" + | + block.hasLocationInfo(_, start, _, end, _) + ) select guard, left, op, right, k, start, end diff --git a/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt01.ql b/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt01.ql index 9e22719a650..ea08c2fb157 100644 --- a/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt01.ql +++ b/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt01.ql @@ -2,4 +2,4 @@ import cpp from ForStmt for where for.conditionAlwaysTrueUponEntry() -select for \ No newline at end of file +select for diff --git a/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt01.ql b/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt01.ql index 0ed91f67f47..c7d0005da1c 100644 --- a/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt01.ql +++ b/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt01.ql @@ -2,4 +2,4 @@ import cpp from WhileStmt while where while.conditionAlwaysTrueUponEntry() -select while \ No newline at end of file +select while diff --git a/cpp/ql/test/library-tests/controlflow/primitives/cfg.ql b/cpp/ql/test/library-tests/controlflow/primitives/cfg.ql index 521231b4958..726f6dcd073 100644 --- a/cpp/ql/test/library-tests/controlflow/primitives/cfg.ql +++ b/cpp/ql/test/library-tests/controlflow/primitives/cfg.ql @@ -1,22 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope().toString(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope().toString(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/library-tests/controlflow/primitives/falseSucc.ql b/cpp/ql/test/library-tests/controlflow/primitives/falseSucc.ql index d9107a47091..6088e3efecc 100644 --- a/cpp/ql/test/library-tests/controlflow/primitives/falseSucc.ql +++ b/cpp/ql/test/library-tests/controlflow/primitives/falseSucc.ql @@ -1,5 +1,4 @@ // Regression test for ODASA-4753 and ODASA-4762. - import cpp from ControlFlowNode x diff --git a/cpp/ql/test/library-tests/controlflow/primitives/trueSucc.ql b/cpp/ql/test/library-tests/controlflow/primitives/trueSucc.ql index 0d230dc288a..0fd0cf09be4 100644 --- a/cpp/ql/test/library-tests/controlflow/primitives/trueSucc.ql +++ b/cpp/ql/test/library-tests/controlflow/primitives/trueSucc.ql @@ -1,5 +1,4 @@ // Regression tests for ODASA-4753 and ODASA-4762. - import cpp from ControlFlowNode x diff --git a/cpp/ql/test/library-tests/conversions/conversions.ql b/cpp/ql/test/library-tests/conversions/conversions.ql index 2216f6f0b1c..6ba2bd8f365 100644 --- a/cpp/ql/test/library-tests/conversions/conversions.ql +++ b/cpp/ql/test/library-tests/conversions/conversions.ql @@ -1,15 +1,17 @@ import default string getValueCategoryString(Expr expr) { - if expr.isLValueCategory() then - result = "lval" - else if expr.isXValueCategory() then - result = "xval" - else if expr.hasLValueToRValueConversion() then - result = "prval(load)" + if expr.isLValueCategory() + then result = "lval" else - result = "prval" + if expr.isXValueCategory() + then result = "xval" + else + if expr.hasLValueToRValueConversion() + then result = "prval(load)" + else result = "prval" } from Cast cast -select cast, cast.getSemanticConversionString(), getValueCategoryString(cast), cast.getType().toString(), cast.getExpr().getType().toString() +select cast, cast.getSemanticConversionString(), getValueCategoryString(cast), + cast.getType().toString(), cast.getExpr().getType().toString() diff --git a/cpp/ql/test/library-tests/cpp11_g/cfg.ql b/cpp/ql/test/library-tests/cpp11_g/cfg.ql index f8b42fd68a5..5fe85186273 100644 --- a/cpp/ql/test/library-tests/cpp11_g/cfg.ql +++ b/cpp/ql/test/library-tests/cpp11_g/cfg.ql @@ -2,25 +2,24 @@ import cpp import semmle.code.cpp.exprs.ObjectiveC string arguments(Function f, int i) { - (result = "," and i = -1) or - (result = "" and i = min(int j | function_template_argument(unresolveElement(f), j, _)) - 1) or - (result = arguments(f, i - 1) + "," + f.getTemplateArgument(i).toString()) + result = "," and i = -1 + or + result = "" and i = min(int j | function_template_argument(unresolveElement(f), j, _)) - 1 + or + result = arguments(f, i - 1) + "," + f.getTemplateArgument(i).toString() } string name(Function f) { - if f.isConstructedFrom(_) then - result = f.toString() + "<" + max(arguments(f, _)).suffix(1) + ">" - else if f instanceof TemplateFunction then - result = f.toString() + " prototype instantiation" + if f.isConstructedFrom(_) + then result = f.toString() + "<" + max(arguments(f, _)).suffix(1) + ">" else - result = f.toString() + if f instanceof TemplateFunction + then result = f.toString() + " prototype instantiation" + else result = f.toString() } from ControlFlowNode x, ControlFlowNode y where y = x.getASuccessor() -select name(x.getControlFlowScope()), - x.getLocation().getStartLine(), - count(x.getAPredecessor*()), // This helps order things sensibly - x.toString(), - y.getLocation().getStartLine(), - y.toString() +select name(x.getControlFlowScope()), x.getLocation().getStartLine(), + count(x.getAPredecessor*()), // This helps order things sensibly + x.toString(), y.getLocation().getStartLine(), y.toString() diff --git a/cpp/ql/test/library-tests/ctorinits/ctors.ql b/cpp/ql/test/library-tests/ctorinits/ctors.ql index 9f528854dcf..0084cf869e2 100644 --- a/cpp/ql/test/library-tests/ctorinits/ctors.ql +++ b/cpp/ql/test/library-tests/ctorinits/ctors.ql @@ -1,7 +1,8 @@ import cpp from Constructor c, int i, Expr e, string what -where e = c.getInitializer(i) - and what = e.getAQlClass() - and what.matches("Constructor%Init") +where + e = c.getInitializer(i) and + what = e.getAQlClass() and + what.matches("Constructor%Init") select c, i, what, e, count(e.getAChild()), count(e.getAChild*().(Literal)) diff --git a/cpp/ql/test/library-tests/ctorinits/dtors.ql b/cpp/ql/test/library-tests/ctorinits/dtors.ql index cd649a6bc96..f6b8c277756 100644 --- a/cpp/ql/test/library-tests/ctorinits/dtors.ql +++ b/cpp/ql/test/library-tests/ctorinits/dtors.ql @@ -1,7 +1,8 @@ import cpp from Destructor d, int i, Expr e, string what -where e = d.getDestruction(i) - and what = e.getAQlClass() - and what.matches("Destructor%Destruction") +where + e = d.getDestruction(i) and + what = e.getAQlClass() and + what.matches("Destructor%Destruction") select d, i, what, e, count(e.getAChild()) diff --git a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql index 362bd8cd6b7..58bbec1c780 100644 --- a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql @@ -2,9 +2,7 @@ import cpp import semmle.code.cpp.dataflow.DataFlow class TestConfig extends DataFlow::Configuration { - TestConfig() { - this = "TestConfig" - } + TestConfig() { this = "TestConfig" } override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" diff --git a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql index 3e3d23e65f9..a1ad99aeef0 100644 --- a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql @@ -2,9 +2,7 @@ import cpp import semmle.code.cpp.dataflow.DataFlow class TestConfig extends DataFlow::Configuration { - TestConfig() { - this = "TestConfig" - } + TestConfig() { this = "TestConfig" } override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/additionalEdges.ql b/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/additionalEdges.ql index eb795d876f9..f83648c4267 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/additionalEdges.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/additionalEdges.ql @@ -12,9 +12,7 @@ class EdgeToExcept extends AdditionalControlFlowEdge { } } -MicrosoftTryExceptStmt getNearestTryExceptParent(Expr e) { - result = getANearParent(e) -} +MicrosoftTryExceptStmt getNearestTryExceptParent(Expr e) { result = getANearParent(e) } private Element getANearParent(Expr e) { result = e.getParent() @@ -23,7 +21,8 @@ private Element getANearParent(Expr e) { result = prev.(Expr).getParent() or result = prev.(Stmt).getParent() - | // do not recurse past __try + | + // do not recurse past __try not prev instanceof MicrosoftTryStmt and prev = getANearParent(e) ) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/standardEdges.ql b/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/standardEdges.ql index 41f59b07487..18edccf8e8e 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/standardEdges.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-edge-tests/standardEdges.ql @@ -3,4 +3,4 @@ import semmle.code.cpp.dataflow.DataFlow from DataFlow::Node nodeFrom, DataFlow::Node nodeTo where DataFlow::localFlowStep(nodeFrom, nodeTo) -select nodeFrom, nodeTo \ No newline at end of file +select nodeFrom, nodeTo diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/DataflowTestCommon.qll b/cpp/ql/test/library-tests/dataflow/dataflow-tests/DataflowTestCommon.qll index 21bf44afd29..02ee4d45380 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/DataflowTestCommon.qll +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/DataflowTestCommon.qll @@ -3,9 +3,7 @@ import semmle.code.cpp.dataflow.DataFlow /** Common data flow configuration to be used by tests. */ class TestAllocationConfig extends DataFlow::Configuration { - TestAllocationConfig() { - this = "TestAllocationConfig" - } + TestAllocationConfig() { this = "TestAllocationConfig" } override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/IRDataflowTestCommon.qll b/cpp/ql/test/library-tests/dataflow/dataflow-tests/IRDataflowTestCommon.qll index ce2eb1ac97a..eb5fa14e2e0 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/IRDataflowTestCommon.qll +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/IRDataflowTestCommon.qll @@ -3,9 +3,7 @@ import semmle.code.cpp.ir.dataflow.DataFlow /** Common data flow configuration to be used by tests. */ class TestAllocationConfig extends DataFlow::Configuration { - TestAllocationConfig() { - this = "TestAllocationConfig" - } + TestAllocationConfig() { this = "TestAllocationConfig" } override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.ql index 4a8bddc8f57..b052bb51151 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.ql @@ -2,6 +2,7 @@ import cpp import semmle.code.cpp.dataflow.DataFlow from DataFlow::Node nodeFrom, DataFlow::Node nodeTo -where DataFlow::localFlowStep(nodeFrom, nodeTo) - and nodeFrom.getFunction().getName().matches("%\\_with\\_local\\_flow") +where + DataFlow::localFlowStep(nodeFrom, nodeTo) and + nodeFrom.getFunction().getName().matches("%\\_with\\_local\\_flow") select nodeFrom, nodeTo diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.ql index 659a75528bb..8de85304583 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.ql @@ -5,8 +5,10 @@ import semmle.code.cpp.dataflow.DataFlow as ASTDataFlow import semmle.code.cpp.ir.dataflow.DataFlow as IRDataFlow predicate astFlow(Location sourceLocation, Location sinkLocation) { - exists(ASTDataFlow::DataFlow::Node source, ASTDataFlow::DataFlow::Node sink, - ASTCommon::TestAllocationConfig cfg | + exists( + ASTDataFlow::DataFlow::Node source, ASTDataFlow::DataFlow::Node sink, + ASTCommon::TestAllocationConfig cfg + | cfg.hasFlow(source, sink) and sourceLocation = source.getLocation() and sinkLocation = sink.getLocation() @@ -14,8 +16,10 @@ predicate astFlow(Location sourceLocation, Location sinkLocation) { } predicate irFlow(Location sourceLocation, Location sinkLocation) { - exists(IRDataFlow::DataFlow::Node source, IRDataFlow::DataFlow::Node sink, - IRCommon::TestAllocationConfig cfg | + exists( + IRDataFlow::DataFlow::Node source, IRDataFlow::DataFlow::Node sink, + IRCommon::TestAllocationConfig cfg + | cfg.hasFlow(source, sink) and sourceLocation = source.getLocation() and sinkLocation = sink.getLocation() @@ -23,15 +27,12 @@ predicate irFlow(Location sourceLocation, Location sinkLocation) { } from Location sourceLocation, Location sinkLocation, string note -where - ( - astFlow(sourceLocation, sinkLocation) and - not irFlow(sourceLocation, sinkLocation) and - note = "AST only" - ) or - ( - irFlow(sourceLocation, sinkLocation) and - not astFlow(sourceLocation, sinkLocation) and - note = "IR only" - ) +where + astFlow(sourceLocation, sinkLocation) and + not irFlow(sourceLocation, sinkLocation) and + note = "AST only" + or + irFlow(sourceLocation, sinkLocation) and + not astFlow(sourceLocation, sinkLocation) and + note = "IR only" select sourceLocation.toString(), sinkLocation.toString(), note diff --git a/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql b/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql index ef2bead9129..fb94b0144b0 100644 --- a/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql +++ b/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql @@ -9,24 +9,22 @@ import semmle.code.cpp.dataflow.RecursionPrevention class TestConf1 extends DataFlow::Configuration { TestConf1() { this = "TestConf1" } - override - predicate isSource(DataFlow::Node source) { any() } - override - predicate isSink(DataFlow::Node sink) { any() } + + override predicate isSource(DataFlow::Node source) { any() } + + override predicate isSink(DataFlow::Node sink) { any() } } class TestConf2 extends DataFlow2::Configuration { TestConf2() { this = "TestConf2" } - override - predicate isSource(DataFlow::Node source) { + + override predicate isSource(DataFlow::Node source) { exists(TestConf1 conf1 | conf1.hasFlowTo(source)) } - override - predicate isSink(DataFlow::Node sink) { - exists(TestConf1 conf1 | conf1.hasFlowTo(sink)) - } - override - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + + override predicate isSink(DataFlow::Node sink) { exists(TestConf1 conf1 | conf1.hasFlowTo(sink)) } + + override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { exists(TestConf1 conf1 | conf1.hasFlowTo(n1) and conf1.hasFlowTo(n2) @@ -36,16 +34,14 @@ class TestConf2 extends DataFlow2::Configuration { class TestConf3 extends DataFlow3::Configuration { TestConf3() { this = "TestConf3" } - override - predicate isSource(DataFlow::Node source) { + + override predicate isSource(DataFlow::Node source) { exists(TestConf2 conf2 | conf2.hasFlowTo(source)) } - override - predicate isSink(DataFlow::Node sink) { - exists(TestConf2 conf2 | conf2.hasFlowTo(sink)) - } - override - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + + override predicate isSink(DataFlow::Node sink) { exists(TestConf2 conf2 | conf2.hasFlowTo(sink)) } + + override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { exists(TestConf2 conf2 | conf2.hasFlowTo(n1) and conf2.hasFlowTo(n2) @@ -55,16 +51,14 @@ class TestConf3 extends DataFlow3::Configuration { class TestConf4 extends DataFlow4::Configuration { TestConf4() { this = "TestConf4" } - override - predicate isSource(DataFlow::Node source) { + + override predicate isSource(DataFlow::Node source) { exists(TestConf3 conf3 | conf3.hasFlowTo(source)) } - override - predicate isSink(DataFlow::Node sink) { - exists(TestConf3 conf3 | conf3.hasFlowTo(sink)) - } - override - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + + override predicate isSink(DataFlow::Node sink) { exists(TestConf3 conf3 | conf3.hasFlowTo(sink)) } + + override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { exists(TestConf3 conf3 | conf3.hasFlowTo(n1) and conf3.hasFlowTo(n2) diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll b/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll index 4cc98bf698f..aa24c2629c7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/IRTaintTestCommon.qll @@ -3,9 +3,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking /** Common data flow configuration to be used by tests. */ class TestAllocationConfig extends TaintTracking::Configuration { - TestAllocationConfig() { - this = "TestAllocationConfig" - } + TestAllocationConfig() { this = "TestAllocationConfig" } override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/TaintTestCommon.qll b/cpp/ql/test/library-tests/dataflow/taint-tests/TaintTestCommon.qll index 61130992e8b..6588e8a5f3d 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/TaintTestCommon.qll +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/TaintTestCommon.qll @@ -3,9 +3,7 @@ import semmle.code.cpp.dataflow.TaintTracking /** Common data flow configuration to be used by tests. */ class TestAllocationConfig extends TaintTracking::Configuration { - TestAllocationConfig() { - this = "TestAllocationConfig" - } + TestAllocationConfig() { this = "TestAllocationConfig" } override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" @@ -26,4 +24,4 @@ class TestAllocationConfig extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node barrier) { barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer") } -} \ No newline at end of file +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.ql b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.ql index b49cd46d6a1..3e9aabe5190 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.ql +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.ql @@ -2,8 +2,7 @@ import cpp import semmle.code.cpp.dataflow.TaintTracking from DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string msg -where TaintTracking::localTaintStep(nodeFrom, nodeTo) - and if DataFlow::localFlowStep(nodeFrom, nodeTo) - then msg = "" - else msg = "TAINT" +where + TaintTracking::localTaintStep(nodeFrom, nodeTo) and + if DataFlow::localFlowStep(nodeFrom, nodeTo) then msg = "" else msg = "TAINT" select nodeFrom, nodeTo, msg diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.ql b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.ql index 7e6811f51dc..82b5723f9b4 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.ql +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.ql @@ -5,8 +5,10 @@ import semmle.code.cpp.dataflow.DataFlow as ASTDataFlow import semmle.code.cpp.ir.dataflow.DataFlow as IRDataFlow predicate astFlow(Location sourceLocation, Location sinkLocation) { - exists(ASTDataFlow::DataFlow::Node source, ASTDataFlow::DataFlow::Node sink, - ASTCommon::TestAllocationConfig cfg | + exists( + ASTDataFlow::DataFlow::Node source, ASTDataFlow::DataFlow::Node sink, + ASTCommon::TestAllocationConfig cfg + | cfg.hasFlow(source, sink) and sourceLocation = source.getLocation() and sinkLocation = sink.getLocation() @@ -14,8 +16,10 @@ predicate astFlow(Location sourceLocation, Location sinkLocation) { } predicate irFlow(Location sourceLocation, Location sinkLocation) { - exists(IRDataFlow::DataFlow::Node source, IRDataFlow::DataFlow::Node sink, - IRCommon::TestAllocationConfig cfg | + exists( + IRDataFlow::DataFlow::Node source, IRDataFlow::DataFlow::Node sink, + IRCommon::TestAllocationConfig cfg + | cfg.hasFlow(source, sink) and sourceLocation = source.getLocation() and sinkLocation = sink.getLocation() @@ -23,15 +27,12 @@ predicate irFlow(Location sourceLocation, Location sinkLocation) { } from Location sourceLocation, Location sinkLocation, string note -where - ( - astFlow(sourceLocation, sinkLocation) and - not irFlow(sourceLocation, sinkLocation) and - note = "AST only" - ) or - ( - irFlow(sourceLocation, sinkLocation) and - not astFlow(sourceLocation, sinkLocation) and - note = "IR only" - ) +where + astFlow(sourceLocation, sinkLocation) and + not irFlow(sourceLocation, sinkLocation) and + note = "AST only" + or + irFlow(sourceLocation, sinkLocation) and + not astFlow(sourceLocation, sinkLocation) and + note = "IR only" select sinkLocation.toString(), sourceLocation.toString(), note diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.ql b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.ql index 4debf88fe5b..45a1be4c476 100644 --- a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.ql +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/declarationEntry.ql @@ -1,8 +1,9 @@ import cpp from Declaration d, DeclarationEntry de, int i, int j -where (d.getADeclarationEntry() = de or de.getDeclaration() = d) -and if d.getADeclarationEntry() = de then i = 1 else i = 0 -and if de.getDeclaration() = d then j = 1 else j = 0 -and d.getLocation().getStartLine() != 0 +where + (d.getADeclarationEntry() = de or de.getDeclaration() = d) and + (if d.getADeclarationEntry() = de then i = 1 else i = 0) and + (if de.getDeclaration() = d then j = 1 else j = 0) and + d.getLocation().getStartLine() != 0 select d, de, i as getADeclarationEntry, j as getDeclaration diff --git a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.ql b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.ql index 292403b6769..7d120121e88 100644 --- a/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.ql +++ b/cpp/ql/test/library-tests/declarationEntry/declarationEntry/fde.ql @@ -1,6 +1,5 @@ import cpp from FunctionDeclarationEntry fde, string imp -where - if fde.isImplicit() then imp = "isImplicit" else imp = "" +where if fde.isImplicit() then imp = "isImplicit" else imp = "" select fde, imp diff --git a/cpp/ql/test/library-tests/declarationEntry/local/declarationEntry.ql b/cpp/ql/test/library-tests/declarationEntry/local/declarationEntry.ql index 9ba717edaa5..71d3797cb24 100644 --- a/cpp/ql/test/library-tests/declarationEntry/local/declarationEntry.ql +++ b/cpp/ql/test/library-tests/declarationEntry/local/declarationEntry.ql @@ -2,16 +2,10 @@ import cpp from Element e, string s where - ( - e instanceof DeclarationEntry or - e instanceof Declaration - ) and ( - e.getFile().toString() != "" - ) and ( - if e.(TypeDeclarationEntry).isTopLevel() then ( - s = "TopLevel" - ) else ( - s = "" - ) - ) + ( + e instanceof DeclarationEntry or + e instanceof Declaration + ) and + e.getFile().toString() != "" and + (if e.(TypeDeclarationEntry).isTopLevel() then s = "TopLevel" else s = "") select e, s diff --git a/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.ql b/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.ql index 99e71a8d4ba..8a77c36c95f 100644 --- a/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.ql +++ b/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.ql @@ -2,4 +2,3 @@ import cpp from DeclarationEntry de select de - diff --git a/cpp/ql/test/library-tests/declspec/guard/test.ql b/cpp/ql/test/library-tests/declspec/guard/test.ql index a37630f59cb..bb9fc4883e9 100644 --- a/cpp/ql/test/library-tests/declspec/guard/test.ql +++ b/cpp/ql/test/library-tests/declspec/guard/test.ql @@ -2,9 +2,9 @@ import cpp // What we select here isn't too important; we're just testing the // __declspec(guard(...)) attributes don't cause extractor errors. - from Function f, string p, int n -where if f.getNumberOfParameters() = 0 - then (p = "" and n = -1) +where + if f.getNumberOfParameters() = 0 + then p = "" and n = -1 else p = f.getParameter(n).toString() select f, n, p diff --git a/cpp/ql/test/library-tests/declstmt/getDeclaration.ql b/cpp/ql/test/library-tests/declstmt/getDeclaration.ql index 87711f2503d..b55b9cca1c4 100644 --- a/cpp/ql/test/library-tests/declstmt/getDeclaration.ql +++ b/cpp/ql/test/library-tests/declstmt/getDeclaration.ql @@ -2,4 +2,3 @@ import cpp from DeclStmt ds, int i select ds, i, ds.getDeclaration(i) - diff --git a/cpp/ql/test/library-tests/declstmt/getDeclarationEntry.ql b/cpp/ql/test/library-tests/declstmt/getDeclarationEntry.ql index 42416c0f3ab..077d86802e0 100644 --- a/cpp/ql/test/library-tests/declstmt/getDeclarationEntry.ql +++ b/cpp/ql/test/library-tests/declstmt/getDeclarationEntry.ql @@ -2,4 +2,3 @@ import cpp from DeclStmt ds, int i select ds, i, ds.getDeclarationEntry(i) - diff --git a/cpp/ql/test/library-tests/default_parameters/variables.ql b/cpp/ql/test/library-tests/default_parameters/variables.ql index 42b144e6917..885f60230fb 100644 --- a/cpp/ql/test/library-tests/default_parameters/variables.ql +++ b/cpp/ql/test/library-tests/default_parameters/variables.ql @@ -1,9 +1,7 @@ import cpp string istr(Initializer i) { - if exists(i.toString()) - then result = i.toString() - else result = "" + if exists(i.toString()) then result = i.toString() else result = "" } string iloc(Initializer i) { @@ -14,16 +12,15 @@ string iloc(Initializer i) { string init(Variable v) { if v.hasInitializer() - then exists(Initializer i | i = v.getInitializer() and - result = iloc(i) + " " + istr(i)) + then + exists(Initializer i | + i = v.getInitializer() and + result = iloc(i) + " " + istr(i) + ) else result = "" } -string estr(Expr e) { - if exists(e.toString()) - then result = e.toString() - else result = "" -} +string estr(Expr e) { if exists(e.toString()) then result = e.toString() else result = "" } string eloc(Expr e) { if exists(e.getLocation().toString()) @@ -33,11 +30,13 @@ string eloc(Expr e) { string assigned(Variable v) { if exists(v.getAnAssignedValue()) - then exists(Expr e | e = v.getAnAssignedValue() and - result = eloc(e) + " " + estr(e)) + then + exists(Expr e | + e = v.getAnAssignedValue() and + result = eloc(e) + " " + estr(e) + ) else result = "" } from Variable v select v, count(init(v)), init(v), count(assigned(v)), assigned(v) - diff --git a/cpp/ql/test/library-tests/defuse/definitionUsePairEquivalence.ql b/cpp/ql/test/library-tests/defuse/definitionUsePairEquivalence.ql index 077c4f26749..a84e397a97e 100644 --- a/cpp/ql/test/library-tests/defuse/definitionUsePairEquivalence.ql +++ b/cpp/ql/test/library-tests/defuse/definitionUsePairEquivalence.ql @@ -4,28 +4,23 @@ import semmle.code.cpp.controlflow.LocalScopeVariableReachability // Test that def/use algorithm is an instance of LocalScopeVariableReachability class MyDefOrUse extends LocalScopeVariableReachability { MyDefOrUse() { this = "MyDefUse" } - - override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { - definition(v, node) - } - - override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { - useOfVar(v, node) - } - + + override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { definition(v, node) } + + override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { useOfVar(v, node) } + override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) { definitionBarrier(v, node) } } predicate equivalence() { - forall(LocalScopeVariable v, Expr first, Expr second | - definitionUsePair(v, first, second) | + forall(LocalScopeVariable v, Expr first, Expr second | definitionUsePair(v, first, second) | exists(MyDefOrUse x | x.reaches(first, v, second)) - ) - and + ) and forall(LocalScopeVariable v, Expr first, Expr second | - exists(MyDefOrUse x | x.reaches(first, v, second)) | + exists(MyDefOrUse x | x.reaches(first, v, second)) + | definitionUsePair(v, first, second) ) } diff --git a/cpp/ql/test/library-tests/defuse/isAddressOfAccess.ql b/cpp/ql/test/library-tests/defuse/isAddressOfAccess.ql index 4fef4fbf0a2..4f61fa54997 100644 --- a/cpp/ql/test/library-tests/defuse/isAddressOfAccess.ql +++ b/cpp/ql/test/library-tests/defuse/isAddressOfAccess.ql @@ -2,10 +2,10 @@ import cpp from VariableAccess va, string description where - if va.isAddressOfAccessNonConst() then - description = "non-const address" - else if va.isAddressOfAccess() then - description = "const address" + if va.isAddressOfAccessNonConst() + then description = "non-const address" else - description = "" + if va.isAddressOfAccess() + then description = "const address" + else description = "" select va, description diff --git a/cpp/ql/test/library-tests/defuse/parameterUsePair.ql b/cpp/ql/test/library-tests/defuse/parameterUsePair.ql index 8d76ae7f024..d471a6a52cf 100644 --- a/cpp/ql/test/library-tests/defuse/parameterUsePair.ql +++ b/cpp/ql/test/library-tests/defuse/parameterUsePair.ql @@ -2,4 +2,4 @@ import cpp from Parameter p, VariableAccess va where parameterUsePair(p, va) -select p, va \ No newline at end of file +select p, va diff --git a/cpp/ql/test/library-tests/defuse/useOfVarActual.ql b/cpp/ql/test/library-tests/defuse/useOfVarActual.ql index ea99f0f5639..d3ce210f780 100644 --- a/cpp/ql/test/library-tests/defuse/useOfVarActual.ql +++ b/cpp/ql/test/library-tests/defuse/useOfVarActual.ql @@ -1,8 +1,9 @@ import cpp from LocalScopeVariable v, VariableAccess use -where useOfVarActual(v, use) -// Also check that `useOfVarActual` is a subset of `useOfVar`; if not -// the query will not return any results -and forall(LocalScopeVariable v0, VariableAccess use0 | useOfVarActual(v0, use0) | useOfVar(v0, use0)) -select v, use \ No newline at end of file +where + useOfVarActual(v, use) and + // Also check that `useOfVarActual` is a subset of `useOfVar`; if not + // the query will not return any results + forall(LocalScopeVariable v0, VariableAccess use0 | useOfVarActual(v0, use0) | useOfVar(v0, use0)) +select v, use diff --git a/cpp/ql/test/library-tests/depends_friends/Friend1.ql b/cpp/ql/test/library-tests/depends_friends/Friend1.ql index 0841a75eb79..dc2000db1df 100644 --- a/cpp/ql/test/library-tests/depends_friends/Friend1.ql +++ b/cpp/ql/test/library-tests/depends_friends/Friend1.ql @@ -2,6 +2,7 @@ * @name Friends1 * @description Check that a class depends on its friend class. */ + import cpp from MetricClass c, Class f1 diff --git a/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql b/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql index 4548c28525d..5446b48af6d 100644 --- a/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql +++ b/cpp/ql/test/library-tests/depends_initializers/InitializerAccesses.ql @@ -1,6 +1,7 @@ /** * @name InitializerAccesses */ + import cpp from Initializer i, VariableAccess va diff --git a/cpp/ql/test/library-tests/depends_initializers/InitializerCFG.ql b/cpp/ql/test/library-tests/depends_initializers/InitializerCFG.ql index 44444c62821..fdb42979dc5 100644 --- a/cpp/ql/test/library-tests/depends_initializers/InitializerCFG.ql +++ b/cpp/ql/test/library-tests/depends_initializers/InitializerCFG.ql @@ -1,14 +1,7 @@ import cpp -Function getCFGFunction(Initializer i) { - result = i.getASuccessor*() -} +Function getCFGFunction(Initializer i) { result = i.getASuccessor*() } from Initializer i, string f -where - if exists(getCFGFunction(i)) then ( - f = getCFGFunction(i).toString() - ) else ( - f = "" - ) +where if exists(getCFGFunction(i)) then f = getCFGFunction(i).toString() else f = "" select i, f diff --git a/cpp/ql/test/library-tests/depends_initializers/InitializerCalls.ql b/cpp/ql/test/library-tests/depends_initializers/InitializerCalls.ql index f37d8faca12..2fb9bf19bd8 100644 --- a/cpp/ql/test/library-tests/depends_initializers/InitializerCalls.ql +++ b/cpp/ql/test/library-tests/depends_initializers/InitializerCalls.ql @@ -1,6 +1,7 @@ /** * @name InitializerCalls */ + import cpp from Initializer i, FunctionCall fc diff --git a/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql b/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql index 53db8f9f22c..eb4aa50d3a4 100644 --- a/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql +++ b/cpp/ql/test/library-tests/derived_types/DerivedTypesBaseType.ql @@ -1,6 +1,6 @@ import cpp -//this query should find the baseType of CC* to be CC, not C. +//this query should find the baseType of CC* to be CC, not C. from DerivedType t, Type baseType where t.getBaseType() = baseType select t, baseType diff --git a/cpp/ql/test/library-tests/destructors/cfg.ql b/cpp/ql/test/library-tests/destructors/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/destructors/cfg.ql +++ b/cpp/ql/test/library-tests/destructors/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/destructors/jump_destructs.ql b/cpp/ql/test/library-tests/destructors/jump_destructs.ql index a805162955f..b1722fe6ee7 100644 --- a/cpp/ql/test/library-tests/destructors/jump_destructs.ql +++ b/cpp/ql/test/library-tests/destructors/jump_destructs.ql @@ -1,22 +1,18 @@ import cpp ControlFlowNode getANonLabelSuccessor(ControlFlowNode n) { - n.getASuccessor() = result and not result instanceof LabelStmt + n.getASuccessor() = result and not result instanceof LabelStmt } class Jump extends Locatable { - Jump() { - this instanceof GotoStmt or - this instanceof ReturnStmt - } + Jump() { + this instanceof GotoStmt or + this instanceof ReturnStmt + } } from Jump j, ControlFlowNode n where getANonLabelSuccessor+(j) = n -select j.(ControlFlowNode).getControlFlowScope(), - j.getLocation().getStartLine(), - j.toString(), - count(n.getAPredecessor*()), // Improves the output's sort order - n.getLocation().getStartLine(), - n.toString() - +select j.(ControlFlowNode).getControlFlowScope(), j.getLocation().getStartLine(), j.toString(), + count(n.getAPredecessor*()), // Improves the output's sort order + n.getLocation().getStartLine(), n.toString() diff --git a/cpp/ql/test/library-tests/enums/enums/Enums1.ql b/cpp/ql/test/library-tests/enums/enums/Enums1.ql index af544276768..d707dbc9198 100644 --- a/cpp/ql/test/library-tests/enums/enums/Enums1.ql +++ b/cpp/ql/test/library-tests/enums/enums/Enums1.ql @@ -1,11 +1,12 @@ import cpp string declaringEnum(EnumConstant c) { - if exists(c.getDeclaringEnum().toString()) - then result = c.getDeclaringEnum().toString() - else result = "" + if exists(c.getDeclaringEnum().toString()) + then result = c.getDeclaringEnum().toString() + else result = "" } from EnumConstant c, string cName where c.hasName(cName) -select c, cName, count(c.getDeclaringEnum()), declaringEnum(c), count(c.getLocation()), count(c.getDefinitionLocation()), count(c.getADeclarationLocation()) +select c, cName, count(c.getDeclaringEnum()), declaringEnum(c), count(c.getLocation()), + count(c.getDefinitionLocation()), count(c.getADeclarationLocation()) diff --git a/cpp/ql/test/library-tests/enums/enums/Enums2.ql b/cpp/ql/test/library-tests/enums/enums/Enums2.ql index d970520119a..d15a4070e2e 100644 --- a/cpp/ql/test/library-tests/enums/enums/Enums2.ql +++ b/cpp/ql/test/library-tests/enums/enums/Enums2.ql @@ -2,6 +2,7 @@ * @name Enums2 * @kind table */ + import cpp from EnumConstantAccess a, string name diff --git a/cpp/ql/test/library-tests/enums/enums/Enums3.ql b/cpp/ql/test/library-tests/enums/enums/Enums3.ql index d1c6ba9ac84..a07a205a2bb 100644 --- a/cpp/ql/test/library-tests/enums/enums/Enums3.ql +++ b/cpp/ql/test/library-tests/enums/enums/Enums3.ql @@ -1,17 +1,14 @@ import cpp -string describe(Enum e) -{ - ( - e instanceof LocalEnum and - result = "LocalEnum" - ) or ( - e instanceof NestedEnum and - result = "NestedEnum" - ) or ( - e instanceof ScopedEnum and - result = "ScopedEnum" - ) +string describe(Enum e) { + e instanceof LocalEnum and + result = "LocalEnum" + or + e instanceof NestedEnum and + result = "NestedEnum" + or + e instanceof ScopedEnum and + result = "ScopedEnum" } from Enum e diff --git a/cpp/ql/test/library-tests/enums/multi_file/enumConstant.ql b/cpp/ql/test/library-tests/enums/multi_file/enumConstant.ql index c065bbf05b3..0e1378fe57d 100644 --- a/cpp/ql/test/library-tests/enums/multi_file/enumConstant.ql +++ b/cpp/ql/test/library-tests/enums/multi_file/enumConstant.ql @@ -2,4 +2,3 @@ import cpp from EnumConstant e select e - diff --git a/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql b/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql index 0721c873275..591799ed4e5 100644 --- a/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql +++ b/cpp/ql/test/library-tests/exprs/comparison_operation/comparison_operation.ql @@ -2,25 +2,23 @@ import cpp from ComparisonOperation co, string s where - ( - co instanceof EqualityOperation and s = "EqualityOperation" - ) or ( - co instanceof EQExpr and s = "EQExpr" - ) or ( - co instanceof NEExpr and s = "NEExpr" - ) or ( - co instanceof RelationalOperation and s = "RelationalOperation" - ) or ( - s = "getGreaterOperand() = " + co.(RelationalOperation).getGreaterOperand().toString() - ) or ( - s = "getLesserOperand() = " + co.(RelationalOperation).getLesserOperand().toString() - ) or ( - co instanceof GTExpr and s = "GTExpr" - ) or ( - co instanceof LTExpr and s = "LTExpr" - ) or ( - co instanceof GEExpr and s = "GEExpr" - ) or ( - co instanceof LEExpr and s = "LEExpr" - ) + co instanceof EqualityOperation and s = "EqualityOperation" + or + co instanceof EQExpr and s = "EQExpr" + or + co instanceof NEExpr and s = "NEExpr" + or + co instanceof RelationalOperation and s = "RelationalOperation" + or + s = "getGreaterOperand() = " + co.(RelationalOperation).getGreaterOperand().toString() + or + s = "getLesserOperand() = " + co.(RelationalOperation).getLesserOperand().toString() + or + co instanceof GTExpr and s = "GTExpr" + or + co instanceof LTExpr and s = "LTExpr" + or + co instanceof GEExpr and s = "GEExpr" + or + co instanceof LEExpr and s = "LEExpr" select co, s diff --git a/cpp/ql/test/library-tests/exprs/min_max/expr.ql b/cpp/ql/test/library-tests/exprs/min_max/expr.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/exprs/min_max/expr.ql +++ b/cpp/ql/test/library-tests/exprs/min_max/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql b/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql index 6d39dae47bd..af99b7d4712 100644 --- a/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql +++ b/cpp/ql/test/library-tests/exprs/unary_operation/unary_operation.ql @@ -1,36 +1,33 @@ import cpp -predicate describe(UnaryOperation uo, string s) -{ - ( - uo instanceof UnaryArithmeticOperation and s = "UnaryArithmeticOperation" - ) or ( - uo instanceof UnaryMinusExpr and s = "UnaryMinusExpr" - ) or ( - uo instanceof UnaryPlusExpr and s = "UnaryPlusExpr" - ) or ( - uo instanceof ConjugationExpr and s = "ConjugationExpr" - ) or ( - uo instanceof CrementOperation and s = "CrementOperation" - ) or ( - uo instanceof IncrementOperation and s = "IncrementOperation" - ) or ( - uo instanceof DecrementOperation and s = "DecrementOperation" - ) or ( - uo instanceof PrefixCrementOperation and s = "PrefixCrementOperation" - ) or ( - uo instanceof PostfixCrementOperation and s = "PostfixCrementOperation" - ) or ( - uo instanceof AddressOfExpr and s = "AddressOfExpr" - ) or ( - s = "getAddressable() = " + uo.(AddressOfExpr).getAddressable().toString() - ) or ( - uo instanceof PointerDereferenceExpr and s = "PointerDereferenceExpr" - ) or ( - uo instanceof UnaryLogicalOperation and s = "UnaryLogicalOperation" - ) or ( - uo instanceof NotExpr and s = "NotExpr" - ) +predicate describe(UnaryOperation uo, string s) { + uo instanceof UnaryArithmeticOperation and s = "UnaryArithmeticOperation" + or + uo instanceof UnaryMinusExpr and s = "UnaryMinusExpr" + or + uo instanceof UnaryPlusExpr and s = "UnaryPlusExpr" + or + uo instanceof ConjugationExpr and s = "ConjugationExpr" + or + uo instanceof CrementOperation and s = "CrementOperation" + or + uo instanceof IncrementOperation and s = "IncrementOperation" + or + uo instanceof DecrementOperation and s = "DecrementOperation" + or + uo instanceof PrefixCrementOperation and s = "PrefixCrementOperation" + or + uo instanceof PostfixCrementOperation and s = "PostfixCrementOperation" + or + uo instanceof AddressOfExpr and s = "AddressOfExpr" + or + s = "getAddressable() = " + uo.(AddressOfExpr).getAddressable().toString() + or + uo instanceof PointerDereferenceExpr and s = "PointerDereferenceExpr" + or + uo instanceof UnaryLogicalOperation and s = "UnaryLogicalOperation" + or + uo instanceof NotExpr and s = "NotExpr" } from UnaryOperation uo diff --git a/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql b/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql index 8bc52c55022..203c9bcb613 100644 --- a/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql +++ b/cpp/ql/test/library-tests/exprs/value_categories/value_categories.ql @@ -2,6 +2,7 @@ import cpp from Expr e, string valcat where - e.isLValueCategory() and valcat = "lvalue" or + e.isLValueCategory() and valcat = "lvalue" + or e.isXValueCategory() and valcat = "xvalue" select e, e.getType().toString(), valcat diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic1.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic1.ql index 7f40302b324..8a67bd0a82e 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic1.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic1.ql @@ -1,7 +1,5 @@ import cpp from Function f -select f, - count(Literal l | l.getEnclosingFunction() = f), - count(ArrayToPointerConversion c | c.getEnclosingFunction() = f) - +select f, count(Literal l | l.getEnclosingFunction() = f), + count(ArrayToPointerConversion c | c.getEnclosingFunction() = f) diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic3.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic3.ql index 80f40af2ba1..57f24c0419e 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic3.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic3.ql @@ -2,12 +2,13 @@ * @name ExprsBasic3 * @kind table */ + import cpp from Function f, FieldAccess fa -where f.hasName("create_foo") - and fa.getEnclosingFunction() = f - and fa.getTarget().getDeclaringType().hasName("Foo") - and fa.getTarget().hasName("name") +where + f.hasName("create_foo") and + fa.getEnclosingFunction() = f and + fa.getTarget().getDeclaringType().hasName("Foo") and + fa.getTarget().hasName("name") select f, fa, fa.getTarget() - diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic4.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic4.ql index ea892a768d1..b5c838cde3d 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic4.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic4.ql @@ -2,14 +2,12 @@ * @name ExprsBasic4 * @kind table */ + import cpp from Field f, string fname, string ftype -where f.hasName(fname) - and f.getDeclaringType().hasName(ftype) - and exists(f.getAnAccess()) +where + f.hasName(fname) and + f.getDeclaringType().hasName(ftype) and + exists(f.getAnAccess()) select f, fname, f.getDeclaringType(), ftype, f.getAnAccess() - - - - diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic5.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic5.ql index d212c67121b..f3e708d6394 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic5.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic5.ql @@ -2,14 +2,13 @@ * @name ExprsBasic5 * @kind table */ + import cpp from Function f, VariableAccess va, GlobalVariable v -where f.hasName("set_current_foo") - and va.getEnclosingFunction() = f - and v.hasName("current_foo") - and va.getTarget() = v +where + f.hasName("set_current_foo") and + va.getEnclosingFunction() = f and + v.hasName("current_foo") and + va.getTarget() = v select va - - - diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic7.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic7.ql index ecfc166233e..69f1643b1fe 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic7.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic7.ql @@ -2,12 +2,11 @@ * @name ExprsBasic7 * @kind table */ + import cpp from AssignExpr e -where e.getEnclosingFunction().hasName("create_foo") - and e.getLValue() instanceof FieldAccess +where + e.getEnclosingFunction().hasName("create_foo") and + e.getLValue() instanceof FieldAccess select e, e.getLValue() - - - diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic8.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic8.ql index 8b8a0c51e90..8479215e8e0 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic8.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic8.ql @@ -2,12 +2,11 @@ * @name ExprsBasic8 * @kind table */ + import cpp from AssignExpr e -where e.getEnclosingFunction().hasName("create_foo") - and e.getRValue() instanceof Literal +where + e.getEnclosingFunction().hasName("create_foo") and + e.getRValue() instanceof Literal select e, e.getRValue() - - - diff --git a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic9.ql b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic9.ql index 9fc39a36d45..598bc630058 100644 --- a/cpp/ql/test/library-tests/exprs_basic/ExprsBasic9.ql +++ b/cpp/ql/test/library-tests/exprs_basic/ExprsBasic9.ql @@ -3,4 +3,3 @@ import cpp from AssignExpr e, int i where exists(e.getChild(i)) select e, i - diff --git a/cpp/ql/test/library-tests/exprs_cast/ExprsCast1.ql b/cpp/ql/test/library-tests/exprs_cast/ExprsCast1.ql index e0781299754..4b9c8702acb 100644 --- a/cpp/ql/test/library-tests/exprs_cast/ExprsCast1.ql +++ b/cpp/ql/test/library-tests/exprs_cast/ExprsCast1.ql @@ -2,6 +2,7 @@ * @name ExprsCast1 * @kind table */ + import cpp from Cast c diff --git a/cpp/ql/test/library-tests/exprs_cast/ExprsCast2.ql b/cpp/ql/test/library-tests/exprs_cast/ExprsCast2.ql index a27a8a17234..631a539d36c 100644 --- a/cpp/ql/test/library-tests/exprs_cast/ExprsCast2.ql +++ b/cpp/ql/test/library-tests/exprs_cast/ExprsCast2.ql @@ -2,18 +2,18 @@ * @name ExprsCast2 * @kind table */ + import cpp string exprString(Expr e) { - if (e instanceof ArrayToPointerConversion) then ( - result = e.(ArrayToPointerConversion).getExpr().(Literal).getValue() - ) else ( - result = e.toString() - ) + if e instanceof ArrayToPointerConversion + then result = e.(ArrayToPointerConversion).getExpr().(Literal).getValue() + else result = e.toString() } from Cast c, Type cType, string cTypeName, string toStruct -where cType = c.getType() - and cType.hasName(cTypeName) - and if cType instanceof Struct then toStruct = "struct" else toStruct = "" +where + cType = c.getType() and + cType.hasName(cTypeName) and + if cType instanceof Struct then toStruct = "struct" else toStruct = "" select c, exprString(c.getExpr()), c.getExpr().getType().toString(), cTypeName, toStruct diff --git a/cpp/ql/test/library-tests/fields/fields/EnumConst.ql b/cpp/ql/test/library-tests/fields/fields/EnumConst.ql index 5a7bf1686c0..e8a1171489d 100644 --- a/cpp/ql/test/library-tests/fields/fields/EnumConst.ql +++ b/cpp/ql/test/library-tests/fields/fields/EnumConst.ql @@ -2,10 +2,14 @@ * @name EnumConst * @kind table */ + import cpp from Enum e, Declaration c, string reason -where (c.(EnumConstant).getDeclaringEnum() = e and reason = "getDeclaringEnum()") or - (c.(EnumConstant).getType() = e and reason = "getType()") or - (c.(Field).getDeclaringType() = e and reason = "getDeclaringType()") +where + c.(EnumConstant).getDeclaringEnum() = e and reason = "getDeclaringEnum()" + or + c.(EnumConstant).getType() = e and reason = "getType()" + or + c.(Field).getDeclaringType() = e and reason = "getDeclaringType()" select e, c, reason diff --git a/cpp/ql/test/library-tests/fields/fields/Fields.ql b/cpp/ql/test/library-tests/fields/fields/Fields.ql index 7bade61799c..28948b148e3 100644 --- a/cpp/ql/test/library-tests/fields/fields/Fields.ql +++ b/cpp/ql/test/library-tests/fields/fields/Fields.ql @@ -2,6 +2,7 @@ * @name Fields * @kind table */ + import cpp predicate nameCheck(Declaration d) { @@ -11,9 +12,11 @@ predicate nameCheck(Declaration d) { } string accessType(Field f) { - (f.isPublic() and result = "public") or - (f.isProtected() and result = "protected") or - (f.isPrivate() and result = "private") + f.isPublic() and result = "public" + or + f.isProtected() and result = "protected" + or + f.isPrivate() and result = "private" } string fieldType(Field f) { @@ -25,16 +28,15 @@ string fieldType(Field f) { } string pointedType(Field f) { - if f.getType() instanceof PointerType then ( - result = f.getType().(PointerType).getBaseType().toString() - ) else ( - result = "" - ) + if f.getType() instanceof PointerType + then result = f.getType().(PointerType).getBaseType().toString() + else result = "" } from Class c, Field f -where f.getDeclaringType() = c and - c.getAField() = f and - nameCheck(c) and - nameCheck(f) +where + f.getDeclaringType() = c and + c.getAField() = f and + nameCheck(c) and + nameCheck(f) select c, f, accessType(f), fieldType(f), pointedType(f) diff --git a/cpp/ql/test/library-tests/fields/fields/MemberVariable.ql b/cpp/ql/test/library-tests/fields/fields/MemberVariable.ql index f6e6c513996..8e715c497f0 100644 --- a/cpp/ql/test/library-tests/fields/fields/MemberVariable.ql +++ b/cpp/ql/test/library-tests/fields/fields/MemberVariable.ql @@ -2,6 +2,7 @@ * @name MemberVariable * @kind table */ + import cpp from MemberVariable m, string static diff --git a/cpp/ql/test/library-tests/fields/segfault/exprs.ql b/cpp/ql/test/library-tests/fields/segfault/exprs.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/fields/segfault/exprs.ql +++ b/cpp/ql/test/library-tests/fields/segfault/exprs.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/files/Files1.ql b/cpp/ql/test/library-tests/files/Files1.ql index 7757119cb10..a4db35de1b8 100644 --- a/cpp/ql/test/library-tests/files/Files1.ql +++ b/cpp/ql/test/library-tests/files/Files1.ql @@ -2,4 +2,3 @@ import cpp from HeaderFile f select f, f.getATopLevelDeclaration() - diff --git a/cpp/ql/test/library-tests/files/Files2.ql b/cpp/ql/test/library-tests/files/Files2.ql index 30bd7867224..b87a06b9761 100644 --- a/cpp/ql/test/library-tests/files/Files2.ql +++ b/cpp/ql/test/library-tests/files/Files2.ql @@ -1,18 +1,11 @@ import cpp -string isCompiledAsC(File f) { - if f.compiledAsC() then result = "C" else result = "-" -} +string isCompiledAsC(File f) { if f.compiledAsC() then result = "C" else result = "-" } -string isCompiledAsCpp(File f) { - if f.compiledAsCpp() then result = "C++" else result = "---" -} +string isCompiledAsCpp(File f) { if f.compiledAsCpp() then result = "C++" else result = "---" } from File f // On 64bit Linux, __va_list_tag is in the unknown file (""). Ignore it. where f.getAbsolutePath() != "" -select (f.getAQlClass().toString() + " ").prefix(10), - isCompiledAsC(f), - isCompiledAsCpp(f), - f.toString() - +select (f.getAQlClass().toString() + " ").prefix(10), isCompiledAsC(f), isCompiledAsCpp(f), + f.toString() diff --git a/cpp/ql/test/library-tests/files/Files3.ql b/cpp/ql/test/library-tests/files/Files3.ql index f51f85b6dbb..9d8d2ffc83c 100644 --- a/cpp/ql/test/library-tests/files/Files3.ql +++ b/cpp/ql/test/library-tests/files/Files3.ql @@ -1,6 +1,7 @@ import cpp from File f, Declaration d -where d = f.getATopLevelDeclaration() - and d.getName() != "__va_list_tag" +where + d = f.getATopLevelDeclaration() and + d.getName() != "__va_list_tag" select f.toString(), d diff --git a/cpp/ql/test/library-tests/floats/float128/usertypes.ql b/cpp/ql/test/library-tests/floats/float128/usertypes.ql index 81584d7b2d8..d3677562532 100644 --- a/cpp/ql/test/library-tests/floats/float128/usertypes.ql +++ b/cpp/ql/test/library-tests/floats/float128/usertypes.ql @@ -1,6 +1,7 @@ import cpp from UserType t, Type related -where related = ((Class)t).getABaseClass() - or related = ((TypedefType)t).getUnderlyingType() +where + related = t.(Class).getABaseClass() or + related = t.(TypedefType).getUnderlyingType() select t, related diff --git a/cpp/ql/test/library-tests/floats/floats/floats.ql b/cpp/ql/test/library-tests/floats/floats/floats.ql index 0381fa4af8c..d3ccc151cb2 100644 --- a/cpp/ql/test/library-tests/floats/floats/floats.ql +++ b/cpp/ql/test/library-tests/floats/floats/floats.ql @@ -1,23 +1,24 @@ import cpp string displayExpr(Expr e) { - if e instanceof UnaryMinusExpr - then result = "-" + displayExpr(((UnaryMinusExpr)e).getOperand()) - else result = e.toString() + if e instanceof UnaryMinusExpr + then result = "-" + displayExpr(e.(UnaryMinusExpr).getOperand()) + else result = e.toString() } string displayPortableExpr(Expr e) { - exists(string displayed | displayed = displayExpr(e) | - if displayed.length() < 5 - then result = displayed - else // If the calculated value is long, then it's probably got - // lots of precision, and the least significant digits may - // vary depending on the machine. So just show the original - // source value, as well as an indication that that's what - // we're doing. - result = "src: " + e.getValueText()) + exists(string displayed | displayed = displayExpr(e) | + if displayed.length() < 5 + then result = displayed + else + // If the calculated value is long, then it's probably got + // lots of precision, and the least significant digits may + // vary depending on the machine. So just show the original + // source value, as well as an indication that that's what + // we're doing. + result = "src: " + e.getValueText() + ) } from Variable v select v, displayPortableExpr(v.getInitializer().getExpr()) - diff --git a/cpp/ql/test/library-tests/friends/friends/instantiated_template_class.ql b/cpp/ql/test/library-tests/friends/friends/instantiated_template_class.ql index 204a2493b19..9188dcdd255 100644 --- a/cpp/ql/test/library-tests/friends/friends/instantiated_template_class.ql +++ b/cpp/ql/test/library-tests/friends/friends/instantiated_template_class.ql @@ -2,5 +2,5 @@ import cpp from Class c where c.getName().matches("SelfFriendlyTemplate<__%>") -select c.toString() as parent, c.getAFriendDecl().getFriend().toString() as friend -order by parent, friend +select c.toString() as parent, c.getAFriendDecl().getFriend().toString() as friend order by + parent, friend diff --git a/cpp/ql/test/library-tests/friends/friends/nesting.ql b/cpp/ql/test/library-tests/friends/friends/nesting.ql index 320e37c1809..2d33db4337e 100644 --- a/cpp/ql/test/library-tests/friends/friends/nesting.ql +++ b/cpp/ql/test/library-tests/friends/friends/nesting.ql @@ -5,6 +5,7 @@ int relativeLine(Locatable first, Locatable second) { } from Class c, FriendDecl d -where c.getName().matches("Outer%") - and d = c.getAFriendDecl() +where + c.getName().matches("Outer%") and + d = c.getAFriendDecl() select c.toString(), d.getFriend().toString(), relativeLine(c, d) diff --git a/cpp/ql/test/library-tests/function_try_stmt/function_try_stmt.ql b/cpp/ql/test/library-tests/function_try_stmt/function_try_stmt.ql index 664d8c6e5da..fb30ed12578 100644 --- a/cpp/ql/test/library-tests/function_try_stmt/function_try_stmt.ql +++ b/cpp/ql/test/library-tests/function_try_stmt/function_try_stmt.ql @@ -1,6 +1,4 @@ import cpp from FunctionTryStmt fts -select fts, - fts.getEnclosingFunction() as f, - f.getBlock().getAStmt() +select fts, fts.getEnclosingFunction() as f, f.getBlock().getAStmt() diff --git a/cpp/ql/test/library-tests/functionpointerish/functionpointerish.ql b/cpp/ql/test/library-tests/functionpointerish/functionpointerish.ql index b662884ea56..2a0c25e2a5e 100644 --- a/cpp/ql/test/library-tests/functionpointerish/functionpointerish.ql +++ b/cpp/ql/test/library-tests/functionpointerish/functionpointerish.ql @@ -1,8 +1,5 @@ import cpp from FunctionPointerIshType t -select t.toString(), - t.getReturnType().toString(), - t.getNumberOfParameters(), - t.getAParameterType().toString() - +select t.toString(), t.getReturnType().toString(), t.getNumberOfParameters(), + t.getAParameterType().toString() diff --git a/cpp/ql/test/library-tests/functions/arguments/arguments.ql b/cpp/ql/test/library-tests/functions/arguments/arguments.ql index f1cd4869724..82283fdf397 100644 --- a/cpp/ql/test/library-tests/functions/arguments/arguments.ql +++ b/cpp/ql/test/library-tests/functions/arguments/arguments.ql @@ -2,4 +2,3 @@ import cpp from FunctionCall fc, int i select fc, i, fc.getArgument(i) - diff --git a/cpp/ql/test/library-tests/functions/arguments/num_arguments.ql b/cpp/ql/test/library-tests/functions/arguments/num_arguments.ql index caedc1b5bc0..fe41964583f 100644 --- a/cpp/ql/test/library-tests/functions/arguments/num_arguments.ql +++ b/cpp/ql/test/library-tests/functions/arguments/num_arguments.ql @@ -2,4 +2,3 @@ import cpp from FunctionCall fc select fc, fc.getNumberOfArguments() - diff --git a/cpp/ql/test/library-tests/functions/constexpr/constexpr.ql b/cpp/ql/test/library-tests/functions/constexpr/constexpr.ql index ccf8dbb4cf7..e7215763365 100644 --- a/cpp/ql/test/library-tests/functions/constexpr/constexpr.ql +++ b/cpp/ql/test/library-tests/functions/constexpr/constexpr.ql @@ -3,5 +3,5 @@ import semmle.code.cpp.Print from Function f select f, getIdentityString(f), - any(boolean b | if f.isDeclaredConstexpr() then b = true else b = false), - any(boolean b | if f.isConstexpr() then b = true else b = false) + any(boolean b | if f.isDeclaredConstexpr() then b = true else b = false), + any(boolean b | if f.isConstexpr() then b = true else b = false) diff --git a/cpp/ql/test/library-tests/functions/functions/Functions1.ql b/cpp/ql/test/library-tests/functions/functions/Functions1.ql index bcb1d736bb8..22d5b0895c7 100644 --- a/cpp/ql/test/library-tests/functions/functions/Functions1.ql +++ b/cpp/ql/test/library-tests/functions/functions/Functions1.ql @@ -1,14 +1,16 @@ /** * @name Functions1 */ + import cpp from Function f, string top1, string top2, Location loc, string loctype where - if f.isTopLevel() then top1 = "isTopLevel" else top1 = "" and - if f instanceof TopLevelFunction then top2 = "TopLevelFunction" else top2 = "" and - ( - (loc = f.getADeclarationLocation() and loctype = "declaration") or - (loc = f.getDefinitionLocation() and loctype = "definition") - ) + (if f.isTopLevel() then top1 = "isTopLevel" else top1 = "") and + (if f instanceof TopLevelFunction then top2 = "TopLevelFunction" else top2 = "") and + ( + loc = f.getADeclarationLocation() and loctype = "declaration" + or + loc = f.getDefinitionLocation() and loctype = "definition" + ) select f, f.getName(), top1, top2, loc.toString(), loctype diff --git a/cpp/ql/test/library-tests/functions/functions/Functions2.ql b/cpp/ql/test/library-tests/functions/functions/Functions2.ql index 86d9d6e9f1a..6cf558e54a9 100644 --- a/cpp/ql/test/library-tests/functions/functions/Functions2.ql +++ b/cpp/ql/test/library-tests/functions/functions/Functions2.ql @@ -2,43 +2,41 @@ * @name Functions2 * @kind table */ + import cpp -bindingset[c, f] string describe(Class c, MemberFunction f) -{ - ( - f = c.getAConstructor() and - result = "getAConstructor()" - ) or ( - f = c.getDestructor() and - result = "getDestructor()" - ) or ( - f instanceof Constructor and - result = "Constructor" - ) or ( - f instanceof Destructor and - result = "Destructor" - ) or ( - f instanceof ConversionConstructor and - result = "ConversionConstructor" - ) or ( - f instanceof CopyConstructor and - result = "CopyConstructor" - ) or ( - f instanceof MoveConstructor and - result = "MoveConstructor" - ) or ( - f instanceof NoArgConstructor and - result = "NoArgConstructor" - ) or ( - f instanceof ConversionOperator and - result = "ConversionOperator" - ) +bindingset[c, f] +string describe(Class c, MemberFunction f) { + f = c.getAConstructor() and + result = "getAConstructor()" + or + f = c.getDestructor() and + result = "getDestructor()" + or + f instanceof Constructor and + result = "Constructor" + or + f instanceof Destructor and + result = "Destructor" + or + f instanceof ConversionConstructor and + result = "ConversionConstructor" + or + f instanceof CopyConstructor and + result = "CopyConstructor" + or + f instanceof MoveConstructor and + result = "MoveConstructor" + or + f instanceof NoArgConstructor and + result = "NoArgConstructor" + or + f instanceof ConversionOperator and + result = "ConversionOperator" } from Class c, string ctype, MemberFunction f where - f.getDeclaringType() = c and - if c instanceof Struct then ctype = "Struct" else ctype = "Class" -select - c, ctype, f, concat(describe(c, f), ", ") + f.getDeclaringType() = c and + if c instanceof Struct then ctype = "Struct" else ctype = "Class" +select c, ctype, f, concat(describe(c, f), ", ") diff --git a/cpp/ql/test/library-tests/functions/getathrowntype/getAThrownType.ql b/cpp/ql/test/library-tests/functions/getathrowntype/getAThrownType.ql index 92b5aa397be..f1ec943d658 100644 --- a/cpp/ql/test/library-tests/functions/getathrowntype/getAThrownType.ql +++ b/cpp/ql/test/library-tests/functions/getathrowntype/getAThrownType.ql @@ -1,13 +1,11 @@ import cpp string describe(Function f) { - ( - f.isNoThrow() and - result = "isNoThrow" - ) or ( - f.isNoExcept() and - result = "isNoExcept" - ) + f.isNoThrow() and + result = "isNoThrow" + or + f.isNoExcept() and + result = "isNoExcept" } from Function f diff --git a/cpp/ql/test/library-tests/identifiers/qualified_names/unnamed.ql b/cpp/ql/test/library-tests/identifiers/qualified_names/unnamed.ql index 866035f0ebb..ce1b7403758 100644 --- a/cpp/ql/test/library-tests/identifiers/qualified_names/unnamed.ql +++ b/cpp/ql/test/library-tests/identifiers/qualified_names/unnamed.ql @@ -1,5 +1,4 @@ // This query lists the declarations that don't have a qualified name - import cpp from Declaration d diff --git a/cpp/ql/test/library-tests/identity_string/identity_string.ql b/cpp/ql/test/library-tests/identity_string/identity_string.ql index 540043d7621..c663bc6d89b 100644 --- a/cpp/ql/test/library-tests/identity_string/identity_string.ql +++ b/cpp/ql/test/library-tests/identity_string/identity_string.ql @@ -8,7 +8,8 @@ abstract class CheckCall extends FunctionCall { exists(int lastArgIndex | lastArgIndex = getNumberOfArguments() - 1 and ( - result = getArgument(lastArgIndex).getValue() or + result = getArgument(lastArgIndex).getValue() + or not exists(getArgument(lastArgIndex).getValue()) and result = "" ) ) @@ -23,17 +24,14 @@ class CheckTypeCall extends CheckCall { } override string getActualString() { - result = getTypeIdentityString(getSpecifiedType()) or + result = getTypeIdentityString(getSpecifiedType()) + or not exists(getTypeIdentityString(getSpecifiedType())) and result = "" } - override string explain() { - result = getSpecifiedType().explain() - } + override string explain() { result = getSpecifiedType().explain() } - final Type getSpecifiedType() { - result = getTarget().getTemplateArgument(0) - } + final Type getSpecifiedType() { result = getTarget().getTemplateArgument(0) } } class CheckFuncCall extends CheckCall { @@ -42,17 +40,14 @@ class CheckFuncCall extends CheckCall { } override string getActualString() { - result = getIdentityString(getSpecifiedFunction()) or + result = getIdentityString(getSpecifiedFunction()) + or not exists(getIdentityString(getSpecifiedFunction())) and result = "" } - override string explain() { - result = getSpecifiedFunction().toString() - } + override string explain() { result = getSpecifiedFunction().toString() } - final Function getSpecifiedFunction() { - result = getArgument(0).(FunctionAccess).getTarget() - } + final Function getSpecifiedFunction() { result = getArgument(0).(FunctionAccess).getTarget() } } class CheckVarCall extends CheckCall { @@ -61,17 +56,14 @@ class CheckVarCall extends CheckCall { } override string getActualString() { - result = getIdentityString(getSpecifiedVariable()) or + result = getIdentityString(getSpecifiedVariable()) + or not exists(getIdentityString(getSpecifiedVariable())) and result = "" } - override string explain() { - result = getSpecifiedVariable().toString() - } + override string explain() { result = getSpecifiedVariable().toString() } - final Variable getSpecifiedVariable() { - result = getArgument(0).(VariableAccess).getTarget() - } + final Variable getSpecifiedVariable() { result = getArgument(0).(VariableAccess).getTarget() } } bindingset[s] @@ -80,7 +72,7 @@ private string normalizeLambdas(string s) { } from CheckCall call, string expected, string actual -where +where expected = call.getExpectedString() and actual = normalizeLambdas(call.getActualString()) and expected != actual diff --git a/cpp/ql/test/library-tests/includes/include_next/includes.ql b/cpp/ql/test/library-tests/includes/include_next/includes.ql index 9f32e2fa669..03c9663428f 100644 --- a/cpp/ql/test/library-tests/includes/include_next/includes.ql +++ b/cpp/ql/test/library-tests/includes/include_next/includes.ql @@ -2,4 +2,3 @@ import cpp from Include i select i, i.getIncludedFile() - diff --git a/cpp/ql/test/library-tests/includes/includes/locations.ql b/cpp/ql/test/library-tests/includes/includes/locations.ql index 790322dc99b..1150bd746fa 100644 --- a/cpp/ql/test/library-tests/includes/includes/locations.ql +++ b/cpp/ql/test/library-tests/includes/includes/locations.ql @@ -3,4 +3,3 @@ import cpp from Location l where not l.getContainer() instanceof Folder select l - diff --git a/cpp/ql/test/library-tests/includes/non_existent/diags.ql b/cpp/ql/test/library-tests/includes/non_existent/diags.ql index d22ba539555..e4c33410e20 100644 --- a/cpp/ql/test/library-tests/includes/non_existent/diags.ql +++ b/cpp/ql/test/library-tests/includes/non_existent/diags.ql @@ -2,4 +2,3 @@ import cpp from Diagnostic d select d.getLocation().toString(), d.getSeverity(), d.getTag(), d.getMessage(), d.getFullMessage() - diff --git a/cpp/ql/test/library-tests/instantiations/test.ql b/cpp/ql/test/library-tests/instantiations/test.ql index af1f94dc9b5..a1808f9558c 100644 --- a/cpp/ql/test/library-tests/instantiations/test.ql +++ b/cpp/ql/test/library-tests/instantiations/test.ql @@ -2,4 +2,3 @@ import cpp from Function f select f - diff --git a/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql b/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql index 2617da4ea91..059acac50e6 100644 --- a/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql +++ b/cpp/ql/test/library-tests/ir/constant_func/constant_func.ql @@ -4,6 +4,9 @@ import semmle.code.cpp.ir.implementation.aliased_ssa.constant.ConstantAnalysis import semmle.code.cpp.ir.internal.IntegerConstant from IRFunction irFunc, int value -where - value = getValue(getConstantValue(irFunc.getReturnInstruction().(ReturnValueInstruction).getReturnValue())) +where + value = getValue(getConstantValue(irFunc + .getReturnInstruction() + .(ReturnValueInstruction) + .getReturnValue())) select irFunc, value diff --git a/cpp/ql/test/library-tests/ir/constants/constants.ql b/cpp/ql/test/library-tests/ir/constants/constants.ql index 14528e70f58..d8cd81bc9f7 100644 --- a/cpp/ql/test/library-tests/ir/constants/constants.ql +++ b/cpp/ql/test/library-tests/ir/constants/constants.ql @@ -3,81 +3,146 @@ import semmle.code.cpp.ir.internal.IntegerConstant as Ints bindingset[n] string resultString(int n) { - if Ints::hasValue(n) then - result = n.toString() - else - result = "unknown" + if Ints::hasValue(n) then result = n.toString() else result = "unknown" } from string expr, int res where - expr = "0 + 0" and res = Ints::add(0, 0) or - expr = "0 + INT_MAX" and res = Ints::add(0, Ints::maxValue()) or - expr = "0 + -INT_MAX" and res = Ints::add(0, Ints::minValue()) or - expr = "1 + INT_MAX" and res = Ints::add(1, Ints::maxValue()) or - expr = "1 + -INT_MAX" and res = Ints::add(1, Ints::minValue()) or - expr = "unknown + unknown" and res = Ints::add(Ints::unknown(), Ints::unknown()) or - expr = "5 + unknown" and res = Ints::add(5, Ints::unknown()) or - expr = "unknown + 5" and res = Ints::add(Ints::unknown(), 5) or - expr = "0 - INT_MAX" and res = Ints::sub(0, Ints::maxValue()) or - expr = "0 - -INT_MAX" and res = Ints::sub(0, Ints::minValue()) or - expr = "-1 - INT_MAX" and res = Ints::sub(-1, Ints::maxValue()) or - expr = "-1 - -INT_MAX" and res = Ints::sub(-1, Ints::minValue()) or - expr = "unknown - unknown" and res = Ints::sub(Ints::unknown(), Ints::unknown()) or - expr = "5 - unknown" and res = Ints::sub(5, Ints::unknown()) or - expr = "unknown - 5" and res = Ints::sub(Ints::unknown(), 5) or - expr = "0 * 0" and res = Ints::mul(0, 0) or - expr = "5 * 7" and res = Ints::mul(5, 7) or - expr = "0 * INT_MAX" and res = Ints::mul(0, Ints::maxValue()) or - expr = "2 * INT_MAX" and res = Ints::mul(2, Ints::maxValue()) or - expr = "-1 * -INT_MAX" and res = Ints::mul(-1, Ints::minValue()) or - expr = "INT_MAX * INT_MAX" and res = Ints::mul(Ints::maxValue(), Ints::maxValue()) or - expr = "0 * unknown" and res = Ints::mul(0, Ints::unknown()) or - expr = "35 / 7" and res = Ints::div(35, 7) or - expr = "35 / 8" and res = Ints::div(35, 8) or - expr = "35 / -7" and res = Ints::div(35, -7) or - expr = "35 / -8" and res = Ints::div(35, -8) or - expr = "-35 / 7" and res = Ints::div(-35, 7) or - expr = "-35 / 8" and res = Ints::div(-35, 8) or - expr = "-35 / -7" and res = Ints::div(-35, -7) or - expr = "-35 / -8" and res = Ints::div(-35, -8) or - expr = "0 / -INT_MAX" and res = Ints::div(0, Ints::minValue()) or - expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) or - expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) or - expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) or - expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) or - expr = "-3 == -3" and res = Ints::compareEQ(-3, -3) or - expr = "-3 == 6" and res = Ints::compareEQ(-3, 6) or - expr = "-3 == unknown" and res = Ints::compareEQ(-3, Ints::unknown()) or - expr = "unknown == 6" and res = Ints::compareEQ(Ints::unknown(), 6) or - expr = "unknown == unknown" and res = Ints::compareEQ(Ints::unknown(), Ints::unknown()) or - expr = "-3 != -3" and res = Ints::compareNE(-3, -3) or - expr = "-3 != 6" and res = Ints::compareNE(-3, 6) or - expr = "-3 != unknown" and res = Ints::compareNE(-3, Ints::unknown()) or - expr = "unknown != 6" and res = Ints::compareNE(Ints::unknown(), 6) or - expr = "unknown != unknown" and res = Ints::compareNE(Ints::unknown(), Ints::unknown()) or - expr = "-3 < -3" and res = Ints::compareLT(-3, -3) or - expr = "-3 < 6" and res = Ints::compareLT(-3, 6) or - expr = "-3 < -7" and res = Ints::compareLT(-3, -7) or - expr = "-3 < unknown" and res = Ints::compareLT(-3, Ints::unknown()) or - expr = "unknown < 6" and res = Ints::compareLT(Ints::unknown(), 6) or - expr = "unknown < unknown" and res = Ints::compareLT(Ints::unknown(), Ints::unknown()) or - expr = "-3 > -3" and res = Ints::compareGT(-3, -3) or - expr = "-3 > 6" and res = Ints::compareGT(-3, 6) or - expr = "-3 > -7" and res = Ints::compareGT(-3, -7) or - expr = "-3 > unknown" and res = Ints::compareGT(-3, Ints::unknown()) or - expr = "unknown > 6" and res = Ints::compareGT(Ints::unknown(), 6) or - expr = "unknown > unknown" and res = Ints::compareGT(Ints::unknown(), Ints::unknown()) or - expr = "-3 <= -3" and res = Ints::compareLE(-3, -3) or - expr = "-3 <= 6" and res = Ints::compareLE(-3, 6) or - expr = "-3 <= -7" and res = Ints::compareLE(-3, -7) or - expr = "-3 <= unknown" and res = Ints::compareLE(-3, Ints::unknown()) or - expr = "unknown <= 6" and res = Ints::compareLE(Ints::unknown(), 6) or - expr = "unknown <= unknown" and res = Ints::compareLE(Ints::unknown(), Ints::unknown()) or - expr = "-3 >= -3" and res = Ints::compareGE(-3, -3) or - expr = "-3 >= 6" and res = Ints::compareGE(-3, 6) or - expr = "-3 >= -7" and res = Ints::compareGE(-3, -7) or - expr = "-3 >= unknown" and res = Ints::compareGE(-3, Ints::unknown()) or - expr = "unknown >= 6" and res = Ints::compareGE(Ints::unknown(), 6) or + expr = "0 + 0" and res = Ints::add(0, 0) + or + expr = "0 + INT_MAX" and res = Ints::add(0, Ints::maxValue()) + or + expr = "0 + -INT_MAX" and res = Ints::add(0, Ints::minValue()) + or + expr = "1 + INT_MAX" and res = Ints::add(1, Ints::maxValue()) + or + expr = "1 + -INT_MAX" and res = Ints::add(1, Ints::minValue()) + or + expr = "unknown + unknown" and res = Ints::add(Ints::unknown(), Ints::unknown()) + or + expr = "5 + unknown" and res = Ints::add(5, Ints::unknown()) + or + expr = "unknown + 5" and res = Ints::add(Ints::unknown(), 5) + or + expr = "0 - INT_MAX" and res = Ints::sub(0, Ints::maxValue()) + or + expr = "0 - -INT_MAX" and res = Ints::sub(0, Ints::minValue()) + or + expr = "-1 - INT_MAX" and res = Ints::sub(-1, Ints::maxValue()) + or + expr = "-1 - -INT_MAX" and res = Ints::sub(-1, Ints::minValue()) + or + expr = "unknown - unknown" and res = Ints::sub(Ints::unknown(), Ints::unknown()) + or + expr = "5 - unknown" and res = Ints::sub(5, Ints::unknown()) + or + expr = "unknown - 5" and res = Ints::sub(Ints::unknown(), 5) + or + expr = "0 * 0" and res = Ints::mul(0, 0) + or + expr = "5 * 7" and res = Ints::mul(5, 7) + or + expr = "0 * INT_MAX" and res = Ints::mul(0, Ints::maxValue()) + or + expr = "2 * INT_MAX" and res = Ints::mul(2, Ints::maxValue()) + or + expr = "-1 * -INT_MAX" and res = Ints::mul(-1, Ints::minValue()) + or + expr = "INT_MAX * INT_MAX" and res = Ints::mul(Ints::maxValue(), Ints::maxValue()) + or + expr = "0 * unknown" and res = Ints::mul(0, Ints::unknown()) + or + expr = "35 / 7" and res = Ints::div(35, 7) + or + expr = "35 / 8" and res = Ints::div(35, 8) + or + expr = "35 / -7" and res = Ints::div(35, -7) + or + expr = "35 / -8" and res = Ints::div(35, -8) + or + expr = "-35 / 7" and res = Ints::div(-35, 7) + or + expr = "-35 / 8" and res = Ints::div(-35, 8) + or + expr = "-35 / -7" and res = Ints::div(-35, -7) + or + expr = "-35 / -8" and res = Ints::div(-35, -8) + or + expr = "0 / -INT_MAX" and res = Ints::div(0, Ints::minValue()) + or + expr = "INT_MAX / 0" and res = Ints::div(Ints::maxValue(), 0) + or + expr = "0 / unknown" and res = Ints::div(0, Ints::unknown()) + or + expr = "unknown / 3" and res = Ints::div(Ints::unknown(), 3) + or + expr = "unknown / unknown" and res = Ints::div(Ints::unknown(), Ints::unknown()) + or + expr = "-3 == -3" and res = Ints::compareEQ(-3, -3) + or + expr = "-3 == 6" and res = Ints::compareEQ(-3, 6) + or + expr = "-3 == unknown" and res = Ints::compareEQ(-3, Ints::unknown()) + or + expr = "unknown == 6" and res = Ints::compareEQ(Ints::unknown(), 6) + or + expr = "unknown == unknown" and res = Ints::compareEQ(Ints::unknown(), Ints::unknown()) + or + expr = "-3 != -3" and res = Ints::compareNE(-3, -3) + or + expr = "-3 != 6" and res = Ints::compareNE(-3, 6) + or + expr = "-3 != unknown" and res = Ints::compareNE(-3, Ints::unknown()) + or + expr = "unknown != 6" and res = Ints::compareNE(Ints::unknown(), 6) + or + expr = "unknown != unknown" and res = Ints::compareNE(Ints::unknown(), Ints::unknown()) + or + expr = "-3 < -3" and res = Ints::compareLT(-3, -3) + or + expr = "-3 < 6" and res = Ints::compareLT(-3, 6) + or + expr = "-3 < -7" and res = Ints::compareLT(-3, -7) + or + expr = "-3 < unknown" and res = Ints::compareLT(-3, Ints::unknown()) + or + expr = "unknown < 6" and res = Ints::compareLT(Ints::unknown(), 6) + or + expr = "unknown < unknown" and res = Ints::compareLT(Ints::unknown(), Ints::unknown()) + or + expr = "-3 > -3" and res = Ints::compareGT(-3, -3) + or + expr = "-3 > 6" and res = Ints::compareGT(-3, 6) + or + expr = "-3 > -7" and res = Ints::compareGT(-3, -7) + or + expr = "-3 > unknown" and res = Ints::compareGT(-3, Ints::unknown()) + or + expr = "unknown > 6" and res = Ints::compareGT(Ints::unknown(), 6) + or + expr = "unknown > unknown" and res = Ints::compareGT(Ints::unknown(), Ints::unknown()) + or + expr = "-3 <= -3" and res = Ints::compareLE(-3, -3) + or + expr = "-3 <= 6" and res = Ints::compareLE(-3, 6) + or + expr = "-3 <= -7" and res = Ints::compareLE(-3, -7) + or + expr = "-3 <= unknown" and res = Ints::compareLE(-3, Ints::unknown()) + or + expr = "unknown <= 6" and res = Ints::compareLE(Ints::unknown(), 6) + or + expr = "unknown <= unknown" and res = Ints::compareLE(Ints::unknown(), Ints::unknown()) + or + expr = "-3 >= -3" and res = Ints::compareGE(-3, -3) + or + expr = "-3 >= 6" and res = Ints::compareGE(-3, 6) + or + expr = "-3 >= -7" and res = Ints::compareGE(-3, -7) + or + expr = "-3 >= unknown" and res = Ints::compareGE(-3, Ints::unknown()) + or + expr = "unknown >= 6" and res = Ints::compareGE(Ints::unknown(), 6) + or expr = "unknown >= unknown" and res = Ints::compareGE(Ints::unknown(), Ints::unknown()) select expr, resultString(res) diff --git a/cpp/ql/test/library-tests/ir/escape/escape.ql b/cpp/ql/test/library-tests/ir/escape/escape.ql index 68a308e65d1..25475252d49 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.ql +++ b/cpp/ql/test/library-tests/ir/escape/escape.ql @@ -15,8 +15,9 @@ where exists(IRFunction irFunc | irFunc = var.getEnclosingIRFunction() and ( - (shouldEscape(var) and variableAddressEscapes(var)) or - (not shouldEscape(var) and not variableAddressEscapes(var)) + shouldEscape(var) and variableAddressEscapes(var) + or + not shouldEscape(var) and not variableAddressEscapes(var) ) ) select var diff --git a/cpp/ql/test/library-tests/ir/escape/ssa_escape.ql b/cpp/ql/test/library-tests/ir/escape/ssa_escape.ql index c1cc2e408e9..2ef33ae749f 100644 --- a/cpp/ql/test/library-tests/ir/escape/ssa_escape.ql +++ b/cpp/ql/test/library-tests/ir/escape/ssa_escape.ql @@ -14,8 +14,9 @@ where exists(IRFunction irFunc | irFunc = var.getEnclosingIRFunction() and ( - (shouldEscape(var) and variableAddressEscapes(var)) or - (not shouldEscape(var) and not variableAddressEscapes(var)) + shouldEscape(var) and variableAddressEscapes(var) + or + not shouldEscape(var) and not variableAddressEscapes(var) ) ) select var diff --git a/cpp/ql/test/library-tests/lambdas/calling_conv/calling_conv.ql b/cpp/ql/test/library-tests/lambdas/calling_conv/calling_conv.ql index 2e9dd6395df..a1808f9558c 100644 --- a/cpp/ql/test/library-tests/lambdas/calling_conv/calling_conv.ql +++ b/cpp/ql/test/library-tests/lambdas/calling_conv/calling_conv.ql @@ -1,4 +1,4 @@ import cpp from Function f -select f \ No newline at end of file +select f diff --git a/cpp/ql/test/library-tests/lambdas/captures/captures.ql b/cpp/ql/test/library-tests/lambdas/captures/captures.ql index 19026ad2a2d..5fad8553274 100644 --- a/cpp/ql/test/library-tests/lambdas/captures/captures.ql +++ b/cpp/ql/test/library-tests/lambdas/captures/captures.ql @@ -4,4 +4,5 @@ from LambdaCapture lc, string mode, int index where exists(LambdaExpression le | le.getCapture(index) = lc) and if lc.isImplicit() then mode = "implicit" else mode = "explicit" -select lc, mode, index, concat(lc.getField().toString(), ", "), concat(lc.getInitializer().toString(), ", ") +select lc, mode, index, concat(lc.getField().toString(), ", "), + concat(lc.getInitializer().toString(), ", ") diff --git a/cpp/ql/test/library-tests/lambdas/captures/elements.ql b/cpp/ql/test/library-tests/lambdas/captures/elements.ql index 38b30a22722..b7a1275f388 100644 --- a/cpp/ql/test/library-tests/lambdas/captures/elements.ql +++ b/cpp/ql/test/library-tests/lambdas/captures/elements.ql @@ -1,7 +1,8 @@ import cpp from Element e -where not e instanceof BuiltInType - and not e instanceof Specifier - and not e instanceof Folder +where + not e instanceof BuiltInType and + not e instanceof Specifier and + not e instanceof Folder select e diff --git a/cpp/ql/test/library-tests/lambdas/cfg/cfg.ql b/cpp/ql/test/library-tests/lambdas/cfg/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/lambdas/cfg/cfg.ql +++ b/cpp/ql/test/library-tests/lambdas/cfg/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/lambdas/cfg/reachability.ql b/cpp/ql/test/library-tests/lambdas/cfg/reachability.ql index 7f5c8e8d915..1202a03d4eb 100644 --- a/cpp/ql/test/library-tests/lambdas/cfg/reachability.ql +++ b/cpp/ql/test/library-tests/lambdas/cfg/reachability.ql @@ -2,6 +2,4 @@ import cpp from ControlFlowNode n where not reachable(n) -select n.getLocation().getStartLine(), - n - +select n.getLocation().getStartLine(), n diff --git a/cpp/ql/test/library-tests/languages/exprs.ql b/cpp/ql/test/library-tests/languages/exprs.ql index 0ad7fdc61c9..74ce2488551 100644 --- a/cpp/ql/test/library-tests/languages/exprs.ql +++ b/cpp/ql/test/library-tests/languages/exprs.ql @@ -1,11 +1,8 @@ import cpp class SomeCStyleCast extends CStyleCast { - override string toString() { - result = "(some cast)..." - } + override string toString() { result = "(some cast)..." } } from Expr e select e - diff --git a/cpp/ql/test/library-tests/literal_locations/duplicate_literal_locations.ql b/cpp/ql/test/library-tests/literal_locations/duplicate_literal_locations.ql index 4346da2c77e..4bf86e1ae17 100644 --- a/cpp/ql/test/library-tests/literal_locations/duplicate_literal_locations.ql +++ b/cpp/ql/test/library-tests/literal_locations/duplicate_literal_locations.ql @@ -3,4 +3,3 @@ import cpp from LocalScopeVariable v, ControlFlowNode def, Expr e where exprDefinition(v, def, e) select v, def, e - diff --git a/cpp/ql/test/library-tests/literal_locations/literal_locations.ql b/cpp/ql/test/library-tests/literal_locations/literal_locations.ql index 39a93114105..233c7cdce8d 100644 --- a/cpp/ql/test/library-tests/literal_locations/literal_locations.ql +++ b/cpp/ql/test/library-tests/literal_locations/literal_locations.ql @@ -2,4 +2,3 @@ import cpp from Literal l select l - diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_child_exprs.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_child_exprs.ql index 32cb1f7b04b..7cde1070add 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_child_exprs.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_child_exprs.ql @@ -4,8 +4,6 @@ import cpp // order as in the source code and still match the element being initialized // (which, in the case of designated initializers, will not necessarily match // the order of the array elements). - from ArrayAggregateLiteral aal, int childIndex, int elementIndex where aal.getElementExpr(elementIndex) = aal.getChild(childIndex) -select aal, aal.getUnspecifiedType(), childIndex, - aal.getChild(childIndex), elementIndex +select aal, aal.getUnspecifiedType(), childIndex, aal.getChild(childIndex), elementIndex diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql index 8027cd712f6..e2236e80db1 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/arrays_value_init.ql @@ -1,7 +1,8 @@ import cpp from ArrayType a, ArrayAggregateLiteral al, int i -where a = al.getType() - and i = [0 .. al.getUnspecifiedType().(ArrayType).getArraySize()] - and al.isValueInitialized(i) +where + a = al.getType() and + i = [0 .. al.getUnspecifiedType().(ArrayType).getArraySize()] and + al.isValueInitialized(i) select al, a, i diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql index 1cb6b731623..560a403015d 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/classes.ql @@ -1,6 +1,7 @@ import cpp from Class c, ClassAggregateLiteral al, Field f -where c = al.getType() - and f = c.getAField() +where + c = al.getType() and + f = c.getAField() select al, c, f, al.getFieldExpr(f) diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/classes_child_exprs.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/classes_child_exprs.ql index 2858fcbc366..e6dbbd7e111 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/classes_child_exprs.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/classes_child_exprs.ql @@ -4,7 +4,6 @@ import cpp // order as in the source code and still match the field being initialized // (which, in the case of designated initializers, will not necessarily match // the order in which the fields were declared). - from ClassAggregateLiteral cal, int i, Field f where cal.getFieldExpr(f) = cal.getChild(i) select cal, cal.getUnspecifiedType(), i, cal.getChild(i), f diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql b/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql index 71752805b78..5e0b3b06d92 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/classes_value_init.ql @@ -1,6 +1,7 @@ import cpp from Class c, ClassAggregateLiteral al, Field f -where c = al.getType() - and al.isValueInitialized(f) +where + c = al.getType() and + al.isValueInitialized(f) select al, c, f diff --git a/cpp/ql/test/library-tests/literals/literals/literals.ql b/cpp/ql/test/library-tests/literals/literals/literals.ql index 39a93114105..233c7cdce8d 100644 --- a/cpp/ql/test/library-tests/literals/literals/literals.ql +++ b/cpp/ql/test/library-tests/literals/literals/literals.ql @@ -2,4 +2,3 @@ import cpp from Literal l select l - diff --git a/cpp/ql/test/library-tests/literals/uuidof/uuidof.ql b/cpp/ql/test/library-tests/literals/uuidof/uuidof.ql index 90cf10c061b..b369e26e5bc 100644 --- a/cpp/ql/test/library-tests/literals/uuidof/uuidof.ql +++ b/cpp/ql/test/library-tests/literals/uuidof/uuidof.ql @@ -1,10 +1,7 @@ import default query predicate classUuids(Class cls, string uuid) { - if exists(cls.getUuid()) then - uuid = cls.getUuid() - else - uuid = "" + if exists(cls.getUuid()) then uuid = cls.getUuid() else uuid = "" } query predicate uuidofOperators(UuidofOperator op, string type, string uuid) { diff --git a/cpp/ql/test/library-tests/locations/constants/locations.ql b/cpp/ql/test/library-tests/locations/constants/locations.ql index 701ddd867ba..553a364d199 100644 --- a/cpp/ql/test/library-tests/locations/constants/locations.ql +++ b/cpp/ql/test/library-tests/locations/constants/locations.ql @@ -4,6 +4,7 @@ import cpp * Plainer output for CStyleCast, that does not reference the (potentially platform * dependent) type of the cast. */ + class CStyleCastPlain extends CStyleCast { override string toString() { result = "Conversion of " + getExpr().toString() } } diff --git a/cpp/ql/test/library-tests/loops/loops.ql b/cpp/ql/test/library-tests/loops/loops.ql index 55bc198159c..b6d8f130586 100644 --- a/cpp/ql/test/library-tests/loops/loops.ql +++ b/cpp/ql/test/library-tests/loops/loops.ql @@ -1,36 +1,32 @@ import cpp class ExprStmt_ extends ExprStmt { - override string toString() { - result = "ExprStmt: " + getExpr().toString() - } + override string toString() { result = "ExprStmt: " + getExpr().toString() } } from Loop l, string s, Element e where - ( - s = "getCondition()" and - e = l.getCondition() - ) or ( - s = "getStmt()" and - e = l.getStmt() - ) or ( - s = "(ForStmt).getInitialization()" and - e = l.(ForStmt).getInitialization() - ) or ( - s = "(ForStmt).getUpdate()" and - e = l.(ForStmt).getUpdate() - ) or ( - s = "(ForStmt).getAnIterationVariable()" and - e = l.(ForStmt).getAnIterationVariable() - ) or ( - s = "(RangeBasedForStmt).getVariable()" and - e = l.(RangeBasedForStmt).getVariable() - ) or ( - s = "(RangeBasedForStmt).getUpdate()" and - e = l.(RangeBasedForStmt).getUpdate() - ) or ( - s = "(RangeBasedForStmt).getEnclosingFunction().getATemplateArgument()" and - e = l.(RangeBasedForStmt).getEnclosingFunction().getATemplateArgument() - ) + s = "getCondition()" and + e = l.getCondition() + or + s = "getStmt()" and + e = l.getStmt() + or + s = "(ForStmt).getInitialization()" and + e = l.(ForStmt).getInitialization() + or + s = "(ForStmt).getUpdate()" and + e = l.(ForStmt).getUpdate() + or + s = "(ForStmt).getAnIterationVariable()" and + e = l.(ForStmt).getAnIterationVariable() + or + s = "(RangeBasedForStmt).getVariable()" and + e = l.(RangeBasedForStmt).getVariable() + or + s = "(RangeBasedForStmt).getUpdate()" and + e = l.(RangeBasedForStmt).getUpdate() + or + s = "(RangeBasedForStmt).getEnclosingFunction().getATemplateArgument()" and + e = l.(RangeBasedForStmt).getEnclosingFunction().getATemplateArgument() select l, s, e diff --git a/cpp/ql/test/library-tests/macros/affects/affects.ql b/cpp/ql/test/library-tests/macros/affects/affects.ql index 6939a59839e..15962858139 100644 --- a/cpp/ql/test/library-tests/macros/affects/affects.ql +++ b/cpp/ql/test/library-tests/macros/affects/affects.ql @@ -3,4 +3,3 @@ import cpp from Element e, MacroAccess ma where affectedbymacroexpansion(unresolveElement(e), unresolveElement(ma)) select e.getLocation(), e, ma.getLocation(), ma - diff --git a/cpp/ql/test/library-tests/macros/arguments/macro_arguments.ql b/cpp/ql/test/library-tests/macros/arguments/macro_arguments.ql index 047ee6a950a..82124877ce4 100644 --- a/cpp/ql/test/library-tests/macros/arguments/macro_arguments.ql +++ b/cpp/ql/test/library-tests/macros/arguments/macro_arguments.ql @@ -4,18 +4,13 @@ string prettyPrintMacroInvocation(MacroInvocation mi) { not exists(mi.getParentInvocation()) and result = mi.getMacro().getName() or - result = prettyPrintMacroInvocation(mi.getParentInvocation()) + - " -> " + - mi.getMacro().getName() + result = prettyPrintMacroInvocation(mi.getParentInvocation()) + " -> " + mi.getMacro().getName() } from MacroInvocation mi, int arg_index, string unexpanded, string expanded -where unexpanded = mi.getUnexpandedArgument(arg_index) - and expanded = mi.getExpandedArgument(arg_index) -select - mi.getLocation().toString().regexpCapture(".*/([^/]*)$", 1), - mi.getActualLocation().toString().regexpCapture(".*/([^/]*)$", 1), - prettyPrintMacroInvocation(mi), - arg_index, - unexpanded, - expanded +where + unexpanded = mi.getUnexpandedArgument(arg_index) and + expanded = mi.getExpandedArgument(arg_index) +select mi.getLocation().toString().regexpCapture(".*/([^/]*)$", 1), + mi.getActualLocation().toString().regexpCapture(".*/([^/]*)$", 1), prettyPrintMacroInvocation(mi), + arg_index, unexpanded, expanded diff --git a/cpp/ql/test/library-tests/macros/inmacroexpansion/inmacroexpansion.ql b/cpp/ql/test/library-tests/macros/inmacroexpansion/inmacroexpansion.ql index e58ea5c3b61..bf93de7fdb5 100644 --- a/cpp/ql/test/library-tests/macros/inmacroexpansion/inmacroexpansion.ql +++ b/cpp/ql/test/library-tests/macros/inmacroexpansion/inmacroexpansion.ql @@ -1,8 +1,7 @@ import cpp from Element e -where not e.getLocation() instanceof UnknownLocation - and not e instanceof Folder -select e, - any(boolean b | if e.isInMacroExpansion() then b = true else b = false) - +where + not e.getLocation() instanceof UnknownLocation and + not e instanceof Folder +select e, any(boolean b | if e.isInMacroExpansion() then b = true else b = false) diff --git a/cpp/ql/test/library-tests/macros/macros/affectedbymacroexpansion.ql b/cpp/ql/test/library-tests/macros/macros/affectedbymacroexpansion.ql index fb1cfc569dd..4ba665e98cc 100644 --- a/cpp/ql/test/library-tests/macros/macros/affectedbymacroexpansion.ql +++ b/cpp/ql/test/library-tests/macros/macros/affectedbymacroexpansion.ql @@ -3,4 +3,3 @@ import cpp from Block b, MacroAccess m where affectedbymacroexpansion(unresolveElement(b), unresolveElement(m)) select b, m - diff --git a/cpp/ql/test/library-tests/macros/macros/inmacroexpansion.ql b/cpp/ql/test/library-tests/macros/macros/inmacroexpansion.ql index 6803e50004f..afed90b56a6 100644 --- a/cpp/ql/test/library-tests/macros/macros/inmacroexpansion.ql +++ b/cpp/ql/test/library-tests/macros/macros/inmacroexpansion.ql @@ -3,4 +3,3 @@ import cpp from Block b, MacroAccess m where inmacroexpansion(unresolveElement(b), unresolveElement(m)) select b, m - diff --git a/cpp/ql/test/library-tests/members/getters/members.ql b/cpp/ql/test/library-tests/members/getters/members.ql index b36b56a4e4c..0338fda2f9c 100644 --- a/cpp/ql/test/library-tests/members/getters/members.ql +++ b/cpp/ql/test/library-tests/members/getters/members.ql @@ -1,72 +1,71 @@ import cpp -newtype TMaybeClass = TClass(Class c) or TNoClass() +newtype TMaybeClass = + TClass(Class c) or + TNoClass() class MaybeClass extends TMaybeClass { abstract string toString(); + abstract Location getLocation(); + abstract string relation(Function f); } string relation(Class c, Function f) { - exists(int i | f = c.getCanonicalMember(i) and result = "getCanonicalMember(" + i + ")") - or exists(int i | f = c.getAMember(i) and result = "getAMember(" + i + ")") - or (f = c.getAMember() and result = "getAMember()") - or (f = c.getAMemberFunction() and result = "getAMemberFunction()") - or (f.getDeclaringType() = c and result = "getDeclaringType()") + exists(int i | f = c.getCanonicalMember(i) and result = "getCanonicalMember(" + i + ")") + or + exists(int i | f = c.getAMember(i) and result = "getAMember(" + i + ")") + or + f = c.getAMember() and result = "getAMember()" + or + f = c.getAMemberFunction() and result = "getAMemberFunction()" + or + f.getDeclaringType() = c and result = "getDeclaringType()" } class YesMaybeClass extends MaybeClass { Class c; - YesMaybeClass() { - this = TClass(c) - } + YesMaybeClass() { this = TClass(c) } - override string toString() { - result = c.toString() - } + override string toString() { result = c.toString() } - override Location getLocation() { - result = c.getLocation() - } + override Location getLocation() { result = c.getLocation() } - override string relation(Function f) { - result = relation(c, f) - } + override string relation(Function f) { result = relation(c, f) } } class NoMaybeClass extends MaybeClass { - NoMaybeClass() { - this = TNoClass() - } + NoMaybeClass() { this = TNoClass() } - override string toString() { - result = "" - } + override string toString() { result = "" } - override Location getLocation() { - result instanceof UnknownLocation - } + override Location getLocation() { result instanceof UnknownLocation } override string relation(Function f) { - not exists(relation(_, f)) - and result = "Orphan" + not exists(relation(_, f)) and + result = "Orphan" } } string functionName(Function f) { exists(string name, string templateArgs, string args | - result = name + templateArgs + args - and name = f.getQualifiedName() - and if exists(f.getATemplateArgument()) - then templateArgs = "<" + concat(int i | | f.getTemplateArgument(i).toString(), "," order by i) + ">" - else templateArgs = "" - and args = "(" + concat(int i | | f.getParameter(i).getType().toString(), "," order by i) + ")") + result = name + templateArgs + args and + name = f.getQualifiedName() and + ( + if exists(f.getATemplateArgument()) + then + templateArgs = "<" + concat(int i | | f.getTemplateArgument(i).toString(), "," order by i) + + ">" + else templateArgs = "" + ) and + args = "(" + concat(int i | | f.getParameter(i).getType().toString(), "," order by i) + ")" + ) } from MaybeClass m, Function f -where not f.getDeclaringType().getName() = "__va_list_tag" - and exists(m.relation(f)) +where + not f.getDeclaringType().getName() = "__va_list_tag" and + exists(m.relation(f)) select m, f, functionName(f), concat(m.relation(f), ", ") - diff --git a/cpp/ql/test/library-tests/members/members/functions.ql b/cpp/ql/test/library-tests/members/members/functions.ql index af1f94dc9b5..a1808f9558c 100644 --- a/cpp/ql/test/library-tests/members/members/functions.ql +++ b/cpp/ql/test/library-tests/members/members/functions.ql @@ -2,4 +2,3 @@ import cpp from Function f select f - diff --git a/cpp/ql/test/library-tests/members/templates/members.ql b/cpp/ql/test/library-tests/members/templates/members.ql index 2e9e53a06eb..d0baacf5a7c 100644 --- a/cpp/ql/test/library-tests/members/templates/members.ql +++ b/cpp/ql/test/library-tests/members/templates/members.ql @@ -8,4 +8,3 @@ string mem(Class c) { from Class c select c, mem(c) - diff --git a/cpp/ql/test/library-tests/multiple_declarations/macroinvocations/multiple_macro_invocations.ql b/cpp/ql/test/library-tests/multiple_declarations/macroinvocations/multiple_macro_invocations.ql index 6c1db3b8dfd..e4858ba1895 100644 --- a/cpp/ql/test/library-tests/multiple_declarations/macroinvocations/multiple_macro_invocations.ql +++ b/cpp/ql/test/library-tests/multiple_declarations/macroinvocations/multiple_macro_invocations.ql @@ -4,7 +4,6 @@ import cpp // a `MacroInvocation` in the database for each preprocessor context in which // the header file is used. This can cause performance issues on large // databases, where there may be hundreds of such contexts. - from MacroInvocation mi where mi.getMacroName() = "MY_MACRO" select mi diff --git a/cpp/ql/test/library-tests/multiple_declarations/preprocbranch/preprocbranch.ql b/cpp/ql/test/library-tests/multiple_declarations/preprocbranch/preprocbranch.ql index 1fd2a7a31d4..21d45f01310 100644 --- a/cpp/ql/test/library-tests/multiple_declarations/preprocbranch/preprocbranch.ql +++ b/cpp/ql/test/library-tests/multiple_declarations/preprocbranch/preprocbranch.ql @@ -1,17 +1,19 @@ import cpp -from PreprocessorBranchDirective pbd_if, PreprocessorBranchDirective pbd, string pbd_next, string pbd_next_line, PreprocessorBranchDirective pbd_endif +from + PreprocessorBranchDirective pbd_if, PreprocessorBranchDirective pbd, string pbd_next, + string pbd_next_line, PreprocessorBranchDirective pbd_endif where - pbd_if = pbd.getIf() and - if exists(pbd.getNext()) then ( - pbd_next = pbd.getNext().toString() and - pbd_next_line = pbd.getNext().getLocation().getStartLine().toString() - ) else ( - pbd_next = "N/A" and - pbd_next_line = "N/A" - ) and - pbd_endif = pbd.getEndIf() -select pbd, - pbd_if, - pbd_next_line, pbd_next, - pbd_endif + pbd_if = pbd.getIf() and + ( + if exists(pbd.getNext()) + then ( + pbd_next = pbd.getNext().toString() and + pbd_next_line = pbd.getNext().getLocation().getStartLine().toString() + ) else ( + pbd_next = "N/A" and + pbd_next_line = "N/A" + ) + ) and + pbd_endif = pbd.getEndIf() +select pbd, pbd_if, pbd_next_line, pbd_next, pbd_endif diff --git a/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers1.ql b/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers1.ql index aae7e8509a9..77a8e195ebe 100644 --- a/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers1.ql +++ b/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers1.ql @@ -1,6 +1,7 @@ import cpp from NameQualifier nq, Location l -where l = nq.getQualifiedElement().getLocation() - and l.getFile().getShortName() = "name_qualifiers" +where + l = nq.getQualifiedElement().getLocation() and + l.getFile().getShortName() = "name_qualifiers" select nq, nq.getQualifiedElement(), nq.getQualifyingElement() diff --git a/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers2.ql b/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers2.ql index 64ab4f4dcfc..593049885eb 100644 --- a/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers2.ql +++ b/cpp/ql/test/library-tests/name_qualifiers/NameQualifiers2.ql @@ -2,6 +2,6 @@ import cpp from NameQualifiableElement e where - e.hasGlobalQualifiedName() - and e instanceof Expr + e.hasGlobalQualifiedName() and + e instanceof Expr select e diff --git a/cpp/ql/test/library-tests/namespaces/namespaces/decls.ql b/cpp/ql/test/library-tests/namespaces/namespaces/decls.ql index 49c15489b4d..03fe059f4a9 100644 --- a/cpp/ql/test/library-tests/namespaces/namespaces/decls.ql +++ b/cpp/ql/test/library-tests/namespaces/namespaces/decls.ql @@ -1,12 +1,12 @@ import cpp string qual(Declaration d) { - if exists(d.getQualifiedName()) - then result = d.getQualifiedName() - else result = "" + if exists(d.getQualifiedName()) then result = d.getQualifiedName() else result = "" } -newtype TMaybeNamespace = SomeNamespace(Namespace ns) or NoNamespace() +newtype TMaybeNamespace = + SomeNamespace(Namespace ns) or + NoNamespace() class MaybeNamespace extends TMaybeNamespace { string toString() { @@ -16,14 +16,13 @@ class MaybeNamespace extends TMaybeNamespace { } Location getLocation() { - exists(Namespace ns | - this = SomeNamespace(ns) and result = ns.getLocation()) + exists(Namespace ns | this = SomeNamespace(ns) and result = ns.getLocation()) } } from MaybeNamespace n, Declaration d -where n = SomeNamespace(d.getNamespace()) - or n = NoNamespace() and not exists(d.getNamespace()) -select n, d, - qual(d), - any(boolean b | if d.isTopLevel() then b = true else b = false) +where + n = SomeNamespace(d.getNamespace()) + or + n = NoNamespace() and not exists(d.getNamespace()) +select n, d, qual(d), any(boolean b | if d.isTopLevel() then b = true else b = false) diff --git a/cpp/ql/test/library-tests/namespaces/namespaces/namequalifiable.ql b/cpp/ql/test/library-tests/namespaces/namespaces/namequalifiable.ql index 2e43c53ce5b..dfe1fc0671d 100644 --- a/cpp/ql/test/library-tests/namespaces/namespaces/namequalifiable.ql +++ b/cpp/ql/test/library-tests/namespaces/namespaces/namequalifiable.ql @@ -1,13 +1,11 @@ import cpp string describe(Element e) { - ( - e instanceof NameQualifiableElement and - result = "NameQualifiableElement" - ) or ( - e instanceof NameQualifyingElement and - result = "NameQualifyingElement" - ) + e instanceof NameQualifiableElement and + result = "NameQualifiableElement" + or + e instanceof NameQualifyingElement and + result = "NameQualifyingElement" } from Element e diff --git a/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.ql b/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.ql index 2d156f4fb3d..e818ef64cc5 100644 --- a/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.ql +++ b/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.ql @@ -1,8 +1,9 @@ import cpp from Namespace n, string sane, string parent -where if n.hasName(n.getName()) then sane = "Yes" else sane = "No" - and if exists(n.getParentNamespace()) - then parent = n.getParentNamespace().toString() - else parent = "" +where + (if n.hasName(n.getName()) then sane = "Yes" else sane = "No") and + if exists(n.getParentNamespace()) + then parent = n.getParentNamespace().toString() + else parent = "" select n, n.getName(), n.getQualifiedName(), sane, parent diff --git a/cpp/ql/test/library-tests/namespaces/same_name/decls.ql b/cpp/ql/test/library-tests/namespaces/same_name/decls.ql index c7d60f5aff1..7981d58c56b 100644 --- a/cpp/ql/test/library-tests/namespaces/same_name/decls.ql +++ b/cpp/ql/test/library-tests/namespaces/same_name/decls.ql @@ -3,4 +3,3 @@ import cpp from Namespace n, Declaration d where n = d.getNamespace() select n, d - diff --git a/cpp/ql/test/library-tests/nested_functions/nested_functions/namespaces.ql b/cpp/ql/test/library-tests/nested_functions/nested_functions/namespaces.ql index d2d2c4637a7..cfe1f716121 100644 --- a/cpp/ql/test/library-tests/nested_functions/nested_functions/namespaces.ql +++ b/cpp/ql/test/library-tests/nested_functions/nested_functions/namespaces.ql @@ -1,24 +1,10 @@ import cpp -Namespace topLevelNamespace(Declaration d) -{ - result.getADeclaration() = d -} +Namespace topLevelNamespace(Declaration d) { result.getADeclaration() = d } from Declaration d, string tl, string ns where - d.getFile().toString() != "" and - ( - if exists(topLevelNamespace(d)) then ( - tl = topLevelNamespace(d).toString() - ) else ( - tl = "NONE" - ) - ) and ( - if exists(d.getNamespace()) then ( - ns = d.getNamespace().toString() - ) else ( - ns = "NONE" - ) - ) + d.getFile().toString() != "" and + (if exists(topLevelNamespace(d)) then tl = topLevelNamespace(d).toString() else tl = "NONE") and + (if exists(d.getNamespace()) then ns = d.getNamespace().toString() else ns = "NONE") select d, tl, ns diff --git a/cpp/ql/test/library-tests/nested_functions/nested_functions/nested_functions.ql b/cpp/ql/test/library-tests/nested_functions/nested_functions/nested_functions.ql index f9eeff6efb0..835f4a576b4 100644 --- a/cpp/ql/test/library-tests/nested_functions/nested_functions/nested_functions.ql +++ b/cpp/ql/test/library-tests/nested_functions/nested_functions/nested_functions.ql @@ -1,11 +1,10 @@ import cpp from Function f, string call -where if exists(f.getACallToThisFunction()) - then call = f.getACallToThisFunction().getLocation().toString() + " " - + f.getACallToThisFunction().toString() - else call = "" -select f, - f.getType(), - call - +where + if exists(f.getACallToThisFunction()) + then + call = f.getACallToThisFunction().getLocation().toString() + " " + + f.getACallToThisFunction().toString() + else call = "" +select f, f.getType(), call diff --git a/cpp/ql/test/library-tests/nested_functions/nested_functions/var_uses.ql b/cpp/ql/test/library-tests/nested_functions/nested_functions/var_uses.ql index f7dfc19d540..aba71319ec2 100644 --- a/cpp/ql/test/library-tests/nested_functions/nested_functions/var_uses.ql +++ b/cpp/ql/test/library-tests/nested_functions/nested_functions/var_uses.ql @@ -2,7 +2,4 @@ import cpp from Variable v, VariableAccess a where a = v.getAnAccess() -select v, - a.getLocation().toString(), - a.getEnclosingFunction() - +select v, a.getLocation().toString(), a.getEnclosingFunction() diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql index 5e248e6901e..9e1cc557510 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql @@ -1,9 +1,11 @@ import cpp from Function f, string e -where if f.hasExceptionSpecification() - then if exists(f.getADeclarationEntry().getNoExceptExpr()) - then e = f.getADeclarationEntry().getNoExceptExpr().toString() - else e = "" +where + if f.hasExceptionSpecification() + then + if exists(f.getADeclarationEntry().getNoExceptExpr()) + then e = f.getADeclarationEntry().getNoExceptExpr().toString() + else e = "" else e = "" select f, f.getFullSignature(), f.getDeclaringType(), e diff --git a/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_expr.ql b/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_expr.ql index 535c0d98390..a1221feea3b 100644 --- a/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_expr.ql +++ b/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_expr.ql @@ -1,6 +1,4 @@ import cpp from NoExceptExpr e -select e, - e.getExpr() - +select e, e.getExpr() diff --git a/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_specifier.ql b/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_specifier.ql index f0b4229c5fd..cb7a8d3ed12 100644 --- a/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_specifier.ql +++ b/cpp/ql/test/library-tests/noexcept/noexcept/noexcept_specifier.ql @@ -1,12 +1,9 @@ import cpp from FunctionDeclarationEntry f, string noExcept, string noExceptExpr -where if f.isNoExcept() then noExcept = "no except" - else noExcept = "--------" - and if exists(f.getNoExceptExpr()) - then noExceptExpr = f.getNoExceptExpr().toString() - else noExceptExpr = "---" -select f, - noExcept, - noExceptExpr - +where + (if f.isNoExcept() then noExcept = "no except" else noExcept = "--------") and + if exists(f.getNoExceptExpr()) + then noExceptExpr = f.getNoExceptExpr().toString() + else noExceptExpr = "---" +select f, noExcept, noExceptExpr diff --git a/cpp/ql/test/library-tests/nulltermination/mayAddNullTerminator.ql b/cpp/ql/test/library-tests/nulltermination/mayAddNullTerminator.ql index 602fbd5b530..ee03fb32dc7 100644 --- a/cpp/ql/test/library-tests/nulltermination/mayAddNullTerminator.ql +++ b/cpp/ql/test/library-tests/nulltermination/mayAddNullTerminator.ql @@ -3,4 +3,4 @@ import semmle.code.cpp.commons.NullTermination from Expr e, VariableAccess va where mayAddNullTerminator(e, va) -select e, va \ No newline at end of file +select e, va diff --git a/cpp/ql/test/library-tests/nulltermination/variableMustBeNullTerminated.ql b/cpp/ql/test/library-tests/nulltermination/variableMustBeNullTerminated.ql index e69a2da6924..bb06039b932 100644 --- a/cpp/ql/test/library-tests/nulltermination/variableMustBeNullTerminated.ql +++ b/cpp/ql/test/library-tests/nulltermination/variableMustBeNullTerminated.ql @@ -3,4 +3,4 @@ import semmle.code.cpp.commons.NullTermination from VariableAccess va where variableMustBeNullTerminated(va) -select va \ No newline at end of file +select va diff --git a/cpp/ql/test/library-tests/numlines/numlines.ql b/cpp/ql/test/library-tests/numlines/numlines.ql index 6d1d90b8b42..256f5c32b5f 100644 --- a/cpp/ql/test/library-tests/numlines/numlines.ql +++ b/cpp/ql/test/library-tests/numlines/numlines.ql @@ -2,15 +2,35 @@ import cpp string functionName(Function f) { exists(string name, string templateArgs, string args | - result = name + templateArgs + args - and name = f.getQualifiedName() - and if exists(f.getATemplateArgument()) - then templateArgs = "<" + concat(int i | exists(f.getTemplateArgument(i)) | f.getTemplateArgument(i).toString(), "," order by i) + ">" - else templateArgs = "" - and args = "(" + concat(int i | exists(f.getParameter(i)) | f.getParameter(i).getType().toString(), "," order by i) + ")") + result = name + templateArgs + args and + name = f.getQualifiedName() and + ( + if exists(f.getATemplateArgument()) + then + templateArgs = "<" + + concat(int i | + exists(f.getTemplateArgument(i)) + | + f.getTemplateArgument(i).toString(), "," order by i + ) + ">" + else templateArgs = "" + ) and + args = "(" + + concat(int i | + exists(f.getParameter(i)) + | + f.getParameter(i).getType().toString(), "," order by i + ) + ")" + ) } from string resource, int ntotal, int ncode, int ncomment -where exists(File f | f.getShortName() = resource and numlines(unresolveElement(f), ntotal, ncode, ncomment)) - or exists(Function f | functionName(f) = resource and numlines(unresolveElement(f), ntotal, ncode, ncomment)) +where + exists(File f | + f.getShortName() = resource and numlines(unresolveElement(f), ntotal, ncode, ncomment) + ) + or + exists(Function f | + functionName(f) = resource and numlines(unresolveElement(f), ntotal, ncode, ncomment) + ) select resource, ntotal, ncode, ncomment diff --git a/cpp/ql/test/library-tests/odasa2646/cfi.ql b/cpp/ql/test/library-tests/odasa2646/cfi.ql index 5d5caceb9d6..1f54b8f85e7 100644 --- a/cpp/ql/test/library-tests/odasa2646/cfi.ql +++ b/cpp/ql/test/library-tests/odasa2646/cfi.ql @@ -1,7 +1,8 @@ import cpp from ConstructorFieldInit cfi, Expr e, string clazz -where e = cfi.getExpr() - and clazz = e.getAQlClass() - and clazz.matches("%Literal") +where + e = cfi.getExpr() and + clazz = e.getAQlClass() and + clazz.matches("%Literal") select cfi, e, clazz diff --git a/cpp/ql/test/library-tests/operators/operators.ql b/cpp/ql/test/library-tests/operators/operators.ql index 0e072dc827e..6937589cf28 100644 --- a/cpp/ql/test/library-tests/operators/operators.ql +++ b/cpp/ql/test/library-tests/operators/operators.ql @@ -1,3 +1,4 @@ import cpp -from Call c select c +from Call c +select c diff --git a/cpp/ql/test/library-tests/opts/options.ql b/cpp/ql/test/library-tests/opts/options.ql index dd75d9f07a3..abfd88d81b9 100644 --- a/cpp/ql/test/library-tests/opts/options.ql +++ b/cpp/ql/test/library-tests/opts/options.ql @@ -1,32 +1,29 @@ import cpp -class CustomTestOptions extends Options -{ - override predicate okToIgnoreReturnValue(FunctionCall fc) { - Options.super.okToIgnoreReturnValue(fc) or - fc.getTarget().getName() = "myIgnoreReturnValue" - } +class CustomTestOptions extends Options { + override predicate okToIgnoreReturnValue(FunctionCall fc) { + Options.super.okToIgnoreReturnValue(fc) or + fc.getTarget().getName() = "myIgnoreReturnValue" + } } from Options opts, Element e, string why where - ( - opts.overrideReturnsNull(e) and - why = "overrideReturnsNull" - ) or ( - opts.returnsNull(e) and - why = "returnsNull" - ) or ( - opts.exits(e) and - why = "exits" - ) or ( - opts.exprExits(e) and - why = "exprExits" - ) or ( - opts.alwaysCheckReturnValue(e) and - why = "alwaysCheckReturnValue" - ) or ( - opts.okToIgnoreReturnValue(e) and - why = "okToIgnoreReturnValue" - ) + opts.overrideReturnsNull(e) and + why = "overrideReturnsNull" + or + opts.returnsNull(e) and + why = "returnsNull" + or + opts.exits(e) and + why = "exits" + or + opts.exprExits(e) and + why = "exprExits" + or + opts.alwaysCheckReturnValue(e) and + why = "alwaysCheckReturnValue" + or + opts.okToIgnoreReturnValue(e) and + why = "okToIgnoreReturnValue" select e, why diff --git a/cpp/ql/test/library-tests/parameters/parameters/Parameters2.ql b/cpp/ql/test/library-tests/parameters/parameters/Parameters2.ql index 124a6386848..ba7fe40d6f1 100644 --- a/cpp/ql/test/library-tests/parameters/parameters/Parameters2.ql +++ b/cpp/ql/test/library-tests/parameters/parameters/Parameters2.ql @@ -1,5 +1,6 @@ import cpp -select count(Function f, Function g | f.getAParameter() = g.getAParameter() - and f != g) - +select count(Function f, Function g | + f.getAParameter() = g.getAParameter() and + f != g + ) diff --git a/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql b/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql index a346afdb931..c19464c6823 100644 --- a/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql +++ b/cpp/ql/test/library-tests/parameters/parameters/Parameters3.ql @@ -2,13 +2,17 @@ * @name Parameters3 * @kind table */ + import cpp from Function f, int i, Parameter p, string pname, boolean named -where f.hasName("Dispatch") -and f.getParameter(i) = p -and p.getName() = pname -and ( - p.isNamed() and named = true - or not p.isNamed() and named = false) +where + f.hasName("Dispatch") and + f.getParameter(i) = p and + p.getName() = pname and + ( + p.isNamed() and named = true + or + not p.isNamed() and named = false + ) select f, i, pname, named diff --git a/cpp/ql/test/library-tests/parameters/toStrings/params.ql b/cpp/ql/test/library-tests/parameters/toStrings/params.ql index 3b3d3ee2a6f..4e401abe37f 100644 --- a/cpp/ql/test/library-tests/parameters/toStrings/params.ql +++ b/cpp/ql/test/library-tests/parameters/toStrings/params.ql @@ -3,4 +3,3 @@ import cpp from ParameterDeclarationEntry pde, string str where if exists(pde.toString()) then str = pde.toString() else str = "" select pde.getLocation().toString(), str - diff --git a/cpp/ql/test/library-tests/permissive/accesses.ql b/cpp/ql/test/library-tests/permissive/accesses.ql index 92511c9a75c..80e03800970 100644 --- a/cpp/ql/test/library-tests/permissive/accesses.ql +++ b/cpp/ql/test/library-tests/permissive/accesses.ql @@ -2,4 +2,3 @@ import cpp from Access a select a - diff --git a/cpp/ql/test/library-tests/permissive/calls.ql b/cpp/ql/test/library-tests/permissive/calls.ql index cb4368e31a1..f52a0677281 100644 --- a/cpp/ql/test/library-tests/permissive/calls.ql +++ b/cpp/ql/test/library-tests/permissive/calls.ql @@ -2,4 +2,3 @@ import cpp from FunctionCall fc select fc, fc.getTarget() - diff --git a/cpp/ql/test/library-tests/permissive/diags.ql b/cpp/ql/test/library-tests/permissive/diags.ql index 965b3498444..cecbfb785d6 100644 --- a/cpp/ql/test/library-tests/permissive/diags.ql +++ b/cpp/ql/test/library-tests/permissive/diags.ql @@ -2,4 +2,3 @@ import cpp from Diagnostic d select d.getLocation(), d.getSeverity(), d.getTag(), d.getMessage(), d.getFullMessage() - diff --git a/cpp/ql/test/library-tests/pod/isPOD.ql b/cpp/ql/test/library-tests/pod/isPOD.ql index cf0b0052e6c..e7860247eb7 100644 --- a/cpp/ql/test/library-tests/pod/isPOD.ql +++ b/cpp/ql/test/library-tests/pod/isPOD.ql @@ -1,8 +1,5 @@ import cpp from Class c, boolean ispod -where - if c.isPOD() - then ispod = true - else ispod = false +where if c.isPOD() then ispod = true else ispod = false select c, ispod diff --git a/cpp/ql/test/library-tests/pod/isPOD03.ql b/cpp/ql/test/library-tests/pod/isPOD03.ql index 8653461a0c2..42f6eed559f 100644 --- a/cpp/ql/test/library-tests/pod/isPOD03.ql +++ b/cpp/ql/test/library-tests/pod/isPOD03.ql @@ -1,9 +1,5 @@ import semmle.code.cpp.PODType03 - from Class c, boolean ispod -where - if isPODClass03(c) - then ispod = true - else ispod = false +where if isPODClass03(c) then ispod = true else ispod = false select c, ispod diff --git a/cpp/ql/test/library-tests/pointsto/address-of-assign/PointsToExpr.ql b/cpp/ql/test/library-tests/pointsto/address-of-assign/PointsToExpr.ql index 90955bea9a8..05c34d4eab2 100644 --- a/cpp/ql/test/library-tests/pointsto/address-of-assign/PointsToExpr.ql +++ b/cpp/ql/test/library-tests/pointsto/address-of-assign/PointsToExpr.ql @@ -1,15 +1,14 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class AccessPT extends PointsToExpr -{ - override predicate interesting() { - this instanceof VariableAccess and - exists(FunctionCall use | - use = this.getParent() and - use.getTarget().hasName("use") - ) - } +class AccessPT extends PointsToExpr { + override predicate interesting() { + this instanceof VariableAccess and + exists(FunctionCall use | + use = this.getParent() and + use.getTarget().hasName("use") + ) + } } from AccessPT access, Element loc diff --git a/cpp/ql/test/library-tests/pointsto/arguments/Report.ql b/cpp/ql/test/library-tests/pointsto/arguments/Report.ql index 54a5c1cff7f..3ff131bf4e4 100644 --- a/cpp/ql/test/library-tests/pointsto/arguments/Report.ql +++ b/cpp/ql/test/library-tests/pointsto/arguments/Report.ql @@ -1,14 +1,13 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class ReportPT extends PointsToExpr -{ - override predicate interesting() { - exists(FunctionCall report | - report.getTarget().hasName("report") and - report.getAnArgument() = this - ) - } +class ReportPT extends PointsToExpr { + override predicate interesting() { + exists(FunctionCall report | + report.getTarget().hasName("report") and + report.getAnArgument() = this + ) + } } from ReportPT report, Element loc diff --git a/cpp/ql/test/library-tests/pointsto/basic/PointsToExpr.ql b/cpp/ql/test/library-tests/pointsto/basic/PointsToExpr.ql index 90955bea9a8..05c34d4eab2 100644 --- a/cpp/ql/test/library-tests/pointsto/basic/PointsToExpr.ql +++ b/cpp/ql/test/library-tests/pointsto/basic/PointsToExpr.ql @@ -1,15 +1,14 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class AccessPT extends PointsToExpr -{ - override predicate interesting() { - this instanceof VariableAccess and - exists(FunctionCall use | - use = this.getParent() and - use.getTarget().hasName("use") - ) - } +class AccessPT extends PointsToExpr { + override predicate interesting() { + this instanceof VariableAccess and + exists(FunctionCall use | + use = this.getParent() and + use.getTarget().hasName("use") + ) + } } from AccessPT access, Element loc diff --git a/cpp/ql/test/library-tests/pointsto/basic/anythingPointsToExpr.ql b/cpp/ql/test/library-tests/pointsto/basic/anythingPointsToExpr.ql index 8e0c24b14a7..b9be16f3d06 100644 --- a/cpp/ql/test/library-tests/pointsto/basic/anythingPointsToExpr.ql +++ b/cpp/ql/test/library-tests/pointsto/basic/anythingPointsToExpr.ql @@ -1,15 +1,14 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class AccessPT extends PointsToExpr -{ - override predicate interesting() { - this instanceof VariableAccess and - exists(FunctionCall use | - use = this.getParent() and - use.getTarget().hasName("use") - ) - } +class AccessPT extends PointsToExpr { + override predicate interesting() { + this instanceof VariableAccess and + exists(FunctionCall use | + use = this.getParent() and + use.getTarget().hasName("use") + ) + } } from Element loc diff --git a/cpp/ql/test/library-tests/pointsto/basic/compoundEdge.ql b/cpp/ql/test/library-tests/pointsto/basic/compoundEdge.ql index 609293d0f06..bfa1128607c 100644 --- a/cpp/ql/test/library-tests/pointsto/basic/compoundEdge.ql +++ b/cpp/ql/test/library-tests/pointsto/basic/compoundEdge.ql @@ -2,4 +2,5 @@ import semmle.code.cpp.pointsto.PointsTo from Element parent, Element element, string label, Element other, int kind where compoundEdge(parent, element, label, other, kind) -select parent.getLocation().getStartLine(), parent, element.getLocation().getStartLine(), element, label, other.getLocation().getStartLine(), other, kind +select parent.getLocation().getStartLine(), parent, element.getLocation().getStartLine(), element, + label, other.getLocation().getStartLine(), other, kind diff --git a/cpp/ql/test/library-tests/pointsto/basic/sets.ql b/cpp/ql/test/library-tests/pointsto/basic/sets.ql index 7e5f82f5138..40eb94bb28f 100644 --- a/cpp/ql/test/library-tests/pointsto/basic/sets.ql +++ b/cpp/ql/test/library-tests/pointsto/basic/sets.ql @@ -2,70 +2,70 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -newtype TElementOrSet = MkElement(Element e) or MkSet(int i) { pointstosets(i, _) } +newtype TElementOrSet = + MkElement(Element e) or + MkSet(int i) { pointstosets(i, _) } class ElementOrSet extends TElementOrSet { - int asSet() { - this = MkSet(result) - } + int asSet() { this = MkSet(result) } - Element asElement() { - this = MkElement(result) - } + Element asElement() { this = MkElement(result) } - string toString() { - result = any(Element e | this = MkElement(e)).toString() or - result = any(int set | this = MkSet(set)).toString() - } + string toString() { + result = any(Element e | this = MkElement(e)).toString() or + result = any(int set | this = MkSet(set)).toString() + } } predicate isSetFlowEnd(boolean isEdge, int x, int y, string label) { - (setflow(x, _) or setflow(_, x)) - and isEdge = false - and x = y - and label = "set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + "}" + (setflow(x, _) or setflow(_, x)) and + isEdge = false and + x = y and + label = "set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + + "}" } predicate isSetFlow(boolean isEdge, int x, int y, string label) { - isEdge = true - and setflow(x, y) - and label = "sf" + isEdge = true and + setflow(x, y) and + label = "sf" } predicate isPointsToSetSrc(boolean isEdge, int x, int y, string label) { - pointstosets(x, _) - and isEdge = false - and x = y - and label = "set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + "}" + pointstosets(x, _) and + isEdge = false and + x = y and + label = "set: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + + "}" } predicate isPointsToSetDest(boolean isEdge, Element x, Element y, string label) { - exists(string loc, string name | - pointstosets(_, unresolveElement(x)) - and isEdge = false - and x = y - and (if exists(x.getLocation().toString()) - then loc = x.getLocation().toString() - else loc = "") - and (if exists(x.toString()) - then name = x.toString() - else name = "") - and label = loc + "\n" + name) + exists(string loc, string name | + pointstosets(_, unresolveElement(x)) and + isEdge = false and + x = y and + ( + if exists(x.getLocation().toString()) + then loc = x.getLocation().toString() + else loc = "" + ) and + (if exists(x.toString()) then name = x.toString() else name = "") and + label = loc + "\n" + name + ) } predicate isPointsToSets(boolean isEdge, int x, Element y, string label) { - isEdge = true - and pointstosets(x, unresolveElement(y)) - and label = "pt: {" - + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") - + "} -> " + y.toString() + isEdge = true and + pointstosets(x, unresolveElement(y)) and + label = "pt: {" + concat(Element e | pointstosets(x, unresolveElement(e)) | e.toString(), ", ") + + "} -> " + y.toString() } from boolean isEdge, ElementOrSet x, ElementOrSet y, string label -where isSetFlowEnd(isEdge, x.asSet(), y.asSet(), label) - or isSetFlow(isEdge, x.asSet(), y.asSet(), label) - or isPointsToSetSrc(isEdge, x.asSet(), y.asSet(), label) - or isPointsToSetDest(isEdge, x.asElement(), y.asElement(), label) - or isPointsToSets(isEdge, x.asSet(), y.asElement(), label) +where + isSetFlowEnd(isEdge, x.asSet(), y.asSet(), label) or + isSetFlow(isEdge, x.asSet(), y.asSet(), label) or + isPointsToSetSrc(isEdge, x.asSet(), y.asSet(), label) or + isPointsToSetDest(isEdge, x.asElement(), y.asElement(), label) or + isPointsToSets(isEdge, x.asSet(), y.asElement(), label) select "pointsto", isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/pointsto/more/PointsToExpr.ql b/cpp/ql/test/library-tests/pointsto/more/PointsToExpr.ql index 48d7c95a054..384327a5ac2 100644 --- a/cpp/ql/test/library-tests/pointsto/more/PointsToExpr.ql +++ b/cpp/ql/test/library-tests/pointsto/more/PointsToExpr.ql @@ -1,12 +1,11 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class ReturnPT extends PointsToExpr -{ - override predicate interesting() { - this instanceof VariableAccess and - this.getParent() instanceof ReturnStmt - } +class ReturnPT extends PointsToExpr { + override predicate interesting() { + this instanceof VariableAccess and + this.getParent() instanceof ReturnStmt + } } from ReturnPT return diff --git a/cpp/ql/test/library-tests/pointsto/new-virtual/PointsToNew.ql b/cpp/ql/test/library-tests/pointsto/new-virtual/PointsToNew.ql index fda36b8d34b..5227bb089c7 100644 --- a/cpp/ql/test/library-tests/pointsto/new-virtual/PointsToNew.ql +++ b/cpp/ql/test/library-tests/pointsto/new-virtual/PointsToNew.ql @@ -1,11 +1,8 @@ import cpp import semmle.code.cpp.pointsto.PointsTo -class MyPointsTo extends PointsToExpr -{ - override predicate interesting() { - any() - } +class MyPointsTo extends PointsToExpr { + override predicate interesting() { any() } } from MyPointsTo new, Element loc diff --git a/cpp/ql/test/library-tests/predefines/expr.ql b/cpp/ql/test/library-tests/predefines/expr.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/predefines/expr.ql +++ b/cpp/ql/test/library-tests/predefines/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/predefines/localVariables.ql b/cpp/ql/test/library-tests/predefines/localVariables.ql index a38e27f2e53..7d1430c7850 100644 --- a/cpp/ql/test/library-tests/predefines/localVariables.ql +++ b/cpp/ql/test/library-tests/predefines/localVariables.ql @@ -2,4 +2,3 @@ import cpp from LocalVariable lv select lv - diff --git a/cpp/ql/test/library-tests/preprocessor/dependent_defs/block.ql b/cpp/ql/test/library-tests/preprocessor/dependent_defs/block.ql index 574d0c02e38..9ead65d23d0 100644 --- a/cpp/ql/test/library-tests/preprocessor/dependent_defs/block.ql +++ b/cpp/ql/test/library-tests/preprocessor/dependent_defs/block.ql @@ -3,7 +3,5 @@ import cpp // A function might have more than one block if it's used in more than one // preprocessor context -- even if the preprocessor context does not affect the // blocks. - from Function f -select f, f.getBlock(), - count(f.getBlock()) +select f, f.getBlock(), count(f.getBlock()) diff --git a/cpp/ql/test/library-tests/preprocessor/dependent_defs/init.ql b/cpp/ql/test/library-tests/preprocessor/dependent_defs/init.ql index 7966a402f9b..e73df15ed12 100644 --- a/cpp/ql/test/library-tests/preprocessor/dependent_defs/init.ql +++ b/cpp/ql/test/library-tests/preprocessor/dependent_defs/init.ql @@ -3,7 +3,5 @@ import cpp // A variable may have more than one initializer because variables are merged // when they have the same name and appear in the same source file, but their // initializers are not merged. - from Variable v -select v, v.getInitializer().getExpr().getValue(), - count(v.getInitializer().getExpr().getValue()) +select v, v.getInitializer().getExpr().getValue(), count(v.getInitializer().getExpr().getValue()) diff --git a/cpp/ql/test/library-tests/preprocessor/hashing/hashing/macroAccess.ql b/cpp/ql/test/library-tests/preprocessor/hashing/hashing/macroAccess.ql index 92d7deb4094..f449631bfe5 100644 --- a/cpp/ql/test/library-tests/preprocessor/hashing/hashing/macroAccess.ql +++ b/cpp/ql/test/library-tests/preprocessor/hashing/hashing/macroAccess.ql @@ -3,4 +3,3 @@ import cpp from MacroAccess ma, Macro m where m = ma.getMacro() select ma, m - diff --git a/cpp/ql/test/library-tests/preprocessor/hashing/undef/preproc.ql b/cpp/ql/test/library-tests/preprocessor/hashing/undef/preproc.ql index 3fa4c9f6dbb..3a62c3b2d59 100644 --- a/cpp/ql/test/library-tests/preprocessor/hashing/undef/preproc.ql +++ b/cpp/ql/test/library-tests/preprocessor/hashing/undef/preproc.ql @@ -2,4 +2,3 @@ import cpp from PreprocessorDirective pd select pd - diff --git a/cpp/ql/test/library-tests/preprocessor/linedirective/linedirective.ql b/cpp/ql/test/library-tests/preprocessor/linedirective/linedirective.ql index 2a774e787ef..b96600bad20 100644 --- a/cpp/ql/test/library-tests/preprocessor/linedirective/linedirective.ql +++ b/cpp/ql/test/library-tests/preprocessor/linedirective/linedirective.ql @@ -1,7 +1,10 @@ import cpp from Element e, string comment -where (e instanceof Include or e instanceof DeclarationEntry or e instanceof Macro) -and (e.getFile().toString() != "") -and if exists(((Include)e).getIncludedFile()) then comment = ((Include)e).getIncludedFile().toString() else comment = "" +where + (e instanceof Include or e instanceof DeclarationEntry or e instanceof Macro) and + e.getFile().toString() != "" and + if exists(e.(Include).getIncludedFile()) + then comment = e.(Include).getIncludedFile().toString() + else comment = "" select e, comment diff --git a/cpp/ql/test/library-tests/preprocessor/macroinvocations/getanaffectedelement.ql b/cpp/ql/test/library-tests/preprocessor/macroinvocations/getanaffectedelement.ql index c361681075c..83ab99ccdfd 100644 --- a/cpp/ql/test/library-tests/preprocessor/macroinvocations/getanaffectedelement.ql +++ b/cpp/ql/test/library-tests/preprocessor/macroinvocations/getanaffectedelement.ql @@ -1,27 +1,33 @@ import cpp predicate reason(MacroInvocation mi, Element e, string reason) { - (mi.getAnAffectedElement() = e and reason = "getAnAffectedElement()") or - (mi.getAnExpandedElement() = e and reason = "getAnExpandedElement()") or - (mi.getAGeneratedElement() = e and reason = "getAGeneratedElement()") or - (mi.getExpr() = e and reason = "getExpr()") or - (mi.getStmt() = e and reason = "getStmt()") or - (mi.getEnclosingFunction() = e and reason = "getEnclosingFunction()") + mi.getAnAffectedElement() = e and reason = "getAnAffectedElement()" + or + mi.getAnExpandedElement() = e and reason = "getAnExpandedElement()" + or + mi.getAGeneratedElement() = e and reason = "getAGeneratedElement()" + or + mi.getExpr() = e and reason = "getExpr()" + or + mi.getStmt() = e and reason = "getStmt()" + or + mi.getEnclosingFunction() = e and reason = "getEnclosingFunction()" } string reasonspart(MacroInvocation mi, Element e) { - reason(mi, e, result) or - exists(string a, string b | - a = reasonspart(mi, e) and - reason(mi, e, b) and - not a.splitAt(" ") >= b and - result = a + " " + b - ) + reason(mi, e, result) + or + exists(string a, string b | + a = reasonspart(mi, e) and + reason(mi, e, b) and + not a.splitAt(" ") >= b and + result = a + " " + b + ) } string reasons(MacroInvocation mi, Element e) { - result = reasonspart(mi, e) and - not reasonspart(mi, e).length() > result.length() + result = reasonspart(mi, e) and + not reasonspart(mi, e).length() > result.length() } from MacroInvocation mi, Element e diff --git a/cpp/ql/test/library-tests/preprocessor/macroinvocations/macroinvocations.ql b/cpp/ql/test/library-tests/preprocessor/macroinvocations/macroinvocations.ql index 14bebd2ad73..d3569110432 100644 --- a/cpp/ql/test/library-tests/preprocessor/macroinvocations/macroinvocations.ql +++ b/cpp/ql/test/library-tests/preprocessor/macroinvocations/macroinvocations.ql @@ -1,11 +1,9 @@ import cpp from MacroAccess mi, string type, string parent -where if mi instanceof MacroInvocation - then type = "MacroInvocation" - else type = "MacroAccess" -and if exists(mi.getParentInvocation()) - then parent = mi.getParentInvocation().toString() - else parent = "none" - +where + (if mi instanceof MacroInvocation then type = "MacroInvocation" else type = "MacroAccess") and + if exists(mi.getParentInvocation()) + then parent = mi.getParentInvocation().toString() + else parent = "none" select mi, type, parent diff --git a/cpp/ql/test/library-tests/preprocessor/preprocessor/preproc.ql b/cpp/ql/test/library-tests/preprocessor/preprocessor/preproc.ql index 2ec13f88936..743d1524017 100644 --- a/cpp/ql/test/library-tests/preprocessor/preprocessor/preproc.ql +++ b/cpp/ql/test/library-tests/preprocessor/preprocessor/preproc.ql @@ -1,7 +1,9 @@ import cpp from Location loc, PreprocessorDirective pd, string head, string body -where loc = pd.getLocation() -and if exists(pd.getHead()) then head = pd.getHead() else head = "N/A" -and if pd instanceof Macro then body = ((Macro)pd).getBody() else body = "N/A" -select loc.getFile(), loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), concat(pd.getAQlClass(), ", "), head, body +where + loc = pd.getLocation() and + (if exists(pd.getHead()) then head = pd.getHead() else head = "N/A") and + if pd instanceof Macro then body = pd.(Macro).getBody() else body = "N/A" +select loc.getFile(), loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), + loc.getEndColumn(), concat(pd.getAQlClass(), ", "), head, body diff --git a/cpp/ql/test/library-tests/proxy_class/locations.ql b/cpp/ql/test/library-tests/proxy_class/locations.ql index 5d6e087f61e..79ad71f0861 100644 --- a/cpp/ql/test/library-tests/proxy_class/locations.ql +++ b/cpp/ql/test/library-tests/proxy_class/locations.ql @@ -1,9 +1,11 @@ import cpp string clazz(Declaration d) { - (d instanceof ProxyClass and result = "ProxyClass") or - (d instanceof TemplateParameter and result = "TemplateParameter") or - (d instanceof Struct and result = "Struct") + d instanceof ProxyClass and result = "ProxyClass" + or + d instanceof TemplateParameter and result = "TemplateParameter" + or + d instanceof Struct and result = "Struct" } from Declaration d diff --git a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.ql b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.ql index e2ff0353b03..530939c66c1 100644 --- a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.ql +++ b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e, e.getType() - diff --git a/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql b/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql index 48db95ba5a2..5fc88e0e037 100644 --- a/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql +++ b/cpp/ql/test/library-tests/qualifiers/class-enum/decls.ql @@ -2,4 +2,3 @@ import cpp from Declaration d select d, d.getQualifiedName() - diff --git a/cpp/ql/test/library-tests/qualifiers/class-enum/expr.ql b/cpp/ql/test/library-tests/qualifiers/class-enum/expr.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/qualifiers/class-enum/expr.ql +++ b/cpp/ql/test/library-tests/qualifiers/class-enum/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/question_mark_colon/cfg.ql b/cpp/ql/test/library-tests/question_mark_colon/cfg.ql index 65ea01a698f..bba0a160aaa 100644 --- a/cpp/ql/test/library-tests/question_mark_colon/cfg.ql +++ b/cpp/ql/test/library-tests/question_mark_colon/cfg.ql @@ -1,14 +1,10 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then result = n.getASuccessor().toString() - else result = "None" + if exists(n.getASuccessor()) then result = n.getASuccessor().toString() else result = "None" } from ControlFlowNode n select n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n, - getASuccessorOrNone(n) - + count(n.getAPredecessor*()), // This helps order things sensibly + n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCompleteness.ql b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCompleteness.ql index 97f70b54d01..232f64e7154 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCompleteness.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCompleteness.ql @@ -9,14 +9,17 @@ import cpp import semmle.code.cpp.rangeanalysis.RangeSSA -/* Count of number of uses of a LocalScopeVariable where no corresponding SSA definition exists, - but at least one SSA definition for that variable can reach that use. - Should always be zero *regardless* of the input */ -select -count(LocalScopeVariable v, Expr use | - exists(RangeSsaDefinition def, BasicBlock db, BasicBlock ub | - def.getAUse(v) = use and db.contains(def.getDefinition()) and ub.contains(use) | - db.getASuccessor+() = ub - ) - and not exists(RangeSsaDefinition def | def.getAUse(v) = use) -) \ No newline at end of file +/* + * Count of number of uses of a LocalScopeVariable where no corresponding SSA definition exists, + * but at least one SSA definition for that variable can reach that use. + * Should always be zero *regardless* of the input + */ + +select count(LocalScopeVariable v, Expr use | + exists(RangeSsaDefinition def, BasicBlock db, BasicBlock ub | + def.getAUse(v) = use and db.contains(def.getDefinition()) and ub.contains(use) + | + db.getASuccessor+() = ub + ) and + not exists(RangeSsaDefinition def | def.getAUse(v) = use) + ) diff --git a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCorrespondence.ql b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCorrespondence.ql index cdbe4297fe0..ecb71f8378b 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCorrespondence.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaCorrespondence.ql @@ -7,16 +7,19 @@ import cpp import semmle.code.cpp.rangeanalysis.RangeSSA -/* Count of number of reachable definitions or parameters where the no corresponding SSA definition exists. - Should always be zero *regardless* of the input */ +/* + * Count of number of reachable definitions or parameters where the no corresponding SSA definition exists. + * Should always be zero *regardless* of the input + */ -select -count(Variable v, ControlFlowNode def | var_definition(v, def) and not unreachable(def) and +select count(Variable v, ControlFlowNode def | + var_definition(v, def) and + not unreachable(def) and not exists(RangeSsaDefinition d | d.getAVariable() = v and d.getDefinition() = def) -) -+ -count(Parameter p | - exists(p.getAnAccess()) - and - not exists(RangeSsaDefinition d | d.getAVariable() = p and d.getDefinition() = p.getFunction().getEntryPoint()) -) + ) + + count(Parameter p | + exists(p.getAnAccess()) and + not exists(RangeSsaDefinition d | + d.getAVariable() = p and d.getDefinition() = p.getFunction().getEntryPoint() + ) + ) diff --git a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaDominance.ql b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaDominance.ql index 0ee7352d0a3..2f9fafef0ab 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaDominance.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaDominance.ql @@ -1,21 +1,26 @@ /** * @name SSA dominance property test - * @description SSA dominance property test. SSA definitions *must* dominate all uses + * @description SSA dominance property test. SSA definitions *must* dominate all uses * @kind test */ import cpp import semmle.code.cpp.rangeanalysis.RangeSSA -/* Count of number of SSA def-use pairs where the defn does not dominate the use. - Should always be zero *regardless* of the input */ +/* + * Count of number of SSA def-use pairs where the defn does not dominate the use. + * Should always be zero *regardless* of the input + */ -select -count(RangeSsaDefinition d, LocalScopeVariable v, Expr u | - d.getAUse(v) = u and - not exists(BasicBlock bd, BasicBlock bu | bd.contains(mkElement(d).(ControlFlowNode)) and bu.contains(u) | - bbStrictlyDominates(bd, bu) - or - exists(int i, int j | bd = bu and bd.getNode(i) = mkElement(d) and bu.getNode(j) = u and i <= j) - ) -) +select count(RangeSsaDefinition d, LocalScopeVariable v, Expr u | + d.getAUse(v) = u and + not exists(BasicBlock bd, BasicBlock bu | + bd.contains(mkElement(d).(ControlFlowNode)) and bu.contains(u) + | + bbStrictlyDominates(bd, bu) + or + exists(int i, int j | + bd = bu and bd.getNode(i) = mkElement(d) and bu.getNode(j) = u and i <= j + ) + ) + ) diff --git a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaPhiInputs.ql b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaPhiInputs.ql index e460ef557bc..2e1f038d136 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaPhiInputs.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaPhiInputs.ql @@ -7,8 +7,11 @@ import cpp import semmle.code.cpp.rangeanalysis.RangeSSA -from RangeSsaDefinition phi, LocalScopeVariable var, RangeSsaDefinition input, int philine, int inputline -where phi.getAPhiInput(var) = input and -philine = phi.getLocation().getStartLine() and -inputline = input.getLocation().getStartLine() +from + RangeSsaDefinition phi, LocalScopeVariable var, RangeSsaDefinition input, int philine, + int inputline +where + phi.getAPhiInput(var) = input and + philine = phi.getLocation().getStartLine() and + inputline = input.getLocation().getStartLine() select philine, phi.toString(var), inputline, input.toString(var) diff --git a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaUniqueness.ql b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaUniqueness.ql index acdafeaf67b..fda74759074 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaUniqueness.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/RangeSSA/RangeSsaUniqueness.ql @@ -7,11 +7,13 @@ import cpp import semmle.code.cpp.rangeanalysis.RangeSSA -/* Count of number of uses where the number of SSA definitions exceeds one. - Should always be zero *regardless* of the input */ +/* + * Count of number of uses where the number of SSA definitions exceeds one. + * Should always be zero *regardless* of the input + */ -select -count(RangeSsaDefinition d1, RangeSsaDefinition d2, Expr u, LocalScopeVariable v | - d1.getAUse(v) = u and - d2.getAUse(v) = u and not d1 = d2 -) +select count(RangeSsaDefinition d1, RangeSsaDefinition d2, Expr u, LocalScopeVariable v | + d1.getAUse(v) = u and + d2.getAUse(v) = u and + not d1 = d2 + ) diff --git a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.ql b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.ql index a779af1d5ec..b009ce5001f 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.ql @@ -3,15 +3,13 @@ import semmle.code.cpp.ir.IR import semmle.code.cpp.controlflow.IRGuards import semmle.code.cpp.ir.ValueNumbering -query predicate instructionBounds(Instruction i, Bound b, int delta, boolean upper, Reason reason, - Location reasonLoc) -{ +query predicate instructionBounds( + Instruction i, Bound b, int delta, boolean upper, Reason reason, Location reasonLoc +) { ( i.getAUse() instanceof ArgumentOperand or - exists(ReturnValueInstruction retInstr | - retInstr.getReturnValueOperand() = i.getAUse() - ) + exists(ReturnValueInstruction retInstr | retInstr.getReturnValueOperand() = i.getAUse()) ) and ( upper = true and @@ -20,8 +18,8 @@ query predicate instructionBounds(Instruction i, Bound b, int delta, boolean upp upper = false and delta = max(int d | boundedInstruction(i, b, d, upper, reason)) ) and - not valueNumber(b.getInstruction()) = valueNumber(i) - and if reason instanceof CondReason - then reasonLoc = reason.(CondReason).getCond().getLocation() - else reasonLoc instanceof UnknownDefaultLocation -} \ No newline at end of file + not valueNumber(b.getInstruction()) = valueNumber(i) and + if reason instanceof CondReason + then reasonLoc = reason.(CondReason).getCond().getLocation() + else reasonLoc instanceof UnknownDefaultLocation +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql index 9875a641627..fbfeb583283 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql +++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.ql @@ -16,4 +16,4 @@ string getASignString(Instruction i) { } from Instruction i -select i, strictconcat(string s | s = getASignString(i) | s, " ") \ No newline at end of file +select i, strictconcat(string s | s = getASignString(i) | s, " ") diff --git a/cpp/ql/test/library-tests/reachability/reachability.ql b/cpp/ql/test/library-tests/reachability/reachability.ql index f7984b3f9f7..d3952318629 100644 --- a/cpp/ql/test/library-tests/reachability/reachability.ql +++ b/cpp/ql/test/library-tests/reachability/reachability.ql @@ -3,4 +3,3 @@ import cpp from ControlFlowNode n where not reachable(n) select n - diff --git a/cpp/ql/test/library-tests/rvalueCast/rvalueCast.ql b/cpp/ql/test/library-tests/rvalueCast/rvalueCast.ql index 9225a2ce870..229a90c8407 100644 --- a/cpp/ql/test/library-tests/rvalueCast/rvalueCast.ql +++ b/cpp/ql/test/library-tests/rvalueCast/rvalueCast.ql @@ -1,7 +1,5 @@ import cpp from Function f -select f, - count(Expr e | f = e.getEnclosingFunction()), - count(ErrorExpr e | f = e.getEnclosingFunction()) - +select f, count(Expr e | f = e.getEnclosingFunction()), + count(ErrorExpr e | f = e.getEnclosingFunction()) diff --git a/cpp/ql/test/library-tests/scanf/scanfFormatLiteral.ql b/cpp/ql/test/library-tests/scanf/scanfFormatLiteral.ql index a77182d5ade..8588a4ea24b 100644 --- a/cpp/ql/test/library-tests/scanf/scanfFormatLiteral.ql +++ b/cpp/ql/test/library-tests/scanf/scanfFormatLiteral.ql @@ -1,4 +1,5 @@ import semmle.code.cpp.commons.Scanf from ScanfFormatLiteral sfl, int n -select sfl.getUse(), n, sfl.getConversionChar(n), sum(sfl.getMaxWidth(n)), sum(sfl.getMaxConvertedLength(n)) +select sfl.getUse(), n, sfl.getConversionChar(n), sum(sfl.getMaxWidth(n)), + sum(sfl.getMaxConvertedLength(n)) diff --git a/cpp/ql/test/library-tests/scopes/includes/function_info.ql b/cpp/ql/test/library-tests/scopes/includes/function_info.ql index 1ff5d3f6425..f708bbd89c1 100644 --- a/cpp/ql/test/library-tests/scopes/includes/function_info.ql +++ b/cpp/ql/test/library-tests/scopes/includes/function_info.ql @@ -1,7 +1,5 @@ import cpp from Function f, boolean cLinkage -where if f.hasCLinkage() - then cLinkage = true - else cLinkage = false +where if f.hasCLinkage() then cLinkage = true else cLinkage = false select f, f.getNamespace(), cLinkage diff --git a/cpp/ql/test/library-tests/scopes/parents/parents.ql b/cpp/ql/test/library-tests/scopes/parents/parents.ql index a917d89e38e..5a39412e932 100644 --- a/cpp/ql/test/library-tests/scopes/parents/parents.ql +++ b/cpp/ql/test/library-tests/scopes/parents/parents.ql @@ -3,6 +3,4 @@ import cpp from Element parent, Element child where parent = child.getParentScope() select count(parent.getParentScope()), // For sensible output ordering - parent, - child - + parent, child diff --git a/cpp/ql/test/library-tests/scopes/scopes/Scopes1.ql b/cpp/ql/test/library-tests/scopes/scopes/Scopes1.ql index b939fd12f54..fc88dde5936 100644 --- a/cpp/ql/test/library-tests/scopes/scopes/Scopes1.ql +++ b/cpp/ql/test/library-tests/scopes/scopes/Scopes1.ql @@ -2,30 +2,32 @@ * @name Scopes1 * @kind table */ + import cpp string describe(Element e) { - if e instanceof GlobalNamespace then ( - result = "GlobalNamespace" - ) else if e instanceof Namespace then ( - result = "Namespace" - ) else if e instanceof NestedClass then ( - result = "NestedClass" - ) else if e instanceof Class then ( - result = "Class" - ) else ( - result = "" - ) + if e instanceof GlobalNamespace + then result = "GlobalNamespace" + else + if e instanceof Namespace + then result = "Namespace" + else + if e instanceof NestedClass + then result = "NestedClass" + else + if e instanceof Class + then result = "Class" + else result = "" } from Element parent, Element child where - ( - parent instanceof Namespace or - parent instanceof Class or - child instanceof Namespace or - child instanceof Class - ) and - parent = child.getParentScope() and - child.toString() != "__va_list_tag" // platform dependent + ( + parent instanceof Namespace or + parent instanceof Class or + child instanceof Namespace or + child instanceof Class + ) and + parent = child.getParentScope() and + child.toString() != "__va_list_tag" // platform dependent select parent, describe(parent), child, describe(child) diff --git a/cpp/ql/test/library-tests/scopes/scopes/Scopes2.ql b/cpp/ql/test/library-tests/scopes/scopes/Scopes2.ql index abb9c5d572e..36101f1902b 100644 --- a/cpp/ql/test/library-tests/scopes/scopes/Scopes2.ql +++ b/cpp/ql/test/library-tests/scopes/scopes/Scopes2.ql @@ -2,20 +2,21 @@ * @name Scopes2 * @kind table */ + import cpp // This test finds places where Element.getParentScope() isn't tree-like. There // should be no results. from Element e, int i where - i = count(e.getParentScope()) and - ( - i > 1 or // multiple parents - e.getParentScope+() = e or // cyclic parent relation - ( - // not GlobalNamespace ancestor - i > 0 and - not e.getParentScope+() instanceof GlobalNamespace - ) - ) + i = count(e.getParentScope()) and + ( + i > 1 // multiple parents + or + e.getParentScope+() = e // cyclic parent relation + or + // not GlobalNamespace ancestor + i > 0 and + not e.getParentScope+() instanceof GlobalNamespace + ) select e, i diff --git a/cpp/ql/test/library-tests/scopes/scopes/Scopes3.ql b/cpp/ql/test/library-tests/scopes/scopes/Scopes3.ql index 6d5f4241767..79c9727a5e8 100644 --- a/cpp/ql/test/library-tests/scopes/scopes/Scopes3.ql +++ b/cpp/ql/test/library-tests/scopes/scopes/Scopes3.ql @@ -2,11 +2,12 @@ * @name Scopes3 * @kind table */ + import cpp from MemberFunction f, string constructor, Class declType, int countAtScope where - if f instanceof Constructor then constructor = "Constructor" else constructor = "" and - declType = f.getDeclaringType() and - countAtScope = count(Element other | other.getParentScope() = declType) + (if f instanceof Constructor then constructor = "Constructor" else constructor = "") and + declType = f.getDeclaringType() and + countAtScope = count(Element other | other.getParentScope() = declType) select f, constructor, declType, countAtScope diff --git a/cpp/ql/test/library-tests/scopes/scopes/Scopes4.ql b/cpp/ql/test/library-tests/scopes/scopes/Scopes4.ql index 2dbaf885694..e0318a3ef02 100644 --- a/cpp/ql/test/library-tests/scopes/scopes/Scopes4.ql +++ b/cpp/ql/test/library-tests/scopes/scopes/Scopes4.ql @@ -2,6 +2,7 @@ * @name Scopes4 * @kind table */ + import cpp from Function f, string top diff --git a/cpp/ql/test/library-tests/scopes/scopes/Scopes5.ql b/cpp/ql/test/library-tests/scopes/scopes/Scopes5.ql index ea99a8bbf85..09817b2a309 100644 --- a/cpp/ql/test/library-tests/scopes/scopes/Scopes5.ql +++ b/cpp/ql/test/library-tests/scopes/scopes/Scopes5.ql @@ -2,6 +2,7 @@ * @name Scopes5 * @kind table */ + import cpp from GlobalNamespace gn diff --git a/cpp/ql/test/library-tests/sideEffects/exprs/exprs.ql b/cpp/ql/test/library-tests/sideEffects/exprs/exprs.ql index 9d339d5ffc6..ea635d5194e 100644 --- a/cpp/ql/test/library-tests/sideEffects/exprs/exprs.ql +++ b/cpp/ql/test/library-tests/sideEffects/exprs/exprs.ql @@ -2,7 +2,7 @@ import cpp from Expr e, string pure, string impure, string globalimpure where - if e.isPure() then pure = "isPure" else pure = "" and - if e.mayBeImpure() then impure = "mayBeImpure" else impure = "" and - if e.mayBeGloballyImpure() then globalimpure = "mayBeGloballyImpure" else globalimpure = "" + (if e.isPure() then pure = "isPure" else pure = "") and + (if e.mayBeImpure() then impure = "mayBeImpure" else impure = "") and + if e.mayBeGloballyImpure() then globalimpure = "mayBeGloballyImpure" else globalimpure = "" select e, pure, impure, globalimpure diff --git a/cpp/ql/test/library-tests/sideEffects/functions/sideEffects.ql b/cpp/ql/test/library-tests/sideEffects/functions/sideEffects.ql index 9ced4033c4e..d2705040373 100644 --- a/cpp/ql/test/library-tests/sideEffects/functions/sideEffects.ql +++ b/cpp/ql/test/library-tests/sideEffects/functions/sideEffects.ql @@ -1,12 +1,13 @@ import cpp string functionType(Function f, int i) { - if exists(f.getParameter(i)) - then result = f.getParameter(i).getType().toString() + " -> " + functionType(f, i + 1) - else (i = f.getNumberOfParameters() and result = f.getType().toString()) + if exists(f.getParameter(i)) + then result = f.getParameter(i).getType().toString() + " -> " + functionType(f, i + 1) + else ( + i = f.getNumberOfParameters() and result = f.getType().toString() + ) } from Function f, boolean b where if f.isSideEffectFree() then b = true else b = false select f, functionType(f, 0), b - diff --git a/cpp/ql/test/library-tests/sideEffects/stmts/stmts.ql b/cpp/ql/test/library-tests/sideEffects/stmts/stmts.ql index a5b6d0ff415..fb998f6fc75 100644 --- a/cpp/ql/test/library-tests/sideEffects/stmts/stmts.ql +++ b/cpp/ql/test/library-tests/sideEffects/stmts/stmts.ql @@ -1,11 +1,7 @@ import cpp from Stmt s, boolean pure, boolean pureExceptLocals -where if s.isPure() - then pure = true - else pure = false - and if s.mayBeGloballyImpure() - then pureExceptLocals = false - else pureExceptLocals = true +where + (if s.isPure() then pure = true else pure = false) and + if s.mayBeGloballyImpure() then pureExceptLocals = false else pureExceptLocals = true select s, pure, pureExceptLocals - diff --git a/cpp/ql/test/library-tests/special_members/detect/detect.ql b/cpp/ql/test/library-tests/special_members/detect/detect.ql index 31f272b865c..2481d9abd41 100644 --- a/cpp/ql/test/library-tests/special_members/detect/detect.ql +++ b/cpp/ql/test/library-tests/special_members/detect/detect.ql @@ -1,23 +1,29 @@ import cpp string functionName(Function f) { - result = f.getQualifiedName() +"("+ f.getParameterString() +")" or + result = f.getQualifiedName() + "(" + f.getParameterString() + ")" + or not exists(f.getQualifiedName()) and - result = f.getName() +"("+ f.getParameterString() +")" + result = f.getName() + "(" + f.getParameterString() + ")" } from MemberFunction f, string description where - description = "1 constructor" - and f instanceof Constructor - and not f instanceof CopyConstructor - and not f instanceof MoveConstructor -or description = "2 copy constructor" and f instanceof CopyConstructor -or description = "3 move constructor" and f instanceof MoveConstructor -or description = "4 copy assignment" and f instanceof CopyAssignmentOperator -or description = "5 move assignment" and f instanceof MoveAssignmentOperator -or description = "6 none of the above" - and not f instanceof Constructor - and not f instanceof CopyAssignmentOperator - and not f instanceof MoveAssignmentOperator + description = "1 constructor" and + f instanceof Constructor and + not f instanceof CopyConstructor and + not f instanceof MoveConstructor + or + description = "2 copy constructor" and f instanceof CopyConstructor + or + description = "3 move constructor" and f instanceof MoveConstructor + or + description = "4 copy assignment" and f instanceof CopyAssignmentOperator + or + description = "5 move assignment" and f instanceof MoveAssignmentOperator + or + description = "6 none of the above" and + not f instanceof Constructor and + not f instanceof CopyAssignmentOperator and + not f instanceof MoveAssignmentOperator select description, functionName(f) diff --git a/cpp/ql/test/library-tests/special_members/generated_copy/assign.ql b/cpp/ql/test/library-tests/special_members/generated_copy/assign.ql index a264dd0e260..d7560a8f4b4 100644 --- a/cpp/ql/test/library-tests/special_members/generated_copy/assign.ql +++ b/cpp/ql/test/library-tests/special_members/generated_copy/assign.ql @@ -1,12 +1,10 @@ import cpp from Class c -where not c.getName().charAt(0) = "_" - and not c instanceof TemplateClass -select - c.getQualifiedName(), - any(string s | - if c.implicitCopyAssignmentOperatorDeleted() then s="can NOT" else s="can"), - any(string s | - if c.hasImplicitCopyAssignmentOperator() then s="does" else s="does NOT"), +where + not c.getName().charAt(0) = "_" and + not c instanceof TemplateClass +select c.getQualifiedName(), + any(string s | if c.implicitCopyAssignmentOperatorDeleted() then s = "can NOT" else s = "can"), + any(string s | if c.hasImplicitCopyAssignmentOperator() then s = "does" else s = "does NOT"), "have implicit copy assignment" diff --git a/cpp/ql/test/library-tests/special_members/generated_copy/ctor.ql b/cpp/ql/test/library-tests/special_members/generated_copy/ctor.ql index e2e8375da68..acbb1ccbca8 100644 --- a/cpp/ql/test/library-tests/special_members/generated_copy/ctor.ql +++ b/cpp/ql/test/library-tests/special_members/generated_copy/ctor.ql @@ -1,12 +1,10 @@ import cpp from Class c -where not c.getName().charAt(0) = "_" - and not c instanceof TemplateClass -select - c.getQualifiedName(), - any(string s | - if c.implicitCopyConstructorDeleted() then s="can NOT" else s="can"), - any(string s | - if c.hasImplicitCopyConstructor() then s="does" else s="does NOT"), +where + not c.getName().charAt(0) = "_" and + not c instanceof TemplateClass +select c.getQualifiedName(), + any(string s | if c.implicitCopyConstructorDeleted() then s = "can NOT" else s = "can"), + any(string s | if c.hasImplicitCopyConstructor() then s = "does" else s = "does NOT"), "have implicit copy constructor" diff --git a/cpp/ql/test/library-tests/special_members/generated_copy/functions.ql b/cpp/ql/test/library-tests/special_members/generated_copy/functions.ql index d7a59a882f6..525eba0fd9e 100644 --- a/cpp/ql/test/library-tests/special_members/generated_copy/functions.ql +++ b/cpp/ql/test/library-tests/special_members/generated_copy/functions.ql @@ -1,7 +1,7 @@ import cpp from Function f, string deleted, string defaulted -where if f.isDeleted() then deleted = "deleted" else deleted = "" - and if f.isDefaulted() then defaulted = "defaulted" else defaulted = "" +where + (if f.isDeleted() then deleted = "deleted" else deleted = "") and + if f.isDefaulted() then defaulted = "defaulted" else defaulted = "" select f, deleted, defaulted - diff --git a/cpp/ql/test/library-tests/specifiers/Specifiers1.ql b/cpp/ql/test/library-tests/specifiers/Specifiers1.ql index 8d58e624a70..ab5b2aeb3be 100644 --- a/cpp/ql/test/library-tests/specifiers/Specifiers1.ql +++ b/cpp/ql/test/library-tests/specifiers/Specifiers1.ql @@ -1,10 +1,9 @@ /** * @name Specifiers1 */ + import cpp from Variable v where v.isConst() -select v.getLocation().getStartLine(), - v - +select v.getLocation().getStartLine(), v diff --git a/cpp/ql/test/library-tests/specifiers/Specifiers2.ql b/cpp/ql/test/library-tests/specifiers/Specifiers2.ql index 5174adba0bd..eff31301259 100644 --- a/cpp/ql/test/library-tests/specifiers/Specifiers2.ql +++ b/cpp/ql/test/library-tests/specifiers/Specifiers2.ql @@ -1,10 +1,9 @@ /** * @name Specifiers2 */ + import cpp from Variable v where v.hasSpecifier("extern") -select v.getLocation().getStartLine(), - v.getName() - +select v.getLocation().getStartLine(), v.getName() diff --git a/cpp/ql/test/library-tests/specifiers/Specifiers3.ql b/cpp/ql/test/library-tests/specifiers/Specifiers3.ql index 8f2717b3e4a..358ca445aec 100644 --- a/cpp/ql/test/library-tests/specifiers/Specifiers3.ql +++ b/cpp/ql/test/library-tests/specifiers/Specifiers3.ql @@ -1,11 +1,11 @@ /** * @name Specifiers3 */ + import cpp from Variable v, Type t -where v.getType() = t - and t.isConst() -select v.getLocation().getStartLine(), - v - +where + v.getType() = t and + t.isConst() +select v.getLocation().getStartLine(), v diff --git a/cpp/ql/test/library-tests/specifiers2/specifiers2.ql b/cpp/ql/test/library-tests/specifiers2/specifiers2.ql index 294b0616ed8..39663d98219 100644 --- a/cpp/ql/test/library-tests/specifiers2/specifiers2.ql +++ b/cpp/ql/test/library-tests/specifiers2/specifiers2.ql @@ -1,23 +1,29 @@ import cpp string interesting(Element e) { - (e instanceof Class and result = "Class") or - (e instanceof Function and result = "Function") or - (e instanceof FunctionDeclarationEntry and result = "FunctionDeclarationEntry") or - (e instanceof TypedefType and result = "TypedefType") or - (e instanceof Variable and result = "Variable") or - (e instanceof VariableDeclarationEntry and result = "VariableDeclarationEntry") + e instanceof Class and result = "Class" + or + e instanceof Function and result = "Function" + or + e instanceof FunctionDeclarationEntry and result = "FunctionDeclarationEntry" + or + e instanceof TypedefType and result = "TypedefType" + or + e instanceof Variable and result = "Variable" + or + e instanceof VariableDeclarationEntry and result = "VariableDeclarationEntry" } from Element e, string name, string specifier where - ( - name = e.(Declaration).getName() or - name = e.(DeclarationEntry).getName() or - name = e.(Type).toString() - ) and ( - specifier = e.(Declaration).getASpecifier().toString() or - specifier = e.(DeclarationEntry).getASpecifier() or - specifier = e.(TypedefType).getBaseType().getASpecifier().toString() - ) + ( + name = e.(Declaration).getName() or + name = e.(DeclarationEntry).getName() or + name = e.(Type).toString() + ) and + ( + specifier = e.(Declaration).getASpecifier().toString() or + specifier = e.(DeclarationEntry).getASpecifier() or + specifier = e.(TypedefType).getBaseType().getASpecifier().toString() + ) select interesting(e), e, name, specifier diff --git a/cpp/ql/test/library-tests/specifiers2/specifiers2d.ql b/cpp/ql/test/library-tests/specifiers2/specifiers2d.ql index a0a8138a062..2c60fa42650 100644 --- a/cpp/ql/test/library-tests/specifiers2/specifiers2d.ql +++ b/cpp/ql/test/library-tests/specifiers2/specifiers2d.ql @@ -2,7 +2,4 @@ import cpp from Variable v, Type t where t = v.getType() -select v, - t, - t.getASpecifier() - +select v, t, t.getASpecifier() diff --git a/cpp/ql/test/library-tests/specifiers3/unspecified_member_var_types.ql b/cpp/ql/test/library-tests/specifiers3/unspecified_member_var_types.ql index 9b4c8645f5b..451cdb6ff98 100644 --- a/cpp/ql/test/library-tests/specifiers3/unspecified_member_var_types.ql +++ b/cpp/ql/test/library-tests/specifiers3/unspecified_member_var_types.ql @@ -1,4 +1,4 @@ import cpp from Struct s -select s, s.getAMemberVariable() as v, v.getType() as t, t.getUnspecifiedType() as u \ No newline at end of file +select s, s.getAMemberVariable() as v, v.getType() as t, t.getUnspecifiedType() as u diff --git a/cpp/ql/test/library-tests/static_cast/expr.ql b/cpp/ql/test/library-tests/static_cast/expr.ql index 3c2a3269e72..2f525817cb2 100644 --- a/cpp/ql/test/library-tests/static_cast/expr.ql +++ b/cpp/ql/test/library-tests/static_cast/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e - diff --git a/cpp/ql/test/library-tests/stmt/generated_blocks/stmt.ql b/cpp/ql/test/library-tests/stmt/generated_blocks/stmt.ql index 834687f6c9a..10089a65980 100644 --- a/cpp/ql/test/library-tests/stmt/generated_blocks/stmt.ql +++ b/cpp/ql/test/library-tests/stmt/generated_blocks/stmt.ql @@ -1,44 +1,33 @@ import cpp -newtype TMaybeStmtParent = TStmtParent(StmtParent p) or TNoStmtParent() +newtype TMaybeStmtParent = + TStmtParent(StmtParent p) or + TNoStmtParent() class MaybeStmtParent extends TMaybeStmtParent { abstract string toString(); + abstract Location getLocation(); } class YesMaybeStmtParent extends MaybeStmtParent { StmtParent p; - YesMaybeStmtParent() { - this = TStmtParent(p) - } + YesMaybeStmtParent() { this = TStmtParent(p) } - override string toString() { - result = p.toString() - } + override string toString() { result = p.toString() } - override Location getLocation() { - result = p.getLocation() - } + override Location getLocation() { result = p.getLocation() } - StmtParent getStmtParent() { - result = p - } + StmtParent getStmtParent() { result = p } } class NoMaybeStmtParent extends MaybeStmtParent { - NoMaybeStmtParent() { - this = TNoStmtParent() - } + NoMaybeStmtParent() { this = TNoStmtParent() } - override string toString() { - result = "" - } + override string toString() { result = "" } - override Location getLocation() { - result instanceof UnknownLocation - } + override Location getLocation() { result instanceof UnknownLocation } } MaybeStmtParent parent(Stmt s) { @@ -49,4 +38,3 @@ MaybeStmtParent parent(Stmt s) { from Stmt s select s, parent(s) - diff --git a/cpp/ql/test/library-tests/stmt/stmt/stmt.ql b/cpp/ql/test/library-tests/stmt/stmt/stmt.ql index b574c337860..45d3f3e02ce 100644 --- a/cpp/ql/test/library-tests/stmt/stmt/stmt.ql +++ b/cpp/ql/test/library-tests/stmt/stmt/stmt.ql @@ -1,6 +1,7 @@ import cpp from Stmt s, string empty, string asm -where if s instanceof EmptyStmt then empty = "EmptyStmt" else empty = "" -and if s instanceof AsmStmt then asm = "AsmStmt" else asm = "" +where + (if s instanceof EmptyStmt then empty = "EmptyStmt" else empty = "") and + if s instanceof AsmStmt then asm = "AsmStmt" else asm = "" select s, empty + asm diff --git a/cpp/ql/test/library-tests/stmt_expr/cfg.ql b/cpp/ql/test/library-tests/stmt_expr/cfg.ql index 6d8f598ab6d..b6699eaee11 100644 --- a/cpp/ql/test/library-tests/stmt_expr/cfg.ql +++ b/cpp/ql/test/library-tests/stmt_expr/cfg.ql @@ -2,14 +2,11 @@ import cpp import semmle.code.cpp.exprs.ObjectiveC from ControlFlowNode x, ControlFlowNode y, string entryPoint -where y = x.getASuccessor() - and if exists(Function f | f.getEntryPoint() = x) - then forex(Function f | f.getEntryPoint() = x | entryPoint = f.toString()) - else entryPoint = "-----" +where + y = x.getASuccessor() and + if exists(Function f | f.getEntryPoint() = x) + then forex(Function f | f.getEntryPoint() = x | entryPoint = f.toString()) + else entryPoint = "-----" select x.getLocation().getStartLine(), - count(x.getAPredecessor*()), // This helps order things sensibly - x.toString(), - entryPoint, - y.getLocation().getStartLine(), - y.toString() - + count(x.getAPredecessor*()), // This helps order things sensibly + x.toString(), entryPoint, y.getLocation().getStartLine(), y.toString() diff --git a/cpp/ql/test/library-tests/string_analysis/StringAnalysis.ql b/cpp/ql/test/library-tests/string_analysis/StringAnalysis.ql index d500fcdef81..eda9acae5d9 100644 --- a/cpp/ql/test/library-tests/string_analysis/StringAnalysis.ql +++ b/cpp/ql/test/library-tests/string_analysis/StringAnalysis.ql @@ -2,13 +2,12 @@ * @name StringAnalysis * @kind table */ + import cpp from AnalysedString s, string str where - if s.(StringLiteral).getUnspecifiedType().(DerivedType).getBaseType() instanceof Wchar_t then ( - str = "[?]" - ) else ( - str = s.toString() - ) + if s.(StringLiteral).getUnspecifiedType().(DerivedType).getBaseType() instanceof Wchar_t + then str = "[?]" + else str = s.toString() select s.getLocation().toString(), str, s.getMaxLength() diff --git a/cpp/ql/test/library-tests/string_literals/string_literals.ql b/cpp/ql/test/library-tests/string_literals/string_literals.ql index 7c901174e3a..05633da2554 100644 --- a/cpp/ql/test/library-tests/string_literals/string_literals.ql +++ b/cpp/ql/test/library-tests/string_literals/string_literals.ql @@ -2,4 +2,3 @@ import cpp from StringLiteral l select l - diff --git a/cpp/ql/test/library-tests/string_literals_nul/string_literals_nul.ql b/cpp/ql/test/library-tests/string_literals_nul/string_literals_nul.ql index 6349271e42b..b415ec150cd 100644 --- a/cpp/ql/test/library-tests/string_literals_nul/string_literals_nul.ql +++ b/cpp/ql/test/library-tests/string_literals_nul/string_literals_nul.ql @@ -1,7 +1,4 @@ import cpp from StringLiteral s -select s.getLocation().getStartLine(), - s, - s.getValueText() - +select s.getLocation().getStartLine(), s, s.getValueText() diff --git a/cpp/ql/test/library-tests/structs/compatible_c/compatible.ql b/cpp/ql/test/library-tests/structs/compatible_c/compatible.ql index c41a2fe45bc..cf0b47ab28d 100644 --- a/cpp/ql/test/library-tests/structs/compatible_c/compatible.ql +++ b/cpp/ql/test/library-tests/structs/compatible_c/compatible.ql @@ -2,9 +2,7 @@ import cpp from Struct s, int i, string m, string members, string locations where - if exists(s.getAMember()) - then m = s.getAMember(i).toString() - else (m = "" and i = -1) - and members = count(s.getAMember()) + " members" - and locations = count(s.getLocation()) + " locations" + (if exists(s.getAMember()) then m = s.getAMember(i).toString() else (m = "" and i = -1)) and + members = count(s.getAMember()) + " members" and + locations = count(s.getLocation()) + " locations" select s, members, locations, i, m diff --git a/cpp/ql/test/library-tests/structs/compatible_c/compatible_types.ql b/cpp/ql/test/library-tests/structs/compatible_c/compatible_types.ql index 45905ccae60..7d5356415ac 100644 --- a/cpp/ql/test/library-tests/structs/compatible_c/compatible_types.ql +++ b/cpp/ql/test/library-tests/structs/compatible_c/compatible_types.ql @@ -3,7 +3,6 @@ import cpp // Some structs have multiple definitions, but those definitions use different // (but compatible) field types. With this query we can check getType() always // returns a single result. - from Struct s, MemberVariable mv, int i, Type t, string types where mv = s.getAMember(i) and diff --git a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.ql b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.ql index dea9634a98b..77426ef6efa 100644 --- a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.ql +++ b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.ql @@ -2,9 +2,7 @@ import cpp from Class c, int i, string m, string members, string locations where - if exists(c.getAMember()) - then m = c.getAMember(i).toString() - else (m = "" and i = -1) - and members = count(c.getAMember()) + " members" - and locations = count(c.getLocation()) + " locations" + (if exists(c.getAMember()) then m = c.getAMember(i).toString() else (m = "" and i = -1)) and + members = count(c.getAMember()) + " members" and + locations = count(c.getLocation()) + " locations" select c, members, locations, i, m diff --git a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.ql b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.ql index 31058e84568..f62280068d5 100644 --- a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.ql +++ b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.ql @@ -3,7 +3,6 @@ import cpp // Some structs have multiple definitions, but those definitions use different // (but compatible) field types. With this query we can check getType() always // returns a single result. - from Class c, MemberVariable mv, int i, Type t, string types where mv = c.getAMember(i) and diff --git a/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_members.ql b/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_members.ql index c41a2fe45bc..cf0b47ab28d 100644 --- a/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_members.ql +++ b/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_members.ql @@ -2,9 +2,7 @@ import cpp from Struct s, int i, string m, string members, string locations where - if exists(s.getAMember()) - then m = s.getAMember(i).toString() - else (m = "" and i = -1) - and members = count(s.getAMember()) + " members" - and locations = count(s.getLocation()) + " locations" + (if exists(s.getAMember()) then m = s.getAMember(i).toString() else (m = "" and i = -1)) and + members = count(s.getAMember()) + " members" and + locations = count(s.getLocation()) + " locations" select s, members, locations, i, m diff --git a/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_structs.ql b/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_structs.ql index 9fb7cc296ca..602b37e0b29 100644 --- a/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_structs.ql +++ b/cpp/ql/test/library-tests/structs/mutual_recursion/compatible_structs.ql @@ -2,7 +2,6 @@ import cpp from Struct s, string distinct where - distinct = count(Struct x | x.getName() = s.getName()) - + " different struct(s) called " - + s.getName() + distinct = count(Struct x | x.getName() = s.getName()) + " different struct(s) called " + + s.getName() select s, distinct diff --git a/cpp/ql/test/library-tests/structs/structs/structs.ql b/cpp/ql/test/library-tests/structs/structs/structs.ql index ce9ac855b75..527f31ea939 100644 --- a/cpp/ql/test/library-tests/structs/structs/structs.ql +++ b/cpp/ql/test/library-tests/structs/structs/structs.ql @@ -1,14 +1,11 @@ import cpp -string describe(Struct s) -{ - ( - s instanceof LocalStruct and - result = "LocalStruct" - ) or ( - s instanceof NestedStruct and - result = "NestedStruct" - ) +string describe(Struct s) { + s instanceof LocalStruct and + result = "LocalStruct" + or + s instanceof NestedStruct and + result = "NestedStruct" } query predicate structs(Struct s, string descStr) { diff --git a/cpp/ql/test/library-tests/sub_basic_blocks/cut.ql b/cpp/ql/test/library-tests/sub_basic_blocks/cut.ql index 0dfa5032ab7..2d89bd3cf95 100644 --- a/cpp/ql/test/library-tests/sub_basic_blocks/cut.ql +++ b/cpp/ql/test/library-tests/sub_basic_blocks/cut.ql @@ -2,12 +2,9 @@ import sbb_test class CutCall extends SubBasicBlockCutNode { - CutCall() { - mkElement(this).(FunctionCall).getTarget().getName() = "cut" - } + CutCall() { mkElement(this).(FunctionCall).getTarget().getName() = "cut" } } from boolean isEdge, SubBasicBlock x, SubBasicBlock y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select x.getEnclosingFunction().toString(), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/sub_basic_blocks/getNode.ql b/cpp/ql/test/library-tests/sub_basic_blocks/getNode.ql index 593ad94d009..60f61f95182 100644 --- a/cpp/ql/test/library-tests/sub_basic_blocks/getNode.ql +++ b/cpp/ql/test/library-tests/sub_basic_blocks/getNode.ql @@ -1,9 +1,7 @@ import sbb_test class CutCall extends SubBasicBlockCutNode { - CutCall() { - mkElement(this).(FunctionCall).getTarget().getName() = "cut" - } + CutCall() { mkElement(this).(FunctionCall).getTarget().getName() = "cut" } } from SubBasicBlock sbb, int i diff --git a/cpp/ql/test/library-tests/sub_basic_blocks/no_cut.ql b/cpp/ql/test/library-tests/sub_basic_blocks/no_cut.ql index f4e194c0793..1f1a6b3eb77 100644 --- a/cpp/ql/test/library-tests/sub_basic_blocks/no_cut.ql +++ b/cpp/ql/test/library-tests/sub_basic_blocks/no_cut.ql @@ -2,8 +2,6 @@ import sbb_test // Note: no instance of `SubBasicBlockCutNode` - from boolean isEdge, SubBasicBlock x, SubBasicBlock y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select x.getEnclosingFunction().toString(), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/sub_basic_blocks/sbb_test.qll b/cpp/ql/test/library-tests/sub_basic_blocks/sbb_test.qll index 3af0841cdd3..3c761d9847f 100644 --- a/cpp/ql/test/library-tests/sub_basic_blocks/sbb_test.qll +++ b/cpp/ql/test/library-tests/sub_basic_blocks/sbb_test.qll @@ -2,30 +2,27 @@ import cpp import semmle.code.cpp.controlflow.SubBasicBlocks string subBasicBlockDebugInfo(SubBasicBlock sbb) { - result = sbb.getStart().toString() + - " [line " + sbb.getStart().getLocation().getStartLine() + "-" + - sbb.getEnd().getLocation().getEndLine() + ", " + - sbb.getNumberOfNodes() + " nodes, " + - "pos " + (sbb.getRankInBasicBlock(_) - 1) + - any(string s | if sbb.firstInBB() then s = " (first in BB)" else s = "") + - any(string s | if sbb.lastInBB() then s = " (last in BB)" else s = "") + - ", " + - count(sbb.getAPredecessor()) + " predecessors, " + - count(sbb.getASuccessor()) + " successors" + - "]" + result = sbb.getStart().toString() + " [line " + sbb.getStart().getLocation().getStartLine() + "-" + + sbb.getEnd().getLocation().getEndLine() + ", " + sbb.getNumberOfNodes() + " nodes, " + + "pos " + (sbb.getRankInBasicBlock(_) - 1) + + any(string s | if sbb.firstInBB() then s = " (first in BB)" else s = "") + + any(string s | if sbb.lastInBB() then s = " (last in BB)" else s = "") + ", " + + count(sbb.getAPredecessor()) + " predecessors, " + count(sbb.getASuccessor()) + " successors" + + "]" } predicate isNode(boolean isEdge, SubBasicBlock x, SubBasicBlock y, string label) { - isEdge = false and - x = y and - label = subBasicBlockDebugInfo(x) + isEdge = false and + x = y and + label = subBasicBlockDebugInfo(x) } predicate isSuccessor(boolean isEdge, SubBasicBlock x, SubBasicBlock y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } diff --git a/cpp/ql/test/library-tests/switch/blocks.ql b/cpp/ql/test/library-tests/switch/blocks.ql index e24e5670bd7..794c597d9a9 100644 --- a/cpp/ql/test/library-tests/switch/blocks.ql +++ b/cpp/ql/test/library-tests/switch/blocks.ql @@ -3,4 +3,3 @@ import cpp from Function f, Block b where b = f.getEntryPoint() select f, b, b.getAStmt() - diff --git a/cpp/ql/test/library-tests/switch/switchcase.ql b/cpp/ql/test/library-tests/switch/switchcase.ql index 31cf19d5fe9..cd70ff782ce 100644 --- a/cpp/ql/test/library-tests/switch/switchcase.ql +++ b/cpp/ql/test/library-tests/switch/switchcase.ql @@ -1,13 +1,22 @@ import cpp from SwitchCase sc, Element e, string reason -where (e = sc.getExpr() and reason = "getExpr") - or (e = sc.getEndExpr() and reason = "getEndExpr") - or (e = sc.getSwitchStmt() and reason = "getSwitchStmt") - or (e = sc.getNextSwitchCase() and reason = "getNextSwitchCase") - or (e = sc.getPreviousSwitchCase() and reason = "getPreviousSwitchCase") - or (e = sc.getLastStmt() and reason = "getLastStmt") - or (e = sc and sc.terminatesInBreakStmt() and reason = "terminatesInBreakStmt()") - or (e = sc and sc.terminatesInReturnStmt() and reason = "terminatesInReturnStmt()") - or (e = sc and sc.terminatesInThrowStmt() and reason = "terminatesInThrowStmt()") +where + e = sc.getExpr() and reason = "getExpr" + or + e = sc.getEndExpr() and reason = "getEndExpr" + or + e = sc.getSwitchStmt() and reason = "getSwitchStmt" + or + e = sc.getNextSwitchCase() and reason = "getNextSwitchCase" + or + e = sc.getPreviousSwitchCase() and reason = "getPreviousSwitchCase" + or + e = sc.getLastStmt() and reason = "getLastStmt" + or + e = sc and sc.terminatesInBreakStmt() and reason = "terminatesInBreakStmt()" + or + e = sc and sc.terminatesInReturnStmt() and reason = "terminatesInReturnStmt()" + or + e = sc and sc.terminatesInThrowStmt() and reason = "terminatesInThrowStmt()" select sc, e, reason diff --git a/cpp/ql/test/library-tests/switch/switchstmt.ql b/cpp/ql/test/library-tests/switch/switchstmt.ql index fd47c0620f1..0390d9505ca 100644 --- a/cpp/ql/test/library-tests/switch/switchstmt.ql +++ b/cpp/ql/test/library-tests/switch/switchstmt.ql @@ -1,8 +1,12 @@ import cpp from SwitchStmt ss, Element e, string reason -where (e = ss.getExpr() and reason = "getExpr") - or (e = ss.getStmt() and reason = "getStmt") - or (e = ss.getASwitchCase() and reason = "getASwitchCase") - or (e = ss.getDefaultCase() and reason = "getDefaultCase") +where + e = ss.getExpr() and reason = "getExpr" + or + e = ss.getStmt() and reason = "getStmt" + or + e = ss.getASwitchCase() and reason = "getASwitchCase" + or + e = ss.getDefaultCase() and reason = "getDefaultCase" select ss, e.getLocation().getStartLine(), e, reason diff --git a/cpp/ql/test/library-tests/switch_cfg/cfg.ql b/cpp/ql/test/library-tests/switch_cfg/cfg.ql index 2c1503bc78f..6d3ffe8f9ef 100644 --- a/cpp/ql/test/library-tests/switch_cfg/cfg.ql +++ b/cpp/ql/test/library-tests/switch_cfg/cfg.ql @@ -1,17 +1,15 @@ import cpp string successorInfo(ControlFlowNode x) { - if exists(x.getASuccessor()) - then exists(ControlFlowNode y | - y = x.getASuccessor() | - result = y.getLocation().getStartLine().toString() + " " - + y.toString()) - else result = "" + if exists(x.getASuccessor()) + then + exists(ControlFlowNode y | y = x.getASuccessor() | + result = y.getLocation().getStartLine().toString() + " " + y.toString() + ) + else result = "" } from ControlFlowNode x select x.getLocation().getStartLine(), - count(x.getAPredecessor*()), // This helps order things sensibly - x.toString(), - successorInfo(x) - + count(x.getAPredecessor*()), // This helps order things sensibly + x.toString(), successorInfo(x) diff --git a/cpp/ql/test/library-tests/synchronization/mutextype.ql b/cpp/ql/test/library-tests/synchronization/mutextype.ql index 728a181a3a6..fe565a0cd4f 100644 --- a/cpp/ql/test/library-tests/synchronization/mutextype.ql +++ b/cpp/ql/test/library-tests/synchronization/mutextype.ql @@ -3,20 +3,18 @@ import testoptions from MutexType mt, string s, Element e where - ( - s = "is MutexType" and - e = mt - ) or ( - s = "getLockAccess()" and - e = mt.getLockAccess() - ) or ( - s = "getMustlockAccess()" and - e = mt.getMustlockAccess() - ) or ( - s = "getTrylockAccess()" and - e = mt.getTrylockAccess() - ) or ( - s = "getUnlockAccess()" and - e = mt.getUnlockAccess() - ) + s = "is MutexType" and + e = mt + or + s = "getLockAccess()" and + e = mt.getLockAccess() + or + s = "getMustlockAccess()" and + e = mt.getMustlockAccess() + or + s = "getTrylockAccess()" and + e = mt.getTrylockAccess() + or + s = "getUnlockAccess()" and + e = mt.getUnlockAccess() select mt, s, e diff --git a/cpp/ql/test/library-tests/synchronization/synchronization.ql b/cpp/ql/test/library-tests/synchronization/synchronization.ql index 962d2616e0b..6c4d4e6c244 100644 --- a/cpp/ql/test/library-tests/synchronization/synchronization.ql +++ b/cpp/ql/test/library-tests/synchronization/synchronization.ql @@ -3,17 +3,15 @@ import testoptions from FunctionCall call, string s, Expr arg where - ( - s = "lockCall" and - lockCall(arg, call) - ) or ( - s = "mustlockCall" and - mustlockCall(arg, call) - ) or ( - s = "trylockCall" and - trylockCall(arg, call) - ) or ( - s = "unlockCall" and - unlockCall(arg, call) - ) + s = "lockCall" and + lockCall(arg, call) + or + s = "mustlockCall" and + mustlockCall(arg, call) + or + s = "trylockCall" and + trylockCall(arg, call) + or + s = "unlockCall" and + unlockCall(arg, call) select call, s, arg diff --git a/cpp/ql/test/library-tests/synchronization/testoptions.qll b/cpp/ql/test/library-tests/synchronization/testoptions.qll index 793a478cf37..f8bce32c4c6 100644 --- a/cpp/ql/test/library-tests/synchronization/testoptions.qll +++ b/cpp/ql/test/library-tests/synchronization/testoptions.qll @@ -1,9 +1,7 @@ import cpp class MutexTypeForTest extends MutexType { - MutexTypeForTest() { - this.(Class).getName() = "Mutex7" - } + MutexTypeForTest() { this.(Class).getName() = "Mutex7" } override predicate mustlockAccess(FunctionCall fc, Expr arg) { exists(Function f | @@ -14,9 +12,7 @@ class MutexTypeForTest extends MutexType { ) } - override predicate trylockAccess(FunctionCall fc, Expr arg) { - none() - } + override predicate trylockAccess(FunctionCall fc, Expr arg) { none() } override predicate unlockAccess(FunctionCall fc, Expr arg) { exists(Function f | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql index 1e88fee7854..5b80f3c92a0 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql +++ b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql @@ -2,10 +2,9 @@ import Compare from - Element scopeElement, - string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label + Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y, + string label where AllCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label) and differentScope(scopeElement) -select - scopeString, isEdge, x, y, label +select scopeString, isEdge, x, y, label diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql index 4461f3617c2..e1bd8c99b78 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql +++ b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql @@ -1,8 +1,5 @@ import Compare -from - ControlFlowNode n1, ControlFlowNode n2, string msg -where - differentEdge(n1, n2, msg) -select - getScopeName(n1), n1, n2, msg +from ControlFlowNode n1, ControlFlowNode n2, string msg +where differentEdge(n1, n2, msg) +select getScopeName(n1), n1, n2, msg diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.ql b/cpp/ql/test/library-tests/templates/CPP-202/template_args.ql index 3666df9cf59..940daeab0e5 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.ql +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.ql @@ -1,8 +1,8 @@ import cpp from Class c, string arg -where if exists(c.getATemplateArgument()) - then arg = c.getATemplateArgument().toString() - else arg = "" +where + if exists(c.getATemplateArgument()) + then arg = c.getATemplateArgument().toString() + else arg = "" select c, arg - diff --git a/cpp/ql/test/library-tests/templates/CPP-203/decls.ql b/cpp/ql/test/library-tests/templates/CPP-203/decls.ql index 6df6c775d59..9b23aa4867d 100644 --- a/cpp/ql/test/library-tests/templates/CPP-203/decls.ql +++ b/cpp/ql/test/library-tests/templates/CPP-203/decls.ql @@ -2,4 +2,3 @@ import cpp from Declaration d select d - diff --git a/cpp/ql/test/library-tests/templates/CPP-204/element.ql b/cpp/ql/test/library-tests/templates/CPP-204/element.ql index 38b30a22722..b7a1275f388 100644 --- a/cpp/ql/test/library-tests/templates/CPP-204/element.ql +++ b/cpp/ql/test/library-tests/templates/CPP-204/element.ql @@ -1,7 +1,8 @@ import cpp from Element e -where not e instanceof BuiltInType - and not e instanceof Specifier - and not e instanceof Folder +where + not e instanceof BuiltInType and + not e instanceof Specifier and + not e instanceof Folder select e diff --git a/cpp/ql/test/library-tests/templates/CPP-223/decls.ql b/cpp/ql/test/library-tests/templates/CPP-223/decls.ql index 6df6c775d59..9b23aa4867d 100644 --- a/cpp/ql/test/library-tests/templates/CPP-223/decls.ql +++ b/cpp/ql/test/library-tests/templates/CPP-223/decls.ql @@ -2,4 +2,3 @@ import cpp from Declaration d select d - diff --git a/cpp/ql/test/library-tests/templates/ambiguous_cctor/ambiguous_cctor.ql b/cpp/ql/test/library-tests/templates/ambiguous_cctor/ambiguous_cctor.ql index c7c3e657290..a0156aadf45 100644 --- a/cpp/ql/test/library-tests/templates/ambiguous_cctor/ambiguous_cctor.ql +++ b/cpp/ql/test/library-tests/templates/ambiguous_cctor/ambiguous_cctor.ql @@ -1,5 +1,6 @@ import cpp from FunctionCall fc, string returnParent -where if fc.getParent() instanceof ReturnStmt then returnParent = "ReturnStmt" else returnParent = "" +where + if fc.getParent() instanceof ReturnStmt then returnParent = "ReturnStmt" else returnParent = "" select fc, returnParent, fc.getEnclosingFunction(), count(fc.getTarget()) diff --git a/cpp/ql/test/library-tests/templates/bug/class.ql b/cpp/ql/test/library-tests/templates/bug/class.ql index 5307f90b4e6..d97fefea044 100644 --- a/cpp/ql/test/library-tests/templates/bug/class.ql +++ b/cpp/ql/test/library-tests/templates/bug/class.ql @@ -2,4 +2,3 @@ import cpp from Class c select c - diff --git a/cpp/ql/test/library-tests/templates/decls/decls.ql b/cpp/ql/test/library-tests/templates/decls/decls.ql index 6df6c775d59..9b23aa4867d 100644 --- a/cpp/ql/test/library-tests/templates/decls/decls.ql +++ b/cpp/ql/test/library-tests/templates/decls/decls.ql @@ -2,4 +2,3 @@ import cpp from Declaration d select d - diff --git a/cpp/ql/test/library-tests/templates/dependent_template_alias/test.ql b/cpp/ql/test/library-tests/templates/dependent_template_alias/test.ql index d61a33c822c..ff0e58f2525 100644 --- a/cpp/ql/test/library-tests/templates/dependent_template_alias/test.ql +++ b/cpp/ql/test/library-tests/templates/dependent_template_alias/test.ql @@ -1,6 +1,7 @@ import cpp from Variable v, Class c -where c = v.getType() - and v.getFile().getBaseName() = "test.cpp" +where + c = v.getType() and + v.getFile().getBaseName() = "test.cpp" select v, c, c.getAMemberVariable() diff --git a/cpp/ql/test/library-tests/templates/extern/elements.ql b/cpp/ql/test/library-tests/templates/extern/elements.ql index 6c5dd498c09..be15ddcd4f4 100644 --- a/cpp/ql/test/library-tests/templates/extern/elements.ql +++ b/cpp/ql/test/library-tests/templates/extern/elements.ql @@ -1,7 +1,8 @@ import cpp from Element e -where exists(e.getLocation()) - and not e.getLocation() instanceof UnknownLocation - and not e instanceof Folder +where + exists(e.getLocation()) and + not e.getLocation() instanceof UnknownLocation and + not e instanceof Folder select e diff --git a/cpp/ql/test/library-tests/templates/friends/decls.ql b/cpp/ql/test/library-tests/templates/friends/decls.ql index ee5f89681b1..af8ef5932f5 100644 --- a/cpp/ql/test/library-tests/templates/friends/decls.ql +++ b/cpp/ql/test/library-tests/templates/friends/decls.ql @@ -3,4 +3,3 @@ import cpp from Declaration d where d.getName() != "__va_list_tag" select d - diff --git a/cpp/ql/test/library-tests/templates/functions/functions.ql b/cpp/ql/test/library-tests/templates/functions/functions.ql index df9e560fcbe..f9bc83860f9 100644 --- a/cpp/ql/test/library-tests/templates/functions/functions.ql +++ b/cpp/ql/test/library-tests/templates/functions/functions.ql @@ -1,7 +1,7 @@ import cpp from Type t, Function f, Expr e -where t = f.getDeclaringType() - and f = e.getEnclosingFunction() +where + t = f.getDeclaringType() and + f = e.getEnclosingFunction() select t, f, e - diff --git a/cpp/ql/test/library-tests/templates/incomplete_instantiations/test.ql b/cpp/ql/test/library-tests/templates/incomplete_instantiations/test.ql index b5d70f52fa2..0dde272976a 100644 --- a/cpp/ql/test/library-tests/templates/incomplete_instantiations/test.ql +++ b/cpp/ql/test/library-tests/templates/incomplete_instantiations/test.ql @@ -1,8 +1,7 @@ import cpp from Class c, Function f -where c = f.getDeclaringType() - and exists(f.getLocation()) +where + c = f.getDeclaringType() and + exists(f.getLocation()) select c, f, count(Stmt s | s.getEnclosingFunction() = f) - - diff --git a/cpp/ql/test/library-tests/templates/instantiation_directive/functions.ql b/cpp/ql/test/library-tests/templates/instantiation_directive/functions.ql index bc3ccc611f9..94def842b75 100644 --- a/cpp/ql/test/library-tests/templates/instantiation_directive/functions.ql +++ b/cpp/ql/test/library-tests/templates/instantiation_directive/functions.ql @@ -2,4 +2,3 @@ import cpp from Function f select f, f.getAParameter().getType() - diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.ql b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.ql index c2e851c051f..e9967270bb8 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.ql +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.ql @@ -2,11 +2,9 @@ import cpp from Element e, string s, Type arg where - ( - s = "ClassTemplateInstantiation" and - arg = e.(ClassTemplateInstantiation).getATemplateArgument() - ) or ( - s = "FunctionTemplateInstantiation" and - arg = e.(FunctionTemplateInstantiation).getATemplateArgument() - ) + s = "ClassTemplateInstantiation" and + arg = e.(ClassTemplateInstantiation).getATemplateArgument() + or + s = "FunctionTemplateInstantiation" and + arg = e.(FunctionTemplateInstantiation).getATemplateArgument() select e, s, arg diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.ql b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.ql index c73f41e9570..ce8abbdf436 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.ql +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.ql @@ -4,25 +4,38 @@ class FunctionMonkeyPatch extends Function { language[monotonicAggregates] override string toString() { exists(string name, string templateArgs, string args | - result = name + templateArgs + args - and name = this.getQualifiedName() - and if exists(this.getATemplateArgument()) - then templateArgs = "<" + concat(int i | exists(this.getTemplateArgument(i)) | this.getTemplateArgument(i).toString(), "," order by i) + ">" - else templateArgs = "" - and args = "(" + concat(int i | exists(this.getParameter(i)) | this.getParameter(i).getType().toString(), "," order by i) + ")") + result = name + templateArgs + args and + name = this.getQualifiedName() and + ( + if exists(this.getATemplateArgument()) + then + templateArgs = "<" + + concat(int i | + exists(this.getTemplateArgument(i)) + | + this.getTemplateArgument(i).toString(), "," order by i + ) + ">" + else templateArgs = "" + ) and + args = "(" + + concat(int i | + exists(this.getParameter(i)) + | + this.getParameter(i).getType().toString(), "," order by i + ) + ")" + ) } } class ParameterMonkeyPatch extends Parameter { - override string toString() { - result = super.getType().getName() + " " + super.toString() - } + override string toString() { result = super.getType().getName() + " " + super.toString() } } from Element e, Element ti -where e.getLocation().getStartLine() != 0 // unhelpful -and not (function_instantiation(unresolveElement(e), _) and e = ti) // trivial -and not (class_instantiation(unresolveElement(e), _) and e = ti) // trivial -and not (variable_instantiation(unresolveElement(e), _) and e = ti) // trivial -and e.isFromTemplateInstantiation(ti) +where + e.getLocation().getStartLine() != 0 and // unhelpful + not (function_instantiation(unresolveElement(e), _) and e = ti) and // trivial + not (class_instantiation(unresolveElement(e), _) and e = ti) and // trivial + not (variable_instantiation(unresolveElement(e), _) and e = ti) and // trivial + e.isFromTemplateInstantiation(ti) select e, ti diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.ql b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.ql index 4f7e4b3dcbe..8e05d7c14c1 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.ql +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.ql @@ -4,9 +4,11 @@ string knownKind(Element e) { e instanceof Expr and result = "Expr" or e instanceof DeclarationEntry and - ( if e.(DeclarationEntry).isDefinition() + ( + if e.(DeclarationEntry).isDefinition() then result = "Definition" - else result = "DeclarationEntry" ) + else result = "DeclarationEntry" + ) or e instanceof Declaration and result = "Declaration" or @@ -38,7 +40,8 @@ predicate hasTwin(Element e) { predicate isInteresting(Element el) { not el.getLocation() instanceof UnknownLocation and exists(el.getLocation()) and - ( el instanceof Class + ( + el instanceof Class or el instanceof Function ) @@ -52,8 +55,7 @@ string conversionString(Element el) { if el.(VariableAccess).getConversion+() instanceof ReferenceToExpr then result = "Ref" else result = "Not ref" - else - result = "" + else result = "" } query predicate isFromUninstantiatedTemplate(Element e, Element template) { @@ -62,9 +64,6 @@ query predicate isFromUninstantiatedTemplate(Element e, Element template) { from Element el where (hasTwin(el) or isInteresting(el)) -select - el, - any(string s | if el.isFromTemplateInstantiation(_) then s="I" else s=""), - any(string s | if el.isFromUninstantiatedTemplate(_) then s="T" else s=""), - kind(el), +select el, any(string s | if el.isFromTemplateInstantiation(_) then s = "I" else s = ""), + any(string s | if el.isFromUninstantiatedTemplate(_) then s = "T" else s = ""), kind(el), conversionString(el) diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/template_is_template.ql b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/template_is_template.ql index b6c4d4df4da..9695667d40e 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/template_is_template.ql +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/template_is_template.ql @@ -17,11 +17,16 @@ predicate isTemplate(Declaration d) { } from Element e, string msg -where canBeTemplate(e) - and ( isTemplate(e) and - not e.isFromUninstantiatedTemplate(_) and - msg = "only isTemplate" ) - and ( e.isFromUninstantiatedTemplate(_) and - not isTemplate(e) and - msg = "only isFromUninstantiatedTemplate" ) +where + canBeTemplate(e) and + ( + isTemplate(e) and + not e.isFromUninstantiatedTemplate(_) and + msg = "only isTemplate" + ) and + ( + e.isFromUninstantiatedTemplate(_) and + not isTemplate(e) and + msg = "only isFromUninstantiatedTemplate" + ) select e, msg diff --git a/cpp/ql/test/library-tests/templates/prototype_bodies/call_operands.ql b/cpp/ql/test/library-tests/templates/prototype_bodies/call_operands.ql index 25937972c15..d7d0092e418 100644 --- a/cpp/ql/test/library-tests/templates/prototype_bodies/call_operands.ql +++ b/cpp/ql/test/library-tests/templates/prototype_bodies/call_operands.ql @@ -1,7 +1,8 @@ import cpp from Expr e, int column -where exists(Call c | c = e.getParent+() | c.getLocation().getStartLine() = 5) - and column = e.getLocation().getStartColumn() - and column > 10 // Excludes the function name token, which isn't represented nicely yet. +where + exists(Call c | c = e.getParent+() | c.getLocation().getStartLine() = 5) and + column = e.getLocation().getStartColumn() and + column > 10 // Excludes the function name token, which isn't represented nicely yet. select column, e.toString() diff --git a/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql b/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql index 51f8e15ae01..c9cccbf24ae 100644 --- a/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql +++ b/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql @@ -1,8 +1,8 @@ import cpp // It should be the case that "f.isDefined()" is equivalent to "exists(f.getBlock())". - from Function f, string isdef, string hasblock -where (if f.isDefined() then isdef = "defined" else isdef = "not defined") - and (if exists(f.getBlock()) then hasblock = "has block" else hasblock = "no block") +where + (if f.isDefined() then isdef = "defined" else isdef = "not defined") and + (if exists(f.getBlock()) then hasblock = "has block" else hasblock = "no block") select f.getName(), isdef, hasblock diff --git a/cpp/ql/test/library-tests/templates/segfault/vars.ql b/cpp/ql/test/library-tests/templates/segfault/vars.ql index 4174e095ec7..1b46d45f299 100644 --- a/cpp/ql/test/library-tests/templates/segfault/vars.ql +++ b/cpp/ql/test/library-tests/templates/segfault/vars.ql @@ -2,4 +2,3 @@ import cpp from Class t select t - diff --git a/cpp/ql/test/library-tests/templates/typedefs/template_typedefs.ql b/cpp/ql/test/library-tests/templates/typedefs/template_typedefs.ql index 72e7836b5a2..f5960ccf26c 100644 --- a/cpp/ql/test/library-tests/templates/typedefs/template_typedefs.ql +++ b/cpp/ql/test/library-tests/templates/typedefs/template_typedefs.ql @@ -1,6 +1,8 @@ import cpp from string name, Type arg -where exists(Function f | name = f.getName() and arg = f.getATemplateArgument()) - or exists(Class c | name = c.getName() and arg = c.getATemplateArgument()) +where + exists(Function f | name = f.getName() and arg = f.getATemplateArgument()) + or + exists(Class c | name = c.getName() and arg = c.getATemplateArgument()) select name, arg.explain() diff --git a/cpp/ql/test/library-tests/templates/variables/template_variables.ql b/cpp/ql/test/library-tests/templates/variables/template_variables.ql index ddda2c6439f..820d72d869b 100644 --- a/cpp/ql/test/library-tests/templates/variables/template_variables.ql +++ b/cpp/ql/test/library-tests/templates/variables/template_variables.ql @@ -1,8 +1,11 @@ import cpp from Variable v, VariableAccess a, int i, string s -where v = a.getTarget() - and if exists(v.getATemplateArgument()) - then s = v.getTemplateArgument(i).toString() - else (s = "" and i = -1) +where + v = a.getTarget() and + if exists(v.getATemplateArgument()) + then s = v.getTemplateArgument(i).toString() + else ( + s = "" and i = -1 + ) select v, a, i, s diff --git a/cpp/ql/test/library-tests/type_sizes/type_sizes.ql b/cpp/ql/test/library-tests/type_sizes/type_sizes.ql index e687f24bc3c..37748d42a25 100644 --- a/cpp/ql/test/library-tests/type_sizes/type_sizes.ql +++ b/cpp/ql/test/library-tests/type_sizes/type_sizes.ql @@ -1,7 +1,5 @@ import cpp from Type t, string s -where if exists(t.getSize().toString()) - then s = t.getSize().toString() - else s = "" +where if exists(t.getSize().toString()) then s = t.getSize().toString() else s = "" select t, s diff --git a/cpp/ql/test/library-tests/type_strings/exprs.ql b/cpp/ql/test/library-tests/type_strings/exprs.ql index 2a036139d21..918256ee81a 100644 --- a/cpp/ql/test/library-tests/type_strings/exprs.ql +++ b/cpp/ql/test/library-tests/type_strings/exprs.ql @@ -2,6 +2,4 @@ import cpp from Expr e where not (e instanceof CStyleCast and e.getValue().matches("%0")) -select e, - e.getType().toString(), - e.getType().explain() +select e, e.getType().toString(), e.getType().explain() diff --git a/cpp/ql/test/library-tests/type_strings/type_strings.ql b/cpp/ql/test/library-tests/type_strings/type_strings.ql index f874534c091..104abad8463 100644 --- a/cpp/ql/test/library-tests/type_strings/type_strings.ql +++ b/cpp/ql/test/library-tests/type_strings/type_strings.ql @@ -1,12 +1,9 @@ import cpp Type getDeclType(Declaration d) { - result = ((GlobalVariable)d).getType() or - result = ((Function )d).getType() + result = d.(GlobalVariable).getType() or + result = d.(Function).getType() } from Declaration d -select d, - getDeclType(d).toString(), - getDeclType(d).explain() - +select d, getDeclType(d).toString(), getDeclType(d).explain() diff --git a/cpp/ql/test/library-tests/typedefs/ODASA-6095.ql b/cpp/ql/test/library-tests/typedefs/ODASA-6095.ql index d1c39010917..032cc82c3f6 100644 --- a/cpp/ql/test/library-tests/typedefs/ODASA-6095.ql +++ b/cpp/ql/test/library-tests/typedefs/ODASA-6095.ql @@ -1,4 +1,5 @@ import cpp + from TypedefType t -where not exists (t.getBaseType().getUnspecifiedType()) +where not exists(t.getBaseType().getUnspecifiedType()) select t.getUnspecifiedType(), t.getUnspecifiedType().getFile() diff --git a/cpp/ql/test/library-tests/typedefs/Typedefs2.ql b/cpp/ql/test/library-tests/typedefs/Typedefs2.ql index fafe9ec44d2..11c7e075909 100644 --- a/cpp/ql/test/library-tests/typedefs/Typedefs2.ql +++ b/cpp/ql/test/library-tests/typedefs/Typedefs2.ql @@ -1,6 +1,7 @@ import cpp from Function f1, Block body, Declaration d -where body = f1.getBlock() - and d = body.getADeclaration() +where + body = f1.getBlock() and + d = body.getADeclaration() select f1, d, concat(d.getAQlClass(), ", ") diff --git a/cpp/ql/test/library-tests/typedefs/Typedefs3.ql b/cpp/ql/test/library-tests/typedefs/Typedefs3.ql index 15cfbf2fa41..a1a48aa8723 100644 --- a/cpp/ql/test/library-tests/typedefs/Typedefs3.ql +++ b/cpp/ql/test/library-tests/typedefs/Typedefs3.ql @@ -1,32 +1,32 @@ import cpp string describe(TypedefType t) { - ( - t instanceof LocalTypedefType and - result = "LocalTypedefType" - ) or ( - t instanceof NestedTypedefType and - result = "NestedTypedefType" - ) or ( - t.(NestedTypedefType).hasSpecifier("private") and - result = "(NestedTypedefType).isPrivate()" - ) or ( - t.(NestedTypedefType).hasSpecifier("protected") and - result = "(NestedTypedefType).isProtected()" - ) or ( - t.(NestedTypedefType).hasSpecifier("public") and - result = "(NestedTypedefType).isPublic()" - ) or exists(Type base | + t instanceof LocalTypedefType and + result = "LocalTypedefType" + or + t instanceof NestedTypedefType and + result = "NestedTypedefType" + or + t.(NestedTypedefType).hasSpecifier("private") and + result = "(NestedTypedefType).isPrivate()" + or + t.(NestedTypedefType).hasSpecifier("protected") and + result = "(NestedTypedefType).isProtected()" + or + t.(NestedTypedefType).hasSpecifier("public") and + result = "(NestedTypedefType).isPublic()" + or + exists(Type base | base = t.getBaseType() and ( - ( - result = "getBaseType() = " + base.(Declaration).getQualifiedName() - ) or ( - not base instanceof Declaration and - result = "getBaseType() = " + base.toString() - ) + result = "getBaseType() = " + base.(Declaration).getQualifiedName() + or + not base instanceof Declaration and + result = "getBaseType() = " + base.toString() ) - ) or exists(Class c | + ) + or + exists(Class c | c.getAMember() = t and result = "member of " + c.toString() ) diff --git a/cpp/ql/test/library-tests/types/__wchar_t/wchar_t.ql b/cpp/ql/test/library-tests/types/__wchar_t/wchar_t.ql index d546ee79ce7..446af45d2d8 100644 --- a/cpp/ql/test/library-tests/types/__wchar_t/wchar_t.ql +++ b/cpp/ql/test/library-tests/types/__wchar_t/wchar_t.ql @@ -1,9 +1,5 @@ import cpp from Type t -where - t.getName().matches("%wchar%") -select - t, - concat(t.getAQlClass(), ", "), - concat(t.(DerivedType).getBaseType().getAQlClass(), ", ") +where t.getName().matches("%wchar%") +select t, concat(t.getAQlClass(), ", "), concat(t.(DerivedType).getBaseType().getAQlClass(), ", ") diff --git a/cpp/ql/test/library-tests/types/alignof/alignof.ql b/cpp/ql/test/library-tests/types/alignof/alignof.ql index 49927bff49e..a727db2fcfa 100644 --- a/cpp/ql/test/library-tests/types/alignof/alignof.ql +++ b/cpp/ql/test/library-tests/types/alignof/alignof.ql @@ -2,11 +2,9 @@ import cpp from AlignofOperator sto, string elemDesc, Element e where - ( - elemDesc = "AlignofTypeOperator.getTypeOperand()" and - e = sto.(AlignofTypeOperator).getTypeOperand() - ) or ( - elemDesc = "AlignofExprOperator.getExprOperand()" and - e = sto.(AlignofExprOperator).getExprOperand() - ) + elemDesc = "AlignofTypeOperator.getTypeOperand()" and + e = sto.(AlignofTypeOperator).getTypeOperand() + or + elemDesc = "AlignofExprOperator.getExprOperand()" and + e = sto.(AlignofExprOperator).getExprOperand() select sto, elemDesc, e diff --git a/cpp/ql/test/library-tests/types/integral_types/integral_type.ql b/cpp/ql/test/library-tests/types/integral_types/integral_type.ql index 570ef681603..e825bed3510 100644 --- a/cpp/ql/test/library-tests/types/integral_types/integral_type.ql +++ b/cpp/ql/test/library-tests/types/integral_types/integral_type.ql @@ -1,47 +1,53 @@ import cpp string integralTypeKind(IntegralType t) { - if exists(int kind | builtintypes(unresolveElement(t), _, kind, _, _, _)) - then exists(int kind | builtintypes(unresolveElement(t), _, kind, _, _, _) | result = (kind.toString() + " ").prefix(2)) - else result = "--" + if exists(int kind | builtintypes(unresolveElement(t), _, kind, _, _, _)) + then + exists(int kind | builtintypes(unresolveElement(t), _, kind, _, _, _) | + result = (kind.toString() + " ").prefix(2) + ) + else result = "--" } string getUnsignedType(IntegralType t) { - if exists(t.getUnsigned()) - then result = t.getUnsigned().toString() - else result = "" + if exists(t.getUnsigned()) + then result = t.getUnsigned().toString() + else result = "" } string describe(IntegralType t) { - ( - t instanceof MicrosoftInt8Type and - result = "MicrosoftInt8Type" - ) or ( - t instanceof MicrosoftInt16Type and - result = "MicrosoftInt16Type" - ) or ( - t instanceof MicrosoftInt32Type and - result = "MicrosoftInt32Type" - ) or ( - t instanceof MicrosoftInt64Type and - result = "MicrosoftInt64Type" - ) + t instanceof MicrosoftInt8Type and + result = "MicrosoftInt8Type" + or + t instanceof MicrosoftInt16Type and + result = "MicrosoftInt16Type" + or + t instanceof MicrosoftInt32Type and + result = "MicrosoftInt32Type" + or + t instanceof MicrosoftInt64Type and + result = "MicrosoftInt64Type" } -from IntegralType t, string tStr, string signed, string unsigned, - string explicitlySigned, string explicitlyUnsigned, - string implicitlySigned -where tStr = (t.toString() + " ").prefix(18) - and if t.isSigned() then signed = "signed" - else signed = "------" - and if t.isUnsigned() then unsigned = "unsigned" - else unsigned = "--------" - and if t.isExplicitlySigned() then explicitlySigned = "explicitlySigned" - else explicitlySigned = "----------------" - and if t.isExplicitlyUnsigned() then explicitlyUnsigned = "explicitlyUnsigned" - else explicitlyUnsigned = "------------------" - and if t.isImplicitlySigned() then implicitlySigned = "implicitlySigned" - else implicitlySigned = "----------------" -select integralTypeKind(t), tStr, signed, unsigned, - explicitlySigned, explicitlyUnsigned, - implicitlySigned, t.getSize(), t.getAlignment(), getUnsignedType(t), concat(describe(t), ", ") +from + IntegralType t, string tStr, string signed, string unsigned, string explicitlySigned, + string explicitlyUnsigned, string implicitlySigned +where + tStr = (t.toString() + " ").prefix(18) and + (if t.isSigned() then signed = "signed" else signed = "------") and + (if t.isUnsigned() then unsigned = "unsigned" else unsigned = "--------") and + ( + if t.isExplicitlySigned() + then explicitlySigned = "explicitlySigned" + else explicitlySigned = "----------------" + ) and + ( + if t.isExplicitlyUnsigned() + then explicitlyUnsigned = "explicitlyUnsigned" + else explicitlyUnsigned = "------------------" + ) and + if t.isImplicitlySigned() + then implicitlySigned = "implicitlySigned" + else implicitlySigned = "----------------" +select integralTypeKind(t), tStr, signed, unsigned, explicitlySigned, explicitlyUnsigned, + implicitlySigned, t.getSize(), t.getAlignment(), getUnsignedType(t), concat(describe(t), ", ") diff --git a/cpp/ql/test/library-tests/types/pointertypes/pointertypes.ql b/cpp/ql/test/library-tests/types/pointertypes/pointertypes.ql index 293346a3f6d..a81c94ecd17 100644 --- a/cpp/ql/test/library-tests/types/pointertypes/pointertypes.ql +++ b/cpp/ql/test/library-tests/types/pointertypes/pointertypes.ql @@ -1,38 +1,42 @@ import cpp predicate describe(Type t, string a, string b) { - ( - a = "getUnspecifiedType()" and - b = t.getUnspecifiedType().toString() - ) or ( - a = "PointerType" and b = "" and - t instanceof PointerType - ) or ( - a = "VoidPointerType" and b = "" and - t instanceof VoidPointerType - ) or ( - a = "CharPointerType" and b = "" and - t instanceof CharPointerType - ) or ( - a = "SpecifiedType" and b = "" and - t instanceof SpecifiedType - ) or ( - a = "getASpecifier()" and - b = t.getASpecifier().toString() - ) or ( - a = "isConst()" and b = "" and - t.isConst() - ) or ( - a = "isVolatile()" and b = "" and - t.isVolatile() - ) or ( - a = "getBaseType()" and - b = t.(DerivedType).getBaseType().toString() - ) + a = "getUnspecifiedType()" and + b = t.getUnspecifiedType().toString() + or + a = "PointerType" and + b = "" and + t instanceof PointerType + or + a = "VoidPointerType" and + b = "" and + t instanceof VoidPointerType + or + a = "CharPointerType" and + b = "" and + t instanceof CharPointerType + or + a = "SpecifiedType" and + b = "" and + t instanceof SpecifiedType + or + a = "getASpecifier()" and + b = t.getASpecifier().toString() + or + a = "isConst()" and + b = "" and + t.isConst() + or + a = "isVolatile()" and + b = "" and + t.isVolatile() + or + a = "getBaseType()" and + b = t.(DerivedType).getBaseType().toString() } from Variable v, Type t, string a, string b where - t = v.getType() and - describe(t, a, b) + t = v.getType() and + describe(t, a, b) select v, t.toString(), a, b diff --git a/cpp/ql/test/library-tests/types/refersTo/refersTo.ql b/cpp/ql/test/library-tests/types/refersTo/refersTo.ql index 2c2e1184b6c..deab57f33ef 100644 --- a/cpp/ql/test/library-tests/types/refersTo/refersTo.ql +++ b/cpp/ql/test/library-tests/types/refersTo/refersTo.ql @@ -1,7 +1,8 @@ import cpp from Type a, Type b, string str -where a.refersTo(b) -and if a.refersToDirectly(b) then str = "direct" else str = "" -and b.getFile().toString() != "" +where + a.refersTo(b) and + (if a.refersToDirectly(b) then str = "direct" else str = "") and + b.getFile().toString() != "" select a.getLocation().getStartLine(), a, b, str diff --git a/cpp/ql/test/library-tests/types/scope/expr.ql b/cpp/ql/test/library-tests/types/scope/expr.ql index 85db6f21784..eebaebb5198 100644 --- a/cpp/ql/test/library-tests/types/scope/expr.ql +++ b/cpp/ql/test/library-tests/types/scope/expr.ql @@ -2,4 +2,3 @@ import cpp from Expr e select e, e.getEnclosingFunction() - diff --git a/cpp/ql/test/library-tests/types/segfault/vars.ql b/cpp/ql/test/library-tests/types/segfault/vars.ql index 2f75e89c1cf..a97f4077f6e 100644 --- a/cpp/ql/test/library-tests/types/segfault/vars.ql +++ b/cpp/ql/test/library-tests/types/segfault/vars.ql @@ -2,4 +2,3 @@ import cpp from Variable v select v, v.getType() - diff --git a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql index ed9b58b594d..db8beba69a0 100644 --- a/cpp/ql/test/library-tests/types/sizeof/sizeof.ql +++ b/cpp/ql/test/library-tests/types/sizeof/sizeof.ql @@ -2,11 +2,9 @@ import cpp from SizeofOperator sto, string elemDesc, Element e where - ( - elemDesc = "SizeofTypeOperator.getTypeOperand()" and - e = sto.(SizeofTypeOperator).getTypeOperand() - ) or ( - elemDesc = "SizeofExprOperator.getExprOperand()" and - e = sto.(SizeofExprOperator).getExprOperand() - ) + elemDesc = "SizeofTypeOperator.getTypeOperand()" and + e = sto.(SizeofTypeOperator).getTypeOperand() + or + elemDesc = "SizeofExprOperator.getExprOperand()" and + e = sto.(SizeofExprOperator).getExprOperand() select sto, elemDesc, e diff --git a/cpp/ql/test/library-tests/types/typeid/typeid.ql b/cpp/ql/test/library-tests/types/typeid/typeid.ql index b3f4221bc14..43abbc697ec 100644 --- a/cpp/ql/test/library-tests/types/typeid/typeid.ql +++ b/cpp/ql/test/library-tests/types/typeid/typeid.ql @@ -2,11 +2,12 @@ import cpp from TypeidOperator to, string exprLoc, string expr where - if exists(to.getExpr()) then ( - exprLoc = to.getExpr().getLocation().toString() and - expr = to.getExpr().toString() - ) else ( - expr = "" and - exprLoc = "" - ) + if exists(to.getExpr()) + then ( + exprLoc = to.getExpr().getLocation().toString() and + expr = to.getExpr().toString() + ) else ( + expr = "" and + exprLoc = "" + ) select to, to.getResultType(), exprLoc, expr diff --git a/cpp/ql/test/library-tests/types/types/Types.ql b/cpp/ql/test/library-tests/types/types/Types.ql index c7eee4c2268..5ae29826ecd 100644 --- a/cpp/ql/test/library-tests/types/types/Types.ql +++ b/cpp/ql/test/library-tests/types/types/Types.ql @@ -1,68 +1,59 @@ import cpp -string describeType(Type t) -{ - ( - t instanceof TypedefType and - result = "TypedefType" - ) or ( - t instanceof PointerType and - result = "PointerType" - ) or ( - t instanceof VoidPointerType and - result = "VoidPointerType" - ) or ( - t instanceof ReferenceType and - result = "ReferenceType" - ) or exists(Type base | - base = t.(DerivedType).getBaseType() and - result = "base: " + base.getName() - ) or ( - t instanceof IntType and - result = "IntType" - ) or ( - t instanceof CharType and - result = "CharType" - ) or ( - t instanceof DoubleType and - result = "DoubleType" - ) or ( - t instanceof Size_t and - result = "Size_t" - ) or ( - t instanceof Ssize_t and - result = "Ssize_t" - ) or ( - t instanceof Ptrdiff_t and - result = "Ptrdiff_t" - ) or ( - t instanceof Wchar_t and - result = "Wchar_t" - ) or ( - t.isConst() and - result = "isConst" - ) +string describeType(Type t) { + t instanceof TypedefType and + result = "TypedefType" + or + t instanceof PointerType and + result = "PointerType" + or + t instanceof VoidPointerType and + result = "VoidPointerType" + or + t instanceof ReferenceType and + result = "ReferenceType" + or + exists(Type base | + base = t.(DerivedType).getBaseType() and + result = "base: " + base.getName() + ) + or + t instanceof IntType and + result = "IntType" + or + t instanceof CharType and + result = "CharType" + or + t instanceof DoubleType and + result = "DoubleType" + or + t instanceof Size_t and + result = "Size_t" + or + t instanceof Ssize_t and + result = "Ssize_t" + or + t instanceof Ptrdiff_t and + result = "Ptrdiff_t" + or + t instanceof Wchar_t and + result = "Wchar_t" + or + t.isConst() and + result = "isConst" } -string describeVar(Variable v) -{ - ( - v.isConst() and - result = "isConst" - ) or ( - v instanceof LocalVariable and - result = "LocalVariable" - ) or ( - v instanceof Parameter and - result = "Parameter" - ) +string describeVar(Variable v) { + v.isConst() and + result = "isConst" + or + v instanceof LocalVariable and + result = "LocalVariable" + or + v instanceof Parameter and + result = "Parameter" } from Variable v, Type t -where - v.getType() = t -select - v, - concat(describeVar(v), ", "), - t, - concat(describeType(t), ", ") +where v.getType() = t +select v, concat(describeVar(v), ", "), t, concat(describeType(t), ", ") diff --git a/cpp/ql/test/library-tests/types/unspecified/exprs.ql b/cpp/ql/test/library-tests/types/unspecified/exprs.ql index b23383a8ec2..17e9a4df121 100644 --- a/cpp/ql/test/library-tests/types/unspecified/exprs.ql +++ b/cpp/ql/test/library-tests/types/unspecified/exprs.ql @@ -3,4 +3,3 @@ import cpp from Expr e, Type t where t = e.getType() select e, t.explain(), t.getUnspecifiedType().explain() - diff --git a/cpp/ql/test/library-tests/types/wchar_t_typedef/wchar_t.ql b/cpp/ql/test/library-tests/types/wchar_t_typedef/wchar_t.ql index d546ee79ce7..446af45d2d8 100644 --- a/cpp/ql/test/library-tests/types/wchar_t_typedef/wchar_t.ql +++ b/cpp/ql/test/library-tests/types/wchar_t_typedef/wchar_t.ql @@ -1,9 +1,5 @@ import cpp from Type t -where - t.getName().matches("%wchar%") -select - t, - concat(t.getAQlClass(), ", "), - concat(t.(DerivedType).getBaseType().getAQlClass(), ", ") +where t.getName().matches("%wchar%") +select t, concat(t.getAQlClass(), ", "), concat(t.(DerivedType).getBaseType().getAQlClass(), ", ") diff --git a/cpp/ql/test/library-tests/unions/Unions1.ql b/cpp/ql/test/library-tests/unions/Unions1.ql index 6a4453a4275..22652cc20ce 100644 --- a/cpp/ql/test/library-tests/unions/Unions1.ql +++ b/cpp/ql/test/library-tests/unions/Unions1.ql @@ -1,25 +1,19 @@ import cpp -string describe(Class c) -{ - ( - c instanceof Struct and - result = "Struct" - ) or ( - c instanceof Union and - result = "Union" - ) or ( - c instanceof LocalUnion and - result = "LocalUnion" - ) or ( - c instanceof NestedUnion and - result = "NestedUnion" - ) +string describe(Class c) { + c instanceof Struct and + result = "Struct" + or + c instanceof Union and + result = "Union" + or + c instanceof LocalUnion and + result = "LocalUnion" + or + c instanceof NestedUnion and + result = "NestedUnion" } from Class c -select - c, - concat(describe(c), ", "), - concat(c.getABaseClass().toString(), ", "), +select c, concat(describe(c), ", "), concat(c.getABaseClass().toString(), ", "), concat(c.getAMemberFunction().toString(), ", ") diff --git a/cpp/ql/test/library-tests/unnamed/elements.ql b/cpp/ql/test/library-tests/unnamed/elements.ql index 211558bd78e..84c42736930 100644 --- a/cpp/ql/test/library-tests/unnamed/elements.ql +++ b/cpp/ql/test/library-tests/unnamed/elements.ql @@ -1,8 +1,7 @@ import cpp from Element e, string s -where not e instanceof Folder - and if e instanceof VariableAccess - then s = "Variable access" - else s = "Other" +where + not e instanceof Folder and + if e instanceof VariableAccess then s = "Variable access" else s = "Other" select e, s diff --git a/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.ql b/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.ql index 0296534a81e..5cc2cdc3495 100644 --- a/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.ql +++ b/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.ql @@ -1,11 +1,9 @@ import cpp from Type t, string s -where // Filter out a couple of types that only appear on some platforms - not t.toString() = "__va_list_tag" - and not t.toString() = "void *" - and if exists(t.getUnspecifiedType()) - then s = t.getUnspecifiedType().toString() - else s = "" +where + // Filter out a couple of types that only appear on some platforms + not t.toString() = "__va_list_tag" and + not t.toString() = "void *" and + if exists(t.getUnspecifiedType()) then s = t.getUnspecifiedType().toString() else s = "" select t, s - diff --git a/cpp/ql/test/library-tests/unspecified_type/unspecified_type/strip_top_level.ql b/cpp/ql/test/library-tests/unspecified_type/unspecified_type/strip_top_level.ql index 2c46b84a963..6f146014d1e 100644 --- a/cpp/ql/test/library-tests/unspecified_type/unspecified_type/strip_top_level.ql +++ b/cpp/ql/test/library-tests/unspecified_type/unspecified_type/strip_top_level.ql @@ -1,6 +1,4 @@ import cpp from Variable v -select v, - v.getType().explain(), - v.getType().stripTopLevelSpecifiers().explain() +select v, v.getType().explain(), v.getType().stripTopLevelSpecifiers().explain() diff --git a/cpp/ql/test/library-tests/unspecified_type/unspecified_type/unspecified_type.ql b/cpp/ql/test/library-tests/unspecified_type/unspecified_type/unspecified_type.ql index 76f6537ba54..5827327e670 100644 --- a/cpp/ql/test/library-tests/unspecified_type/unspecified_type/unspecified_type.ql +++ b/cpp/ql/test/library-tests/unspecified_type/unspecified_type/unspecified_type.ql @@ -1,7 +1,4 @@ import cpp from Variable v -select v, - v.getType().explain(), - v.getUnspecifiedType().explain() - +select v, v.getType().explain(), v.getUnspecifiedType().explain() diff --git a/cpp/ql/test/library-tests/usings/Usings2.ql b/cpp/ql/test/library-tests/usings/Usings2.ql index 0278f1fafaa..bc4a076b0c5 100644 --- a/cpp/ql/test/library-tests/usings/Usings2.ql +++ b/cpp/ql/test/library-tests/usings/Usings2.ql @@ -1,6 +1,5 @@ import cpp from UsingEntry ue, Element e -where - e = ue.getEnclosingElement() +where e = ue.getEnclosingElement() select ue, e diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/GlobalValueNumbering.ql b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/GlobalValueNumbering.ql index a921093fcc7..3807d5c36e0 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/GlobalValueNumbering.ql +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/GlobalValueNumbering.ql @@ -3,10 +3,9 @@ import semmle.code.cpp.valuenumbering.GlobalValueNumbering from GVN g where strictcount(g.getAnExpr()) > 1 -select - g, - strictconcat(Location loc - | loc = g.getAnExpr().getLocation() - | loc.getStartLine() + - ":c" + loc.getStartColumn() + "-c" + loc.getEndColumn() - , " ") +select g, + strictconcat(Location loc | + loc = g.getAnExpr().getLocation() + | + loc.getStartLine() + ":c" + loc.getStartColumn() + "-c" + loc.getEndColumn(), " " + ) diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql index 97d59c73331..528bb6174a5 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql @@ -1,6 +1,7 @@ /** * @kind graph */ + import semmle.code.cpp.ir.PrintIR import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.ValueNumbering diff --git a/cpp/ql/test/library-tests/valuenumbering/HashCons/HashCons.ql b/cpp/ql/test/library-tests/valuenumbering/HashCons/HashCons.ql index 577e6ac62de..ef55853f6f2 100644 --- a/cpp/ql/test/library-tests/valuenumbering/HashCons/HashCons.ql +++ b/cpp/ql/test/library-tests/valuenumbering/HashCons/HashCons.ql @@ -3,10 +3,9 @@ import semmle.code.cpp.valuenumbering.HashCons from HashCons h where strictcount(h.getAnExpr()) > 1 -select - h, - strictconcat(Location loc - | loc = h.getAnExpr().getLocation() - | loc.getStartLine() + - ":c" + loc.getStartColumn() + "-c" + loc.getEndColumn() - , " ") +select h, + strictconcat(Location loc | + loc = h.getAnExpr().getLocation() + | + loc.getStartLine() + ":c" + loc.getStartColumn() + "-c" + loc.getEndColumn(), " " + ) diff --git a/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql b/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql index 1bb474de828..3e8aaa5cbf9 100644 --- a/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql +++ b/cpp/ql/test/library-tests/variables/constexpr/constexpr.ql @@ -1,5 +1,4 @@ import cpp from Variable v -select v, - any(boolean b | if v.isConstexpr() then b = true else b = false) +select v, any(boolean b | if v.isConstexpr() then b = true else b = false) diff --git a/cpp/ql/test/library-tests/variables/global/variables.ql b/cpp/ql/test/library-tests/variables/global/variables.ql index 93bc17f63ce..087915ea326 100644 --- a/cpp/ql/test/library-tests/variables/global/variables.ql +++ b/cpp/ql/test/library-tests/variables/global/variables.ql @@ -3,4 +3,3 @@ import cpp from Variable v, Type t where t = v.getType() select v, t.explain(), count(Type u | u = v.getType()) - diff --git a/cpp/ql/test/library-tests/variables/thread_local/thread_local.ql b/cpp/ql/test/library-tests/variables/thread_local/thread_local.ql index 19f9bd829a9..c82ae04262a 100644 --- a/cpp/ql/test/library-tests/variables/thread_local/thread_local.ql +++ b/cpp/ql/test/library-tests/variables/thread_local/thread_local.ql @@ -1,6 +1,4 @@ import cpp from Variable v -select v, - any(boolean b | if v.isThreadLocal() then b = true else b = false) - +select v, any(boolean b | if v.isThreadLocal() then b = true else b = false) diff --git a/cpp/ql/test/library-tests/variables/variables/structs.ql b/cpp/ql/test/library-tests/variables/variables/structs.ql index 8f7fc0ca560..4746d5474d1 100644 --- a/cpp/ql/test/library-tests/variables/variables/structs.ql +++ b/cpp/ql/test/library-tests/variables/variables/structs.ql @@ -2,4 +2,3 @@ import cpp from Struct s select s, count(s.getAField()) - diff --git a/cpp/ql/test/library-tests/variables/variables/types.ql b/cpp/ql/test/library-tests/variables/variables/types.ql index c79d42ed128..651f6508deb 100644 --- a/cpp/ql/test/library-tests/variables/variables/types.ql +++ b/cpp/ql/test/library-tests/variables/variables/types.ql @@ -1,20 +1,20 @@ import cpp -from Type t, - string baseType1, string baseType2, - string unsignedInt, string unsignedIntegral -where if t.(IntType).isUnsigned() - then unsignedInt = "unsigned int" - else unsignedInt = "" - and if t.(IntegralType).isUnsigned() - then unsignedIntegral = "unsigned integral" - else unsignedIntegral = "" - and if exists(t.(ArrayType).getBaseType()) - then baseType1 = t.(ArrayType).getBaseType().toString() - else baseType1 = "" - and if exists(t.(DerivedType).getBaseType()) - then baseType2 = t.(DerivedType).getBaseType().toString() - else baseType2 = "" -select t.toString(), concat(t.getAQlClass(), ", "), - baseType1, baseType2, unsignedInt, unsignedIntegral - +from Type t, string baseType1, string baseType2, string unsignedInt, string unsignedIntegral +where + (if t.(IntType).isUnsigned() then unsignedInt = "unsigned int" else unsignedInt = "") and + ( + if t.(IntegralType).isUnsigned() + then unsignedIntegral = "unsigned integral" + else unsignedIntegral = "" + ) and + ( + if exists(t.(ArrayType).getBaseType()) + then baseType1 = t.(ArrayType).getBaseType().toString() + else baseType1 = "" + ) and + if exists(t.(DerivedType).getBaseType()) + then baseType2 = t.(DerivedType).getBaseType().toString() + else baseType2 = "" +select t.toString(), concat(t.getAQlClass(), ", "), baseType1, baseType2, unsignedInt, + unsignedIntegral diff --git a/cpp/ql/test/library-tests/variables/variables/variable.ql b/cpp/ql/test/library-tests/variables/variables/variable.ql index ca9e2a4a64b..92b54c00770 100644 --- a/cpp/ql/test/library-tests/variables/variables/variable.ql +++ b/cpp/ql/test/library-tests/variables/variables/variable.ql @@ -1,10 +1,10 @@ import cpp from Variable v, Type t, string qlClass, string const, string static -where t = v.getType() - and qlClass = v.getAQlClass() - and (qlClass.matches("%Variable%") or qlClass.matches("%Field%")) - and if v.isConst() then const = "const" else const = "" - and if v.isStatic() then static = "static" else static = "" +where + t = v.getType() and + qlClass = v.getAQlClass() and + (qlClass.matches("%Variable%") or qlClass.matches("%Field%")) and + (if v.isConst() then const = "const" else const = "") and + if v.isStatic() then static = "static" else static = "" select v, t, qlClass, const, static - diff --git a/cpp/ql/test/library-tests/vector_types/builtin_ops.ql b/cpp/ql/test/library-tests/vector_types/builtin_ops.ql index 4e522c7cf78..548eab083e1 100644 --- a/cpp/ql/test/library-tests/vector_types/builtin_ops.ql +++ b/cpp/ql/test/library-tests/vector_types/builtin_ops.ql @@ -2,4 +2,3 @@ import cpp from BuiltInOperation bop select bop - diff --git a/cpp/ql/test/library-tests/virtual_functions/cfg/cfg.ql b/cpp/ql/test/library-tests/virtual_functions/cfg/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/virtual_functions/cfg/cfg.ql +++ b/cpp/ql/test/library-tests/virtual_functions/cfg/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/virtual_functions/virtual_functions/VirtualFunctions4.ql b/cpp/ql/test/library-tests/virtual_functions/virtual_functions/VirtualFunctions4.ql index 8a83fc25f97..92deaca3482 100644 --- a/cpp/ql/test/library-tests/virtual_functions/virtual_functions/VirtualFunctions4.ql +++ b/cpp/ql/test/library-tests/virtual_functions/virtual_functions/VirtualFunctions4.ql @@ -1,15 +1,11 @@ import cpp -string describe(VirtualFunction f) -{ - f instanceof PureVirtualFunction and - result = "PureVirtualFunction" +string describe(VirtualFunction f) { + f instanceof PureVirtualFunction and + result = "PureVirtualFunction" } from VirtualFunction f -select - f, - f.getDeclaringType(), - concat(f.getAnOverridingFunction().getDeclaringType().toString(), ", "), - concat(f.getAnOverriddenFunction().getDeclaringType().toString(), ", "), - concat(describe(f), ", ") +select f, f.getDeclaringType(), + concat(f.getAnOverridingFunction().getDeclaringType().toString(), ", "), + concat(f.getAnOverriddenFunction().getDeclaringType().toString(), ", "), concat(describe(f), ", ") diff --git a/cpp/ql/test/library-tests/virtual_functions/virtual_functions/classes.ql b/cpp/ql/test/library-tests/virtual_functions/virtual_functions/classes.ql index 9e986c361d4..c5f78fc2842 100644 --- a/cpp/ql/test/library-tests/virtual_functions/virtual_functions/classes.ql +++ b/cpp/ql/test/library-tests/virtual_functions/virtual_functions/classes.ql @@ -1,7 +1,5 @@ import cpp from Class c -select c, - count(VirtualFunction f | f.getDeclaringType() = c), - count(PureVirtualFunction f | f.getDeclaringType() = c) - +select c, count(VirtualFunction f | f.getDeclaringType() = c), + count(PureVirtualFunction f | f.getDeclaringType() = c) diff --git a/cpp/ql/test/library-tests/vla/cfg.ql b/cpp/ql/test/library-tests/vla/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/library-tests/vla/cfg.ql +++ b/cpp/ql/test/library-tests/vla/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/library-tests/vla/type.ql b/cpp/ql/test/library-tests/vla/type.ql index e0f5fb8ca16..e8e344ed2f4 100644 --- a/cpp/ql/test/library-tests/vla/type.ql +++ b/cpp/ql/test/library-tests/vla/type.ql @@ -1,6 +1,7 @@ import cpp from Type t, VlaDeclStmt d, int i, VlaDimensionStmt s -where t = d.getType() - and s = d.getVlaDimensionStmt(i) +where + t = d.getType() and + s = d.getVlaDimensionStmt(i) select t, d, i, s, s.getDimensionExpr() diff --git a/cpp/ql/test/library-tests/vla/variable.ql b/cpp/ql/test/library-tests/vla/variable.ql index 0a866668325..fff88c04a00 100644 --- a/cpp/ql/test/library-tests/vla/variable.ql +++ b/cpp/ql/test/library-tests/vla/variable.ql @@ -1,6 +1,7 @@ import cpp from Variable v, VlaDeclStmt d, int i, VlaDimensionStmt s -where v = d.getVariable() - and s = d.getVlaDimensionStmt(i) +where + v = d.getVariable() and + s = d.getVlaDimensionStmt(i) select v, d, i, s, s.getDimensionExpr() diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/formattingFunction.ql b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/formattingFunction.ql index 41db501e504..4cbd09954bb 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/formattingFunction.ql +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_mixed_byte_wprintf/formattingFunction.ql @@ -1,9 +1,6 @@ import cpp from FormattingFunction f -select - f, - concat(f.getFormatCharType().toString(), ", "), +select f, concat(f.getFormatCharType().toString(), ", "), concat(f.getDefaultCharType().toString(), ", "), - concat(f.getNonDefaultCharType().toString(), ", "), - concat(f.getWideCharType().toString(), ", ") + concat(f.getNonDefaultCharType().toString(), ", "), concat(f.getWideCharType().toString(), ", ") diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/formattingFunction.ql b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/formattingFunction.ql index 45f12aca07f..7df168850ab 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/formattingFunction.ql +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_two_byte_wprintf/formattingFunction.ql @@ -1,8 +1,5 @@ import cpp from FormattingFunction f -select - f, - concat(f.getDefaultCharType().toString(), ", "), - concat(f.getNonDefaultCharType().toString(), ", "), - concat(f.getWideCharType().toString(), ", ") +select f, concat(f.getDefaultCharType().toString(), ", "), + concat(f.getNonDefaultCharType().toString(), ", "), concat(f.getWideCharType().toString(), ", ") diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/formattingFunction.ql b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/formattingFunction.ql index 45f12aca07f..7df168850ab 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/formattingFunction.ql +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/formattingFunction.ql @@ -1,8 +1,5 @@ import cpp from FormattingFunction f -select - f, - concat(f.getDefaultCharType().toString(), ", "), - concat(f.getNonDefaultCharType().toString(), ", "), - concat(f.getWideCharType().toString(), ", ") +select f, concat(f.getDefaultCharType().toString(), ", "), + concat(f.getNonDefaultCharType().toString(), ", "), concat(f.getWideCharType().toString(), ", ") diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/ArrayTypeTest.ql b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/ArrayTypeTest.ql index fcb014aaf23..31730c41f60 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/ArrayTypeTest.ql +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/ArrayTypeTest.ql @@ -5,10 +5,7 @@ import cpp // StackAddressEscapes.ql, so the purpose of this test is to make // sure that the types behave in the way that we expect. from ArrayExpr arrayExpr -select - arrayExpr, - arrayExpr.getArrayBase().getUnspecifiedType().toString() + - ", " + - arrayExpr.getArrayBase().getFullyConverted().getUnspecifiedType().toString() + - ", " + - arrayExpr.getUnspecifiedType().toString() +select arrayExpr, + arrayExpr.getArrayBase().getUnspecifiedType().toString() + ", " + + arrayExpr.getArrayBase().getFullyConverted().getUnspecifiedType().toString() + ", " + + arrayExpr.getUnspecifiedType().toString() diff --git a/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies.ql b/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies.ql index 09c28fe2e43..ca97c66afa4 100644 --- a/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies.ql +++ b/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependencies.ql @@ -2,8 +2,5 @@ import TestPackage // this is a copy of the body of ExternalDependencies.ql from File file, int num, string encodedDependency -where - encodedDependencies(file, encodedDependency, num) -select - encodedDependency, num -order by num desc +where encodedDependencies(file, encodedDependency, num) +select encodedDependency, num order by num desc diff --git a/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index b75a8dbcb17..408dca51171 100644 --- a/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/cpp/ql/test/query-tests/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -9,8 +9,7 @@ import TestPackage * recover that information once we are in the dashboard database, using the * ExternalEntity.getASourceLink() method. */ + from File file, int num, string encodedDependency -where - encodedDependencies(file, encodedDependency, num) -select - encodedDependency, file +where encodedDependencies(file, encodedDependency, num) +select encodedDependency, file diff --git a/cpp/ql/test/query-tests/Metrics/Dependencies/TestPackage.qll b/cpp/ql/test/query-tests/Metrics/Dependencies/TestPackage.qll index 8b6fedb44a9..42ddb58a36f 100644 --- a/cpp/ql/test/query-tests/Metrics/Dependencies/TestPackage.qll +++ b/cpp/ql/test/query-tests/Metrics/Dependencies/TestPackage.qll @@ -4,19 +4,11 @@ import Metrics.Dependencies.ExternalDependencies * Count directories as libraries for testing purposes. */ class TestPackage extends LibraryElement { - TestPackage() { - this instanceof Folder - } + TestPackage() { this instanceof Folder } - override string getName() { - result = this.(Folder).getBaseName() - } + override string getName() { result = this.(Folder).getBaseName() } - override string getVersion() { - result = "1.0" - } + override string getVersion() { result = "1.0" } - override File getAFile() { - result.getParentContainer() = this - } + override File getAFile() { result.getParentContainer() = this } } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.ql b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.ql index a3d4c4526f7..82969c3d28f 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.ql +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.ql @@ -2,12 +2,9 @@ import cpp import LoopConditionsConst from Loop l, Expr condition -where - l.getCondition() = condition -select - l, condition, - concat(int val | loopEntryConst(condition, val) | val.toString(), ", "), - concat(BasicBlock bb | bb.getASuccessor() = l.getStmt() | bb.toString(), ", "), - concat(l.getStmt().toString(), ", "), - concat(BasicBlock bb | bb.getASuccessor() = l.getFollowingStmt() | bb.toString(), ", "), - concat(l.getFollowingStmt().toString(), ", ") +where l.getCondition() = condition +select l, condition, concat(int val | loopEntryConst(condition, val) | val.toString(), ", "), + concat(BasicBlock bb | bb.getASuccessor() = l.getStmt() | bb.toString(), ", "), + concat(l.getStmt().toString(), ", "), + concat(BasicBlock bb | bb.getASuccessor() = l.getFollowingStmt() | bb.toString(), ", "), + concat(l.getFollowingStmt().toString(), ", ") diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.qll b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.qll index 0108745a576..b3379ffb8f3 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.qll +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/LoopConditionsConst.qll @@ -1,10 +1,9 @@ import cpp import semmle.code.cpp.controlflow.internal.ConstantExprs -predicate loopEntryConst(Expr condition, int val) -{ - exists(LoopEntryConditionEvaluator x, ControlFlowNode loop | - x.isLoopEntry(condition, loop) and - val = x.getValue(condition) - ) +predicate loopEntryConst(Expr condition, int val) { + exists(LoopEntryConditionEvaluator x, ControlFlowNode loop | + x.isLoopEntry(condition, loop) and + val = x.getValue(condition) + ) } diff --git a/cpp/ql/test/query-tests/definitions/locationInfo.ql b/cpp/ql/test/query-tests/definitions/locationInfo.ql index 8cbb154a0e1..a36addac793 100644 --- a/cpp/ql/test/query-tests/definitions/locationInfo.ql +++ b/cpp/ql/test/query-tests/definitions/locationInfo.ql @@ -4,18 +4,14 @@ import definitions * An element that is the source of a jump-to-definition link. */ class Link extends Top { - Link() { - exists(definitionOf(this, _)) - } + Link() { exists(definitionOf(this, _)) } } /** * Gets the length of the longest line in file `f`. */ pragma[nomagic] -private int maxCols(File f) { - result = max(Location l | l.getFile() = f | l.getEndColumn()) -} +private int maxCols(File f) { result = max(Location l | l.getFile() = f | l.getEndColumn()) } /** * Gets the location of an element that has a link-to-definition (in a similar manner to @@ -35,22 +31,18 @@ predicate linkLocationInfo(Link e, string filepath, int begin, int end) { * Gets a string describing a problem with a `Link`. */ string issues(Link e) { - ( - strictcount(Top def | - def = definitionOf(e, _) - ) > 1 and - result = "has more than one definition" - ) or ( - exists(string filepath1, int begin1, int end1, Link e2, string filepath2, int begin2, int end2 | - linkLocationInfo(e, filepath1, begin1, end1) and - linkLocationInfo(e2, filepath2, begin2, end2) and - filepath1 = filepath2 and - not end1 < begin2 and - not begin1 > end2 and - e != e2 - ) and - result = "overlaps another link" - ) + strictcount(Top def | def = definitionOf(e, _)) > 1 and + result = "has more than one definition" + or + exists(string filepath1, int begin1, int end1, Link e2, string filepath2, int begin2, int end2 | + linkLocationInfo(e, filepath1, begin1, end1) and + linkLocationInfo(e2, filepath2, begin2, end2) and + filepath1 = filepath2 and + not end1 < begin2 and + not begin1 > end2 and + e != e2 + ) and + result = "overlaps another link" } from Link e diff --git a/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/files.ql b/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/files.ql index 4d947c6d946..6a12322d227 100644 --- a/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/files.ql +++ b/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/files.ql @@ -1,16 +1,14 @@ import cpp string describe(File f) { - ( - f instanceof CFile and - result = "CFile" - ) or ( - f instanceof CppFile and - result = "CppFile" - ) or ( - f instanceof HeaderFile and - result = "HeaderFile" - ) + f instanceof CFile and + result = "CFile" + or + f instanceof CppFile and + result = "CppFile" + or + f instanceof HeaderFile and + result = "HeaderFile" } from File f diff --git a/cpp/ql/test/successor-tests/assignexpr/cfg.ql b/cpp/ql/test/successor-tests/assignexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/assignexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/assignexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/block/emptyblock/emptyblock01.ql b/cpp/ql/test/successor-tests/block/emptyblock/emptyblock01.ql index 9be68bfac49..ecadf57692e 100644 --- a/cpp/ql/test/successor-tests/block/emptyblock/emptyblock01.ql +++ b/cpp/ql/test/successor-tests/block/emptyblock/emptyblock01.ql @@ -1,6 +1,8 @@ import cpp from Block s, int i, Stmt f, boolean succ -where s.getParentStmt().hasChild(s, i) and s.getParentStmt().hasChild(f, i + 1) - and if f = s.getASuccessor() then succ = true else succ = false +where + s.getParentStmt().hasChild(s, i) and + s.getParentStmt().hasChild(f, i + 1) and + if f = s.getASuccessor() then succ = true else succ = false select s, i, f, count(s.getASuccessor()), succ diff --git a/cpp/ql/test/successor-tests/break_labels/cfg.ql b/cpp/ql/test/successor-tests/break_labels/cfg.ql index bcf61586de4..637ee9d6395 100644 --- a/cpp/ql/test/successor-tests/break_labels/cfg.ql +++ b/cpp/ql/test/successor-tests/break_labels/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,21 +18,21 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and - x = y and - label = x.toString() + "\n" + x.getLocation().toString().regexpReplaceAll(".*/", "") + isEdge = false and + x = y and + label = x.toString() + "\n" + x.getLocation().toString().regexpReplaceAll(".*/", "") } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/cfg.ql b/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/conditional_destructors/cfg.ql b/cpp/ql/test/successor-tests/conditional_destructors/cfg.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/conditional_destructors/cfg.ql +++ b/cpp/ql/test/successor-tests/conditional_destructors/cfg.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr01.ql b/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr01.ql index 5ee32c370ad..f9f41916368 100644 --- a/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr01.ql +++ b/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr01.ql @@ -1,7 +1,8 @@ /** * @name defdestructordeleteexpr01 - * @description Control flow that involves a default constructor. + * @description Control flow that involves a default constructor. */ + import cpp from ControlFlowNode c diff --git a/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr01.ql b/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr01.ql index 2c9ab7555f3..9267612ebc5 100644 --- a/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr01.ql +++ b/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr01.ql @@ -2,6 +2,7 @@ * @name deleteexpr01 * @description The expression statement is followed by the reeference to c, which is followed by the delete call. */ + import cpp from ControlFlowNode node diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt01.ql b/cpp/ql/test/successor-tests/dostmt/dostmt01.ql index 4ba8e80292c..09a3406d6d4 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt01.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt01.ql @@ -7,10 +7,10 @@ import cpp from DoStmt ds, int k, LabelStmt l where - ds.getEnclosingFunction().hasName("normal") - and ds.getParentStmt().hasChild(ds, k) - and ds.getParentStmt().hasChild(l, k + 1) - and l = ds.getCondition().getASuccessor() - and l = ds.getCondition().getAFalseSuccessor() - and count(ds.getCondition().getAFalseSuccessor()) = 1 -select ds.getCondition(), l.getName() \ No newline at end of file + ds.getEnclosingFunction().hasName("normal") and + ds.getParentStmt().hasChild(ds, k) and + ds.getParentStmt().hasChild(l, k + 1) and + l = ds.getCondition().getASuccessor() and + l = ds.getCondition().getAFalseSuccessor() and + count(ds.getCondition().getAFalseSuccessor()) = 1 +select ds.getCondition(), l.getName() diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt02.ql b/cpp/ql/test/successor-tests/dostmt/dostmt02.ql index a24654c8f89..4a7275d899b 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt02.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt02.ql @@ -7,8 +7,8 @@ import cpp from DoStmt ds where - ds.getEnclosingFunction().hasName("normal") - and ds.getStmt() = ds.getCondition().getASuccessor() - and ds.getStmt() = ds.getCondition().getATrueSuccessor() - and count(ds.getCondition().getATrueSuccessor()) = 1 -select ds.getCondition(), ds.getStmt() \ No newline at end of file + ds.getEnclosingFunction().hasName("normal") and + ds.getStmt() = ds.getCondition().getASuccessor() and + ds.getStmt() = ds.getCondition().getATrueSuccessor() and + count(ds.getCondition().getATrueSuccessor()) = 1 +select ds.getCondition(), ds.getStmt() diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt03.ql b/cpp/ql/test/successor-tests/dostmt/dostmt03.ql index 9727c51d201..f41e7a54628 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt03.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt03.ql @@ -7,4 +7,4 @@ import cpp from DoStmt ds where count(ds.getCondition().getASuccessor()) > 2 -select ds \ No newline at end of file +select ds diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt04.ql b/cpp/ql/test/successor-tests/dostmt/dostmt04.ql index 3ca6113e3f5..61c1bb80f26 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt04.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt04.ql @@ -7,9 +7,9 @@ import cpp from DoStmt ds, ExprStmt last, Expr succ where - ds.getEnclosingFunction().hasName("normal") - and last = ((Block)ds.getStmt()).getLastStmt() - and succ = last.getExpr().getASuccessor() - and succ = ds.getCondition().getAChild*() - and count(last.getExpr().getASuccessor()) = 1 -select last.getExpr(), succ \ No newline at end of file + ds.getEnclosingFunction().hasName("normal") and + last = ds.getStmt().(Block).getLastStmt() and + succ = last.getExpr().getASuccessor() and + succ = ds.getCondition().getAChild*() and + count(last.getExpr().getASuccessor()) = 1 +select last.getExpr(), succ diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt05.ql b/cpp/ql/test/successor-tests/dostmt/dostmt05.ql index 14c53ad9ac8..849fa9d05b5 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt05.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt05.ql @@ -6,9 +6,9 @@ import cpp from DoStmt ds -where not -( - ds.getStmt() = ds.getASuccessor() - and count(ds.getASuccessor()) = 1 -) -select ds \ No newline at end of file +where + not ( + ds.getStmt() = ds.getASuccessor() and + count(ds.getASuccessor()) = 1 + ) +select ds diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt06.ql b/cpp/ql/test/successor-tests/dostmt/dostmt06.ql index c16dfe4029c..7121228153a 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt06.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt06.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt07.ql b/cpp/ql/test/successor-tests/dostmt/dostmt07.ql index a17c2672625..2915a448c85 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt07.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt07.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt08.ql b/cpp/ql/test/successor-tests/dostmt/dostmt08.ql index 5aeb1a5fd31..baa97587c22 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt08.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt08.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt09.ql b/cpp/ql/test/successor-tests/dostmt/dostmt09.ql index 44021d4100c..54f6ca1b8e2 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt09.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt09.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_3") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_3") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt10.ql b/cpp/ql/test/successor-tests/dostmt/dostmt10.ql index 3ed660612b3..203bc907107 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt10.ql +++ b/cpp/ql/test/successor-tests/dostmt/dostmt10.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("normal") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("normal") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/enum/cfg.ql b/cpp/ql/test/successor-tests/enum/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/enum/cfg.ql +++ b/cpp/ql/test/successor-tests/enum/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/graphable.ql b/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/graphable.ql +++ b/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/graphable.ql b/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/graphable.ql +++ b/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/exprstmt/cfg.ql b/cpp/ql/test/successor-tests/exprstmt/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/exprstmt/cfg.ql +++ b/cpp/ql/test/successor-tests/exprstmt/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/cfg.ql b/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/cfg.ql +++ b/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/cfg.ql b/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/cfg.ql +++ b/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt01.ql b/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt01.ql index e58562724b7..bec85d6c39d 100644 --- a/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt01.ql +++ b/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt01.ql @@ -1,23 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt01.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt01.ql index e6c37734bb3..d4071a08095 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt01.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt01.ql @@ -7,10 +7,10 @@ import cpp from ForStmt fs, int k, LabelStmt l where - fs.getEnclosingFunction().hasName("normal") - and fs.getParentStmt().hasChild(fs, k) - and fs.getParentStmt().hasChild(l, k + 1) - and l = fs.getCondition().getASuccessor() - and l = fs.getCondition().getAFalseSuccessor() - and count(fs.getCondition().getAFalseSuccessor()) = 1 -select fs.getCondition(), l.getName() \ No newline at end of file + fs.getEnclosingFunction().hasName("normal") and + fs.getParentStmt().hasChild(fs, k) and + fs.getParentStmt().hasChild(l, k + 1) and + l = fs.getCondition().getASuccessor() and + l = fs.getCondition().getAFalseSuccessor() and + count(fs.getCondition().getAFalseSuccessor()) = 1 +select fs.getCondition(), l.getName() diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt02.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt02.ql index cc09f342582..6997ece34e5 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt02.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt02.ql @@ -7,8 +7,8 @@ import cpp from ForStmt fs where - fs.getEnclosingFunction().hasName("normal") - and fs.getStmt() = fs.getCondition().getASuccessor() - and fs.getStmt() = fs.getCondition().getATrueSuccessor() - and count(fs.getCondition().getATrueSuccessor()) = 1 -select fs.getCondition(), fs.getStmt() \ No newline at end of file + fs.getEnclosingFunction().hasName("normal") and + fs.getStmt() = fs.getCondition().getASuccessor() and + fs.getStmt() = fs.getCondition().getATrueSuccessor() and + count(fs.getCondition().getATrueSuccessor()) = 1 +select fs.getCondition(), fs.getStmt() diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt03.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt03.ql index 25e9bbd0368..c5b1bbbea12 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt03.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt03.ql @@ -7,4 +7,4 @@ import cpp from ForStmt fs where count(fs.getCondition().getASuccessor()) > 2 -select fs \ No newline at end of file +select fs diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt04.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt04.ql index b5c3345d9e6..a33bcb89808 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt04.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt04.ql @@ -8,9 +8,9 @@ import cpp from ForStmt fs, ExprStmt last, Expr succ where - fs.getEnclosingFunction().hasName("normal") - and last = ((Block)fs.getStmt()).getLastStmt() - and succ = fs.getCondition().getAChild*() - and succ = last.getExpr().getASuccessor() - and count(last.getExpr().getASuccessor()) = 1 -select fs, last.getExpr(), succ \ No newline at end of file + fs.getEnclosingFunction().hasName("normal") and + last = fs.getStmt().(Block).getLastStmt() and + succ = fs.getCondition().getAChild*() and + succ = last.getExpr().getASuccessor() and + count(last.getExpr().getASuccessor()) = 1 +select fs, last.getExpr(), succ diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt05.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt05.ql index ff0aec634fb..45e7c042270 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt05.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt05.ql @@ -6,9 +6,9 @@ import cpp from ForStmt fs -where not -( - fs.getASuccessor() = fs.getCondition().getAChild*() - and count(fs.getASuccessor()) = 1 -) -select fs \ No newline at end of file +where + not ( + fs.getASuccessor() = fs.getCondition().getAChild*() and + count(fs.getASuccessor()) = 1 + ) +select fs diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt06.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt06.ql index 52af8876ed4..146a0780e4f 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt06.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt06.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt07.ql b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt07.ql index e1c3b77d24a..25624534f25 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt07.ql +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt07.ql @@ -7,21 +7,17 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) select f.getName(), nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/forstmt/tinyforstmt/cfg.ql b/cpp/ql/test/successor-tests/forstmt/tinyforstmt/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/forstmt/tinyforstmt/cfg.ql +++ b/cpp/ql/test/successor-tests/forstmt/tinyforstmt/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/gotostmt/cfg.ql b/cpp/ql/test/successor-tests/gotostmt/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/gotostmt/cfg.ql +++ b/cpp/ql/test/successor-tests/gotostmt/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt01.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt01.ql index 56801dbd73a..aa0253e2cad 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt01.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt01.ql @@ -7,8 +7,8 @@ import cpp from IfStmt is where - is.getEnclosingFunction().hasName("normal") - and is.getElse() = is.getCondition().getASuccessor() - and is.getElse() = is.getCondition().getAFalseSuccessor() - and count(is.getCondition().getAFalseSuccessor()) = 1 -select is.getCondition(), ((LabelStmt)is.getElse().getChild(0)).getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + is.getElse() = is.getCondition().getASuccessor() and + is.getElse() = is.getCondition().getAFalseSuccessor() and + count(is.getCondition().getAFalseSuccessor()) = 1 +select is.getCondition(), is.getElse().getChild(0).(LabelStmt).getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt02.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt02.ql index 5b1245dfdac..e20467dcc99 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt02.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt02.ql @@ -7,8 +7,8 @@ import cpp from IfStmt is where - is.getEnclosingFunction().hasName("normal") - and is.getThen() = is.getCondition().getASuccessor() - and is.getThen() = is.getCondition().getATrueSuccessor() - and count(is.getCondition().getATrueSuccessor()) = 1 -select is.getCondition(), ((LabelStmt)is.getThen().getChild(0)).getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + is.getThen() = is.getCondition().getASuccessor() and + is.getThen() = is.getCondition().getATrueSuccessor() and + count(is.getCondition().getATrueSuccessor()) = 1 +select is.getCondition(), is.getThen().getChild(0).(LabelStmt).getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt03.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt03.ql index 4ba71826e99..033ae7ea5f7 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt03.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt03.ql @@ -7,4 +7,4 @@ import cpp from IfStmt is where count(is.getCondition().getASuccessor()) > 2 -select is \ No newline at end of file +select is diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt04.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt04.ql index 5724bc83c71..c6fbf3c99f7 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt04.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt04.ql @@ -7,10 +7,10 @@ import cpp from IfStmt is, int k, Stmt last, LabelStmt l3 where - is.getEnclosingFunction().hasName("normal") - and is.getParentStmt().hasChild(is, k) - and is.getParentStmt().hasChild(l3, k + 1) - and last = ((Block)is.getThen()).getLastStmt() - and l3 = last.getASuccessor() - and count(last.getASuccessor()) = 1 -select last, l3.getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + is.getParentStmt().hasChild(is, k) and + is.getParentStmt().hasChild(l3, k + 1) and + last = is.getThen().(Block).getLastStmt() and + l3 = last.getASuccessor() and + count(last.getASuccessor()) = 1 +select last, l3.getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt05.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt05.ql index 3e3504ff948..c63ea97a41e 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt05.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt05.ql @@ -6,9 +6,9 @@ import cpp from IfStmt is -where not -( - is.getASuccessor() = is.getCondition().getAChild*() - and count(is.getASuccessor()) = 1 -) -select is \ No newline at end of file +where + not ( + is.getASuccessor() = is.getCondition().getAChild*() and + count(is.getASuccessor()) = 1 + ) +select is diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt06.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt06.ql index 3a06ea36f5b..fc6ae7d3bc8 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt06.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt06.ql @@ -7,10 +7,10 @@ import cpp from IfStmt is, int k, Stmt last, LabelStmt l3 where - is.getEnclosingFunction().hasName("normal") - and is.getParentStmt().hasChild(is, k) - and is.getParentStmt().hasChild(l3, k + 1) - and last = ((Block)is.getElse()).getLastStmt() - and l3 = last.getASuccessor() - and count(last.getASuccessor()) = 1 -select last, l3.getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + is.getParentStmt().hasChild(is, k) and + is.getParentStmt().hasChild(l3, k + 1) and + last = is.getElse().(Block).getLastStmt() and + l3 = last.getASuccessor() and + count(last.getASuccessor()) = 1 +select last, l3.getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt07.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt07.ql index b8620b7e1ad..e1d7ac614e9 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt07.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt07.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt08.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt08.ql index 590d978577a..3aef6413162 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt08.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt08.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt09.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt09.ql index f36e58f7a18..72f120f49b7 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt09.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt09.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt10.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt10.ql index 7377b6cec78..3d1aa477d12 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt10.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt10.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt11.ql b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt11.ql index 474ea26c6db..b8be6ed3fa4 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt11.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt11.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("normal") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("normal") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt01.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt01.ql index 76ab83985d3..d1c9a589ab1 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt01.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt01.ql @@ -7,10 +7,10 @@ import cpp from IfStmt is, int k, LabelStmt l2 where - is.getEnclosingFunction().hasName("normal") - and is.getParentStmt().hasChild(is, k) - and is.getParentStmt().hasChild(l2, k + 1) - and l2 = is.getCondition().getASuccessor() - and l2 = is.getCondition().getAFalseSuccessor() - and count(is.getCondition().getAFalseSuccessor()) = 1 -select is.getCondition(), l2.getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + is.getParentStmt().hasChild(is, k) and + is.getParentStmt().hasChild(l2, k + 1) and + l2 = is.getCondition().getASuccessor() and + l2 = is.getCondition().getAFalseSuccessor() and + count(is.getCondition().getAFalseSuccessor()) = 1 +select is.getCondition(), l2.getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt02.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt02.ql index 36b2406e97b..90cfc707daa 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt02.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt02.ql @@ -7,9 +7,9 @@ import cpp from IfStmt is, Block t where - is.getEnclosingFunction().hasName("normal") - and t = is.getThen() - and t = is.getCondition().getASuccessor() - and t = is.getCondition().getATrueSuccessor() - and count(is.getCondition().getATrueSuccessor()) = 1 -select is.getCondition(), ((LabelStmt)t.getChild(0)).getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + t = is.getThen() and + t = is.getCondition().getASuccessor() and + t = is.getCondition().getATrueSuccessor() and + count(is.getCondition().getATrueSuccessor()) = 1 +select is.getCondition(), t.getChild(0).(LabelStmt).getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt03.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt03.ql index 04eeac42bb9..56a33295b91 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt03.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt03.ql @@ -7,4 +7,4 @@ import cpp from IfStmt is where count(is.getCondition().getASuccessor()) > 2 -select is \ No newline at end of file +select is diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt04.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt04.ql index 3d563db9014..f203b5f0ea2 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt04.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt04.ql @@ -7,10 +7,10 @@ import cpp from IfStmt is, int k, Stmt last, LabelStmt l2 where - is.getEnclosingFunction().hasName("normal") - and is.getParentStmt().hasChild(is, k) - and is.getParentStmt().hasChild(l2, k + 1) - and last = ((Block)is.getThen()).getLastStmt() - and l2 = last.getASuccessor() - and count(last.getASuccessor()) = 1 -select last, l2.getName() \ No newline at end of file + is.getEnclosingFunction().hasName("normal") and + is.getParentStmt().hasChild(is, k) and + is.getParentStmt().hasChild(l2, k + 1) and + last = is.getThen().(Block).getLastStmt() and + l2 = last.getASuccessor() and + count(last.getASuccessor()) = 1 +select last, l2.getName() diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt05.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt05.ql index 41a3c90583c..46d6d103b8a 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt05.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt05.ql @@ -6,9 +6,9 @@ import cpp from IfStmt is -where not -( - is.getASuccessor() = is.getCondition().getAChild*() - and count(is.getASuccessor()) = 1 -) -select is \ No newline at end of file +where + not ( + is.getASuccessor() = is.getCondition().getAChild*() and + count(is.getASuccessor()) = 1 + ) +select is diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt06.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt06.ql index 09ffcd0097e..a42c45b18d2 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt06.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt06.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt07.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt07.ql index e91c4730d42..6dcc397aaf1 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt07.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt07.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt08.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt08.ql index 5783178f830..5ca3e0bce8d 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt08.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt08.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt09.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt09.ql index 9db4d3624f4..e7590a96be1 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt09.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt09.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt10.ql b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt10.ql index 89099a7181a..3977486354f 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt10.ql +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt10.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("normal") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("normal") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer01.ql b/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer01.ql index e58562724b7..bec85d6c39d 100644 --- a/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer01.ql +++ b/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer01.ql @@ -1,23 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer01.ql b/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer01.ql index e58562724b7..bec85d6c39d 100644 --- a/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer01.ql +++ b/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer01.ql @@ -1,23 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/initializer/initializer/initializer01.ql b/cpp/ql/test/successor-tests/initializer/initializer/initializer01.ql index e58562724b7..bec85d6c39d 100644 --- a/cpp/ql/test/successor-tests/initializer/initializer/initializer01.ql +++ b/cpp/ql/test/successor-tests/initializer/initializer/initializer01.ql @@ -1,23 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql b/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql index b5c6f07bd40..4ccbe8aa1db 100644 --- a/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql +++ b/cpp/ql/test/successor-tests/initializer/parameterinitializer/controlflownode.ql @@ -1,5 +1,5 @@ import cpp from ControlFlowNode n -select n.getLocation().getStartLine(), n.getControlFlowScope(), n, - count(n.getAPredecessor()), count(n.getASuccessor()) +select n.getLocation().getStartLine(), n.getControlFlowScope(), n, count(n.getAPredecessor()), + count(n.getASuccessor()) diff --git a/cpp/ql/test/successor-tests/landexpr/cfg.ql b/cpp/ql/test/successor-tests/landexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/landexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/landexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/lorexpr/cfg.ql b/cpp/ql/test/successor-tests/lorexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/lorexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/lorexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/ltrbinopexpr/cfg.ql b/cpp/ql/test/successor-tests/ltrbinopexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/ltrbinopexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/ltrbinopexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/cfg.ql b/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/newexpr/newexpr/cfg.ql b/cpp/ql/test/successor-tests/newexpr/newexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/newexpr/newexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/newexpr/newexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/pruning/graphable.ql b/cpp/ql/test/successor-tests/pruning/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/pruning/graphable.ql +++ b/cpp/ql/test/successor-tests/pruning/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/questionexpr/cfg.ql b/cpp/ql/test/successor-tests/questionexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/questionexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/questionexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/returnstmt/graphable.ql b/cpp/ql/test/successor-tests/returnstmt/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/returnstmt/graphable.ql +++ b/cpp/ql/test/successor-tests/returnstmt/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/stackvariables/stackvariables/graphable.ql b/cpp/ql/test/successor-tests/stackvariables/stackvariables/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/stackvariables/stackvariables/graphable.ql +++ b/cpp/ql/test/successor-tests/stackvariables/stackvariables/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/staticlocals/no_dynamic_init/exprs.ql b/cpp/ql/test/successor-tests/staticlocals/no_dynamic_init/exprs.ql index 7eb550d895e..31d7b956062 100644 --- a/cpp/ql/test/successor-tests/staticlocals/no_dynamic_init/exprs.ql +++ b/cpp/ql/test/successor-tests/staticlocals/no_dynamic_init/exprs.ql @@ -5,4 +5,3 @@ import cpp // expressions seeing as we have to compile a query anyway. from Expr e select e.getLocation(), e - diff --git a/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals01.ql b/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals01.ql index e58562724b7..bec85d6c39d 100644 --- a/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals01.ql +++ b/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals01.ql @@ -1,23 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/stmt_expr/cfg.ql b/cpp/ql/test/successor-tests/stmt_expr/cfg.ql index e58562724b7..bec85d6c39d 100644 --- a/cpp/ql/test/successor-tests/stmt_expr/cfg.ql +++ b/cpp/ql/test/successor-tests/stmt_expr/cfg.ql @@ -1,23 +1,18 @@ import cpp string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - n.getLocation().getStartLine(), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), + n.getLocation().getStartLine(), count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/cfg.ql b/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/switchstmt/duff/cfg.ql b/cpp/ql/test/successor-tests/switchstmt/duff/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/switchstmt/duff/cfg.ql +++ b/cpp/ql/test/successor-tests/switchstmt/duff/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/switchstmt/duff2/cfg.ql b/cpp/ql/test/successor-tests/switchstmt/duff2/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/switchstmt/duff2/cfg.ql +++ b/cpp/ql/test/successor-tests/switchstmt/duff2/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/cfg.ql b/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/cfg.ql +++ b/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/switchstmt/switchbody/graphable.ql b/cpp/ql/test/successor-tests/switchstmt/switchbody/graphable.ql index 4c3d73d46ee..9c93d81d163 100644 --- a/cpp/ql/test/successor-tests/switchstmt/switchbody/graphable.ql +++ b/cpp/ql/test/successor-tests/switchstmt/switchbody/graphable.ql @@ -2,11 +2,13 @@ import cpp class DestructorCallEnhanced extends DestructorCall { - override string toString() { - if exists(this.getQualifier().(VariableAccess).getTarget().getName()) - then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName() - else result = super.toString() - } + override string toString() { + if exists(this.getQualifier().(VariableAccess).getTarget().getName()) + then + result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + + this.getTarget().getName() + else result = super.toString() + } } string scope(ControlFlowNode x) { @@ -16,19 +18,19 @@ string scope(ControlFlowNode x) { } predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - isEdge = false and x = y and label = x.toString() + isEdge = false and x = y and label = x.toString() } predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) { - exists(string truelabel, string falselabel | - isEdge = true - and x.getASuccessor() = y - and if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "" - and if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "" - and label = truelabel + falselabel) + exists(string truelabel, string falselabel | + isEdge = true and + x.getASuccessor() = y and + (if x.getATrueSuccessor() = y then truelabel = "T" else truelabel = "") and + (if x.getAFalseSuccessor() = y then falselabel = "F" else falselabel = "") and + label = truelabel + falselabel + ) } from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label) select scope(x), isEdge, x, y, label - diff --git a/cpp/ql/test/successor-tests/switchstmt/switchstmt/cfg.ql b/cpp/ql/test/successor-tests/switchstmt/switchstmt/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/switchstmt/switchstmt/cfg.ql +++ b/cpp/ql/test/successor-tests/switchstmt/switchstmt/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/unaryopexpr/cfg.ql b/cpp/ql/test/successor-tests/unaryopexpr/cfg.ql index 358d7912906..190dd3f3fc5 100644 --- a/cpp/ql/test/successor-tests/unaryopexpr/cfg.ql +++ b/cpp/ql/test/successor-tests/unaryopexpr/cfg.ql @@ -1,34 +1,28 @@ import cpp int getCFLine(ControlFlowNode n) { - if n instanceof Function - then // Functions appear at the end of the control flow, so we get - // nicer results if we take the last position in the function, - // rather than the function's position (which is the start). - result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) - else result = n.getLocation().getStartLine() + if n instanceof Function + then + // Functions appear at the end of the control flow, so we get + // nicer results if we take the last position in the function, + // rather than the function's position (which is the start). + result = max(ControlFlowNode c | c.getControlFlowScope() = n | c.getLocation().getStartLine()) + else result = n.getLocation().getStartLine() } string getASuccessorOrNone(ControlFlowNode n) { - if exists(n.getASuccessor()) - then exists (ControlFlowNode s, string trueSucc, string falseSucc | - s = n.getASuccessor() - and if s = n.getATrueSuccessor() then trueSucc = " " - else trueSucc = "" - and if s = n.getAFalseSuccessor() then falseSucc = " " - else falseSucc = "" - and result = trueSucc + falseSucc - + getCFLine(s) + ": " - + s.toString()) - else result = "" + if exists(n.getASuccessor()) + then + exists(ControlFlowNode s, string trueSucc, string falseSucc | + s = n.getASuccessor() and + (if s = n.getATrueSuccessor() then trueSucc = " " else trueSucc = "") and + (if s = n.getAFalseSuccessor() then falseSucc = " " else falseSucc = "") and + result = trueSucc + falseSucc + getCFLine(s) + ": " + s.toString() + ) + else result = "" } from ControlFlowNode n -select n.getLocation().getFile().getShortName(), - n.getControlFlowScope(), - getCFLine(n), - count(n.getAPredecessor*()), // This helps order things sensibly - n.getLocation(), - n, - getASuccessorOrNone(n) - +select n.getLocation().getFile().getShortName(), n.getControlFlowScope(), getCFLine(n), + count(n.getAPredecessor*()), // This helps order things sensibly + n.getLocation(), n, getASuccessorOrNone(n) diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt01.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt01.ql index 5fbad7d7eab..1108c86436d 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt01.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt01.ql @@ -7,10 +7,10 @@ import cpp from WhileStmt ws, int k, LabelStmt l where - ws.getEnclosingFunction().hasName("normal") - and ws.getParentStmt().hasChild(ws, k) - and ws.getParentStmt().hasChild(l, k + 1) - and l = ws.getCondition().getASuccessor() - and l = ws.getCondition().getAFalseSuccessor() - and count(ws.getCondition().getAFalseSuccessor()) = 1 -select ws.getCondition(), l.getName() \ No newline at end of file + ws.getEnclosingFunction().hasName("normal") and + ws.getParentStmt().hasChild(ws, k) and + ws.getParentStmt().hasChild(l, k + 1) and + l = ws.getCondition().getASuccessor() and + l = ws.getCondition().getAFalseSuccessor() and + count(ws.getCondition().getAFalseSuccessor()) = 1 +select ws.getCondition(), l.getName() diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt02.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt02.ql index 360c30a5f7a..70a897fc7d8 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt02.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt02.ql @@ -7,8 +7,8 @@ import cpp from WhileStmt ws where - ws.getEnclosingFunction().hasName("normal") - and ws.getStmt() = ws.getCondition().getASuccessor() - and ws.getStmt() = ws.getCondition().getATrueSuccessor() - and count(ws.getCondition().getATrueSuccessor()) = 1 -select ws.getCondition(), ws.getStmt() \ No newline at end of file + ws.getEnclosingFunction().hasName("normal") and + ws.getStmt() = ws.getCondition().getASuccessor() and + ws.getStmt() = ws.getCondition().getATrueSuccessor() and + count(ws.getCondition().getATrueSuccessor()) = 1 +select ws.getCondition(), ws.getStmt() diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt03.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt03.ql index 67a2e2d0dcc..62f887f5fcb 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt03.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt03.ql @@ -7,4 +7,4 @@ import cpp from WhileStmt ws where count(ws.getCondition().getASuccessor()) > 2 -select ws \ No newline at end of file +select ws diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt04.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt04.ql index 0cfe44ad54a..1ae9f4931a5 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt04.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt04.ql @@ -7,9 +7,9 @@ import cpp from WhileStmt ws, ExprStmt last, Expr succ where - ws.getEnclosingFunction().hasName("normal") - and last = ((Block)ws.getStmt()).getLastStmt() - and succ = last.getExpr().getASuccessor() - and succ = ws.getCondition().getAChild*() - and count(last.getExpr().getASuccessor()) = 1 -select last.getExpr(), succ \ No newline at end of file + ws.getEnclosingFunction().hasName("normal") and + last = ws.getStmt().(Block).getLastStmt() and + succ = last.getExpr().getASuccessor() and + succ = ws.getCondition().getAChild*() and + count(last.getExpr().getASuccessor()) = 1 +select last.getExpr(), succ diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt05.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt05.ql index 555e9292acb..73b0d9bd348 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt05.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt05.ql @@ -6,9 +6,9 @@ import cpp from WhileStmt ws -where not -( - ws.getCondition().getAChild*() = ws.getASuccessor() - and count(ws.getASuccessor()) = 1 -) -select ws \ No newline at end of file +where + not ( + ws.getCondition().getAChild*() = ws.getASuccessor() and + count(ws.getASuccessor()) = 1 + ) +select ws diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt06.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt06.ql index b23cf64e53a..df3cd08c92f 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt06.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt06.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt07.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt07.ql index 8105f381065..db1b7c12376 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt07.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt07.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_1") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_1") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt08.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt08.ql index 1670fe7418c..bc24effc94e 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt08.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt08.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt09.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt09.ql index a4b25894baa..54f50f0c836 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt09.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt09.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_true_3") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_true_3") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt10.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt10.ql index 3d5a62a2c32..bf4df5d3e67 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt10.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt10.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("normal") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("normal") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt11.ql b/cpp/ql/test/successor-tests/whilestmt/whilestmt11.ql index c7ff95ed390..df987f2a655 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt11.ql +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt11.ql @@ -7,22 +7,18 @@ import cpp from Function f, ControlFlowNode n, ControlFlowNode s, int fStart, int nOffset, int sOffset where - f.hasName("always_false_2") - and f = n.getControlFlowScope() - and s = n.getASuccessor() - and fStart = f.getLocation().getStartLine() - and - ( - if(n.getLocation() instanceof UnknownLocation) then - nOffset = -1 - else - nOffset = n.getLocation().getStartLine() - fStart - ) - and - ( - if(s.getLocation() instanceof UnknownLocation) then - sOffset = -1 - else - sOffset = s.getLocation().getStartLine() - fStart - ) -select nOffset, n, sOffset, s \ No newline at end of file + f.hasName("always_false_2") and + f = n.getControlFlowScope() and + s = n.getASuccessor() and + fStart = f.getLocation().getStartLine() and + ( + if n.getLocation() instanceof UnknownLocation + then nOffset = -1 + else nOffset = n.getLocation().getStartLine() - fStart + ) and + ( + if s.getLocation() instanceof UnknownLocation + then sOffset = -1 + else sOffset = s.getLocation().getStartLine() - fStart + ) +select nOffset, n, sOffset, s