Merge branch 'main' into repeatedWord

This commit is contained in:
Erik Krogh Kristensen
2022-08-09 21:22:47 +02:00
761 changed files with 51997 additions and 64658 deletions

View File

@@ -1,3 +1,15 @@
## 0.3.2
### Bug Fixes
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.
## 0.3.1
### Minor Analysis Improvements
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.
## 0.3.0
### Deprecated APIs

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* The IR dataflow library now includes flow through global variables. This enables new findings in many scenarios.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* A new class predicate `MustFlowConfiguration::allowInterproceduralFlow` has been added to the `semmle.code.cpp.ir.dataflow.MustFlow` library. The new predicate can be overridden to disable interprocedural flow.

View File

@@ -1,4 +1,5 @@
---
category: minorAnalysis
---
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the the C++ logical and variable declarations in conditions.
## 0.3.1
### Minor Analysis Improvements
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.

View File

@@ -0,0 +1,5 @@
## 0.3.2
### Bug Fixes
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.3.0
lastReleaseVersion: 0.3.2

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 0.3.1-dev
version: 0.3.3-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -6,6 +6,7 @@
import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
/**
* Get the `Element` that represents this `@element`.
@@ -28,9 +29,12 @@ Element mkElement(@element e) { unresolveElement(result) = e }
pragma[inline]
@element unresolveElement(Element e) {
not result instanceof @usertype and
not result instanceof @variable and
result = e
or
e = resolveClass(result)
or
e = resolveGlobalVariable(result)
}
/**

View File

@@ -6,6 +6,7 @@ import semmle.code.cpp.Element
import semmle.code.cpp.exprs.Access
import semmle.code.cpp.Initializer
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
/**
* A C/C++ variable. For example, in the following code there are four
@@ -32,6 +33,8 @@ private import semmle.code.cpp.internal.ResolveClass
* can have multiple declarations.
*/
class Variable extends Declaration, @variable {
Variable() { isVariable(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "Variable" }
/** Gets the initializer of this variable, if any. */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/**
* Provides classes for modeling built-in operations. Built-in operations are
* Provides classes for modeling built-in operations. Built-in operations are
* typically compiler specific and are used by libraries and generated code.
*/
@@ -120,8 +120,8 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
/**
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is a GNU/Clang extension.
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is a gcc/clang extension.
* ```
* struct S {
* int a, b;
@@ -137,8 +137,8 @@ class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
/**
* A C/C++ `__INTADDR__` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is an EDG extension.
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is an EDG extension.
* ```
* struct S {
* int a, b;
@@ -173,7 +173,7 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
*
* Returns `true` if the type has a copy constructor.
* ```
* std::integral_constant< bool, __has_copy(_Tp)> hc;
* std::integral_constant<bool, __has_copy(_Tp)> hc;
* ```
*/
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
@@ -189,7 +189,7 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
* Returns `true` if a copy assignment operator has an empty exception
* specification.
* ```
* std::integral_constant< bool, __has_nothrow_assign(_Tp)> hnta;
* std::integral_constant<bool, __has_nothrow_assign(_Tp)> hnta;
* ```
*/
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
@@ -220,7 +220,7 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
*
* Returns `true` if the copy constructor has an empty exception specification.
* ```
* std::integral_constant< bool, __has_nothrow_copy(MyType) >;
* std::integral_constant<bool, __has_nothrow_copy(MyType) >;
* ```
*/
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
@@ -266,7 +266,7 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
*
* Returns true if the type has a trivial copy constructor.
* ```
* std::integral_constant< bool, __has_trivial_copy(MyType) > htc;
* std::integral_constant<bool, __has_trivial_copy(MyType)> htc;
* ```
*/
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
@@ -468,7 +468,7 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
* ```
* template<typename _Tp1, typename _Tp2>
* struct types_compatible
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2) >
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2)>
* { };
* ```
*/
@@ -479,8 +479,7 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
/**
* A clang `__builtin_shufflevector` expression.
*
* It outputs a permutation of elements from one or two input vectors.
* Please see
* It outputs a permutation of elements from one or two input vectors. See
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
* for more information.
* ```
@@ -494,11 +493,29 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
}
/**
* A gcc `__builtin_shuffle` expression.
*
* It outputs a permutation of elements from one or two input vectors.
* See https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
* for more information.
* ```
* // Concatenate every other element of 4-element vectors V1 and V2.
* M = {0, 2, 4, 6};
* V3 = __builtin_shuffle(V1, V2, M);
* ```
*/
class BuiltInOperationBuiltInShuffle extends BuiltInOperation, @builtinshuffle {
override string toString() { result = "__builtin_shuffle" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffle" }
}
/**
* A clang `__builtin_convertvector` expression.
*
* Allows for conversion of vectors of equal element count and compatible
* element types. Please see
* element types. See
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
* for more information.
* ```
@@ -547,7 +564,7 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
* ```
* template<typename T, typename... Args>
* struct is_trivially_constructible
* : public integral_constant<bool, __is_trivially_constructible(T, Args...) >
* : public integral_constant<bool, __is_trivially_constructible(T, Args...)>
* { };
* ```
*/
@@ -612,13 +629,10 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
* The `__is_trivially_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the assignment operator `C::operator =(const C& c)` is
* trivial.
* Returns `true` if the assignment operator `C::operator =(const D& d)` is
* trivial (i.e., it will not call any operation that is non-trivial).
* ```
* template<typename T>
* struct is_trivially_assignable
* : public integral_constant<bool, __is_trivially_assignable(T) >
* { };
* bool v = __is_trivially_assignable(MyType1, MyType2);
* ```
*/
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
@@ -631,10 +645,10 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
* The `__is_nothrow_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const C& c) nothrow`
* Returns true if there exists a `C::operator =(const D& d) nothrow`
* assignment operator (i.e, with an empty exception specification).
* ```
* bool v = __is_nothrow_assignable(MyType);
* bool v = __is_nothrow_assignable(MyType1, MyType2);
* ```
*/
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
@@ -643,15 +657,30 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
}
/**
* The `__is_assignable` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const D& d)` assignment
* operator.
* ```
* bool v = __is_assignable(MyType1, MyType2);
* ```
*/
class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
override string toString() { result = "__is_assignable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
}
/**
* The `__is_standard_layout` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type is a primitive type, or a `class`, `struct` or
* `union` WITHOUT (1) virtual functions or base classes, (2) reference member
* variable or (3) multiple occurrences of base `class` objects, among other
* restrictions. Please see
* https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* `union` without (1) virtual functions or base classes, (2) reference member
* variable, or (3) multiple occurrences of base `class` objects, among other
* restrictions. See https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* for more information.
* ```
* bool v = __is_standard_layout(MyType);
@@ -668,7 +697,7 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
* implementations of the `<type_traits>` header).
*
* Returns `true` if instances of this type can be copied by trivial
* means. The copying is done in a manner similar to the `memcpy`
* means. The copying is done in a manner similar to the `memcpy`
* function.
*/
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
@@ -682,13 +711,13 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
* the `<type_traits>` header).
*
* Returns `true` if the type is a scalar type, a reference type or an array of
* literal types, among others. Please see
* literal types, among others. See
* https://en.cppreference.com/w/cpp/named_req/LiteralType
* for more information.
*
* ```
* template <typename _Tp>
* std::integral_constant< bool, __is_literal_type(_Tp)> ilt;
* std::integral_constant<bool, __is_literal_type(_Tp)> ilt;
* ```
*/
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
@@ -705,7 +734,7 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr
* compiler, with semantics of the `memcpy` operation.
* ```
* template <typename _Tp>
* std::integral_constant< bool, __has_trivial_move_constructor(_Tp)> htmc;
* std::integral_constant<bool, __has_trivial_move_constructor(_Tp)> htmc;
* ```
*/
class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
@@ -723,7 +752,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
* ```
* template<typename T>
* struct has_trivial_move_assign
* : public integral_constant<bool, __has_trivial_move_assign(T) >
* : public integral_constant<bool, __has_trivial_move_assign(T)>
* { };
* ```
*/
@@ -758,7 +787,7 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
* ```
* template<typename T, typename... Args>
* struct is_constructible
* : public integral_constant<bool, __is_constructible(T, Args...) >
* : public integral_constant<bool, __is_constructible(T, Args...)>
* { };
* ```
*/
@@ -785,7 +814,7 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
}
/**
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type defines a _finalizer_ `C::!C(void)`, to be called
* from either the regular destructor or the garbage collector.
@@ -800,10 +829,10 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
}
/**
* The `__is_delegate` built-in operation. This is a Microsoft extension.
* The `__is_delegate` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the function has been declared as a `delegate`, used in
* message forwarding. Please see
* message forwarding. See
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
* for more information.
*/
@@ -814,9 +843,9 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
}
/**
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type has been declared as an `interface`. Please see
* Returns `true` if the type has been declared as an `interface`. See
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
* for more information.
*/
@@ -827,9 +856,9 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
}
/**
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the object passed in is a _platform array_. Please see
* Returns `true` if the object passed in is a _platform array_. See
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
* for more information.
* ```
@@ -844,9 +873,9 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
}
/**
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type is a _reference class_. Please see
* Returns `true` if the type is a _reference class_. See
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* for more information.
* ```
@@ -861,10 +890,10 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
}
/**
* The `__is_sealed` built-in operation. This is a Microsoft extension.
* The `__is_sealed` built-in operation. This is a Microsoft extension.
*
* Returns `true` if a given class or virtual function is marked as `sealed`,
* meaning that it cannot be extended or overridden. The `sealed` keyword
* meaning that it cannot be extended or overridden. The `sealed` keyword
* is similar to the C++11 `final` keyword.
* ```
* ref class X sealed {
@@ -879,7 +908,7 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
}
/**
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if passed a value type that contains no references to the
* garbage-collected heap.
@@ -898,9 +927,9 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
}
/**
* The `__is_value_class` built-in operation. This is a Microsoft extension.
* The `__is_value_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if passed a value type. Please see
* Returns `true` if passed a value type. See
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* For more information.
* ```
@@ -922,7 +951,7 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
* ```
* template<typename T>
* struct is_final
* : public integral_constant<bool, __is_final(T) >
* : public integral_constant<bool, __is_final(T)>
* { };
* ```
*/
@@ -933,7 +962,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
}
/**
* The `__builtin_choose_expr` expression. This is a GNU/Clang extension.
* The `__builtin_choose_expr` expression. This is a gcc/clang extension.
*
* The expression functions similarly to the ternary `?:` operator, except
* that it is evaluated at compile-time.
@@ -978,3 +1007,50 @@ class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
/** Gets the operand corresponding to the imaginary part of the complex number. */
Expr getImaginaryOperand() { this.hasChild(result, 1) }
}
/**
* A C++ `__is_aggregate` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type has is an aggregate type.
* ```
* std::integral_constant<bool, __is_aggregate(_Tp)> ia;
* ```
*/
class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate {
override string toString() { result = "__is_aggregate" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAggregate" }
}
/**
* A C++ `__has_unique_object_representations` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type is trivially copyable and if the object representation
* is unique for two objects with the same value.
* ```
* bool v = __has_unique_object_representations(MyType);
* ```
*/
class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation,
@hasuniqueobjectrepresentations {
override string toString() { result = "__has_unique_object_representations" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" }
}
/**
* A C/C++ `__builtin_bit_cast` built-in operation (used by some implementations
* of `std::bit_cast`).
*
* Performs a bit cast from a value to a type.
* ```
* __builtin_bit_cast(Type, value);
* ```
*/
class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
override string toString() { result = "__builtin_bit_cast" }
override string getAPrimaryQlClass() { result = "BuiltInBitCast" }
}

View File

@@ -596,9 +596,12 @@ class ParenthesisExpr extends Conversion, @parexpr {
}
/**
* A C/C++ expression that has not been resolved.
* A C/C++ expression that could not be resolved, or that can no longer be
* represented due to a database upgrade or downgrade.
*
* It is assigned `ErroneousType` as its type.
* If the expression could not be resolved, it has type `ErroneousType`. In the
* case of a database upgrade or downgrade, the original type from before the
* upgrade or downgrade is kept if that type can be represented.
*/
class ErrorExpr extends Expr, @errorexpr {
override string toString() { result = "<error expr>" }

View File

@@ -0,0 +1,57 @@
private predicate hasDefinition(@globalvariable g) {
exists(@var_decl vd | var_decls(vd, g, _, _, _) | var_def(vd))
}
private predicate onlyOneCompleteGlobalVariableExistsWithMangledName(@mangledname name) {
strictcount(@globalvariable g | hasDefinition(g) and mangled_name(g, name)) = 1
}
/** Holds if `g` is a unique global variable with a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithDefinition(@mangledname name, @globalvariable g) {
hasDefinition(g) and
mangled_name(g, name) and
onlyOneCompleteGlobalVariableExistsWithMangledName(name)
}
/** Holds if `g` is a global variable without a definition named `name`. */
private predicate isGlobalWithMangledNameAndWithoutDefinition(@mangledname name, @globalvariable g) {
not hasDefinition(g) and
mangled_name(g, name)
}
/**
* Holds if `incomplete` is a global variable without a definition, and there exists
* a unique global variable `complete` with the same name that does have a definition.
*/
private predicate hasTwinWithDefinition(@globalvariable incomplete, @globalvariable complete) {
exists(@mangledname name |
not variable_instantiation(incomplete, complete) and
isGlobalWithMangledNameAndWithoutDefinition(name, incomplete) and
isGlobalWithMangledNameAndWithDefinition(name, complete)
)
}
import Cached
cached
private module Cached {
/**
* If `v` is a global variable without a definition, and there exists a unique
* global variable with the same name that does have a definition, then the
* result is that unique global variable. Otherwise, the result is `v`.
*/
cached
@variable resolveGlobalVariable(@variable v) {
hasTwinWithDefinition(v, result)
or
not hasTwinWithDefinition(v, _) and
result = v
}
cached
predicate isVariable(@variable v) {
not v instanceof @globalvariable
or
v = resolveGlobalVariable(_)
}
}

View File

@@ -38,6 +38,9 @@ abstract class MustFlowConfiguration extends string {
*/
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
/** Holds if this configuration allows flow from arguments to parameters. */
predicate allowInterproceduralFlow() { any() }
/**
* Holds if data must flow from `source` to `sink` for this configuration.
*
@@ -204,10 +207,25 @@ private module Cached {
}
}
/**
* Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this
* predicate ensures that joins go from `n` to the result instead of the other
* way around.
*/
pragma[inline]
private Declaration getEnclosingCallable(DataFlow::Node n) {
pragma[only_bind_into](result) = pragma[only_bind_out](n).getEnclosingCallable()
}
/** Holds if `nodeFrom` flows to `nodeTo`. */
private predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, MustFlowConfiguration config) {
exists(config) and
Cached::step(nodeFrom, nodeTo)
Cached::step(pragma[only_bind_into](nodeFrom), pragma[only_bind_into](nodeTo)) and
(
config.allowInterproceduralFlow()
or
getEnclosingCallable(nodeFrom) = getEnclosingCallable(nodeTo)
)
or
config.isAdditionalFlowStep(nodeFrom, nodeTo)
}

View File

@@ -244,7 +244,25 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
* calling context. For example, this would happen with flow through a
* global or static variable.
*/
predicate jumpStep(Node n1, Node n2) { none() }
predicate jumpStep(Node n1, Node n2) {
exists(GlobalOrNamespaceVariable v |
v =
n1.asInstruction()
.(StoreInstruction)
.getResultAddress()
.(VariableAddressInstruction)
.getAstVariable() and
v = n2.asVariable()
or
v =
n2.asInstruction()
.(LoadInstruction)
.getSourceAddress()
.(VariableAddressInstruction)
.getAstVariable() and
v = n1.asVariable()
)
}
/**
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.

View File

@@ -947,7 +947,7 @@ abstract class TranslatedElement extends TTranslatedElement {
}
/**
* Represents the IR translation of a root element, either a function or a global variable.
* The IR translation of a root element, either a function or a global variable.
*/
abstract class TranslatedRootElement extends TranslatedElement {
TranslatedRootElement() {

View File

@@ -65,7 +65,7 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
result = this.getInstruction(InitializerVariableAddressTag())
or
tag = InitializerVariableAddressTag() and
result = getChild(1).getFirstInstruction()
result = this.getChild(1).getFirstInstruction()
or
tag = ReturnTag() and
result = this.getInstruction(AliasedUseTag())

View File

@@ -1650,6 +1650,11 @@ case @expr.kind of
| 327 = @co_await
| 328 = @co_yield
| 329 = @temp_init
| 330 = @isassignable
| 331 = @isaggregate
| 332 = @hasuniqueobjectrepresentations
| 333 = @builtinbitcast
| 334 = @builtinshuffle
;
@var_args_expr = @vastartexpr
@@ -1711,6 +1716,11 @@ case @expr.kind of
| @isfinalexpr
| @builtinchooseexpr
| @builtincomplex
| @isassignable
| @isaggregate
| @hasuniqueobjectrepresentations
| @builtinbitcast
| @builtinshuffle
;
new_allocated_type(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add new builtin operations
compatibility: backwards

View File

@@ -1,3 +1,11 @@
## 0.3.1
## 0.3.0
### Breaking Changes
* Contextual queries and the query libraries they depend on have been moved to the `codeql/cpp-all` package.
## 0.2.0
## 0.1.4

View File

@@ -10,7 +10,6 @@
* @precision medium
* @tags security
* external/cwe/cwe-480
* external/microsoft/c6317
*/
import cpp

View File

@@ -7,8 +7,7 @@
* @problem.severity error
* @precision high
* @id cpp/string-copy-return-value-as-boolean
* @tags external/microsoft/C6324
* correctness
* @tags correctness
*/
import cpp

View File

@@ -7,7 +7,6 @@
* @id cpp/inconsistent-loop-direction
* @tags correctness
* external/cwe/cwe-835
* external/microsoft/6293
* @msrc.severity important
*/

View File

@@ -52,6 +52,18 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
)
}
// We disable flow into callables in this query as we'd otherwise get a result on this piece of code:
// ```cpp
// int* id(int* px) {
// return px; // this returns the local variable `x`, but it's fine as the local variable isn't declared in this scope.
// }
// void f() {
// int x;
// int* px = id(&x);
// }
// ```
override predicate allowInterproceduralFlow() { none() }
/**
* This configuration intentionally conflates addresses of fields and their object, and pointer offsets
* with their base pointer as this allows us to detect cases where an object's address flows to a
@@ -74,13 +86,9 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
from
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
ReturnStackAllocatedMemoryConfig conf, Function f
ReturnStackAllocatedMemoryConfig conf
where
conf.hasFlowPath(source, sink) and
source.getNode().asInstruction() = var and
// Only raise an alert if we're returning from the _same_ callable as the on that
// declared the stack variable.
var.getEnclosingFunction() = pragma[only_bind_into](f) and
sink.getNode().getEnclosingCallable() = pragma[only_bind_into](f)
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
source.getNode().asInstruction() = var
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
var.getAst().toString()

View File

@@ -77,7 +77,7 @@ class ExecState extends DataFlow::FlowState {
ExecState() {
this =
"ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and
interestingConcatenation(fst, snd)
interestingConcatenation(pragma[only_bind_into](fst), pragma[only_bind_into](snd))
}
DataFlow::Node getFstNode() { result = fst }

View File

@@ -8,11 +8,6 @@
* @precision high
* @tags security
* external/cwe/cwe-253
* external/microsoft/C6214
* external/microsoft/C6215
* external/microsoft/C6216
* external/microsoft/C6217
* external/microsoft/C6230
*/
import cpp

View File

@@ -9,7 +9,6 @@
* @msrc.severity important
* @tags security
* external/cwe/cwe-428
* external/microsoft/C6277
*/
import cpp

View File

@@ -10,7 +10,6 @@
* @precision high
* @tags security
* external/cwe/cwe-704
* external/microsoft/c/c6276
*/
import cpp

View File

@@ -11,7 +11,6 @@
* @precision high
* @tags security
* external/cwe/cwe-732
* external/microsoft/C6248
*/
import cpp

View File

@@ -1,4 +1,5 @@
---
category: breaking
---
## 0.3.0
### Breaking Changes
* Contextual queries and the query libraries they depend on have been moved to the `codeql/cpp-all` package.

View File

@@ -0,0 +1 @@
## 0.3.1

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.2.0
lastReleaseVersion: 0.3.1

View File

@@ -0,0 +1,6 @@
...
mbtowc(&wc, ptr, 4)); // BAD:we can get unpredictable results
...
mbtowc(&wc, ptr, MB_LEN_MAX); // GOOD
...

View File

@@ -0,0 +1,23 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p> Using a function to convert multibyte or wide characters with an invalid length argument may result in an out-of-range access error or unexpected results.</p>
</overview>
<example>
<p>The following example shows the erroneous and corrected method of using function mbtowc.</p>
<sample src="DangerousWorksWithMultibyteOrWideCharacters.cpp" />
</example>
<references>
<li>
CERT Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts">ARR30-C. Do not form or use out-of-bounds pointers or array subscripts - SEI CERT C Coding Standard - Confluence</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,236 @@
/**
* @name Dangerous use convert function.
* @description Using convert function with an invalid length argument can result in an out-of-bounds access error or unexpected result.
* @kind problem
* @id cpp/dangerous-use-convert-function
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-125
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/** Holds if there are indications that the variable is treated as a string. */
predicate exprMayBeString(Expr exp) {
(
exists(StringLiteral sl | globalValueNumber(exp) = globalValueNumber(sl))
or
exists(FunctionCall fctmp |
(
fctmp.getAnArgument().(VariableAccess).getTarget() = exp.(VariableAccess).getTarget() or
globalValueNumber(fctmp.getAnArgument()) = globalValueNumber(exp)
) and
fctmp.getTarget().hasName(["strlen", "strcat", "strncat", "strcpy", "sptintf", "printf"])
)
or
exists(AssignExpr astmp |
astmp.getRValue().getValue() = "0" and
astmp.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() =
exp.(VariableAccess).getTarget()
)
or
exists(ComparisonOperation cotmp, Expr exptmp1, Expr exptmp2 |
exptmp1.getValue() = "0" and
(
exptmp2.(PointerDereferenceExpr).getOperand().(VariableAccess).getTarget() =
exp.(VariableAccess).getTarget() or
exptmp2.(ArrayExpr).getArrayBase().(VariableAccess).getTarget() =
exp.getAChild().(VariableAccess).getTarget()
) and
cotmp.hasOperands(exptmp1, exptmp2)
)
)
}
/** Holds if expression is constant or operator call `sizeof`. */
predicate argConstOrSizeof(Expr exp) {
exp.getValue().toInt() > 1 or
exp.(SizeofTypeOperator).getTypeOperand().getSize() > 1
}
/** Holds if expression is macro. */
predicate argMacro(Expr exp) {
exists(MacroInvocation matmp |
exp = matmp.getExpr() and
(
matmp.getMacroName() = "MB_LEN_MAX" or
matmp.getMacroName() = "MB_CUR_MAX"
)
)
}
/** Holds if erroneous situations of using functions `mbtowc` and `mbrtowc` are detected. */
predicate findUseCharacterConversion(Expr exp, string msg) {
exists(FunctionCall fc |
fc = exp and
(
exists(Loop lptmp | lptmp = fc.getEnclosingStmt().getParentStmt*()) and
fc.getTarget().hasName(["mbtowc", "mbrtowc", "_mbtowc_l"]) and
not fc.getArgument(0).isConstant() and
not fc.getArgument(1).isConstant() and
(
exprMayBeString(fc.getArgument(1)) and
argConstOrSizeof(fc.getArgument(2)) and
fc.getArgument(2).getValue().toInt() < 5 and
not argMacro(fc.getArgument(2)) and
msg = "Size can be less than maximum character length, use macro MB_CUR_MAX."
or
not exprMayBeString(fc.getArgument(1)) and
(
argConstOrSizeof(fc.getArgument(2))
or
argMacro(fc.getArgument(2))
or
exists(DecrementOperation dotmp |
globalValueNumber(dotmp.getAnOperand()) = globalValueNumber(fc.getArgument(2)) and
not exists(AssignSubExpr aetmp |
(
aetmp.getLValue().(VariableAccess).getTarget() =
fc.getArgument(2).(VariableAccess).getTarget() or
globalValueNumber(aetmp.getLValue()) = globalValueNumber(fc.getArgument(2))
) and
globalValueNumber(aetmp.getRValue()) = globalValueNumber(fc)
)
)
) and
msg =
"Access beyond the allocated memory is possible, the length can change without changing the pointer."
or
exists(AssignPointerAddExpr aetmp |
(
aetmp.getLValue().(VariableAccess).getTarget() =
fc.getArgument(0).(VariableAccess).getTarget() or
globalValueNumber(aetmp.getLValue()) = globalValueNumber(fc.getArgument(0))
) and
globalValueNumber(aetmp.getRValue()) = globalValueNumber(fc)
) and
msg = "Maybe you're using the function's return value incorrectly."
)
)
)
}
/** Holds if detecting erroneous situations of working with multibyte characters. */
predicate findUseMultibyteCharacter(Expr exp, string msg) {
exists(ArrayType arrayType, ArrayExpr arrayExpr |
arrayExpr = exp and
arrayExpr.getArrayBase().getType() = arrayType and
(
exists(AssignExpr assZero, SizeofExprOperator sizeofArray, Expr oneValue |
oneValue.getValue() = "1" and
sizeofArray.getExprOperand().getType() = arrayType and
assZero.getLValue() = arrayExpr and
arrayExpr.getArrayOffset().(SubExpr).hasOperands(sizeofArray, oneValue) and
assZero.getRValue().getValue() = "0"
) and
arrayType.getArraySize() != arrayType.getByteSize() and
msg =
"The size of the array element is greater than one byte, so the offset will point outside the array."
or
exists(FunctionCall mbFunction |
(
mbFunction.getTarget().getName().matches("_mbs%") or
mbFunction.getTarget().getName().matches("mbs%") or
mbFunction.getTarget().getName().matches("_mbc%") or
mbFunction.getTarget().getName().matches("mbc%")
) and
mbFunction.getAnArgument().(VariableAccess).getTarget().getADeclarationEntry().getType() =
arrayType
) and
exists(Loop loop, SizeofExprOperator sizeofArray, AssignExpr assignExpr |
arrayExpr.getEnclosingStmt().getParentStmt*() = loop and
sizeofArray.getExprOperand().getType() = arrayType and
assignExpr.getLValue() = arrayExpr and
loop.getCondition().(LTExpr).getLeftOperand().(VariableAccess).getTarget() =
arrayExpr.getArrayOffset().getAChild*().(VariableAccess).getTarget() and
loop.getCondition().(LTExpr).getRightOperand() = sizeofArray
) and
msg =
"This buffer may contain multibyte characters, so attempting to copy may result in part of the last character being lost."
)
)
or
exists(FunctionCall mbccpy, Loop loop, SizeofExprOperator sizeofOp |
mbccpy.getTarget().hasName("_mbccpy") and
mbccpy.getArgument(0) = exp and
exp.getEnclosingStmt().getParentStmt*() = loop and
sizeofOp.getExprOperand().getType() =
exp.getAChild*().(VariableAccess).getTarget().getADeclarationEntry().getType() and
loop.getCondition().(LTExpr).getLeftOperand().(VariableAccess).getTarget() =
exp.getAChild*().(VariableAccess).getTarget() and
loop.getCondition().(LTExpr).getRightOperand() = sizeofOp and
msg =
"This buffer may contain multibyte characters, so an attempt to copy may result in an overflow."
)
}
/** Holds if erroneous situations of using functions `MultiByteToWideChar` and `WideCharToMultiByte` or `mbstowcs` and `_mbstowcs_l` and `mbsrtowcs` are detected. */
predicate findUseStringConversion(
Expr exp, string msg, int posBufSrc, int posBufDst, int posSizeDst, string nameCalls
) {
exists(FunctionCall fc |
fc = exp and
posBufSrc in [0 .. fc.getNumberOfArguments() - 1] and
posSizeDst in [0 .. fc.getNumberOfArguments() - 1] and
(
fc.getTarget().hasName(nameCalls) and
(
globalValueNumber(fc.getArgument(posBufDst)) = globalValueNumber(fc.getArgument(posBufSrc)) and
msg =
"According to the definition of the functions, if the source buffer and the destination buffer are the same, undefined behavior is possible."
or
exists(ArrayType arrayDst |
fc.getArgument(posBufDst).(VariableAccess).getTarget().getADeclarationEntry().getType() =
arrayDst and
fc.getArgument(posSizeDst).getValue().toInt() >= arrayDst.getArraySize() and
not exists(AssignExpr assZero |
assZero.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() =
fc.getArgument(posBufDst).(VariableAccess).getTarget() and
assZero.getRValue().getValue() = "0"
) and
not exists(Expr someExp, FunctionCall checkSize |
checkSize.getASuccessor*() = fc and
checkSize.getTarget().hasName(nameCalls) and
checkSize.getArgument(posSizeDst).getValue() = "0" and
globalValueNumber(checkSize) = globalValueNumber(someExp) and
someExp.getEnclosingStmt().getParentStmt*() instanceof IfStmt
) and
exprMayBeString(fc.getArgument(posBufDst)) and
msg =
"According to the definition of the functions, it is not guaranteed to write a null character at the end of the string, so access beyond the bounds of the destination buffer is possible."
)
or
exists(FunctionCall allocMem |
allocMem.getTarget().hasName(["calloc", "malloc"]) and
globalValueNumber(fc.getArgument(posBufDst)) = globalValueNumber(allocMem) and
(
allocMem.getArgument(allocMem.getNumberOfArguments() - 1).getValue() = "1" or
not exists(SizeofOperator sizeofOperator |
globalValueNumber(allocMem
.getArgument(allocMem.getNumberOfArguments() - 1)
.getAChild*()) = globalValueNumber(sizeofOperator)
)
) and
msg =
"The buffer destination has a type other than char, you need to take this into account when allocating memory."
)
or
fc.getArgument(posBufDst).getValue() = "0" and
fc.getArgument(posSizeDst).getValue() != "0" and
msg =
"If the destination buffer is NULL and its size is not 0, then undefined behavior is possible."
)
)
)
}
from Expr exp, string msg
where
findUseCharacterConversion(exp, msg) or
findUseMultibyteCharacter(exp, msg) or
findUseStringConversion(exp, msg, 1, 0, 2, ["mbstowcs", "_mbstowcs_l", "mbsrtowcs"]) or
findUseStringConversion(exp, msg, 2, 4, 5, ["MultiByteToWideChar", "WideCharToMultiByte"])
select exp, msg

View File

@@ -27,6 +27,9 @@ groups, and finally set the target user.</p>
</example>
<references>
<li>CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/POS36-C.+Observe+correct+revocation+order+while+relinquishing+privileges">POS36-C. Observe correct revocation order while relinquishing privileges</a>.
</li>
<li>CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/POS37-C.+Ensure+that+privilege+relinquishment+is+successful">POS37-C. Ensure that privilege relinquishment is successful</a>.
</li>

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 0.2.1-dev
version: 0.3.2-dev
groups:
- cpp
- queries

View File

@@ -0,0 +1,26 @@
| test1.cpp:28:5:28:23 | call to WideCharToMultiByte | According to the definition of the functions, if the source buffer and the destination buffer are the same, undefined behavior is possible. |
| test1.cpp:29:5:29:23 | call to MultiByteToWideChar | According to the definition of the functions, if the source buffer and the destination buffer are the same, undefined behavior is possible. |
| test1.cpp:45:3:45:21 | call to WideCharToMultiByte | According to the definition of the functions, it is not guaranteed to write a null character at the end of the string, so access beyond the bounds of the destination buffer is possible. |
| test1.cpp:58:3:58:21 | call to MultiByteToWideChar | The buffer destination has a type other than char, you need to take this into account when allocating memory. |
| test1.cpp:70:3:70:21 | call to MultiByteToWideChar | The buffer destination has a type other than char, you need to take this into account when allocating memory. |
| test1.cpp:76:10:76:28 | call to WideCharToMultiByte | If the destination buffer is NULL and its size is not 0, then undefined behavior is possible. |
| test1.cpp:93:5:93:23 | call to WideCharToMultiByte | According to the definition of the functions, it is not guaranteed to write a null character at the end of the string, so access beyond the bounds of the destination buffer is possible. |
| test2.cpp:15:5:15:12 | call to mbstowcs | According to the definition of the functions, if the source buffer and the destination buffer are the same, undefined behavior is possible. |
| test2.cpp:17:5:17:15 | call to _mbstowcs_l | According to the definition of the functions, if the source buffer and the destination buffer are the same, undefined behavior is possible. |
| test2.cpp:19:5:19:13 | call to mbsrtowcs | According to the definition of the functions, if the source buffer and the destination buffer are the same, undefined behavior is possible. |
| test2.cpp:35:3:35:10 | call to mbstowcs | According to the definition of the functions, it is not guaranteed to write a null character at the end of the string, so access beyond the bounds of the destination buffer is possible. |
| test2.cpp:48:3:48:10 | call to mbstowcs | The buffer destination has a type other than char, you need to take this into account when allocating memory. |
| test2.cpp:60:3:60:10 | call to mbstowcs | The buffer destination has a type other than char, you need to take this into account when allocating memory. |
| test2.cpp:66:10:66:17 | call to mbstowcs | If the destination buffer is NULL and its size is not 0, then undefined behavior is possible. |
| test2.cpp:80:3:80:10 | call to mbstowcs | According to the definition of the functions, it is not guaranteed to write a null character at the end of the string, so access beyond the bounds of the destination buffer is possible. |
| test3.cpp:16:5:16:13 | access to array | This buffer may contain multibyte characters, so attempting to copy may result in part of the last character being lost. |
| test3.cpp:36:13:36:18 | ... + ... | This buffer may contain multibyte characters, so an attempt to copy may result in an overflow. |
| test3.cpp:47:3:47:24 | access to array | The size of the array element is greater than one byte, so the offset will point outside the array. |
| test.cpp:66:27:66:32 | call to mbtowc | Size can be less than maximum character length, use macro MB_CUR_MAX. |
| test.cpp:76:27:76:32 | call to mbtowc | Size can be less than maximum character length, use macro MB_CUR_MAX. |
| test.cpp:106:11:106:16 | call to mbtowc | Access beyond the allocated memory is possible, the length can change without changing the pointer. |
| test.cpp:123:11:123:16 | call to mbtowc | Access beyond the allocated memory is possible, the length can change without changing the pointer. |
| test.cpp:140:11:140:16 | call to mbtowc | Access beyond the allocated memory is possible, the length can change without changing the pointer. |
| test.cpp:158:11:158:16 | call to mbtowc | Access beyond the allocated memory is possible, the length can change without changing the pointer. |
| test.cpp:181:11:181:16 | call to mbtowc | Access beyond the allocated memory is possible, the length can change without changing the pointer. |
| test.cpp:197:11:197:16 | call to mbtowc | Maybe you're using the function's return value incorrectly. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-125/DangerousWorksWithMultibyteOrWideCharacters.ql

View File

@@ -0,0 +1,206 @@
typedef unsigned long size_t;
#define MB_CUR_MAX 6
#define MB_LEN_MAX 16
int mbtowc(wchar_t *out, const char *in, size_t size);
int wprintf (const wchar_t* format, ...);
int strlen( const char * string );
int checkErrors();
void goodTest0()
{
char * ptr = "123456789";
int ret;
int len;
len = 9;
for (wchar_t wc; (ret = mbtowc(&wc, ptr, len)) > 0; len-=ret) { // GOOD
wprintf(L"%lc", wc);
ptr += ret;
}
}
void goodTest1(const char* ptr)
{
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, len)) > 0; len-=ret) { // GOOD
wprintf(L"%lc", wc);
ptr += ret;
}
}
void goodTest2(char* ptr)
{
int ret;
ptr[10]=0;
int len = 9;
for (wchar_t wc; (ret = mbtowc(&wc, ptr, 16)) > 0; len-=ret) { // GOOD
wprintf(L"%lc", wc);
ptr += ret;
}
}
void goodTest3(const char* ptr)
{
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, MB_CUR_MAX)) > 0; len-=ret) { // GOOD
wprintf(L"%lc", wc);
ptr += ret;
}
}
void goodTest4(const char* ptr)
{
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, MB_LEN_MAX)) > 0; len-=ret) { // GOOD
wprintf(L"%lc", wc);
ptr += ret;
}
}
void badTest1(const char* ptr)
{
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, 4)) > 0; len-=ret) { // BAD:we can get unpredictable results
wprintf(L"%lc", wc);
ptr += ret;
}
}
void badTest2(const char* ptr)
{
int ret;
int len;
len = strlen(ptr);
for (wchar_t wc; (ret = mbtowc(&wc, ptr, sizeof(wchar_t))) > 0; len-=ret) { // BAD:we can get unpredictable results
wprintf(L"%lc", wc);
ptr += ret;
}
}
void goodTest5(const char* ptr,wchar_t *wc,int wc_len)
{
int ret;
int len;
len = wc_len;
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, len); // GOOD
if (ret <0)
break;
if (ret == 0 || ret > len)
break;
len-=ret;
ptr+=ret;
wc++;
}
}
void badTest3(const char* ptr,int wc_len)
{
int ret;
int len;
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, MB_CUR_MAX); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
break;
len-=ret;
ptr+=ret;
wc++;
}
}
void badTest4(const char* ptr,int wc_len)
{
int ret;
int len;
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, 16); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
break;
len-=ret;
ptr+=ret;
wc++;
}
}
void badTest5(const char* ptr,int wc_len)
{
int ret;
int len;
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, sizeof(wchar_t)); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
break;
len-=ret;
ptr+=ret;
wc++;
}
}
void badTest6(const char* ptr,int wc_len)
{
int ret;
int len;
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && wc_len > 0) {
ret = mbtowc(wc, ptr, wc_len); // BAD
if (ret <0)
if (checkErrors()) {
++ptr;
--len;
continue;
} else
break;
if (ret == 0 || ret > len)
break;
wc_len--;
len-=ret;
wc++;
ptr+=ret;
}
}
void badTest7(const char* ptr,int wc_len)
{
int ret;
int len;
len = wc_len;
wchar_t *wc = new wchar_t[wc_len];
while (*ptr && wc_len > 0) {
ret = mbtowc(wc, ptr, len); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
break;
len--;
wc++;
ptr+=ret;
}
}
void badTest8(const char* ptr,wchar_t *wc)
{
int ret;
int len;
len = strlen(ptr);
while (*ptr && len > 0) {
ret = mbtowc(wc, ptr, len); // BAD
if (ret <0)
break;
if (ret == 0 || ret > len)
break;
len-=ret;
ptr++;
wc+=ret;
}
}

View File

@@ -0,0 +1,95 @@
#define CP_ACP 1
#define CP_UTF8 1
#define WC_COMPOSITECHECK 1
#define NULL 0
typedef unsigned int UINT;
typedef unsigned long DWORD, *PDWORD, *LPDWORD;
typedef char CHAR;
#define CONST const
typedef wchar_t WCHAR;
typedef CHAR *LPSTR;
typedef CONST CHAR *LPCSTR;
typedef CONST WCHAR *LPCWSTR;
typedef int BOOL;
typedef BOOL *LPBOOL;
int WideCharToMultiByte(UINT CodePage,DWORD dwFlags,LPCWSTR lpWideCharStr,int cchWideChar,LPSTR lpMultiByteStr,int cbMultiByte,LPCWSTR lpDefaultChar,LPBOOL lpUsedDefaultChar);
int MultiByteToWideChar(UINT CodePage,DWORD dwFlags,LPCSTR lpMultiByteStr,int cbMultiByte,LPCWSTR lpWideCharStr,int cchWideChar);
int printf ( const char * format, ... );
typedef unsigned int size_t;
void* calloc (size_t num, size_t size);
void* malloc (size_t size);
void badTest1(void *src, int size) {
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, (LPSTR)src, size, 0, 0); // BAD
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, (LPCWSTR)src, 30); // BAD
}
void goodTest2(){
wchar_t src[] = L"0123456789ABCDEF";
char dst[16];
int res = WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // GOOD
if (res == sizeof(dst)) {
dst[res-1] = NULL;
} else {
dst[res] = NULL;
}
printf("%s\n", dst);
}
void badTest2(){
wchar_t src[] = L"0123456789ABCDEF";
char dst[16];
WideCharToMultiByte(CP_UTF8, 0, src, -1, dst, 16, NULL, NULL); // BAD
printf("%s\n", dst);
}
void goodTest3(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)calloc(size + 1, sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // GOOD
}
void badTest3(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
}
void goodTest4(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)malloc((size + 1)*sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // GOOD
}
void badTest4(){
char src[] = "0123456789ABCDEF";
int size = MultiByteToWideChar(CP_UTF8, 0, src,sizeof(src),NULL,0);
wchar_t * dst = (wchar_t*)malloc(size + 1);
MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size+1); // BAD
}
int goodTest5(void *src){
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 0, 0, 0); // GOOD
}
int badTest5 (void *src) {
return WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, 0, 3, 0, 0); // BAD
}
void goodTest6(WCHAR *src)
{
int size;
char dst[5] ="";
size = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, src, -1, dst, 0, 0, 0);
if(size>=sizeof(dst)){
printf("buffer size error\n");
return;
}
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, sizeof(dst), 0, 0); // GOOD
printf("%s\n", dst);
}
void badTest6(WCHAR *src)
{
char dst[5] ="";
WideCharToMultiByte(CP_ACP, 0, src, -1, dst, 260, 0, 0); // BAD
printf("%s\n", dst);
}

View File

@@ -0,0 +1,82 @@
#define NULL 0
typedef unsigned int size_t;
struct mbstate_t{};
struct _locale_t{};
int printf ( const char * format, ... );
void* calloc (size_t num, size_t size);
void* malloc (size_t size);
size_t mbstowcs(wchar_t *wcstr,const char *mbstr,size_t count);
size_t _mbstowcs_l(wchar_t *wcstr,const char *mbstr,size_t count, _locale_t locale);
size_t mbsrtowcs(wchar_t *wcstr,const char *mbstr,size_t count, mbstate_t *mbstate);
void badTest1(void *src, int size) {
mbstowcs((wchar_t*)src,(char*)src,size); // BAD
_locale_t locale;
_mbstowcs_l((wchar_t*)src,(char*)src,size,locale); // BAD
mbstate_t *mbstate;
mbsrtowcs((wchar_t*)src,(char*)src,size,mbstate); // BAD
}
void goodTest2(){
char src[] = "0123456789ABCDEF";
wchar_t dst[16];
int res = mbstowcs(dst, src,16); // GOOD
if (res == sizeof(dst)) {
dst[res-1] = NULL;
} else {
dst[res] = NULL;
}
printf("%s\n", dst);
}
void badTest2(){
char src[] = "0123456789ABCDEF";
wchar_t dst[16];
mbstowcs(dst, src,16); // BAD
printf("%s\n", dst);
}
void goodTest3(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)calloc(size + 1, sizeof(wchar_t));
mbstowcs(dst, src,size+1); // GOOD
}
void badTest3(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)calloc(size + 1, 1);
mbstowcs(dst, src,size+1); // BAD
}
void goodTest4(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)malloc((size + 1)*sizeof(wchar_t));
mbstowcs(dst, src,size+1); // GOOD
}
void badTest4(){
char src[] = "0123456789ABCDEF";
int size = mbstowcs(NULL, src,NULL);
wchar_t * dst = (wchar_t*)malloc(size + 1);
mbstowcs(dst, src,size+1); // BAD
}
int goodTest5(void *src){
return mbstowcs(NULL, (char*)src,NULL); // GOOD
}
int badTest5 (void *src) {
return mbstowcs(NULL, (char*)src,3); // BAD
}
void goodTest6(void *src){
wchar_t dst[5];
int size = mbstowcs(NULL, (char*)src,NULL);
if(size>=sizeof(dst)){
printf("buffer size error\n");
return;
}
mbstowcs(dst, (char*)src,sizeof(dst)); // GOOD
printf("%s\n", dst);
}
void badTest6(void *src){
wchar_t dst[5];
mbstowcs(dst, (char*)src,260); // BAD
printf("%s\n", dst);
}

View File

@@ -0,0 +1,48 @@
#define NULL 0
typedef unsigned int size_t;
unsigned char * _mbsnbcpy(unsigned char * strDest,const unsigned char * strSource,size_t count);
size_t _mbclen(const unsigned char *c);
void _mbccpy(unsigned char *dest,const unsigned char *src);
unsigned char *_mbsinc(const unsigned char *current);
void goodTest1(unsigned char *src){
unsigned char dst[50];
_mbsnbcpy(dst,src,sizeof(dst)); // GOOD
}
size_t badTest1(unsigned char *src){
int cb = 0;
unsigned char dst[50];
while( cb < sizeof(dst) )
dst[cb++]=*src++; // BAD
return _mbclen(dst);
}
void goodTest2(unsigned char *src){
int cb = 0;
unsigned char dst[50];
while( (cb + _mbclen(src)) <= sizeof(dst) )
{
_mbccpy(dst+cb,src); // GOOD
cb+=_mbclen(src);
src=_mbsinc(src);
}
}
void badTest2(unsigned char *src){
int cb = 0;
unsigned char dst[50];
while( cb < sizeof(dst) )
{
_mbccpy(dst+cb,src); // BAD
cb+=_mbclen(src);
src=_mbsinc(src);
}
}
void goodTest3(){
wchar_t name[50];
name[sizeof(name) / sizeof(*name) - 1] = L'\0'; // GOOD
}
void badTest3(){
wchar_t name[50];
name[sizeof(name) - 1] = L'\0'; // BAD
}

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: --clang
struct mystruct {
int f1;
int f2;
@@ -13,3 +13,6 @@ void f(void) {
int i2 = edg_offsetof(struct mystruct,f2);
}
void g(void) {
double f = __builtin_bit_cast(double,42l);
}

View File

@@ -13,3 +13,6 @@
| edg.c:13:14:13:45 | (size_t)... | 0 | 0 |
| edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 |
| edg.c:13:43:13:44 | f2 | 0 | 0 |
| edg.c:17:16:17:45 | __builtin_bit_cast | 1 | 1 |
| edg.c:17:16:17:45 | double | 0 | 0 |
| edg.c:17:42:17:44 | 42 | 1 | 1 |

View File

@@ -296,3 +296,20 @@
| ms.cpp:255:24:255:43 | a_struct | | <none> |
| ms.cpp:256:24:256:49 | __is_final | a_final_struct | 1 |
| ms.cpp:256:24:256:49 | a_final_struct | | <none> |
| ms.cpp:258:29:258:62 | __is_assignable | a_struct,a_struct | 1 |
| ms.cpp:258:29:258:62 | a_struct | | <none> |
| ms.cpp:258:29:258:62 | a_struct | | <none> |
| ms.cpp:259:29:259:59 | __is_assignable | a_struct,empty | 0 |
| ms.cpp:259:29:259:59 | a_struct | | <none> |
| ms.cpp:259:29:259:59 | empty | | <none> |
| ms.cpp:260:29:260:57 | __is_assignable | a_struct,int | 0 |
| ms.cpp:260:29:260:57 | a_struct | | <none> |
| ms.cpp:260:29:260:57 | int | | <none> |
| ms.cpp:262:28:262:51 | __is_aggregate | a_struct | 1 |
| ms.cpp:262:28:262:51 | a_struct | | <none> |
| ms.cpp:263:28:263:46 | __is_aggregate | int | 0 |
| ms.cpp:263:28:263:46 | int | | <none> |
| ms.cpp:265:49:265:88 | __has_unique_object_representations | int | 1 |
| ms.cpp:265:49:265:88 | int | | <none> |
| ms.cpp:266:49:266:90 | __has_unique_object_representations | float | 0 |
| ms.cpp:266:49:266:90 | float | | <none> |

View File

@@ -254,5 +254,14 @@ void f(void) {
bool b_is_final1 = __is_final(a_struct);
bool b_is_final2 = __is_final(a_final_struct);
}
bool b_is_assignable1 = __is_assignable(a_struct,a_struct);
bool b_is_assignable2 = __is_assignable(a_struct,empty);
bool b_is_assignable3 = __is_assignable(a_struct,int);
bool b_is_aggregate1 = __is_aggregate(a_struct);
bool b_is_aggregate2 = __is_aggregate(int);
bool b_has_unique_object_representations1 = __has_unique_object_representations(int);
bool b_has_unique_object_representations2 = __has_unique_object_representations(float);
}

View File

@@ -334,19 +334,19 @@ namespace FlowThroughGlobals {
}
int f() {
sink(globalVar); // tainted or clean? Not sure.
sink(globalVar); // $ ir=333:17 ir=347:17 // tainted or clean? Not sure.
taintGlobal();
sink(globalVar); // $ MISSING: ast,ir
sink(globalVar); // $ ir=333:17 ir=347:17 MISSING: ast
}
int calledAfterTaint() {
sink(globalVar); // $ MISSING: ast,ir
sink(globalVar); // $ ir=333:17 ir=347:17 MISSING: ast
}
int taintAndCall() {
globalVar = source();
calledAfterTaint();
sink(globalVar); // $ ast,ir
sink(globalVar); // $ ast ir=333:17 ir=347:17
}
}

View File

@@ -47,14 +47,14 @@ void do_source()
void do_sink()
{
sink(global1);
sink(global2); // $ MISSING: ast,ir
sink(global3); // $ MISSING: ast,ir
sink(global4); // $ MISSING: ast,ir
sink(global2); // $ ir MISSING: ast
sink(global3); // $ ir MISSING: ast
sink(global4); // $ ir MISSING: ast
sink(global5);
sink(global6);
sink(global7); // $ MISSING: ast,ir
sink(global8); // $ MISSING: ast,ir
sink(global9); // $ MISSING: ast,ir
sink(global7); // $ ir MISSING: ast
sink(global8); // $ ir MISSING: ast
sink(global9); // $ ir MISSING: ast
sink(global10);
}

View File

@@ -15,7 +15,7 @@ predicate locationIsInStandardHeaders(Location loc) {
predicate shouldDumpFunction(Declaration decl) {
not locationIsInStandardHeaders(decl.getLocation()) and
(
not decl instanceof Variable
decl instanceof Function
or
decl.(GlobalOrNamespaceVariable).hasInitializer()
)

View File

@@ -15,6 +15,7 @@
| test.cpp:3:8:3:8 | operator= |
| test.cpp:3:8:3:10 | Str<T> |
| test.cpp:3:8:3:10 | Str<int> |
| test.cpp:7:16:7:16 | T |
| test.cpp:8:11:8:21 | val |
| test.cpp:8:19:8:19 | val |
| test.cpp:10:6:10:6 | f |

View File

@@ -4,11 +4,7 @@
| c.c:6:5:6:6 | ls | array of 4 {int} | 1 |
| c.c:8:5:8:7 | iss | array of 4 {array of 2 {int}} | 1 |
| c.c:12:11:12:11 | i | typedef {int} as "int_alias" | 1 |
| c.h:4:12:4:13 | ks | array of {int} | 1 |
| c.h:8:12:8:14 | iss | array of {array of 2 {int}} | 1 |
| c.h:10:12:10:12 | i | int | 1 |
| d.cpp:3:7:3:8 | xs | array of {int} | 1 |
| d.h:3:14:3:15 | xs | array of 2 {int} | 1 |
| file://:0:0:0:0 | (unnamed parameter 0) | reference to {const {struct __va_list_tag}} | 1 |
| file://:0:0:0:0 | (unnamed parameter 0) | rvalue reference to {struct __va_list_tag} | 1 |
| file://:0:0:0:0 | fp_offset | unsigned int | 1 |

View File

@@ -1,2 +1,4 @@
| vector_types2.cpp:10:15:10:42 | __builtin_shuffle |
| vector_types2.cpp:11:15:11:45 | __builtin_shuffle |
| vector_types.cpp:31:13:31:49 | __builtin_shufflevector |
| vector_types.cpp:58:10:58:52 | __builtin_convertvector |

View File

@@ -13,6 +13,12 @@
| file://:0:0:0:0 | gp_offset | gp_offset | file://:0:0:0:0 | unsigned int | 4 |
| file://:0:0:0:0 | overflow_arg_area | overflow_arg_area | file://:0:0:0:0 | void * | 8 |
| file://:0:0:0:0 | reg_save_area | reg_save_area | file://:0:0:0:0 | void * | 8 |
| vector_types2.cpp:5:7:5:7 | a | a | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:6:7:6:7 | b | b | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:7:7:7:12 | mask_1 | mask_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:8:7:8:12 | mask_2 | mask_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:10:7:10:11 | res_1 | res_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types2.cpp:11:7:11:11 | res_2 | res_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
| vector_types.cpp:9:21:9:21 | x | x | vector_types.cpp:6:15:6:17 | v4f | 16 |
| vector_types.cpp:14:18:14:20 | lhs | lhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
| vector_types.cpp:14:27:14:29 | rhs | rhs | vector_types.cpp:6:15:6:17 | v4f | 16 |

View File

@@ -0,0 +1,12 @@
// semmle-extractor-options: --gnu --gnu_version 80000
typedef int v4i __attribute__((vector_size (16)));
void f() {
v4i a = {1,2,3,4};
v4i b = {5,6,7,8};
v4i mask_1 = {3,0,1,2};
v4i mask_2 = {3,5,4,2};
v4i res_1 = __builtin_shuffle(a, mask_1);
v4i res_2 = __builtin_shuffle(a, b, mask_2);
}

View File

@@ -100,12 +100,6 @@ edges
| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference dereference) |
| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference to) |
| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | Unary |
| test.cpp:225:14:225:15 | px | test.cpp:226:10:226:11 | Load |
| test.cpp:226:10:226:11 | Load | test.cpp:226:10:226:11 | px |
| test.cpp:226:10:226:11 | px | test.cpp:226:10:226:11 | StoreValue |
| test.cpp:231:16:231:17 | & ... | test.cpp:225:14:225:15 | px |
| test.cpp:231:17:231:17 | Unary | test.cpp:231:16:231:17 | & ... |
| test.cpp:231:17:231:17 | x | test.cpp:231:17:231:17 | Unary |
nodes
| test.cpp:17:9:17:11 | & ... | semmle.label | & ... |
| test.cpp:17:9:17:11 | StoreValue | semmle.label | StoreValue |
@@ -221,13 +215,6 @@ nodes
| test.cpp:190:10:190:13 | Unary | semmle.label | Unary |
| test.cpp:190:10:190:13 | Unary | semmle.label | Unary |
| test.cpp:190:10:190:13 | pRef | semmle.label | pRef |
| test.cpp:225:14:225:15 | px | semmle.label | px |
| test.cpp:226:10:226:11 | Load | semmle.label | Load |
| test.cpp:226:10:226:11 | StoreValue | semmle.label | StoreValue |
| test.cpp:226:10:226:11 | px | semmle.label | px |
| test.cpp:231:16:231:17 | & ... | semmle.label | & ... |
| test.cpp:231:17:231:17 | Unary | semmle.label | Unary |
| test.cpp:231:17:231:17 | x | semmle.label | x |
#select
| test.cpp:17:9:17:11 | StoreValue | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
| test.cpp:25:9:25:11 | StoreValue | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |

View File

@@ -1,4 +1,134 @@
edges
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:33:15:33:18 | copy |
| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:44:15:44:19 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:11:22:11:25 | *argv | globalVars.c:12:2:12:15 | Store |
| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | Store |
| globalVars.c:12:2:12:15 | Store | globalVars.c:8:7:8:10 | copy |
| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | Store |
| globalVars.c:16:2:16:12 | Store | globalVars.c:9:7:9:11 | copy2 |
| globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection |
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection |
| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection |
| globalVars.c:24:11:24:14 | argv indirection | globalVars.c:11:22:11:25 | *argv |
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... |
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy |
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy indirection |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection |
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection |
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str |
| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:30:15:30:18 | printWrapper output argument |
| globalVars.c:30:15:30:18 | printWrapper output argument | globalVars.c:35:11:35:14 | copy |
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | (const char *)... |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:19:25:19:27 | *str |
| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:41:15:41:19 | printWrapper output argument |
| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | (const char *)... |
| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 indirection |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | (const char *)... |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection |
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... |
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection |
subpaths
| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | globalVars.c:30:15:30:18 | printWrapper output argument |
| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | globalVars.c:41:15:41:19 | printWrapper output argument |
nodes
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 |
| globalVars.c:11:22:11:25 | *argv | semmle.label | *argv |
| globalVars.c:11:22:11:25 | argv | semmle.label | argv |
| globalVars.c:12:2:12:15 | Store | semmle.label | Store |
| globalVars.c:15:21:15:23 | val | semmle.label | val |
| globalVars.c:16:2:16:12 | Store | semmle.label | Store |
| globalVars.c:19:25:19:27 | *str | semmle.label | *str |
| globalVars.c:19:25:19:27 | ReturnIndirection | semmle.label | ReturnIndirection |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv | semmle.label | argv |
| globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection |
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection |
| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection |
| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection |
| globalVars.c:30:15:30:18 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:33:15:33:18 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:35:11:35:14 | copy | semmle.label | copy |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
| globalVars.c:41:15:41:19 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:41:15:41:19 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument |
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection |
| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection |
#select
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv |
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv |

View File

@@ -1,4 +1,8 @@
edges
| tests2.cpp:50:13:50:19 | global1 | tests2.cpp:82:14:82:20 | global1 |
| tests2.cpp:50:13:50:19 | global1 | tests2.cpp:82:14:82:20 | global1 |
| tests2.cpp:50:23:50:43 | Store | tests2.cpp:50:13:50:19 | global1 |
| tests2.cpp:50:23:50:43 | call to mysql_get_client_info | tests2.cpp:50:23:50:43 | Store |
| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:26 | (const char *)... |
| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:26 | (const char *)... |
| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:30 | (const char *)... |
@@ -6,6 +10,8 @@ edges
| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... |
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info |
| tests2.cpp:82:14:82:20 | global1 | tests2.cpp:82:14:82:20 | global1 |
| tests2.cpp:82:14:82:20 | global1 | tests2.cpp:82:14:82:20 | global1 |
| tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 |
| tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw |
| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | tests2.cpp:111:14:111:15 | c1 [read] [ptr] |
@@ -23,6 +29,9 @@ edges
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | (const void *)... |
| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf |
nodes
| tests2.cpp:50:13:50:19 | global1 | semmle.label | global1 |
| tests2.cpp:50:23:50:43 | Store | semmle.label | Store |
| tests2.cpp:50:23:50:43 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv |
| tests2.cpp:63:13:63:26 | (const char *)... | semmle.label | (const char *)... |
@@ -39,6 +48,8 @@ nodes
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info |
| tests2.cpp:81:14:81:19 | (const char *)... | semmle.label | (const char *)... |
| tests2.cpp:82:14:82:20 | global1 | semmle.label | global1 |
| tests2.cpp:82:14:82:20 | global1 | semmle.label | global1 |
| tests2.cpp:91:42:91:45 | str1 | semmle.label | str1 |
| tests2.cpp:93:14:93:17 | str1 | semmle.label | str1 |
| tests2.cpp:101:8:101:15 | call to getpwuid | semmle.label | call to getpwuid |
@@ -70,6 +81,7 @@ subpaths
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info |
| tests2.cpp:81:14:81:19 | (const char *)... | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | call to mysql_get_client_info |
| tests2.cpp:82:14:82:20 | global1 | tests2.cpp:50:23:50:43 | call to mysql_get_client_info | tests2.cpp:82:14:82:20 | global1 | This operation exposes system data from $@. | tests2.cpp:50:23:50:43 | call to mysql_get_client_info | call to mysql_get_client_info |
| tests2.cpp:93:14:93:17 | str1 | tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 | str1 |
| tests2.cpp:102:14:102:15 | pw | tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid | call to getpwuid |
| tests2.cpp:111:14:111:19 | (const char *)... | tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:111:14:111:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv | call to getenv |

View File

@@ -5,6 +5,14 @@ edges
| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... |
| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... |
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... |
| tests.cpp:62:7:62:18 | global_token | tests.cpp:69:17:69:28 | global_token |
| tests.cpp:62:7:62:18 | global_token | tests.cpp:71:27:71:38 | global_token |
| tests.cpp:62:7:62:18 | global_token | tests.cpp:71:27:71:38 | global_token |
| tests.cpp:62:22:62:27 | Store | tests.cpp:62:7:62:18 | global_token |
| tests.cpp:62:22:62:27 | call to getenv | tests.cpp:62:22:62:27 | Store |
| tests.cpp:69:17:69:28 | global_token | tests.cpp:73:27:73:31 | maybe |
| tests.cpp:71:27:71:38 | global_token | tests.cpp:71:27:71:38 | global_token |
| tests.cpp:71:27:71:38 | global_token | tests.cpp:71:27:71:38 | global_token |
| tests.cpp:86:29:86:31 | *msg | tests.cpp:88:15:88:17 | msg |
| tests.cpp:86:29:86:31 | msg | tests.cpp:88:15:88:17 | msg |
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... |
@@ -52,6 +60,13 @@ nodes
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv |
| tests.cpp:59:43:59:64 | (const char *)... | semmle.label | (const char *)... |
| tests.cpp:62:7:62:18 | global_token | semmle.label | global_token |
| tests.cpp:62:22:62:27 | Store | semmle.label | Store |
| tests.cpp:62:22:62:27 | call to getenv | semmle.label | call to getenv |
| tests.cpp:69:17:69:28 | global_token | semmle.label | global_token |
| tests.cpp:71:27:71:38 | global_token | semmle.label | global_token |
| tests.cpp:71:27:71:38 | global_token | semmle.label | global_token |
| tests.cpp:73:27:73:31 | maybe | semmle.label | maybe |
| tests.cpp:86:29:86:31 | *msg | semmle.label | *msg |
| tests.cpp:86:29:86:31 | msg | semmle.label | msg |
| tests.cpp:88:15:88:17 | msg | semmle.label | msg |
@@ -97,6 +112,8 @@ subpaths
| tests.cpp:58:41:58:62 | (const char_type *)... | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv |
| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
| tests.cpp:59:43:59:64 | (const char *)... | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv |
| tests.cpp:71:27:71:38 | global_token | tests.cpp:62:22:62:27 | call to getenv | tests.cpp:71:27:71:38 | global_token | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv | call to getenv |
| tests.cpp:73:27:73:31 | maybe | tests.cpp:62:22:62:27 | call to getenv | tests.cpp:73:27:73:31 | maybe | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv | call to getenv |
| tests.cpp:88:15:88:17 | msg | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:88:15:88:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |
| tests.cpp:97:13:97:34 | (const char *)... | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv |

View File

@@ -68,9 +68,9 @@ void test2(bool cond)
maybe = cond ? global_token : global_other;
printf("token = '%s'\n", global_token); // BAD: outputs SECRET_TOKEN environment variable [NOT DETECTED]
printf("token = '%s'\n", global_token); // BAD: outputs SECRET_TOKEN environment variable
printf("other = '%s'\n", global_other);
printf("maybe = '%s'\n", maybe); // BAD: may output SECRET_TOKEN environment variable [NOT DETECTED]
printf("maybe = '%s'\n", maybe); // BAD: may output SECRET_TOKEN environment variable
}
void test3()

View File

@@ -79,7 +79,7 @@ void test1()
send(sock, mysql_get_client_info(), val(), val()); // BAD
send(sock, buffer, val(), val()); // BAD
send(sock, global1, val(), val()); // BAD [NOT DETECTED]
send(sock, global1, val(), val()); // BAD
send(sock, global2, val(), val()); // GOOD: not system data
}

View File

@@ -2,11 +2,26 @@ edges
| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p |
| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p |
| tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p |
| tests3.cpp:35:16:35:20 | p_3_3 | tests3.cpp:38:2:38:6 | p_3_3 |
| tests3.cpp:35:24:35:56 | Store | tests3.cpp:35:16:35:20 | p_3_3 |
| tests3.cpp:35:24:35:56 | call to createXMLReader | tests3.cpp:35:24:35:56 | Store |
| tests3.cpp:41:16:41:20 | p_3_4 | tests3.cpp:45:2:45:6 | p_3_4 |
| tests3.cpp:41:24:41:56 | Store | tests3.cpp:41:16:41:20 | p_3_4 |
| tests3.cpp:41:24:41:56 | call to createXMLReader | tests3.cpp:41:24:41:56 | Store |
| tests3.cpp:48:16:48:20 | p_3_5 | tests3.cpp:56:2:56:6 | p_3_5 |
| tests3.cpp:48:24:48:56 | Store | tests3.cpp:48:16:48:20 | p_3_5 |
| tests3.cpp:48:24:48:56 | call to createXMLReader | tests3.cpp:48:24:48:56 | Store |
| tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p |
| tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p |
| tests5.cpp:27:25:27:38 | call to createLSParser | tests5.cpp:29:2:29:2 | p |
| tests5.cpp:40:25:40:38 | call to createLSParser | tests5.cpp:43:2:43:2 | p |
| tests5.cpp:55:25:55:38 | call to createLSParser | tests5.cpp:59:2:59:2 | p |
| tests5.cpp:63:14:63:17 | g_p1 | tests5.cpp:76:2:76:5 | g_p1 |
| tests5.cpp:63:21:63:24 | g_p2 | tests5.cpp:77:2:77:5 | g_p2 |
| tests5.cpp:67:2:67:32 | Store | tests5.cpp:63:14:63:17 | g_p1 |
| tests5.cpp:67:17:67:30 | call to createLSParser | tests5.cpp:67:2:67:32 | Store |
| tests5.cpp:70:2:70:32 | Store | tests5.cpp:63:21:63:24 | g_p2 |
| tests5.cpp:70:17:70:30 | call to createLSParser | tests5.cpp:70:2:70:32 | Store |
| tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p |
| tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p |
| tests5.cpp:83:2:83:2 | p | tests5.cpp:85:2:85:2 | p |
@@ -46,6 +61,18 @@ nodes
| tests2.cpp:37:2:37:2 | p | semmle.label | p |
| tests3.cpp:23:21:23:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:25:2:25:2 | p | semmle.label | p |
| tests3.cpp:35:16:35:20 | p_3_3 | semmle.label | p_3_3 |
| tests3.cpp:35:24:35:56 | Store | semmle.label | Store |
| tests3.cpp:35:24:35:56 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:38:2:38:6 | p_3_3 | semmle.label | p_3_3 |
| tests3.cpp:41:16:41:20 | p_3_4 | semmle.label | p_3_4 |
| tests3.cpp:41:24:41:56 | Store | semmle.label | Store |
| tests3.cpp:41:24:41:56 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:45:2:45:6 | p_3_4 | semmle.label | p_3_4 |
| tests3.cpp:48:16:48:20 | p_3_5 | semmle.label | p_3_5 |
| tests3.cpp:48:24:48:56 | Store | semmle.label | Store |
| tests3.cpp:48:24:48:56 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:56:2:56:6 | p_3_5 | semmle.label | p_3_5 |
| tests3.cpp:60:21:60:53 | call to createXMLReader | semmle.label | call to createXMLReader |
| tests3.cpp:63:2:63:2 | p | semmle.label | p |
| tests3.cpp:67:21:67:53 | call to createXMLReader | semmle.label | call to createXMLReader |
@@ -61,6 +88,14 @@ nodes
| tests5.cpp:43:2:43:2 | p | semmle.label | p |
| tests5.cpp:55:25:55:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:59:2:59:2 | p | semmle.label | p |
| tests5.cpp:63:14:63:17 | g_p1 | semmle.label | g_p1 |
| tests5.cpp:63:21:63:24 | g_p2 | semmle.label | g_p2 |
| tests5.cpp:67:2:67:32 | Store | semmle.label | Store |
| tests5.cpp:67:17:67:30 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:70:2:70:32 | Store | semmle.label | Store |
| tests5.cpp:70:17:70:30 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:76:2:76:5 | g_p1 | semmle.label | g_p1 |
| tests5.cpp:77:2:77:5 | g_p2 | semmle.label | g_p2 |
| tests5.cpp:81:25:81:38 | call to createLSParser | semmle.label | call to createLSParser |
| tests5.cpp:83:2:83:2 | p | semmle.label | p |
| tests5.cpp:83:2:83:2 | p | semmle.label | p |
@@ -108,6 +143,9 @@ subpaths
| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser |
| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser |
| tests3.cpp:25:2:25:2 | p | tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:23:21:23:53 | call to createXMLReader | XML parser |
| tests3.cpp:38:2:38:6 | p_3_3 | tests3.cpp:35:24:35:56 | call to createXMLReader | tests3.cpp:38:2:38:6 | p_3_3 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:35:24:35:56 | call to createXMLReader | XML parser |
| tests3.cpp:45:2:45:6 | p_3_4 | tests3.cpp:41:24:41:56 | call to createXMLReader | tests3.cpp:45:2:45:6 | p_3_4 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:41:24:41:56 | call to createXMLReader | XML parser |
| tests3.cpp:56:2:56:6 | p_3_5 | tests3.cpp:48:24:48:56 | call to createXMLReader | tests3.cpp:56:2:56:6 | p_3_5 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:48:24:48:56 | call to createXMLReader | XML parser |
| tests3.cpp:63:2:63:2 | p | tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:60:21:60:53 | call to createXMLReader | XML parser |
| tests3.cpp:70:2:70:2 | p | tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:67:21:67:53 | call to createXMLReader | XML parser |
| tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:26:34:26:48 | (int)... | XML parser |
@@ -118,6 +156,8 @@ subpaths
| tests5.cpp:29:2:29:2 | p | tests5.cpp:27:25:27:38 | call to createLSParser | tests5.cpp:29:2:29:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:27:25:27:38 | call to createLSParser | XML parser |
| tests5.cpp:43:2:43:2 | p | tests5.cpp:40:25:40:38 | call to createLSParser | tests5.cpp:43:2:43:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:40:25:40:38 | call to createLSParser | XML parser |
| tests5.cpp:59:2:59:2 | p | tests5.cpp:55:25:55:38 | call to createLSParser | tests5.cpp:59:2:59:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:55:25:55:38 | call to createLSParser | XML parser |
| tests5.cpp:76:2:76:5 | g_p1 | tests5.cpp:67:17:67:30 | call to createLSParser | tests5.cpp:76:2:76:5 | g_p1 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:67:17:67:30 | call to createLSParser | XML parser |
| tests5.cpp:77:2:77:5 | g_p2 | tests5.cpp:70:17:70:30 | call to createLSParser | tests5.cpp:77:2:77:5 | g_p2 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:70:17:70:30 | call to createLSParser | XML parser |
| tests5.cpp:83:2:83:2 | p | tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser | XML parser |
| tests5.cpp:89:2:89:2 | p | tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:89:2:89:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser | XML parser |
| tests.cpp:17:2:17:2 | p | tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:15:23:15:43 | XercesDOMParser output argument | XML parser |

View File

@@ -35,14 +35,14 @@ void test3_2(InputSource &data) {
SAX2XMLReader *p_3_3 = XMLReaderFactory::createXMLReader();
void test3_3(InputSource &data) {
p_3_3->parse(data); // BAD (parser not correctly configured) [NOT DETECTED]
p_3_3->parse(data); // BAD (parser not correctly configured)
}
SAX2XMLReader *p_3_4 = XMLReaderFactory::createXMLReader();
void test3_4(InputSource &data) {
p_3_4->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true);
p_3_4->parse(data); // GOOD
p_3_4->parse(data); // GOOD [FALSE POSITIVE]
}
SAX2XMLReader *p_3_5 = XMLReaderFactory::createXMLReader();
@@ -53,7 +53,7 @@ void test3_5_init() {
void test3_5(InputSource &data) {
test3_5_init();
p_3_5->parse(data); // GOOD
p_3_5->parse(data); // GOOD [FALSE POSITIVE]
}
void test3_6(InputSource &data) {

View File

@@ -73,8 +73,8 @@ void test5_6_init() {
void test5_6() {
test5_6_init();
g_p1->parse(*g_data); // GOOD
g_p2->parse(*g_data); // BAD (parser not correctly configured) [NOT DETECTED]
g_p1->parse(*g_data); // GOOD [FALSE POSITIVE]
g_p2->parse(*g_data); // BAD (parser not correctly configured)
}
void test5_7(DOMImplementationLS *impl, InputSource &data) {