зеркало из https://github.com/github/codeql.git
Merge branch 'main' into docs-11486-security-severity
This commit is contained in:
Коммит
f06cca8eff
|
@ -12,6 +12,7 @@ on:
|
|||
- main
|
||||
paths:
|
||||
- "java/ql/src/utils/modelgenerator/**/*.*"
|
||||
- "misc/scripts/models-as-data/*.*"
|
||||
- ".github/workflows/mad_modelDiff.yml"
|
||||
|
||||
permissions:
|
||||
|
@ -61,8 +62,9 @@ jobs:
|
|||
DATABASE=$2
|
||||
cd codeql-$QL_VARIANT
|
||||
SHORTNAME=`basename $DATABASE`
|
||||
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE ${SHORTNAME}.temp.model.yml
|
||||
mv java/ql/lib/ext/generated/${SHORTNAME}.temp.model.yml $MODELS/${SHORTNAME}Generated_${QL_VARIANT}.model.yml
|
||||
python java/ql/src/utils/modelgenerator/GenerateFlowModel.py --with-summaries --with-sinks $DATABASE $SHORTNAME/$QL_VARIANT
|
||||
mkdir -p $MODELS/$SHORTNAME
|
||||
mv java/ql/lib/ext/generated/$SHORTNAME/$QL_VARIANT $MODELS/$SHORTNAME
|
||||
cd ..
|
||||
}
|
||||
|
||||
|
@ -85,16 +87,16 @@ jobs:
|
|||
set -x
|
||||
MODELS=`pwd`/tmp-models
|
||||
ls -1 tmp-models/
|
||||
for m in $MODELS/*_main.model.yml ; do
|
||||
for m in $MODELS/*/main/*.model.yml ; do
|
||||
t="${m/main/"pr"}"
|
||||
basename=`basename $m`
|
||||
name="diff_${basename/_main.model.yml/""}"
|
||||
name="diff_${basename/.model.yml/""}"
|
||||
(diff -w -u $m $t | diff2html -i stdin -F $MODELS/$name.html) || true
|
||||
done
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: models
|
||||
path: tmp-models/*.model.yml
|
||||
path: tmp-models/**/**/*.model.yml
|
||||
retention-days: 20
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
description: Support C++17 if and switch initializers
|
||||
compatibility: partial
|
||||
constexpr_if_initialization.rel: delete
|
||||
if_initialization.rel: delete
|
||||
switch_initialization.rel: delete
|
||||
exprparents.rel: run exprparents.qlo
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* A library for detecting general string concatenations.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.models.implementations.Strcat
|
||||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
/**
|
||||
* A call that performs a string concatenation. A string can be either a C
|
||||
* string (i.e., a value of type `char*`), or a C++ string (i.e., a value of
|
||||
* type `std::string`).
|
||||
*/
|
||||
class StringConcatenation extends Call {
|
||||
StringConcatenation() {
|
||||
// sprintf-like functions, i.e., concat through formatting
|
||||
this instanceof FormattingFunctionCall
|
||||
or
|
||||
this.getTarget() instanceof StrcatFunction
|
||||
or
|
||||
this.getTarget() instanceof StrlcatFunction
|
||||
or
|
||||
// operator+ and ostream (<<) concat
|
||||
exists(Call call, Operator op |
|
||||
call.getTarget() = op and
|
||||
op.hasQualifiedName(["std", "bsl"], ["operator+", "operator<<"]) and
|
||||
op.getType()
|
||||
.stripType()
|
||||
.(UserType)
|
||||
.hasQualifiedName(["std", "bsl"], ["basic_string", "basic_ostream"]) and
|
||||
this = call
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an operand of this concatenation (one of the string operands being
|
||||
* concatenated).
|
||||
* Will not return out param for sprintf-like functions, but will consider the format string
|
||||
* to be part of the operands.
|
||||
*/
|
||||
Expr getAnOperand() {
|
||||
// The result is an argument of 'this' (a call)
|
||||
result = this.getAnArgument() and
|
||||
// addresses odd behavior with overloaded operators
|
||||
// i.e., "call to operator+" appearing as an operand
|
||||
// occurs in cases like `string s = s1 + s2 + s3`, which is represented as
|
||||
// `string s = (s1.operator+(s2)).operator+(s3);`
|
||||
// By limiting to non-calls we get the leaf operands (the variables or raw strings)
|
||||
// also, by not enumerating allowed types (variables and strings) we avoid issues
|
||||
// with missed corner cases or extensions/changes to CodeQL in the future which might
|
||||
// invalidate that approach.
|
||||
not result instanceof Call and
|
||||
// Limit the result type to string
|
||||
(
|
||||
result.getUnderlyingType().stripType().getName() = "char"
|
||||
or
|
||||
result
|
||||
.getType()
|
||||
.getUnspecifiedType()
|
||||
.(UserType)
|
||||
.hasQualifiedName(["std", "bsl"], "basic_string")
|
||||
) and
|
||||
// when 'this' is a `FormattingFunctionCall` the result must be the format string argument
|
||||
// or one of the formatting arguments
|
||||
(
|
||||
this instanceof FormattingFunctionCall
|
||||
implies
|
||||
(
|
||||
result = this.(FormattingFunctionCall).getFormat()
|
||||
or
|
||||
exists(int n |
|
||||
result = this.getArgument(n) and
|
||||
n >= this.(FormattingFunctionCall).getTarget().getFirstFormatArgumentIndex()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data flow node representing the concatenation result.
|
||||
*/
|
||||
DataFlow::Node getResultNode() {
|
||||
if this.getTarget() instanceof StrcatFunction
|
||||
then
|
||||
result.asDefiningArgument() =
|
||||
this.getArgument(this.getTarget().(StrcatFunction).getParamDest())
|
||||
or
|
||||
// Hardcoding it is also the return
|
||||
result.asExpr() = this.(Call)
|
||||
else
|
||||
if this.getTarget() instanceof StrlcatFunction
|
||||
then (
|
||||
result.asDefiningArgument() =
|
||||
this.getArgument(this.getTarget().(StrlcatFunction).getParamDest())
|
||||
) else
|
||||
if this instanceof FormattingFunctionCall
|
||||
then result.asDefiningArgument() = this.(FormattingFunctionCall).getOutputArgument(_)
|
||||
else result.asExpr() = this.(Call)
|
||||
}
|
||||
}
|
|
@ -54,18 +54,6 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
|||
not f.isStatic()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, Function f) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
|
||||
|
|
|
@ -249,9 +249,7 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
|||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) {
|
||||
mayBenefitFromCallContext(call, f, _)
|
||||
}
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call) { mayBenefitFromCallContext(call, _, _) }
|
||||
|
||||
/**
|
||||
* Holds if `call` is a call through a function pointer, and the pointer
|
||||
|
|
|
@ -22,4 +22,8 @@ module CppDataFlow implements InputSig {
|
|||
predicate getAdditionalFlowIntoCallNodeTerm = Private::getAdditionalFlowIntoCallNodeTerm/2;
|
||||
|
||||
predicate validParameterAliasStep = Private::validParameterAliasStep/2;
|
||||
|
||||
predicate mayBenefitFromCallContext = Private::mayBenefitFromCallContext/1;
|
||||
|
||||
predicate viableImplInCallContext = Private::viableImplInCallContext/2;
|
||||
}
|
||||
|
|
|
@ -355,13 +355,13 @@ private predicate linearAccessImpl(Expr expr, VariableAccess v, float p, float q
|
|||
* `cmpWithLinearBound(guard, v, Greater(), true)` and
|
||||
* `cmpWithLinearBound(guard, v, Lesser(), false)` hold.
|
||||
* If `guard` is `4 - v > 5` then
|
||||
* `cmpWithLinearBound(guard, v, Lesser(), false)` and
|
||||
* `cmpWithLinearBound(guard, v, Greater(), true)` hold.
|
||||
* `cmpWithLinearBound(guard, v, Lesser(), true)` and
|
||||
* `cmpWithLinearBound(guard, v, Greater(), false)` hold.
|
||||
*
|
||||
* A more sophisticated predicate, such as `boundFromGuard`, is needed
|
||||
* to compute an actual bound for `v`. This predicate can be used if
|
||||
* you just want to check whether a variable is bounded, or to restrict
|
||||
* a more expensive analysis to just guards that bound a variable.
|
||||
* If an actual bound for `v` is needed, use `upperBound` or `lowerBound`.
|
||||
* This predicate can be used if you just want to check whether a variable
|
||||
* is bounded, or to restrict a more expensive analysis to just guards that
|
||||
* bound a variable.
|
||||
*/
|
||||
predicate cmpWithLinearBound(
|
||||
ComparisonOperation guard, VariableAccess v,
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
description: Remove the old CFG tables
|
||||
compatibility: full
|
||||
|
||||
falsecond.rel: delete
|
||||
successors.rel: delete
|
||||
truecond.rel: delete
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/include-non-header` style query will now ignore the `.def` extension for textual header inclusions.
|
|
@ -18,6 +18,7 @@ from Include i, File f, string extension
|
|||
where
|
||||
f = i.getIncludedFile() and
|
||||
extension = f.getExtension().toLowerCase() and
|
||||
extension != "def" and
|
||||
extension != "inc" and
|
||||
extension != "inl" and
|
||||
extension != "tcc" and
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
__builtin_foobar(i)i
|
||||
__builtin_malloc(i,i,i,f*)f
|
|
@ -1,4 +0,0 @@
|
|||
| file://:0:0:0:0 | __builtin_add_overflow | true | 0 | file://:0:0:0:0 | bool |
|
||||
| file://:0:0:0:0 | __builtin_foobar | true | 1 | file://:0:0:0:0 | int |
|
||||
| file://:0:0:0:0 | __builtin_malloc | true | 4 | file://:0:0:0:0 | float |
|
||||
| test.c:1:6:1:6 | f | false | 3 | file://:0:0:0:0 | long |
|
|
@ -1,5 +0,0 @@
|
|||
import cpp
|
||||
|
||||
from Function f, boolean isBuiltin
|
||||
where if f instanceof BuiltInFunction then isBuiltin = true else isBuiltin = false
|
||||
select f, isBuiltin, f.getNumberOfParameters(), f.getType()
|
|
@ -1,20 +0,0 @@
|
|||
long f(int a, int b, int c) {
|
||||
// A builtin from the builtin_functions_file.
|
||||
int i1 = __builtin_foobar(a);
|
||||
|
||||
// A builtin that's not in the file, but the extractor should handle, given the
|
||||
// --gnu_version flag we pass in.
|
||||
int i2;
|
||||
__builtin_add_overflow(a, b, &i2);
|
||||
|
||||
// A builtin that would normally be defined by the extractor with a type
|
||||
// expecting it to be called like this:
|
||||
//void* x = __builtin_malloc(a);
|
||||
// But we override the type in the builtin_functions_file so it's called like
|
||||
// this:
|
||||
float f1, f2;
|
||||
f1 = __builtin_malloc(a, b, c, &f2);
|
||||
|
||||
return 42;
|
||||
}
|
||||
// semmle-extractor-options: --gnu_version 50100 --edg --builtin_functions_file --edg ${testdir}/builtins.txt
|
|
@ -166,3 +166,4 @@ uniqueContentApprox
|
|||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
|
|
|
@ -31,3 +31,4 @@ uniqueContentApprox
|
|||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
|
|
|
@ -193,3 +193,4 @@ uniqueContentApprox
|
|||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
|
|
|
@ -27,3 +27,4 @@ uniqueContentApprox
|
|||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// #include <iostream>
|
||||
// #include <string>
|
||||
// #include <stdio.h>
|
||||
// #include <string.h>
|
||||
// #include <sstream>
|
||||
#include "stl.h"
|
||||
|
||||
int sprintf(char *s, const char *format, ...);
|
||||
char *strcat(char * s1, const char * s2);
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
void test1(){
|
||||
string str1 = "Hello";
|
||||
string str2 = "World";
|
||||
string str3 = "!";
|
||||
string str4 = "Concatenation";
|
||||
string str5 = "is";
|
||||
string str6 = "fun";
|
||||
|
||||
// Using the + operator
|
||||
string result1 = str1 + " " + str2 + str3;
|
||||
|
||||
// Using the append() function
|
||||
//----TODO: currently not modeled----
|
||||
// string result2 = str4.append(" ") + str5.append(" ") + str6;
|
||||
|
||||
// Using the insert() function
|
||||
//----TODO: currently not modeled----
|
||||
// string result3 = str1.insert(5, " ") + str2.insert(5, "! ");
|
||||
|
||||
// Using the replace() function
|
||||
//----TODO: currently not modeled----
|
||||
// string result4 = str1.replace(0, 5, "Hi") + str2.replace(0, 5, "There");
|
||||
|
||||
// Using the push_back() function
|
||||
//----TODO: currently not modeled----
|
||||
// string result5;
|
||||
// for (char c : str1) {
|
||||
// result5.push_back(c);
|
||||
// }
|
||||
|
||||
// Using the stream operator
|
||||
string result6;
|
||||
std::stringstream ss;
|
||||
ss << str1 << " " << str2 << str3;
|
||||
}
|
||||
|
||||
|
||||
void test2(char* ucstr) {
|
||||
char str1[20] = "Hello";
|
||||
char str2[20] = "World";
|
||||
char result[40];
|
||||
char *result2;
|
||||
|
||||
// Using sprintf
|
||||
sprintf(result, "%s %s %s", str1, str2, ucstr);
|
||||
|
||||
// Using strcat
|
||||
strcat(str1, ucstr);
|
||||
}
|
|
@ -0,0 +1,644 @@
|
|||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "type_traits.h"
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept;
|
||||
template<class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
|
||||
}
|
||||
|
||||
// --- iterator ---
|
||||
|
||||
namespace std {
|
||||
struct ptrdiff_t;
|
||||
|
||||
template<class I> struct iterator_traits;
|
||||
|
||||
template <class Category,
|
||||
class value_type,
|
||||
class difference_type = ptrdiff_t,
|
||||
class pointer_type = value_type*,
|
||||
class reference_type = value_type&>
|
||||
struct iterator {
|
||||
typedef Category iterator_category;
|
||||
|
||||
iterator();
|
||||
iterator(iterator<Category, remove_const_t<value_type> > const &other); // non-const -> const conversion constructor
|
||||
|
||||
iterator &operator++();
|
||||
iterator operator++(int);
|
||||
iterator &operator--();
|
||||
iterator operator--(int);
|
||||
bool operator==(iterator other) const;
|
||||
bool operator!=(iterator other) const;
|
||||
reference_type operator*() const;
|
||||
pointer_type operator->() const;
|
||||
iterator operator+(int);
|
||||
iterator operator-(int);
|
||||
iterator &operator+=(int);
|
||||
iterator &operator-=(int);
|
||||
int operator-(iterator);
|
||||
reference_type operator[](int);
|
||||
};
|
||||
|
||||
struct input_iterator_tag {};
|
||||
struct forward_iterator_tag : public input_iterator_tag {};
|
||||
struct bidirectional_iterator_tag : public forward_iterator_tag {};
|
||||
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
|
||||
|
||||
struct output_iterator_tag {};
|
||||
|
||||
template<class Container>
|
||||
class back_insert_iterator {
|
||||
protected:
|
||||
Container* container = nullptr;
|
||||
public:
|
||||
using iterator_category = output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
using container_type = Container;
|
||||
constexpr back_insert_iterator() noexcept = default;
|
||||
constexpr explicit back_insert_iterator(Container& x);
|
||||
back_insert_iterator& operator=(const typename Container::value_type& value);
|
||||
back_insert_iterator& operator=(typename Container::value_type&& value);
|
||||
back_insert_iterator& operator*();
|
||||
back_insert_iterator& operator++();
|
||||
back_insert_iterator operator++(int);
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
constexpr back_insert_iterator<Container> back_inserter(Container& x) {
|
||||
return back_insert_iterator<Container>(x);
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
class front_insert_iterator {
|
||||
protected:
|
||||
Container* container = nullptr;
|
||||
public:
|
||||
using iterator_category = output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
using container_type = Container;
|
||||
constexpr front_insert_iterator() noexcept = default;
|
||||
constexpr explicit front_insert_iterator(Container& x);
|
||||
constexpr front_insert_iterator& operator=(const typename Container::value_type& value);
|
||||
constexpr front_insert_iterator& operator=(typename Container::value_type&& value);
|
||||
constexpr front_insert_iterator& operator*();
|
||||
constexpr front_insert_iterator& operator++();
|
||||
constexpr front_insert_iterator operator++(int);
|
||||
};
|
||||
template<class Container>
|
||||
constexpr front_insert_iterator<Container> front_inserter(Container& x) {
|
||||
return front_insert_iterator<Container>(x);
|
||||
}
|
||||
}
|
||||
|
||||
// --- string ---
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
typedef size_t streamsize;
|
||||
|
||||
template <class T> class allocator {
|
||||
public:
|
||||
allocator() throw();
|
||||
typedef size_t size_type;
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||
class basic_string {
|
||||
public:
|
||||
using value_type = charT;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
typedef typename Allocator::size_type size_type;
|
||||
static const size_type npos = -1;
|
||||
|
||||
explicit basic_string(const Allocator& a = Allocator());
|
||||
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
template<class InputIterator> basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());
|
||||
|
||||
const charT* c_str() const;
|
||||
charT* data() noexcept;
|
||||
size_t length() const;
|
||||
|
||||
typedef std::iterator<random_access_iterator_tag, charT> iterator;
|
||||
typedef std::iterator<random_access_iterator_tag, const charT> const_iterator;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
const_iterator cbegin() const;
|
||||
const_iterator cend() const;
|
||||
|
||||
void push_back(charT c);
|
||||
|
||||
const charT& front() const;
|
||||
charT& front();
|
||||
const charT& back() const;
|
||||
charT& back();
|
||||
|
||||
const_reference operator[](size_type pos) const;
|
||||
reference operator[](size_type pos);
|
||||
const_reference at(size_type n) const;
|
||||
reference at(size_type n);
|
||||
template<class T> basic_string& operator+=(const T& t);
|
||||
basic_string& operator+=(const charT* s);
|
||||
basic_string& append(const basic_string& str);
|
||||
basic_string& append(const charT* s);
|
||||
basic_string& append(size_type n, charT c);
|
||||
template<class InputIterator> basic_string& append(InputIterator first, InputIterator last);
|
||||
basic_string& assign(const basic_string& str);
|
||||
basic_string& assign(size_type n, charT c);
|
||||
template<class InputIterator> basic_string& assign(InputIterator first, InputIterator last);
|
||||
basic_string& insert(size_type pos, const basic_string& str);
|
||||
basic_string& insert(size_type pos, size_type n, charT c);
|
||||
basic_string& insert(size_type pos, const charT* s);
|
||||
iterator insert(const_iterator p, size_type n, charT c);
|
||||
template<class InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last);
|
||||
basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
|
||||
basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c);
|
||||
size_type copy(charT* s, size_type n, size_type pos = 0) const;
|
||||
void clear() noexcept;
|
||||
basic_string substr(size_type pos = 0, size_type n = npos) const;
|
||||
void swap(basic_string& s) noexcept/*(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value)*/;
|
||||
};
|
||||
|
||||
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const basic_string<charT, traits, Allocator>& rhs);
|
||||
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
|
||||
|
||||
typedef basic_string<char> string;
|
||||
}
|
||||
|
||||
// --- istring / ostream / stringstream ---
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_istream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
using char_type = charT;
|
||||
using int_type = int; //typename traits::int_type;
|
||||
|
||||
basic_istream<charT, traits>& operator>>(int& n);
|
||||
|
||||
int_type get();
|
||||
basic_istream<charT, traits>& get(char_type& c);
|
||||
basic_istream<charT, traits>& get(char_type* s, streamsize n);
|
||||
int_type peek();
|
||||
basic_istream<charT, traits>& read (char_type* s, streamsize n);
|
||||
streamsize readsome(char_type* s, streamsize n);
|
||||
basic_istream<charT, traits>& putback(char_type c);
|
||||
basic_istream<charT,traits>& unget();
|
||||
|
||||
basic_istream<charT,traits>& getline(char_type* s, streamsize n);
|
||||
basic_istream<charT,traits>& getline(char_type* s, streamsize n, char_type delim);
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>&, charT*);
|
||||
template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
|
||||
|
||||
template<class charT, class traits, class Allocator> basic_istream<charT,traits>& getline(basic_istream<charT,traits>& is, basic_string<charT,traits,Allocator>& str, charT delim);
|
||||
template<class charT, class traits, class Allocator> basic_istream<charT,traits>& getline(basic_istream<charT,traits>& is, basic_string<charT,traits,Allocator>& str);
|
||||
|
||||
template <class charT, class traits = char_traits<charT> >
|
||||
class basic_ostream /*: virtual public basic_ios<charT,traits> - not needed for this test */ {
|
||||
public:
|
||||
typedef charT char_type;
|
||||
|
||||
basic_ostream<charT, traits>& operator<<(int n);
|
||||
|
||||
basic_ostream<charT, traits>& put(char_type c);
|
||||
basic_ostream<charT, traits>& write(const char_type* s, streamsize n);
|
||||
basic_ostream<charT,traits>& flush();
|
||||
};
|
||||
|
||||
template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);
|
||||
template<class charT, class traits, class Allocator> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const basic_string<charT, traits, Allocator>& str);
|
||||
|
||||
template<class charT, class traits = char_traits<charT>>
|
||||
class basic_iostream : public basic_istream<charT, traits>, public basic_ostream<charT, traits> {
|
||||
public:
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
|
||||
class basic_stringstream : public basic_iostream<charT, traits> {
|
||||
public:
|
||||
explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/);
|
||||
explicit basic_stringstream( const basic_string<charT, traits, Allocator>& str/*, ios_base::openmode which = ios_base::out | ios_base::in*/);
|
||||
basic_stringstream(const basic_stringstream& rhs) = delete;
|
||||
basic_stringstream(basic_stringstream&& rhs);
|
||||
basic_stringstream& operator=(const basic_stringstream& rhs) = delete;
|
||||
basic_stringstream& operator=(basic_stringstream&& rhs);
|
||||
|
||||
void swap(basic_stringstream& rhs);
|
||||
|
||||
basic_string<charT, traits, Allocator> str() const;
|
||||
void str(const basic_string<charT, traits, Allocator>& str);
|
||||
};
|
||||
|
||||
typedef basic_istream<char> istream;
|
||||
typedef basic_ostream<char> ostream;
|
||||
extern istream cin;
|
||||
extern ostream cout;
|
||||
|
||||
using stringstream = basic_stringstream<char>;
|
||||
}
|
||||
|
||||
// --- vector ---
|
||||
|
||||
namespace std {
|
||||
template<class T, class Allocator = allocator<T>>
|
||||
class vector {
|
||||
public:
|
||||
using value_type = T;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = unsigned int;
|
||||
using iterator = std::iterator<random_access_iterator_tag, T>;
|
||||
using const_iterator = std::iterator<random_access_iterator_tag, const T>;
|
||||
|
||||
vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { }
|
||||
explicit vector(const Allocator&) noexcept;
|
||||
explicit vector(size_type n, const Allocator& = Allocator());
|
||||
vector(size_type n, const T& value, const Allocator& = Allocator());
|
||||
template<class InputIterator, class IteratorCategory = typename InputIterator::iterator_category> vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
|
||||
// use of `iterator_category` makes sure InputIterator is (probably) an iterator, and not an `int` or
|
||||
// similar that should match a different overload (SFINAE).
|
||||
~vector();
|
||||
|
||||
vector& operator=(const vector& x);
|
||||
vector& operator=(vector&& x) noexcept/*(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value)*/;
|
||||
template<class InputIterator, class IteratorCategory = typename InputIterator::iterator_category> void assign(InputIterator first, InputIterator last);
|
||||
// use of `iterator_category` makes sure InputIterator is (probably) an iterator, and not an `int` or
|
||||
// similar that should match a different overload (SFINAE).
|
||||
void assign(size_type n, const T& u);
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
size_type size() const noexcept;
|
||||
|
||||
reference operator[](size_type n);
|
||||
const_reference operator[](size_type n) const;
|
||||
const_reference at(size_type n) const;
|
||||
reference at(size_type n);
|
||||
reference front();
|
||||
const_reference front() const;
|
||||
reference back();
|
||||
const_reference back() const;
|
||||
|
||||
T* data() noexcept;
|
||||
const T* data() const noexcept;
|
||||
|
||||
void push_back(const T& x);
|
||||
void push_back(T&& x);
|
||||
|
||||
iterator insert(const_iterator position, const T& x);
|
||||
iterator insert(const_iterator position, T&& x);
|
||||
iterator insert(const_iterator position, size_type n, const T& x);
|
||||
template<class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last);
|
||||
|
||||
template <class... Args> iterator emplace (const_iterator position, Args&&... args);
|
||||
template <class... Args> void emplace_back (Args&&... args);
|
||||
|
||||
void swap(vector&) noexcept/*(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value)*/;
|
||||
|
||||
void clear() noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
// --- make_shared / make_unique ---
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
class shared_ptr {
|
||||
public:
|
||||
shared_ptr() noexcept;
|
||||
explicit shared_ptr(T*);
|
||||
shared_ptr(const shared_ptr&) noexcept;
|
||||
template<class U> shared_ptr(const shared_ptr<U>&) noexcept;
|
||||
template<class U> shared_ptr(shared_ptr<U>&&) noexcept;
|
||||
|
||||
shared_ptr<T>& operator=(const shared_ptr<T>&) noexcept;
|
||||
shared_ptr<T>& operator=(shared_ptr<T>&&) noexcept;
|
||||
|
||||
T& operator*() const noexcept;
|
||||
T* operator->() const noexcept;
|
||||
|
||||
T* get() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unique_ptr {
|
||||
public:
|
||||
constexpr unique_ptr() noexcept;
|
||||
explicit unique_ptr(T*) noexcept;
|
||||
unique_ptr(unique_ptr<T>&&) noexcept;
|
||||
|
||||
unique_ptr<T>& operator=(unique_ptr<T>&&) noexcept;
|
||||
|
||||
T& operator*() const;
|
||||
T* operator->() const noexcept;
|
||||
|
||||
T* get() const noexcept;
|
||||
};
|
||||
|
||||
template<typename T, class... Args> unique_ptr<T> make_unique(Args&&...);
|
||||
|
||||
template<typename T, class... Args> shared_ptr<T> make_shared(Args&&...);
|
||||
}
|
||||
|
||||
// --- pair ---
|
||||
|
||||
namespace std {
|
||||
template <class T1, class T2>
|
||||
struct pair {
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
|
||||
T1 first;
|
||||
T2 second;
|
||||
pair();
|
||||
pair(const T1& x, const T2& y) : first(x), second(y) {};
|
||||
template<class U, class V> pair(const pair<U, V> &p);
|
||||
|
||||
void swap(pair& p) /*noexcept(...)*/;
|
||||
};
|
||||
|
||||
template<class T1, class T2> constexpr pair<decay_t<T1>, decay_t<T2>> make_pair(T1&& x, T2&& y) {
|
||||
return pair<decay_t<T1>, decay_t<T2>>(std::forward<T1>(x), std::forward<T2>(y));
|
||||
}
|
||||
}
|
||||
|
||||
// --- map ---
|
||||
|
||||
namespace std {
|
||||
template<class T = void> struct less;
|
||||
|
||||
template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>
|
||||
class map {
|
||||
public:
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = pair<const Key, T>;
|
||||
using iterator = std::iterator<random_access_iterator_tag, value_type >;
|
||||
using const_iterator = std::iterator<random_access_iterator_tag, const value_type >;
|
||||
|
||||
map() /*: map(Compare()) { }*/;
|
||||
map(const map& x);
|
||||
map(map&& x);
|
||||
~map();
|
||||
|
||||
map& operator=(const map& x);
|
||||
map& operator=(map&& x) /*noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>)*/;
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
T& operator[](const key_type& x);
|
||||
T& operator[](key_type&& x);
|
||||
T& at(const key_type& x);
|
||||
const T& at(const key_type& x) const;
|
||||
|
||||
template<class... Args> pair<iterator, bool> emplace(Args&&... args);
|
||||
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
|
||||
|
||||
pair<iterator, bool> insert(const value_type& x);
|
||||
pair<iterator, bool> insert(value_type&& x);
|
||||
iterator insert(const_iterator position, const value_type& x);
|
||||
iterator insert(const_iterator position, value_type&& x);
|
||||
|
||||
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
|
||||
template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
|
||||
template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
|
||||
template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
|
||||
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
|
||||
template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
|
||||
template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
|
||||
template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
|
||||
|
||||
iterator erase(iterator position);
|
||||
iterator erase(const_iterator position);
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void swap(map&) /*noexcept(/*==allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>)*/;
|
||||
void clear() noexcept;
|
||||
|
||||
template<class C2> void merge(map<Key, T, C2, Allocator>& source);
|
||||
template<class C2> void merge(map<Key, T, C2, Allocator>&& source);
|
||||
|
||||
iterator find(const key_type& x);
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
iterator lower_bound(const key_type& x);
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
iterator upper_bound(const key_type& x);
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
|
||||
pair<iterator, iterator> equal_range(const key_type& x);
|
||||
pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
|
||||
};
|
||||
|
||||
template<class T> struct hash;
|
||||
template<class T = void> struct equal_to;
|
||||
|
||||
template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
|
||||
class unordered_map {
|
||||
public:
|
||||
using key_type = Key;
|
||||
using mapped_type = T;
|
||||
using value_type = pair<const Key, T>;
|
||||
using iterator = std::iterator<random_access_iterator_tag, value_type >;
|
||||
using const_iterator = std::iterator<random_access_iterator_tag, const value_type >;
|
||||
|
||||
unordered_map();
|
||||
unordered_map(const unordered_map&);
|
||||
unordered_map(unordered_map&&);
|
||||
~unordered_map();
|
||||
|
||||
unordered_map& operator=(const unordered_map&);
|
||||
unordered_map& operator=(unordered_map&&) /*noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>)*/;
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
mapped_type& operator[](const key_type& k);
|
||||
mapped_type& operator[](key_type&& k);
|
||||
mapped_type& at(const key_type& k);
|
||||
const mapped_type& at(const key_type& k) const;
|
||||
|
||||
template<class... Args> pair<iterator, bool> emplace(Args&&... args);
|
||||
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
|
||||
|
||||
pair<iterator, bool> insert(const value_type& obj);
|
||||
pair<iterator, bool> insert(value_type&& obj);
|
||||
iterator insert(const_iterator hint, const value_type& obj);
|
||||
iterator insert(const_iterator hint, value_type&& obj);
|
||||
|
||||
template<class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
|
||||
template<class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
|
||||
template<class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
|
||||
template<class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
|
||||
template<class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
|
||||
template<class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
|
||||
template<class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
|
||||
template<class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);
|
||||
|
||||
iterator erase(iterator position);
|
||||
iterator erase(const_iterator position);
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void swap(unordered_map&) /*noexcept(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>)*/;
|
||||
void clear() noexcept;
|
||||
|
||||
template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
|
||||
template<class H2, class P2> void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
|
||||
|
||||
iterator find(const key_type& k);
|
||||
const_iterator find(const key_type& k) const;
|
||||
|
||||
pair<iterator, iterator> equal_range(const key_type& k);
|
||||
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
|
||||
};
|
||||
};
|
||||
|
||||
// --- set ---
|
||||
|
||||
namespace std {
|
||||
template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
|
||||
class set {
|
||||
public:
|
||||
using key_type = Key;
|
||||
using value_type = Key;
|
||||
using size_type = size_t;
|
||||
using allocator_type = Allocator;
|
||||
using iterator = std::iterator<random_access_iterator_tag, value_type >;
|
||||
using const_iterator = std::iterator<random_access_iterator_tag, const value_type >;
|
||||
|
||||
set() /*: set(Compare())*/ { }
|
||||
set(const set& x);
|
||||
set(set&& x);
|
||||
template<class InputIterator> set(InputIterator first, InputIterator last/*, const Compare& comp = Compare(), const Allocator& = Allocator()*/);
|
||||
~set();
|
||||
|
||||
set& operator=(const set& x);
|
||||
set& operator=(set&& x) noexcept/*(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Compare>)*/;
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
template<class... Args> pair<iterator, bool> emplace(Args&&... args);
|
||||
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
|
||||
pair<iterator,bool> insert(const value_type& x);
|
||||
pair<iterator,bool> insert(value_type&& x);
|
||||
iterator insert(const_iterator position, const value_type& x);
|
||||
iterator insert(const_iterator position, value_type&& x);
|
||||
template<class InputIterator> void insert(InputIterator first, InputIterator last);
|
||||
|
||||
iterator erase(iterator position);
|
||||
iterator erase(const_iterator position);
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void swap(set&) noexcept/*(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Compare>)*/;
|
||||
void clear() noexcept;
|
||||
|
||||
template<class C2> void merge(set<Key, C2, Allocator>& source);
|
||||
template<class C2> void merge(set<Key, C2, Allocator>&& source);
|
||||
|
||||
iterator find(const key_type& x);
|
||||
const_iterator find(const key_type& x) const;
|
||||
|
||||
iterator lower_bound(const key_type& x);
|
||||
const_iterator lower_bound(const key_type& x) const;
|
||||
iterator upper_bound(const key_type& x);
|
||||
const_iterator upper_bound(const key_type& x) const;
|
||||
pair<iterator, iterator> equal_range(const key_type& x);
|
||||
pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
|
||||
};
|
||||
|
||||
template<class Key, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<Key>>
|
||||
class unordered_set {
|
||||
public:
|
||||
using key_type = Key;
|
||||
using value_type = Key;
|
||||
using hasher = Hash;
|
||||
using key_equal = Pred;
|
||||
using allocator_type = Allocator;
|
||||
using size_type = size_t;
|
||||
using iterator = std::iterator<random_access_iterator_tag, value_type >;
|
||||
using const_iterator = std::iterator<random_access_iterator_tag, const value_type >;
|
||||
|
||||
unordered_set();
|
||||
unordered_set(const unordered_set&);
|
||||
unordered_set(unordered_set&&);
|
||||
template<class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n = 0/*, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()*/);
|
||||
~unordered_set();
|
||||
|
||||
unordered_set& operator=(const unordered_set&);
|
||||
unordered_set& operator=(unordered_set&&) noexcept/*(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_move_assignable_v<Hash> && is_nothrow_move_assignable_v<Pred>)*/;
|
||||
|
||||
iterator begin() noexcept;
|
||||
const_iterator begin() const noexcept;
|
||||
iterator end() noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
|
||||
template<class... Args> pair<iterator, bool> emplace(Args&&... args);
|
||||
template<class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
|
||||
pair<iterator, bool> insert(const value_type& obj);
|
||||
pair<iterator, bool> insert(value_type&& obj);
|
||||
iterator insert(const_iterator hint, const value_type& obj);
|
||||
iterator insert(const_iterator hint, value_type&& obj);
|
||||
template<class InputIterator> void insert(InputIterator first, InputIterator last);
|
||||
|
||||
iterator erase(iterator position);
|
||||
iterator erase(const_iterator position);
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
void swap(unordered_set&) noexcept/*(allocator_traits<Allocator>::is_always_equal::value && is_nothrow_swappable_v<Hash> && is_nothrow_swappable_v<Pred>)*/;
|
||||
void clear() noexcept;
|
||||
|
||||
template<class H2, class P2> void merge(unordered_set<Key, H2, P2, Allocator>& source);
|
||||
template<class H2, class P2> void merge(unordered_set<Key, H2, P2, Allocator>&& source);
|
||||
|
||||
iterator find(const key_type& k);
|
||||
const_iterator find(const key_type& k) const;
|
||||
pair<iterator, iterator> equal_range(const key_type& k);
|
||||
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
| concat.cpp:23:27:23:27 | call to operator+ | concat.cpp:23:22:23:25 | str1 | concat.cpp:23:22:23:31 | call to operator+ |
|
||||
| concat.cpp:23:27:23:27 | call to operator+ | concat.cpp:23:22:23:25 | str1 | concat.cpp:23:22:23:31 | call to operator+ |
|
||||
| concat.cpp:23:27:23:27 | call to operator+ | concat.cpp:23:22:23:25 | str1 | concat.cpp:23:27:23:27 | call to operator+ |
|
||||
| concat.cpp:23:27:23:27 | call to operator+ | concat.cpp:23:29:23:31 | | concat.cpp:23:22:23:31 | call to operator+ |
|
||||
| concat.cpp:23:27:23:27 | call to operator+ | concat.cpp:23:29:23:31 | | concat.cpp:23:22:23:31 | call to operator+ |
|
||||
| concat.cpp:23:27:23:27 | call to operator+ | concat.cpp:23:29:23:31 | | concat.cpp:23:27:23:27 | call to operator+ |
|
||||
| concat.cpp:23:33:23:33 | call to operator+ | concat.cpp:23:35:23:38 | str2 | concat.cpp:23:22:23:38 | call to operator+ |
|
||||
| concat.cpp:23:33:23:33 | call to operator+ | concat.cpp:23:35:23:38 | str2 | concat.cpp:23:22:23:38 | call to operator+ |
|
||||
| concat.cpp:23:33:23:33 | call to operator+ | concat.cpp:23:35:23:38 | str2 | concat.cpp:23:33:23:33 | call to operator+ |
|
||||
| concat.cpp:23:40:23:40 | call to operator+ | concat.cpp:23:42:23:45 | str3 | concat.cpp:23:40:23:40 | call to operator+ |
|
||||
| concat.cpp:47:8:47:8 | call to operator<< | concat.cpp:47:11:47:14 | str1 | concat.cpp:47:8:47:17 | call to operator<< |
|
||||
| concat.cpp:47:16:47:16 | call to operator<< | concat.cpp:47:19:47:21 | | concat.cpp:47:16:47:24 | call to operator<< |
|
||||
| concat.cpp:47:23:47:23 | call to operator<< | concat.cpp:47:26:47:29 | str2 | concat.cpp:47:23:47:32 | call to operator<< |
|
||||
| concat.cpp:47:31:47:31 | call to operator<< | concat.cpp:47:34:47:37 | str3 | concat.cpp:47:31:47:38 | call to operator<< |
|
||||
| concat.cpp:58:5:58:11 | call to sprintf | concat.cpp:58:21:58:30 | %s %s %s | concat.cpp:58:13:58:18 | sprintf output argument |
|
||||
| concat.cpp:58:5:58:11 | call to sprintf | concat.cpp:58:33:58:36 | str1 | concat.cpp:58:13:58:18 | sprintf output argument |
|
||||
| concat.cpp:58:5:58:11 | call to sprintf | concat.cpp:58:39:58:42 | str2 | concat.cpp:58:13:58:18 | sprintf output argument |
|
||||
| concat.cpp:58:5:58:11 | call to sprintf | concat.cpp:58:45:58:49 | ucstr | concat.cpp:58:13:58:18 | sprintf output argument |
|
||||
| concat.cpp:61:5:61:10 | call to strcat | concat.cpp:61:12:61:15 | str1 | concat.cpp:61:5:61:10 | call to strcat |
|
||||
| concat.cpp:61:5:61:10 | call to strcat | concat.cpp:61:12:61:15 | str1 | concat.cpp:61:12:61:15 | strcat output argument |
|
||||
| concat.cpp:61:5:61:10 | call to strcat | concat.cpp:61:18:61:22 | ucstr | concat.cpp:61:5:61:10 | call to strcat |
|
||||
| concat.cpp:61:5:61:10 | call to strcat | concat.cpp:61:18:61:22 | ucstr | concat.cpp:61:12:61:15 | strcat output argument |
|
|
@ -0,0 +1,10 @@
|
|||
import cpp
|
||||
import semmle.code.cpp.commons.StringConcatenation
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
from StringConcatenation s, Expr op, DataFlow::Node res
|
||||
where
|
||||
s.getLocation().getFile().getBaseName() = "concat.cpp" and
|
||||
op = s.getAnOperand() and
|
||||
res = s.getResultNode()
|
||||
select s, op, res
|
|
@ -0,0 +1,35 @@
|
|||
template<class T>
|
||||
struct remove_const { typedef T type; };
|
||||
|
||||
template<class T>
|
||||
struct remove_const<const T> { typedef T type; };
|
||||
|
||||
// `remove_const_t<T>` removes any `const` specifier from `T`
|
||||
template<class T>
|
||||
using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
template<class T>
|
||||
struct remove_reference { typedef T type; };
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T &> { typedef T type; };
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T &&> { typedef T type; };
|
||||
|
||||
// `remove_reference_t<T>` removes any `&` from `T`
|
||||
template<class T>
|
||||
using remove_reference_t = typename remove_reference<T>::type;
|
||||
|
||||
template<class T>
|
||||
struct decay_impl {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, size_t t_size>
|
||||
struct decay_impl<T[t_size]> {
|
||||
typedef T* type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using decay_t = typename decay_impl<remove_reference_t<T>>::type;
|
|
@ -99,3 +99,4 @@ uniqueContentApprox
|
|||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
|
|
|
@ -42,3 +42,4 @@ uniqueContentApprox
|
|||
identityLocalStep
|
||||
missingArgumentCall
|
||||
multipleArgumentCall
|
||||
lambdaCallEnclosingCallableMismatch
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "test.H"
|
||||
#include "test.xpm"
|
||||
#include "test2.c"
|
||||
#include "test.H" // GOOD
|
||||
#include "test.xpm" // GOOD
|
||||
#include "test2.c" // BAD
|
||||
#include "test.def" // GOOD
|
||||
|
|
|
@ -18,7 +18,12 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||
|
||||
public IMethodSymbol SourceDeclaration => Symbol.OriginalDefinition;
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => Symbol.GetSymbolLocation();
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation =>
|
||||
IsCompilerGeneratedDelegate()
|
||||
? Symbol.ContainingType.GetSymbolLocation()
|
||||
: Symbol.GetSymbolLocation();
|
||||
|
||||
public override bool NeedsPopulation => base.NeedsPopulation || IsCompilerGeneratedDelegate();
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
|
@ -47,6 +52,13 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||
ExtractCompilerGenerated(trapFile);
|
||||
}
|
||||
|
||||
private bool IsCompilerGeneratedDelegate() =>
|
||||
// Lambdas with parameter defaults or a `params` parameter are implemented
|
||||
// using compiler generated delegate types.
|
||||
Symbol.MethodKind == MethodKind.DelegateInvoke &&
|
||||
Symbol.ContainingType is INamedTypeSymbol nt &&
|
||||
nt.IsImplicitlyDeclared;
|
||||
|
||||
public static new OrdinaryMethod Create(Context cx, IMethodSymbol method)
|
||||
{
|
||||
if (method.MethodKind == MethodKind.ReducedExtension)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
|
||||
* The `Call::getArgumentForParameter` predicate has been reworked to add support for arguments passed to `params` parameters.
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* C# 12: Add extractor support for lambda expressions with parameter defaults like `(int x, int y = 1) => ...` and lambda expressions with a `param` parameter like `(params int[] x) => ...)`.
|
|
@ -163,7 +163,48 @@ private predicate isMaybeNullArgument(Ssa::ExplicitDefinition def, MaybeNullExpr
|
|||
|
|
||||
p = pdef.getParameter().getUnboundDeclaration() and
|
||||
arg = p.getAnAssignedArgument() and
|
||||
not arg.getEnclosingCallable().getEnclosingCallable*() instanceof TestMethod
|
||||
not arg.getEnclosingCallable().getEnclosingCallable*() instanceof TestMethod and
|
||||
(
|
||||
p.isParams()
|
||||
implies
|
||||
(
|
||||
isValidExplicitParamsType(p, arg.getType()) and
|
||||
not exists(Call c | c.getAnArgument() = arg and hasMultipleParamsArguments(c))
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type `t` is a valid argument type for passing an explicit array
|
||||
* to the `params` parameter `p`. For example, the types `object[]` and `string[]`
|
||||
* of the arguments on lines 4 and 5, respectively, are valid for the parameter
|
||||
* `args` on line 1 in
|
||||
*
|
||||
* ```csharp
|
||||
* void M(params object[] args) { ... }
|
||||
*
|
||||
* void CallM(object[] os, string[] ss, string s) {
|
||||
* M(os);
|
||||
* M(ss);
|
||||
* M(s);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate isValidExplicitParamsType(Parameter p, Type t) {
|
||||
p.isParams() and
|
||||
t.isImplicitlyConvertibleTo(p.getType())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if call `c` has multiple arguments for a `params` parameter
|
||||
* of the targeted callable.
|
||||
*/
|
||||
private predicate hasMultipleParamsArguments(Call c) {
|
||||
exists(Parameter p | p = c.getTarget().getAParameter() |
|
||||
p.isParams() and
|
||||
exists(c.getArgument(any(int i | i > p.getPosition())))
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -148,17 +148,17 @@ private module Cached {
|
|||
import Cached
|
||||
|
||||
private module DispatchImpl {
|
||||
/**
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context. This is the case if the
|
||||
* call is a delegate call, or if the qualifier accesses a parameter of
|
||||
* the enclosing callable `c` (including the implicit `this` parameter).
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c) {
|
||||
private predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c) {
|
||||
c = call.getEnclosingCallable() and
|
||||
call.(NonDelegateDataFlowCall).getDispatchCall().mayBenefitFromCallContext()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call) { mayBenefitFromCallContext(call, _) }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
|
|
|
@ -20,4 +20,8 @@ module CsharpDataFlow implements InputSig {
|
|||
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
|
||||
|
||||
predicate accessPathLimit = Private::accessPathLimit/0;
|
||||
|
||||
predicate mayBenefitFromCallContext = Private::mayBenefitFromCallContext/1;
|
||||
|
||||
predicate viableImplInCallContext = Private::viableImplInCallContext/2;
|
||||
}
|
||||
|
|
|
@ -602,18 +602,6 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
|||
nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private Expr getImplicitArgument(Call c, int pos) {
|
||||
result = c.getArgument(pos) and
|
||||
not exists(result.getExplicitArgumentName())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Expr getExplicitArgument(Call c, string name) {
|
||||
result = c.getAnArgument() and
|
||||
result.getExplicitArgumentName() = name
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is a `params` argument of `c`, for parameter `p`, and `arg` will
|
||||
* be wrapped in an array by the C# compiler.
|
||||
|
@ -624,11 +612,7 @@ private predicate isParamsArg(Call c, Expr arg, Parameter p) {
|
|||
p = target.getAParameter() and
|
||||
p.isParams() and
|
||||
numArgs = c.getNumberOfArguments() and
|
||||
arg =
|
||||
[
|
||||
getImplicitArgument(c, [p.getPosition() .. numArgs - 1]),
|
||||
getExplicitArgument(c, p.getName())
|
||||
]
|
||||
arg = c.getArgumentForParameter(p)
|
||||
|
|
||||
numArgs > target.getNumberOfParameters()
|
||||
or
|
||||
|
|
|
@ -57,60 +57,29 @@ class Call extends DotNet::Call, Expr, @call {
|
|||
*
|
||||
* This takes into account both positional and named arguments, but does not
|
||||
* consider default arguments.
|
||||
*
|
||||
* An argument must always have a type that is convertible to the relevant
|
||||
* parameter type. Therefore, `params` arguments are only taken into account
|
||||
* when they are passed as explicit arrays. For example, in the call to `M1`
|
||||
* on line 5, `o` is not an argument for `M1`'s `args` parameter, while
|
||||
* `new object[] { o }` on line 6 is, in
|
||||
*
|
||||
* ```csharp
|
||||
* class C {
|
||||
* void M1(params object[] args) { }
|
||||
*
|
||||
* void M2(object o) {
|
||||
* M1(o);
|
||||
* M1(new object[] { o });
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
cached
|
||||
override Expr getArgumentForParameter(DotNet::Parameter p) {
|
||||
this.getTarget().getAParameter() = p and
|
||||
(
|
||||
// Appears in the positional part of the call
|
||||
result = this.getImplicitArgument(p.getPosition()) and
|
||||
(
|
||||
p.(Parameter).isParams()
|
||||
implies
|
||||
(
|
||||
isValidExplicitParamsType(p, result.getType()) and
|
||||
not this.hasMultipleParamsArguments()
|
||||
)
|
||||
)
|
||||
result = this.getImplicitArgument(p)
|
||||
or
|
||||
// Appears in the named part of the call
|
||||
result = this.getExplicitArgument(p.getName()) and
|
||||
(p.(Parameter).isParams() implies isValidExplicitParamsType(p, result.getType()))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this call has multiple arguments for a `params` parameter
|
||||
* of the targeted callable.
|
||||
*/
|
||||
private predicate hasMultipleParamsArguments() {
|
||||
exists(Parameter p | p = this.getTarget().getAParameter() |
|
||||
p.isParams() and
|
||||
exists(this.getArgument(any(int i | i > p.getPosition())))
|
||||
result = this.getExplicitArgument(p.getName())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private Expr getImplicitArgument(int pos) {
|
||||
result = this.getArgument(pos) and
|
||||
not exists(result.getExplicitArgumentName())
|
||||
private Expr getImplicitArgument(DotNet::Parameter p) {
|
||||
not exists(result.getExplicitArgumentName()) and
|
||||
(
|
||||
p.(Parameter).isParams() and
|
||||
result = this.getArgument(any(int i | i >= p.getPosition()))
|
||||
or
|
||||
not p.(Parameter).isParams() and
|
||||
result = this.getArgument(p.getPosition())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
|
@ -213,12 +182,22 @@ class Call extends DotNet::Call, Expr, @call {
|
|||
/**
|
||||
* Gets the argument that corresponds to parameter `p` of a potential
|
||||
* run-time target of this call.
|
||||
*
|
||||
* Does not consider
|
||||
* - default arguments,
|
||||
* - named arguments.
|
||||
*/
|
||||
Expr getRuntimeArgumentForParameter(Parameter p) {
|
||||
exists(Callable c |
|
||||
c = this.getARuntimeTarget() and
|
||||
p = c.getAParameter() and
|
||||
result = this.getRuntimeArgument(p.getPosition())
|
||||
(
|
||||
p.isParams() and
|
||||
result = this.getRuntimeArgument(any(int i | i >= p.getPosition()))
|
||||
or
|
||||
not p.isParams() and
|
||||
result = this.getRuntimeArgument(p.getPosition())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -254,28 +233,6 @@ class Call extends DotNet::Call, Expr, @call {
|
|||
override string toString() { result = "call" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the type `t` is a valid argument type for passing an explicit array
|
||||
* to the `params` parameter `p`. For example, the types `object[]` and `string[]`
|
||||
* of the arguments on lines 4 and 5, respectively, are valid for the parameter
|
||||
* `args` on line 1 in
|
||||
*
|
||||
* ```csharp
|
||||
* void M(params object[] args) { ... }
|
||||
*
|
||||
* void CallM(object[] os, string[] ss, string s) {
|
||||
* M(os);
|
||||
* M(ss);
|
||||
* M(s);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate isValidExplicitParamsType(Parameter p, Type t) {
|
||||
p.isParams() and
|
||||
t.isImplicitlyConvertibleTo(p.getType())
|
||||
}
|
||||
|
||||
/**
|
||||
* A method call, for example `a.M()` on line 5 in
|
||||
*
|
||||
|
|
|
@ -1,2 +1,7 @@
|
|||
description: Remove unused VCS relations.
|
||||
compatibility: backwards
|
||||
|
||||
svnaffectedfiles.rel: delete
|
||||
svnchurn.rel: delete
|
||||
svnentries.rel: delete
|
||||
svnentrymsg.rel: delete
|
||||
|
|
|
@ -2,3 +2,5 @@ description: Support type annotations
|
|||
compatibility: backwards
|
||||
|
||||
type_annotation.rel: run type_annotation.qlo
|
||||
ref_readonly_returns.rel: delete
|
||||
ref_returns.rel: delete
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
description: Implement structured nullability
|
||||
compatibility: backwards
|
||||
|
||||
specific_type_parameter_annotation.rel: delete
|
||||
type_argument_annotation.rel: delete
|
||||
|
|
|
@ -117,137 +117,307 @@ arguments.cs:
|
|||
# 40| 0: [IntLiteral] 1
|
||||
# 40| 1: [IntLiteral] 2
|
||||
# 40| 1: [IntLiteral] 0
|
||||
# 43| 10: [Method] f4
|
||||
# 43| -1: [TypeMention] Void
|
||||
# 41| 6: [LocalVariableDeclStmt] ... ...;
|
||||
# 41| 0: [LocalVariableDeclAndInitExpr] Int16 s1 = ...
|
||||
# 41| -1: [TypeMention] short
|
||||
# 41| 0: [LocalVariableAccess] access to local variable s1
|
||||
# 41| 1: [CastExpr] (...) ...
|
||||
# 41| 1: [IntLiteral] 1
|
||||
# 41| 1: [LocalVariableDeclAndInitExpr] Int16 s2 = ...
|
||||
# 41| -1: [TypeMention] short
|
||||
# 41| 0: [LocalVariableAccess] access to local variable s2
|
||||
# 41| 1: [CastExpr] (...) ...
|
||||
# 41| 1: [IntLiteral] 2
|
||||
# 42| 7: [ExprStmt] ...;
|
||||
# 42| 0: [MethodCall] call to method f3
|
||||
# 42| 0: [IntLiteral] 0
|
||||
# 42| 1: [CastExpr] (...) ...
|
||||
# 42| 1: [LocalVariableAccess] access to local variable s1
|
||||
# 42| 2: [CastExpr] (...) ...
|
||||
# 42| 1: [LocalVariableAccess] access to local variable s2
|
||||
# 45| 10: [Method] f4
|
||||
# 45| -1: [TypeMention] Void
|
||||
#-----| 2: (Parameters)
|
||||
# 43| 0: [Parameter] args
|
||||
# 43| -1: [TypeMention] Object[]
|
||||
# 43| 1: [TypeMention] object
|
||||
# 44| 4: [BlockStmt] {...}
|
||||
# 45| 0: [ExprStmt] ...;
|
||||
# 45| 0: [MethodCall] call to method f4
|
||||
# 45| 0: [ArrayCreation] array creation of type Object[]
|
||||
# 45| -2: [TypeMention] Object[]
|
||||
# 45| 1: [TypeMention] object
|
||||
# 45| -1: [ArrayInitializer] { ..., ... }
|
||||
# 45| 0: [NullLiteral] null
|
||||
# 45| 1: [NullLiteral] null
|
||||
# 48| 11: [Property] Prop
|
||||
# 48| -1: [TypeMention] int
|
||||
# 48| 3: [Getter] get_Prop
|
||||
# 48| 4: [Setter] set_Prop
|
||||
#-----| 2: (Parameters)
|
||||
# 48| 0: [Parameter] value
|
||||
# 50| 12: [Indexer] Item
|
||||
# 45| 0: [Parameter] args
|
||||
# 45| -1: [TypeMention] Object[]
|
||||
# 45| 1: [TypeMention] object
|
||||
# 46| 4: [BlockStmt] {...}
|
||||
# 47| 0: [ExprStmt] ...;
|
||||
# 47| 0: [MethodCall] call to method f4
|
||||
# 47| 0: [ArrayCreation] array creation of type Object[]
|
||||
# 47| -2: [TypeMention] Object[]
|
||||
# 47| 1: [TypeMention] object
|
||||
# 47| -1: [ArrayInitializer] { ..., ... }
|
||||
# 47| 0: [NullLiteral] null
|
||||
# 47| 1: [NullLiteral] null
|
||||
# 50| 11: [Property] Prop
|
||||
# 50| -1: [TypeMention] int
|
||||
# 50| 3: [Getter] get_Prop
|
||||
# 50| 4: [Setter] set_Prop
|
||||
#-----| 2: (Parameters)
|
||||
# 50| 0: [Parameter] value
|
||||
# 52| 12: [Indexer] Item
|
||||
# 52| -1: [TypeMention] int
|
||||
#-----| 1: (Parameters)
|
||||
# 50| 0: [Parameter] a
|
||||
# 50| -1: [TypeMention] int
|
||||
# 50| 1: [Parameter] b
|
||||
# 50| -1: [TypeMention] int
|
||||
# 50| 3: [Getter] get_Item
|
||||
# 52| 0: [Parameter] a
|
||||
# 52| -1: [TypeMention] int
|
||||
# 52| 1: [Parameter] b
|
||||
# 52| -1: [TypeMention] int
|
||||
# 52| 3: [Getter] get_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 50| 0: [Parameter] a
|
||||
# 50| 1: [Parameter] b
|
||||
# 50| 4: [AddExpr] ... + ...
|
||||
# 50| 0: [ParameterAccess] access to parameter a
|
||||
# 50| 1: [ParameterAccess] access to parameter b
|
||||
# 50| 4: [Setter] set_Item
|
||||
# 52| 0: [Parameter] a
|
||||
# 52| 1: [Parameter] b
|
||||
# 52| 4: [AddExpr] ... + ...
|
||||
# 52| 0: [ParameterAccess] access to parameter a
|
||||
# 52| 1: [ParameterAccess] access to parameter b
|
||||
# 52| 4: [Setter] set_Item
|
||||
#-----| 2: (Parameters)
|
||||
# 50| 0: [Parameter] a
|
||||
# 50| 1: [Parameter] b
|
||||
# 50| 2: [Parameter] value
|
||||
# 50| 4: [BlockStmt] {...}
|
||||
# 52| 13: [Method] f5
|
||||
# 52| -1: [TypeMention] Void
|
||||
# 53| 4: [BlockStmt] {...}
|
||||
# 54| 0: [ExprStmt] ...;
|
||||
# 54| 0: [AssignExpr] ... = ...
|
||||
# 54| 0: [PropertyCall] access to property Prop
|
||||
# 54| 1: [IntLiteral] 0
|
||||
# 55| 1: [ExprStmt] ...;
|
||||
# 55| 0: [AssignExpr] ... = ...
|
||||
# 55| 0: [PropertyCall] access to property Prop
|
||||
# 55| 1: [IndexerCall] access to indexer
|
||||
# 55| -1: [ThisAccess] this access
|
||||
# 55| 0: [IntLiteral] 1
|
||||
# 55| 1: [IntLiteral] 2
|
||||
# 56| 2: [ExprStmt] ...;
|
||||
# 52| 0: [Parameter] a
|
||||
# 52| 1: [Parameter] b
|
||||
# 52| 2: [Parameter] value
|
||||
# 52| 4: [BlockStmt] {...}
|
||||
# 54| 13: [Method] f5
|
||||
# 54| -1: [TypeMention] Void
|
||||
# 55| 4: [BlockStmt] {...}
|
||||
# 56| 0: [ExprStmt] ...;
|
||||
# 56| 0: [AssignExpr] ... = ...
|
||||
# 56| 0: [TupleExpr] (..., ...)
|
||||
# 56| 0: [PropertyCall] access to property Prop
|
||||
# 56| 1: [IndexerCall] access to indexer
|
||||
# 56| -1: [ThisAccess] this access
|
||||
# 56| 0: [IntLiteral] 3
|
||||
# 56| 1: [IntLiteral] 4
|
||||
# 56| 1: [TupleExpr] (..., ...)
|
||||
# 56| 0: [IntLiteral] 5
|
||||
# 56| 1: [IntLiteral] 6
|
||||
# 57| 3: [ExprStmt] ...;
|
||||
# 57| 0: [PostIncrExpr] ...++
|
||||
# 56| 0: [PropertyCall] access to property Prop
|
||||
# 56| 1: [IntLiteral] 0
|
||||
# 57| 1: [ExprStmt] ...;
|
||||
# 57| 0: [AssignExpr] ... = ...
|
||||
# 57| 0: [PropertyCall] access to property Prop
|
||||
# 58| 4: [ExprStmt] ...;
|
||||
# 58| 0: [AssignAddExpr] ... += ...
|
||||
# 58| 0: [PropertyCall] access to property Prop
|
||||
# 58| 1: [IntLiteral] 7
|
||||
# 59| 5: [ExprStmt] ...;
|
||||
# 57| 1: [IndexerCall] access to indexer
|
||||
# 57| -1: [ThisAccess] this access
|
||||
# 57| 0: [IntLiteral] 1
|
||||
# 57| 1: [IntLiteral] 2
|
||||
# 58| 2: [ExprStmt] ...;
|
||||
# 58| 0: [AssignExpr] ... = ...
|
||||
# 58| 0: [TupleExpr] (..., ...)
|
||||
# 58| 0: [PropertyCall] access to property Prop
|
||||
# 58| 1: [IndexerCall] access to indexer
|
||||
# 58| -1: [ThisAccess] this access
|
||||
# 58| 0: [IntLiteral] 3
|
||||
# 58| 1: [IntLiteral] 4
|
||||
# 58| 1: [TupleExpr] (..., ...)
|
||||
# 58| 0: [IntLiteral] 5
|
||||
# 58| 1: [IntLiteral] 6
|
||||
# 59| 3: [ExprStmt] ...;
|
||||
# 59| 0: [PostIncrExpr] ...++
|
||||
# 59| 0: [IndexerCall] access to indexer
|
||||
# 59| -1: [ThisAccess] this access
|
||||
# 59| 0: [IntLiteral] 8
|
||||
# 59| 1: [IntLiteral] 9
|
||||
# 60| 6: [ExprStmt] ...;
|
||||
# 59| 0: [PropertyCall] access to property Prop
|
||||
# 60| 4: [ExprStmt] ...;
|
||||
# 60| 0: [AssignAddExpr] ... += ...
|
||||
# 60| 0: [IndexerCall] access to indexer
|
||||
# 60| -1: [ThisAccess] this access
|
||||
# 60| 0: [IntLiteral] 10
|
||||
# 60| 1: [IntLiteral] 11
|
||||
# 60| 1: [IntLiteral] 12
|
||||
# 61| 7: [LocalVariableDeclStmt] ... ...;
|
||||
# 61| 0: [LocalVariableDeclAndInitExpr] (Int32,Int32) tuple = ...
|
||||
# 61| -1: [TypeMention] (int, int)
|
||||
# 61| 0: [LocalVariableAccess] access to local variable tuple
|
||||
# 61| 1: [TupleExpr] (..., ...)
|
||||
# 61| 0: [IntLiteral] 13
|
||||
# 61| 1: [IntLiteral] 14
|
||||
# 62| 8: [ExprStmt] ...;
|
||||
# 62| 0: [AssignExpr] ... = ...
|
||||
# 62| 0: [TupleExpr] (..., ...)
|
||||
# 62| 0: [PropertyCall] access to property Prop
|
||||
# 62| 1: [IndexerCall] access to indexer
|
||||
# 62| -1: [ThisAccess] this access
|
||||
# 62| 0: [IntLiteral] 15
|
||||
# 62| 1: [IntLiteral] 16
|
||||
# 62| 1: [LocalVariableAccess] access to local variable tuple
|
||||
# 66| 14: [Method] f6
|
||||
# 66| -1: [TypeMention] Void
|
||||
# 60| 0: [PropertyCall] access to property Prop
|
||||
# 60| 1: [IntLiteral] 7
|
||||
# 61| 5: [ExprStmt] ...;
|
||||
# 61| 0: [PostIncrExpr] ...++
|
||||
# 61| 0: [IndexerCall] access to indexer
|
||||
# 61| -1: [ThisAccess] this access
|
||||
# 61| 0: [IntLiteral] 8
|
||||
# 61| 1: [IntLiteral] 9
|
||||
# 62| 6: [ExprStmt] ...;
|
||||
# 62| 0: [AssignAddExpr] ... += ...
|
||||
# 62| 0: [IndexerCall] access to indexer
|
||||
# 62| -1: [ThisAccess] this access
|
||||
# 62| 0: [IntLiteral] 10
|
||||
# 62| 1: [IntLiteral] 11
|
||||
# 62| 1: [IntLiteral] 12
|
||||
# 63| 7: [LocalVariableDeclStmt] ... ...;
|
||||
# 63| 0: [LocalVariableDeclAndInitExpr] (Int32,Int32) tuple = ...
|
||||
# 63| -1: [TypeMention] (int, int)
|
||||
# 63| 0: [LocalVariableAccess] access to local variable tuple
|
||||
# 63| 1: [TupleExpr] (..., ...)
|
||||
# 63| 0: [IntLiteral] 13
|
||||
# 63| 1: [IntLiteral] 14
|
||||
# 64| 8: [ExprStmt] ...;
|
||||
# 64| 0: [AssignExpr] ... = ...
|
||||
# 64| 0: [TupleExpr] (..., ...)
|
||||
# 64| 0: [PropertyCall] access to property Prop
|
||||
# 64| 1: [IndexerCall] access to indexer
|
||||
# 64| -1: [ThisAccess] this access
|
||||
# 64| 0: [IntLiteral] 15
|
||||
# 64| 1: [IntLiteral] 16
|
||||
# 64| 1: [LocalVariableAccess] access to local variable tuple
|
||||
# 68| 14: [Method] f6
|
||||
# 68| -1: [TypeMention] Void
|
||||
#-----| 0: (Attributes)
|
||||
# 65| 1: [DefaultAttribute] [My(...)]
|
||||
# 65| -1: [TypeMention] MyAttribute
|
||||
# 65| 0: [BoolLiteral] false
|
||||
# 66| 4: [BlockStmt] {...}
|
||||
# 69| 15: [Method] f7
|
||||
# 69| -1: [TypeMention] Void
|
||||
# 67| 1: [DefaultAttribute] [My(...)]
|
||||
# 67| -1: [TypeMention] MyAttribute
|
||||
# 67| 0: [BoolLiteral] false
|
||||
# 68| 4: [BlockStmt] {...}
|
||||
# 71| 15: [Method] f7
|
||||
# 71| -1: [TypeMention] Void
|
||||
#-----| 0: (Attributes)
|
||||
# 68| 1: [DefaultAttribute] [My(...)]
|
||||
# 68| -1: [TypeMention] MyAttribute
|
||||
# 68| 0: [BoolLiteral] true
|
||||
# 68| 1: [StringLiteralUtf16] ""
|
||||
# 68| 2: [IntLiteral] 0
|
||||
# 69| 4: [BlockStmt] {...}
|
||||
# 72| [Class] MyAttribute
|
||||
#-----| 3: (Base types)
|
||||
# 72| 0: [TypeMention] Attribute
|
||||
# 74| 4: [Field] x
|
||||
# 74| -1: [TypeMention] int
|
||||
# 75| 5: [Property] y
|
||||
# 75| -1: [TypeMention] string
|
||||
# 75| 3: [Getter] get_y
|
||||
# 75| 4: [Setter] set_y
|
||||
#-----| 2: (Parameters)
|
||||
# 75| 0: [Parameter] value
|
||||
# 76| 6: [InstanceConstructor] MyAttribute
|
||||
# 70| 1: [DefaultAttribute] [My(...)]
|
||||
# 70| -1: [TypeMention] MyAttribute
|
||||
# 70| 0: [BoolLiteral] true
|
||||
# 70| 1: [StringLiteralUtf16] ""
|
||||
# 70| 2: [IntLiteral] 0
|
||||
# 71| 4: [BlockStmt] {...}
|
||||
# 73| 17: [Method] f8`1
|
||||
# 73| -1: [TypeMention] Void
|
||||
#-----| 1: (Type parameters)
|
||||
# 73| 0: [TypeParameter] T
|
||||
#-----| 2: (Parameters)
|
||||
# 76| 0: [Parameter] b
|
||||
# 76| -1: [TypeMention] bool
|
||||
# 76| 4: [BlockStmt] {...}
|
||||
# 73| 0: [Parameter] o
|
||||
# 73| -1: [TypeMention] int
|
||||
# 73| 1: [Parameter] args
|
||||
# 73| -1: [TypeMention] T[]
|
||||
# 73| 1: [TypeMention] T
|
||||
# 74| 4: [BlockStmt] {...}
|
||||
# 75| 0: [ExprStmt] ...;
|
||||
# 75| 0: [MethodCall] call to method f8`1
|
||||
# 75| 0: [IntLiteral] 0
|
||||
# 75| 1: [ArrayAccess] access to array element
|
||||
# 75| -1: [ParameterAccess] access to parameter args
|
||||
# 75| 0: [IntLiteral] 0
|
||||
# 75| 2: [ArrayAccess] access to array element
|
||||
# 75| -1: [ParameterAccess] access to parameter args
|
||||
# 75| 0: [IntLiteral] 1
|
||||
# 76| 1: [ExprStmt] ...;
|
||||
# 76| 0: [MethodCall] call to method f8`1
|
||||
# 76| 0: [IntLiteral] 0
|
||||
# 76| 1: [ArrayCreation] array creation of type T[]
|
||||
# 76| -2: [TypeMention] T[]
|
||||
# 76| 1: [TypeMention] T
|
||||
# 76| -1: [ArrayInitializer] { ..., ... }
|
||||
# 76| 0: [ArrayAccess] access to array element
|
||||
# 76| -1: [ParameterAccess] access to parameter args
|
||||
# 76| 0: [IntLiteral] 0
|
||||
# 76| 1: [ArrayAccess] access to array element
|
||||
# 76| -1: [ParameterAccess] access to parameter args
|
||||
# 76| 0: [IntLiteral] 1
|
||||
# 77| 2: [ExprStmt] ...;
|
||||
# 77| 0: [MethodCall] call to method f8`1
|
||||
# 77| 0: [IntLiteral] 0
|
||||
# 77| 1: [ParameterAccess] access to parameter args
|
||||
# 78| 3: [ExprStmt] ...;
|
||||
# 78| 0: [MethodCall] call to method f8`1
|
||||
# 78| 0: [ParameterAccess] access to parameter args
|
||||
# 78| 1: [IntLiteral] 0
|
||||
# 80| 4: [ExprStmt] ...;
|
||||
# 80| 0: [MethodCall] call to method f8<Double>
|
||||
# 80| 0: [IntLiteral] 0
|
||||
# 80| 1: [DoubleLiteral] 1.1
|
||||
# 80| 2: [DoubleLiteral] 2.2
|
||||
# 81| 5: [ExprStmt] ...;
|
||||
# 81| 0: [MethodCall] call to method f8<Double>
|
||||
# 81| 0: [IntLiteral] 0
|
||||
# 81| 1: [ArrayCreation] array creation of type Double[]
|
||||
# 81| -2: [TypeMention] Double[]
|
||||
# 81| 1: [TypeMention] double
|
||||
# 81| -1: [ArrayInitializer] { ..., ... }
|
||||
# 81| 0: [DoubleLiteral] 1.1
|
||||
# 81| 1: [DoubleLiteral] 2.2
|
||||
# 83| 6: [ExprStmt] ...;
|
||||
# 83| 0: [MethodCall] call to method f8<Double>
|
||||
# 83| 0: [IntLiteral] 0
|
||||
# 83| 1: [CastExpr] (...) ...
|
||||
# 83| 1: [IntLiteral] 1
|
||||
# 83| 2: [CastExpr] (...) ...
|
||||
# 83| 1: [IntLiteral] 2
|
||||
# 84| 7: [ExprStmt] ...;
|
||||
# 84| 0: [MethodCall] call to method f8<Double>
|
||||
# 84| 0: [IntLiteral] 0
|
||||
# 84| 1: [ArrayCreation] array creation of type Double[]
|
||||
# 84| -2: [TypeMention] Double[]
|
||||
# 84| 1: [TypeMention] double
|
||||
# 84| -1: [ArrayInitializer] { ..., ... }
|
||||
# 84| 0: [CastExpr] (...) ...
|
||||
# 84| 1: [IntLiteral] 1
|
||||
# 84| 1: [CastExpr] (...) ...
|
||||
# 84| 1: [IntLiteral] 2
|
||||
# 85| 8: [ExprStmt] ...;
|
||||
# 85| 0: [MethodCall] call to method f8<Double>
|
||||
# 85| 0: [IntLiteral] 0
|
||||
# 85| 1: [ArrayCreation] array creation of type Double[]
|
||||
# 85| -2: [TypeMention] Double[]
|
||||
# 85| 1: [TypeMention] double
|
||||
# 85| -1: [ArrayInitializer] { ..., ... }
|
||||
# 85| 0: [CastExpr] (...) ...
|
||||
# 85| 1: [IntLiteral] 1
|
||||
# 85| 1: [CastExpr] (...) ...
|
||||
# 85| 1: [IntLiteral] 2
|
||||
# 89| [Class] MyAttribute
|
||||
#-----| 3: (Base types)
|
||||
# 89| 0: [TypeMention] Attribute
|
||||
# 91| 4: [Field] x
|
||||
# 91| -1: [TypeMention] int
|
||||
# 92| 5: [Property] y
|
||||
# 92| -1: [TypeMention] string
|
||||
# 92| 3: [Getter] get_y
|
||||
# 92| 4: [Setter] set_y
|
||||
#-----| 2: (Parameters)
|
||||
# 92| 0: [Parameter] value
|
||||
# 93| 6: [InstanceConstructor] MyAttribute
|
||||
#-----| 2: (Parameters)
|
||||
# 93| 0: [Parameter] b
|
||||
# 93| -1: [TypeMention] bool
|
||||
# 93| 4: [BlockStmt] {...}
|
||||
lambdas.cs:
|
||||
# 3| [Class] LambdaArgumentsTest
|
||||
# 5| 5: [Method] M1
|
||||
# 5| -1: [TypeMention] Void
|
||||
# 6| 4: [BlockStmt] {...}
|
||||
# 7| 0: [LocalVariableDeclStmt] ... ...;
|
||||
# 7| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> l1 = ...
|
||||
# 7| -1: [TypeMention] Func<int, int>
|
||||
# 7| 0: [LocalVariableAccess] access to local variable l1
|
||||
# 7| 1: [LambdaExpr] (...) => ...
|
||||
#-----| 2: (Parameters)
|
||||
# 7| 0: [Parameter] x
|
||||
# 7| -1: [TypeMention] int
|
||||
# 7| 4: [AddExpr] ... + ...
|
||||
# 7| 0: [ParameterAccess] access to parameter x
|
||||
# 7| 1: [IntLiteral] 1
|
||||
# 8| 1: [ExprStmt] ...;
|
||||
# 8| 0: [DelegateCall] delegate call
|
||||
# 8| -1: [LocalVariableAccess] access to local variable l1
|
||||
# 8| 0: [IntLiteral] 1
|
||||
# 10| 2: [LocalVariableDeclStmt] ... ...;
|
||||
# 10| 0: [LocalVariableDeclAndInitExpr] <>__AnonType0<> l2 = ...
|
||||
# 10| -1: [TypeMention] <>__AnonType0<>
|
||||
# 10| 0: [LocalVariableAccess] access to local variable l2
|
||||
# 10| 1: [LambdaExpr] (...) => ...
|
||||
#-----| 2: (Parameters)
|
||||
# 10| 0: [Parameter] x
|
||||
# 10| -1: [TypeMention] int
|
||||
# 10| 1: [Parameter] y
|
||||
# 10| -1: [TypeMention] int
|
||||
# 10| 1: [IntLiteral] 1
|
||||
# 10| 4: [AddExpr] ... + ...
|
||||
# 10| 0: [ParameterAccess] access to parameter x
|
||||
# 10| 1: [ParameterAccess] access to parameter y
|
||||
# 11| 3: [ExprStmt] ...;
|
||||
# 11| 0: [DelegateCall] delegate call
|
||||
# 11| -1: [LocalVariableAccess] access to local variable l2
|
||||
# 11| 0: [IntLiteral] 2
|
||||
# 11| 1: [IntLiteral] 3
|
||||
# 12| 4: [ExprStmt] ...;
|
||||
# 12| 0: [DelegateCall] delegate call
|
||||
# 12| -1: [LocalVariableAccess] access to local variable l2
|
||||
# 12| 0: [IntLiteral] 4
|
||||
# 13| 5: [ExprStmt] ...;
|
||||
# 13| 0: [DelegateCall] delegate call
|
||||
# 13| -1: [LocalVariableAccess] access to local variable l2
|
||||
# 13| 0: [IntLiteral] 5
|
||||
# 13| 1: [IntLiteral] 6
|
||||
# 15| 6: [LocalVariableDeclStmt] ... ...;
|
||||
# 15| 0: [LocalVariableDeclAndInitExpr] <>__AnonType0<> l3 = ...
|
||||
# 15| -1: [TypeMention] <>__AnonType0<>
|
||||
# 15| 0: [LocalVariableAccess] access to local variable l3
|
||||
# 15| 1: [LambdaExpr] (...) => ...
|
||||
#-----| 2: (Parameters)
|
||||
# 15| 0: [Parameter] x
|
||||
# 15| -1: [TypeMention] Int32[]
|
||||
# 15| 1: [TypeMention] int
|
||||
# 15| 4: [PropertyCall] access to property Length
|
||||
# 15| -1: [ParameterAccess] access to parameter x
|
||||
# 16| 7: [ExprStmt] ...;
|
||||
# 16| 0: [DelegateCall] delegate call
|
||||
# 16| -1: [LocalVariableAccess] access to local variable l3
|
||||
# 17| 8: [ExprStmt] ...;
|
||||
# 17| 0: [DelegateCall] delegate call
|
||||
# 17| -1: [LocalVariableAccess] access to local variable l3
|
||||
# 17| 0: [IntLiteral] 7
|
||||
# 17| 1: [IntLiteral] 8
|
||||
# 17| 2: [IntLiteral] 9
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
| arguments.cs:30:9:30:38 | object creation of type ArgumentsTest | arguments.cs:30:30:30:31 | 10 | y |
|
||||
| arguments.cs:30:9:30:38 | object creation of type ArgumentsTest | arguments.cs:30:37:30:37 | 5 | x |
|
||||
| arguments.cs:35:9:35:19 | call to method f3 | arguments.cs:35:12:35:12 | 0 | o |
|
||||
| arguments.cs:35:9:35:19 | call to method f3 | arguments.cs:35:15:35:15 | 1 | args |
|
||||
| arguments.cs:35:9:35:19 | call to method f3 | arguments.cs:35:18:35:18 | 2 | args |
|
||||
| arguments.cs:36:9:36:33 | call to method f3 | arguments.cs:36:12:36:12 | 0 | o |
|
||||
| arguments.cs:36:9:36:33 | call to method f3 | arguments.cs:36:15:36:32 | array creation of type Int32[] | args |
|
||||
| arguments.cs:37:9:37:25 | call to method f3 | arguments.cs:37:18:37:18 | 1 | args |
|
||||
| arguments.cs:37:9:37:25 | call to method f3 | arguments.cs:37:24:37:24 | 0 | o |
|
||||
| arguments.cs:38:9:38:19 | call to method f3 | arguments.cs:38:12:38:12 | 0 | o |
|
||||
| arguments.cs:38:9:38:19 | call to method f3 | arguments.cs:38:15:38:18 | access to parameter args | args |
|
||||
|
@ -17,21 +20,47 @@
|
|||
| arguments.cs:39:9:39:28 | call to method f3 | arguments.cs:39:27:39:27 | 0 | o |
|
||||
| arguments.cs:40:9:40:42 | call to method f3 | arguments.cs:40:18:40:35 | array creation of type Int32[] | args |
|
||||
| arguments.cs:40:9:40:42 | call to method f3 | arguments.cs:40:41:40:41 | 0 | o |
|
||||
| arguments.cs:54:9:54:12 | access to property Prop | arguments.cs:54:16:54:16 | 0 | value |
|
||||
| arguments.cs:55:9:55:12 | access to property Prop | arguments.cs:55:16:55:25 | access to indexer | value |
|
||||
| arguments.cs:55:16:55:25 | access to indexer | arguments.cs:55:21:55:21 | 1 | a |
|
||||
| arguments.cs:55:16:55:25 | access to indexer | arguments.cs:55:24:55:24 | 2 | b |
|
||||
| arguments.cs:56:10:56:13 | access to property Prop | arguments.cs:56:31:56:31 | 5 | value |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | arguments.cs:56:21:56:21 | 3 | a |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | arguments.cs:56:24:56:24 | 4 | b |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | arguments.cs:56:34:56:34 | 6 | value |
|
||||
| arguments.cs:58:9:58:12 | access to property Prop | arguments.cs:58:9:58:17 | ... + ... | value |
|
||||
| arguments.cs:59:9:59:18 | access to indexer | arguments.cs:59:14:59:14 | 8 | a |
|
||||
| arguments.cs:59:9:59:18 | access to indexer | arguments.cs:59:17:59:17 | 9 | b |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:9:60:26 | ... + ... | value |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:14:60:15 | 10 | a |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:14:60:15 | 10 | a |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:18:60:19 | 11 | b |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:18:60:19 | 11 | b |
|
||||
| arguments.cs:62:16:62:27 | access to indexer | arguments.cs:62:21:62:22 | 15 | a |
|
||||
| arguments.cs:62:16:62:27 | access to indexer | arguments.cs:62:25:62:26 | 16 | b |
|
||||
| arguments.cs:42:9:42:21 | call to method f3 | arguments.cs:42:12:42:12 | 0 | o |
|
||||
| arguments.cs:42:9:42:21 | call to method f3 | arguments.cs:42:15:42:16 | (...) ... | args |
|
||||
| arguments.cs:42:9:42:21 | call to method f3 | arguments.cs:42:19:42:20 | (...) ... | args |
|
||||
| arguments.cs:47:9:47:39 | call to method f4 | arguments.cs:47:12:47:32 | array creation of type Object[] | args |
|
||||
| arguments.cs:47:9:47:39 | call to method f4 | arguments.cs:47:35:47:38 | null | args |
|
||||
| arguments.cs:56:9:56:12 | access to property Prop | arguments.cs:56:16:56:16 | 0 | value |
|
||||
| arguments.cs:57:9:57:12 | access to property Prop | arguments.cs:57:16:57:25 | access to indexer | value |
|
||||
| arguments.cs:57:16:57:25 | access to indexer | arguments.cs:57:21:57:21 | 1 | a |
|
||||
| arguments.cs:57:16:57:25 | access to indexer | arguments.cs:57:24:57:24 | 2 | b |
|
||||
| arguments.cs:58:10:58:13 | access to property Prop | arguments.cs:58:31:58:31 | 5 | value |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | arguments.cs:58:21:58:21 | 3 | a |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | arguments.cs:58:24:58:24 | 4 | b |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | arguments.cs:58:34:58:34 | 6 | value |
|
||||
| arguments.cs:60:9:60:12 | access to property Prop | arguments.cs:60:9:60:17 | ... + ... | value |
|
||||
| arguments.cs:61:9:61:18 | access to indexer | arguments.cs:61:14:61:14 | 8 | a |
|
||||
| arguments.cs:61:9:61:18 | access to indexer | arguments.cs:61:17:61:17 | 9 | b |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:9:62:26 | ... + ... | value |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:14:62:15 | 10 | a |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:14:62:15 | 10 | a |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:18:62:19 | 11 | b |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:18:62:19 | 11 | b |
|
||||
| arguments.cs:64:16:64:27 | access to indexer | arguments.cs:64:21:64:22 | 15 | a |
|
||||
| arguments.cs:64:16:64:27 | access to indexer | arguments.cs:64:25:64:26 | 16 | b |
|
||||
| arguments.cs:75:9:75:31 | call to method f8`1 | arguments.cs:75:12:75:12 | 0 | o |
|
||||
| arguments.cs:75:9:75:31 | call to method f8`1 | arguments.cs:75:15:75:21 | access to array element | args |
|
||||
| arguments.cs:75:9:75:31 | call to method f8`1 | arguments.cs:75:24:75:30 | access to array element | args |
|
||||
| arguments.cs:76:9:76:43 | call to method f8`1 | arguments.cs:76:12:76:12 | 0 | o |
|
||||
| arguments.cs:76:9:76:43 | call to method f8`1 | arguments.cs:76:15:76:42 | array creation of type T[] | args |
|
||||
| arguments.cs:77:9:77:19 | call to method f8`1 | arguments.cs:77:12:77:12 | 0 | o |
|
||||
| arguments.cs:77:9:77:19 | call to method f8`1 | arguments.cs:77:15:77:18 | access to parameter args | args |
|
||||
| arguments.cs:78:9:78:28 | call to method f8`1 | arguments.cs:78:18:78:21 | access to parameter args | args |
|
||||
| arguments.cs:78:9:78:28 | call to method f8`1 | arguments.cs:78:27:78:27 | 0 | o |
|
||||
| arguments.cs:80:9:80:31 | call to method f8<Double> | arguments.cs:80:20:80:20 | 0 | o |
|
||||
| arguments.cs:80:9:80:31 | call to method f8<Double> | arguments.cs:80:23:80:25 | 1.1 | args |
|
||||
| arguments.cs:80:9:80:31 | call to method f8<Double> | arguments.cs:80:28:80:30 | 2.2 | args |
|
||||
| arguments.cs:81:9:81:48 | call to method f8<Double> | arguments.cs:81:20:81:20 | 0 | o |
|
||||
| arguments.cs:81:9:81:48 | call to method f8<Double> | arguments.cs:81:23:81:47 | array creation of type Double[] | args |
|
||||
| arguments.cs:83:9:83:27 | call to method f8<Double> | arguments.cs:83:20:83:20 | 0 | o |
|
||||
| arguments.cs:83:9:83:27 | call to method f8<Double> | arguments.cs:83:23:83:23 | (...) ... | args |
|
||||
| arguments.cs:83:9:83:27 | call to method f8<Double> | arguments.cs:83:26:83:26 | (...) ... | args |
|
||||
| arguments.cs:84:9:84:44 | call to method f8<Double> | arguments.cs:84:20:84:20 | 0 | o |
|
||||
| arguments.cs:84:9:84:44 | call to method f8<Double> | arguments.cs:84:23:84:43 | array creation of type Double[] | args |
|
||||
| arguments.cs:85:9:85:44 | call to method f8<Double> | arguments.cs:85:20:85:20 | 0 | o |
|
||||
| arguments.cs:85:9:85:44 | call to method f8<Double> | arguments.cs:85:23:85:43 | array creation of type Double[] | args |
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
| arguments.cs:30:9:30:38 | object creation of type ArgumentsTest | arguments.cs:30:30:30:31 | 10 | arguments.cs:5:41:5:41 | y |
|
||||
| arguments.cs:30:9:30:38 | object creation of type ArgumentsTest | arguments.cs:30:37:30:37 | 5 | arguments.cs:5:30:5:30 | x |
|
||||
| arguments.cs:35:9:35:19 | call to method f3 | arguments.cs:35:12:35:12 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:35:9:35:19 | call to method f3 | arguments.cs:35:15:35:15 | 1 | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:35:9:35:19 | call to method f3 | arguments.cs:35:18:35:18 | 2 | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:36:9:36:33 | call to method f3 | arguments.cs:36:12:36:12 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:36:9:36:33 | call to method f3 | arguments.cs:36:15:36:32 | array creation of type Int32[] | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:37:9:37:25 | call to method f3 | arguments.cs:37:18:37:18 | 1 | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:37:9:37:25 | call to method f3 | arguments.cs:37:24:37:24 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:38:9:38:19 | call to method f3 | arguments.cs:38:12:38:12 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:38:9:38:19 | call to method f3 | arguments.cs:38:15:38:18 | access to parameter args | arguments.cs:33:33:33:36 | args |
|
||||
|
@ -17,23 +20,49 @@
|
|||
| arguments.cs:39:9:39:28 | call to method f3 | arguments.cs:39:27:39:27 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:40:9:40:42 | call to method f3 | arguments.cs:40:18:40:35 | array creation of type Int32[] | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:40:9:40:42 | call to method f3 | arguments.cs:40:41:40:41 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:54:9:54:12 | access to property Prop | arguments.cs:54:16:54:16 | 0 | arguments.cs:48:21:48:23 | value |
|
||||
| arguments.cs:55:9:55:12 | access to property Prop | arguments.cs:55:16:55:25 | access to indexer | arguments.cs:48:21:48:23 | value |
|
||||
| arguments.cs:55:16:55:25 | access to indexer | arguments.cs:55:21:55:21 | 1 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:55:16:55:25 | access to indexer | arguments.cs:55:24:55:24 | 2 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:56:10:56:13 | access to property Prop | arguments.cs:56:31:56:31 | 5 | arguments.cs:48:21:48:23 | value |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | arguments.cs:56:21:56:21 | 3 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | arguments.cs:56:24:56:24 | 4 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | arguments.cs:56:34:56:34 | 6 | arguments.cs:50:44:50:46 | value |
|
||||
| arguments.cs:58:9:58:12 | access to property Prop | arguments.cs:58:9:58:17 | ... + ... | arguments.cs:48:21:48:23 | value |
|
||||
| arguments.cs:59:9:59:18 | access to indexer | arguments.cs:59:14:59:14 | 8 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:59:9:59:18 | access to indexer | arguments.cs:59:14:59:14 | 8 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:59:9:59:18 | access to indexer | arguments.cs:59:17:59:17 | 9 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:59:9:59:18 | access to indexer | arguments.cs:59:17:59:17 | 9 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:9:60:26 | ... + ... | arguments.cs:50:44:50:46 | value |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:14:60:15 | 10 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:14:60:15 | 10 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:18:60:19 | 11 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:60:9:60:20 | access to indexer | arguments.cs:60:18:60:19 | 11 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:62:16:62:27 | access to indexer | arguments.cs:62:21:62:22 | 15 | arguments.cs:50:18:50:18 | a |
|
||||
| arguments.cs:62:16:62:27 | access to indexer | arguments.cs:62:25:62:26 | 16 | arguments.cs:50:25:50:25 | b |
|
||||
| arguments.cs:42:9:42:21 | call to method f3 | arguments.cs:42:12:42:12 | 0 | arguments.cs:33:17:33:17 | o |
|
||||
| arguments.cs:42:9:42:21 | call to method f3 | arguments.cs:42:15:42:16 | (...) ... | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:42:9:42:21 | call to method f3 | arguments.cs:42:19:42:20 | (...) ... | arguments.cs:33:33:33:36 | args |
|
||||
| arguments.cs:47:9:47:39 | call to method f4 | arguments.cs:47:12:47:32 | array creation of type Object[] | arguments.cs:45:29:45:32 | args |
|
||||
| arguments.cs:47:9:47:39 | call to method f4 | arguments.cs:47:35:47:38 | null | arguments.cs:45:29:45:32 | args |
|
||||
| arguments.cs:56:9:56:12 | access to property Prop | arguments.cs:56:16:56:16 | 0 | arguments.cs:50:21:50:23 | value |
|
||||
| arguments.cs:57:9:57:12 | access to property Prop | arguments.cs:57:16:57:25 | access to indexer | arguments.cs:50:21:50:23 | value |
|
||||
| arguments.cs:57:16:57:25 | access to indexer | arguments.cs:57:21:57:21 | 1 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:57:16:57:25 | access to indexer | arguments.cs:57:24:57:24 | 2 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:58:10:58:13 | access to property Prop | arguments.cs:58:31:58:31 | 5 | arguments.cs:50:21:50:23 | value |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | arguments.cs:58:21:58:21 | 3 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | arguments.cs:58:24:58:24 | 4 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | arguments.cs:58:34:58:34 | 6 | arguments.cs:52:44:52:46 | value |
|
||||
| arguments.cs:60:9:60:12 | access to property Prop | arguments.cs:60:9:60:17 | ... + ... | arguments.cs:50:21:50:23 | value |
|
||||
| arguments.cs:61:9:61:18 | access to indexer | arguments.cs:61:14:61:14 | 8 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:61:9:61:18 | access to indexer | arguments.cs:61:14:61:14 | 8 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:61:9:61:18 | access to indexer | arguments.cs:61:17:61:17 | 9 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:61:9:61:18 | access to indexer | arguments.cs:61:17:61:17 | 9 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:9:62:26 | ... + ... | arguments.cs:52:44:52:46 | value |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:14:62:15 | 10 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:14:62:15 | 10 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:18:62:19 | 11 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:62:9:62:20 | access to indexer | arguments.cs:62:18:62:19 | 11 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:64:16:64:27 | access to indexer | arguments.cs:64:21:64:22 | 15 | arguments.cs:52:18:52:18 | a |
|
||||
| arguments.cs:64:16:64:27 | access to indexer | arguments.cs:64:25:64:26 | 16 | arguments.cs:52:25:52:25 | b |
|
||||
| arguments.cs:75:9:75:31 | call to method f8`1 | arguments.cs:75:12:75:12 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:75:9:75:31 | call to method f8`1 | arguments.cs:75:15:75:21 | access to array element | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:75:9:75:31 | call to method f8`1 | arguments.cs:75:24:75:30 | access to array element | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:76:9:76:43 | call to method f8`1 | arguments.cs:76:12:76:12 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:76:9:76:43 | call to method f8`1 | arguments.cs:76:15:76:42 | array creation of type T[] | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:77:9:77:19 | call to method f8`1 | arguments.cs:77:12:77:12 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:77:9:77:19 | call to method f8`1 | arguments.cs:77:15:77:18 | access to parameter args | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:78:9:78:28 | call to method f8`1 | arguments.cs:78:18:78:21 | access to parameter args | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:78:9:78:28 | call to method f8`1 | arguments.cs:78:27:78:27 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:80:9:80:31 | call to method f8<Double> | arguments.cs:80:20:80:20 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:80:9:80:31 | call to method f8<Double> | arguments.cs:80:23:80:25 | 1.1 | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:80:9:80:31 | call to method f8<Double> | arguments.cs:80:28:80:30 | 2.2 | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:81:9:81:48 | call to method f8<Double> | arguments.cs:81:20:81:20 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:81:9:81:48 | call to method f8<Double> | arguments.cs:81:23:81:47 | array creation of type Double[] | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:83:9:83:27 | call to method f8<Double> | arguments.cs:83:20:83:20 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:83:9:83:27 | call to method f8<Double> | arguments.cs:83:23:83:23 | (...) ... | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:83:9:83:27 | call to method f8<Double> | arguments.cs:83:26:83:26 | (...) ... | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:84:9:84:44 | call to method f8<Double> | arguments.cs:84:20:84:20 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:84:9:84:44 | call to method f8<Double> | arguments.cs:84:23:84:43 | array creation of type Double[] | arguments.cs:73:34:73:37 | args |
|
||||
| arguments.cs:85:9:85:44 | call to method f8<Double> | arguments.cs:85:20:85:20 | 0 | arguments.cs:73:20:73:20 | o |
|
||||
| arguments.cs:85:9:85:44 | call to method f8<Double> | arguments.cs:85:23:85:43 | array creation of type Double[] | arguments.cs:73:34:73:37 | args |
|
||||
|
|
|
@ -7,5 +7,7 @@
|
|||
| arguments.cs:39:27:39:27 | 0 | o |
|
||||
| arguments.cs:40:18:40:35 | array creation of type Int32[] | args |
|
||||
| arguments.cs:40:41:40:41 | 0 | o |
|
||||
| arguments.cs:68:28:68:29 | "" | y |
|
||||
| arguments.cs:68:36:68:36 | 0 | x |
|
||||
| arguments.cs:70:28:70:29 | "" | y |
|
||||
| arguments.cs:70:36:70:36 | 0 | x |
|
||||
| arguments.cs:78:18:78:21 | access to parameter args | args |
|
||||
| arguments.cs:78:27:78:27 | 0 | o |
|
||||
|
|
|
@ -20,25 +20,62 @@
|
|||
| arguments.cs:39:27:39:27 | 0 | 0 |
|
||||
| arguments.cs:40:18:40:35 | array creation of type Int32[] | 0 |
|
||||
| arguments.cs:40:41:40:41 | 0 | 0 |
|
||||
| arguments.cs:45:12:45:32 | array creation of type Object[] | 0 |
|
||||
| arguments.cs:45:35:45:38 | null | 0 |
|
||||
| arguments.cs:55:21:55:21 | 1 | 0 |
|
||||
| arguments.cs:55:24:55:24 | 2 | 0 |
|
||||
| arguments.cs:56:10:56:13 | access to property Prop | 0 |
|
||||
| arguments.cs:56:16:56:25 | access to indexer | 0 |
|
||||
| arguments.cs:56:21:56:21 | 3 | 0 |
|
||||
| arguments.cs:56:24:56:24 | 4 | 0 |
|
||||
| arguments.cs:56:31:56:31 | 5 | 0 |
|
||||
| arguments.cs:56:34:56:34 | 6 | 0 |
|
||||
| arguments.cs:59:14:59:14 | 8 | 0 |
|
||||
| arguments.cs:59:17:59:17 | 9 | 0 |
|
||||
| arguments.cs:60:14:60:15 | 10 | 0 |
|
||||
| arguments.cs:60:14:60:15 | 10 | 0 |
|
||||
| arguments.cs:60:18:60:19 | 11 | 0 |
|
||||
| arguments.cs:60:18:60:19 | 11 | 0 |
|
||||
| arguments.cs:61:22:61:23 | 13 | 0 |
|
||||
| arguments.cs:61:26:61:27 | 14 | 0 |
|
||||
| arguments.cs:62:10:62:13 | access to property Prop | 0 |
|
||||
| arguments.cs:62:16:62:27 | access to indexer | 0 |
|
||||
| arguments.cs:62:21:62:22 | 15 | 0 |
|
||||
| arguments.cs:62:25:62:26 | 16 | 0 |
|
||||
| arguments.cs:42:12:42:12 | 0 | 0 |
|
||||
| arguments.cs:42:15:42:16 | (...) ... | 0 |
|
||||
| arguments.cs:42:19:42:20 | (...) ... | 0 |
|
||||
| arguments.cs:47:12:47:32 | array creation of type Object[] | 0 |
|
||||
| arguments.cs:47:35:47:38 | null | 0 |
|
||||
| arguments.cs:57:21:57:21 | 1 | 0 |
|
||||
| arguments.cs:57:24:57:24 | 2 | 0 |
|
||||
| arguments.cs:58:10:58:13 | access to property Prop | 0 |
|
||||
| arguments.cs:58:16:58:25 | access to indexer | 0 |
|
||||
| arguments.cs:58:21:58:21 | 3 | 0 |
|
||||
| arguments.cs:58:24:58:24 | 4 | 0 |
|
||||
| arguments.cs:58:31:58:31 | 5 | 0 |
|
||||
| arguments.cs:58:34:58:34 | 6 | 0 |
|
||||
| arguments.cs:61:14:61:14 | 8 | 0 |
|
||||
| arguments.cs:61:17:61:17 | 9 | 0 |
|
||||
| arguments.cs:62:14:62:15 | 10 | 0 |
|
||||
| arguments.cs:62:14:62:15 | 10 | 0 |
|
||||
| arguments.cs:62:18:62:19 | 11 | 0 |
|
||||
| arguments.cs:62:18:62:19 | 11 | 0 |
|
||||
| arguments.cs:63:22:63:23 | 13 | 0 |
|
||||
| arguments.cs:63:26:63:27 | 14 | 0 |
|
||||
| arguments.cs:64:10:64:13 | access to property Prop | 0 |
|
||||
| arguments.cs:64:16:64:27 | access to indexer | 0 |
|
||||
| arguments.cs:64:21:64:22 | 15 | 0 |
|
||||
| arguments.cs:64:25:64:26 | 16 | 0 |
|
||||
| arguments.cs:75:12:75:12 | 0 | 0 |
|
||||
| arguments.cs:75:15:75:21 | access to array element | 0 |
|
||||
| arguments.cs:75:20:75:20 | 0 | 0 |
|
||||
| arguments.cs:75:24:75:30 | access to array element | 0 |
|
||||
| arguments.cs:75:29:75:29 | 1 | 0 |
|
||||
| arguments.cs:76:12:76:12 | 0 | 0 |
|
||||
| arguments.cs:76:15:76:42 | array creation of type T[] | 0 |
|
||||
| arguments.cs:76:30:76:30 | 0 | 0 |
|
||||
| arguments.cs:76:39:76:39 | 1 | 0 |
|
||||
| arguments.cs:77:12:77:12 | 0 | 0 |
|
||||
| arguments.cs:77:15:77:18 | access to parameter args | 0 |
|
||||
| arguments.cs:78:18:78:21 | access to parameter args | 0 |
|
||||
| arguments.cs:78:27:78:27 | 0 | 0 |
|
||||
| arguments.cs:80:20:80:20 | 0 | 0 |
|
||||
| arguments.cs:80:23:80:25 | 1.1 | 0 |
|
||||
| arguments.cs:80:28:80:30 | 2.2 | 0 |
|
||||
| arguments.cs:81:20:81:20 | 0 | 0 |
|
||||
| arguments.cs:81:23:81:47 | array creation of type Double[] | 0 |
|
||||
| arguments.cs:83:20:83:20 | 0 | 0 |
|
||||
| arguments.cs:83:23:83:23 | (...) ... | 0 |
|
||||
| arguments.cs:83:26:83:26 | (...) ... | 0 |
|
||||
| arguments.cs:84:20:84:20 | 0 | 0 |
|
||||
| arguments.cs:84:23:84:43 | array creation of type Double[] | 0 |
|
||||
| arguments.cs:85:20:85:20 | 0 | 0 |
|
||||
| arguments.cs:85:23:85:43 | array creation of type Double[] | 0 |
|
||||
| lambdas.cs:8:12:8:12 | 1 | 0 |
|
||||
| lambdas.cs:11:12:11:12 | 2 | 0 |
|
||||
| lambdas.cs:11:15:11:15 | 3 | 0 |
|
||||
| lambdas.cs:12:12:12:12 | 4 | 0 |
|
||||
| lambdas.cs:13:12:13:12 | 5 | 0 |
|
||||
| lambdas.cs:13:15:13:15 | 6 | 0 |
|
||||
| lambdas.cs:17:12:17:12 | 7 | 0 |
|
||||
| lambdas.cs:17:15:17:15 | 8 | 0 |
|
||||
| lambdas.cs:17:18:17:18 | 9 | 0 |
|
||||
|
|
|
@ -38,6 +38,8 @@ class ArgumentsTest
|
|||
f3(0, args);
|
||||
f3(args: args, o: 0);
|
||||
f3(args: new int[] { 1, 2 }, o: 0);
|
||||
short s1 = 1, s2 = 2;
|
||||
f3(0, s1, s2);
|
||||
}
|
||||
|
||||
void f4(params object[] args)
|
||||
|
@ -67,6 +69,21 @@ class ArgumentsTest
|
|||
|
||||
[MyAttribute(true, y = "", x = 0)]
|
||||
void f7() { }
|
||||
|
||||
void f8<T>(int o, params T[] args)
|
||||
{
|
||||
f8(0, args[0], args[1]);
|
||||
f8(0, new T[] { args[0], args[1] });
|
||||
f8(0, args);
|
||||
f8(args: args, o: 0);
|
||||
|
||||
f8<double>(0, 1.1, 2.2);
|
||||
f8<double>(0, new double[] { 1.1, 2.2 });
|
||||
|
||||
f8<double>(0, 1, 2);
|
||||
f8<double>(0, new double[] { 1, 2 });
|
||||
f8<double>(0, new double[] { 1, 2 });
|
||||
}
|
||||
}
|
||||
|
||||
class MyAttribute : Attribute
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
| lambdas.cs:8:9:8:13 | delegate call | lambdas.cs:7:23:7:23 | x | lambdas.cs:8:12:8:12 | 1 |
|
||||
| lambdas.cs:11:9:11:16 | delegate call | lambdas.cs:10:23:10:23 | x | lambdas.cs:11:12:11:12 | 2 |
|
||||
| lambdas.cs:11:9:11:16 | delegate call | lambdas.cs:10:30:10:30 | y | lambdas.cs:11:15:11:15 | 3 |
|
||||
| lambdas.cs:12:9:12:13 | delegate call | lambdas.cs:10:23:10:23 | x | lambdas.cs:12:12:12:12 | 4 |
|
||||
| lambdas.cs:13:9:13:16 | delegate call | lambdas.cs:10:23:10:23 | x | lambdas.cs:13:12:13:12 | 5 |
|
||||
| lambdas.cs:13:9:13:16 | delegate call | lambdas.cs:10:30:10:30 | y | lambdas.cs:13:15:13:15 | 6 |
|
||||
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:12:17:12 | 7 |
|
||||
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:15:17:15 | 8 |
|
||||
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:18:17:18 | 9 |
|
|
@ -0,0 +1,7 @@
|
|||
import csharp
|
||||
|
||||
from Call call, Parameter p, Expr arg
|
||||
where
|
||||
call.getARuntimeTarget() instanceof LambdaExpr and
|
||||
arg = call.getRuntimeArgumentForParameter(p)
|
||||
select call, p, arg
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
class LambdaArgumentsTest
|
||||
{
|
||||
void M1()
|
||||
{
|
||||
var l1 = (int x) => x + 1;
|
||||
l1(1);
|
||||
|
||||
var l2 = (int x, int y = 1) => x + y;
|
||||
l2(2, 3);
|
||||
l2(4);
|
||||
l2(5, 6);
|
||||
|
||||
var l3 = (params int[] x) => x.Length;
|
||||
l3();
|
||||
l3(7, 8, 9);
|
||||
}
|
||||
}
|
|
@ -13,27 +13,56 @@
|
|||
| arguments.cs:33:17:33:17 | o | arguments.cs:38:12:38:12 | 0 |
|
||||
| arguments.cs:33:17:33:17 | o | arguments.cs:39:27:39:27 | 0 |
|
||||
| arguments.cs:33:17:33:17 | o | arguments.cs:40:41:40:41 | 0 |
|
||||
| arguments.cs:33:17:33:17 | o | arguments.cs:42:12:42:12 | 0 |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:35:15:35:15 | 1 |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:35:18:35:18 | 2 |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:36:15:36:32 | array creation of type Int32[] |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:37:18:37:18 | 1 |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:38:15:38:18 | access to parameter args |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:39:18:39:21 | access to parameter args |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:40:18:40:35 | array creation of type Int32[] |
|
||||
| arguments.cs:48:21:48:23 | value | arguments.cs:54:16:54:16 | 0 |
|
||||
| arguments.cs:48:21:48:23 | value | arguments.cs:55:16:55:25 | access to indexer |
|
||||
| arguments.cs:48:21:48:23 | value | arguments.cs:56:31:56:31 | 5 |
|
||||
| arguments.cs:48:21:48:23 | value | arguments.cs:58:9:58:17 | ... + ... |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:55:21:55:21 | 1 |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:56:21:56:21 | 3 |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:59:14:59:14 | 8 |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:59:14:59:14 | 8 |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:60:14:60:15 | 10 |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:60:14:60:15 | 10 |
|
||||
| arguments.cs:50:18:50:18 | a | arguments.cs:62:21:62:22 | 15 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:55:24:55:24 | 2 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:56:24:56:24 | 4 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:59:17:59:17 | 9 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:59:17:59:17 | 9 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:60:18:60:19 | 11 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:60:18:60:19 | 11 |
|
||||
| arguments.cs:50:25:50:25 | b | arguments.cs:62:25:62:26 | 16 |
|
||||
| arguments.cs:50:44:50:46 | value | arguments.cs:56:34:56:34 | 6 |
|
||||
| arguments.cs:50:44:50:46 | value | arguments.cs:60:9:60:26 | ... + ... |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:42:15:42:16 | (...) ... |
|
||||
| arguments.cs:33:33:33:36 | args | arguments.cs:42:19:42:20 | (...) ... |
|
||||
| arguments.cs:45:29:45:32 | args | arguments.cs:47:12:47:32 | array creation of type Object[] |
|
||||
| arguments.cs:45:29:45:32 | args | arguments.cs:47:35:47:38 | null |
|
||||
| arguments.cs:50:21:50:23 | value | arguments.cs:56:16:56:16 | 0 |
|
||||
| arguments.cs:50:21:50:23 | value | arguments.cs:57:16:57:25 | access to indexer |
|
||||
| arguments.cs:50:21:50:23 | value | arguments.cs:58:31:58:31 | 5 |
|
||||
| arguments.cs:50:21:50:23 | value | arguments.cs:60:9:60:17 | ... + ... |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:57:21:57:21 | 1 |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:58:21:58:21 | 3 |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:61:14:61:14 | 8 |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:61:14:61:14 | 8 |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:62:14:62:15 | 10 |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:62:14:62:15 | 10 |
|
||||
| arguments.cs:52:18:52:18 | a | arguments.cs:64:21:64:22 | 15 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:57:24:57:24 | 2 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:58:24:58:24 | 4 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:61:17:61:17 | 9 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:61:17:61:17 | 9 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:62:18:62:19 | 11 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:62:18:62:19 | 11 |
|
||||
| arguments.cs:52:25:52:25 | b | arguments.cs:64:25:64:26 | 16 |
|
||||
| arguments.cs:52:44:52:46 | value | arguments.cs:58:34:58:34 | 6 |
|
||||
| arguments.cs:52:44:52:46 | value | arguments.cs:62:9:62:26 | ... + ... |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:75:12:75:12 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:76:12:76:12 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:77:12:77:12 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:78:27:78:27 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:80:20:80:20 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:81:20:81:20 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:83:20:83:20 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:84:20:84:20 | 0 |
|
||||
| arguments.cs:73:20:73:20 | o | arguments.cs:85:20:85:20 | 0 |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:75:15:75:21 | access to array element |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:75:24:75:30 | access to array element |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:76:15:76:42 | array creation of type T[] |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:77:15:77:18 | access to parameter args |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:78:18:78:21 | access to parameter args |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:80:23:80:25 | 1.1 |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:80:28:80:30 | 2.2 |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:81:23:81:47 | array creation of type Double[] |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:83:23:83:23 | (...) ... |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:83:26:83:26 | (...) ... |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:84:23:84:43 | array creation of type Double[] |
|
||||
| arguments.cs:73:34:73:37 | args | arguments.cs:85:23:85:43 | array creation of type Double[] |
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
public class LambdaParameters
|
||||
{
|
||||
public void M1()
|
||||
{
|
||||
var l1 = (int x, int y = 1) => x + y;
|
||||
var l2 = (object? o = default) => o;
|
||||
var l3 = (int x, int y = 1, int z = 2) => x + y + z;
|
||||
var l4 = ([Optional, DefaultParameterValue(7)] int x) => x;
|
||||
var l5 = ([Optional, DateTimeConstant(14L)] DateTime x) => x;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
noDefaultValue
|
||||
| LambdaParameters.cs:9:18:9:44 | (...) => ... | LambdaParameters.cs:9:23:9:23 | x | 0 |
|
||||
| LambdaParameters.cs:11:18:11:59 | (...) => ... | LambdaParameters.cs:11:23:11:23 | x | 0 |
|
||||
| Parameters.cs:7:17:7:18 | M1 | Parameters.cs:7:24:7:24 | a | 0 |
|
||||
| Parameters.cs:7:17:7:18 | M1 | Parameters.cs:7:34:7:34 | b | 1 |
|
||||
| Parameters.cs:7:17:7:18 | M1 | Parameters.cs:7:44:7:44 | c | 2 |
|
||||
|
@ -16,6 +18,12 @@ noDefaultValue
|
|||
| Parameters.dll:0:0:0:0 | implicit conversion | Parameters.dll:0:0:0:0 | i | 0 |
|
||||
| Parameters.dll:0:0:0:0 | implicit conversion | Parameters.dll:0:0:0:0 | s | 0 |
|
||||
withDefaultValue
|
||||
| LambdaParameters.cs:9:18:9:44 | (...) => ... | LambdaParameters.cs:9:30:9:30 | y | 1 | LambdaParameters.cs:9:34:9:34 | 1 | 1 |
|
||||
| LambdaParameters.cs:10:18:10:43 | (...) => ... | LambdaParameters.cs:10:27:10:27 | o | 0 | LambdaParameters.cs:10:31:10:37 | default | null |
|
||||
| LambdaParameters.cs:11:18:11:59 | (...) => ... | LambdaParameters.cs:11:30:11:30 | y | 1 | LambdaParameters.cs:11:34:11:34 | 1 | 1 |
|
||||
| LambdaParameters.cs:11:18:11:59 | (...) => ... | LambdaParameters.cs:11:41:11:41 | z | 2 | LambdaParameters.cs:11:45:11:45 | 2 | 2 |
|
||||
| LambdaParameters.cs:12:18:12:66 | (...) => ... | LambdaParameters.cs:12:60:12:60 | x | 0 | LambdaParameters.cs:12:19:12:60 | 7 | 7 |
|
||||
| LambdaParameters.cs:13:18:13:68 | (...) => ... | LambdaParameters.cs:13:62:13:62 | x | 0 | LambdaParameters.cs:13:19:13:62 | object creation of type DateTime | - |
|
||||
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:34:8:34 | b | 1 | Parameters.cs:8:38:8:41 | null | null |
|
||||
| Parameters.cs:8:17:8:18 | M2 | Parameters.cs:8:51:8:51 | c | 2 | Parameters.cs:8:55:8:70 | "default string" | default string |
|
||||
| Parameters.cs:9:17:9:18 | M3 | Parameters.cs:9:24:9:24 | a | 0 | Parameters.cs:9:28:9:28 | 1 | 1 |
|
||||
|
@ -81,6 +89,7 @@ withDefaultValue
|
|||
| Parameters.dll:0:0:0:0 | M23 | Parameters.dll:0:0:0:0 | arg12 | 0 | Parameters.dll:0:0:0:0 | (...) ... | 0 |
|
||||
| Parameters.dll:0:0:0:0 | M24 | Parameters.dll:0:0:0:0 | arg13 | 0 | Parameters.dll:0:0:0:0 | (...) ... | 7 |
|
||||
dateTimeDefaults
|
||||
| LambdaParameters.cs:13:18:13:68 | (...) => ... | LambdaParameters.cs:13:62:13:62 | x | LambdaParameters.cs:13:19:13:62 | object creation of type DateTime | DateTime(long) | 14 |
|
||||
| Parameters.cs:22:17:22:19 | M14 | Parameters.cs:22:64:22:67 | arg4 | Parameters.cs:22:21:22:67 | object creation of type DateTime | DateTime(long) | 14 |
|
||||
| Parameters.cs:23:17:23:19 | M15 | Parameters.cs:23:68:23:71 | arg5 | Parameters.cs:23:21:23:71 | object creation of type DateTime | DateTime(long) | 10001 |
|
||||
| Parameters.dll:0:0:0:0 | M14 | Parameters.dll:0:0:0:0 | arg4 | Parameters.dll:0:0:0:0 | object creation of type DateTime | DateTime(long) | 14 |
|
||||
|
|
|
@ -443,6 +443,8 @@ nodes
|
|||
| NullAlwaysBad.cs:9:30:9:30 | access to parameter s |
|
||||
| NullMaybeBad.cs:7:27:7:27 | access to parameter o |
|
||||
| NullMaybeBad.cs:13:17:13:20 | null |
|
||||
| Params.cs:14:17:14:20 | access to parameter args |
|
||||
| Params.cs:20:12:20:15 | null |
|
||||
| StringConcatenation.cs:14:16:14:23 | SSA def(s) |
|
||||
| StringConcatenation.cs:15:16:15:16 | access to local variable s |
|
||||
| StringConcatenation.cs:16:17:16:17 | access to local variable s |
|
||||
|
@ -831,6 +833,7 @@ edges
|
|||
| GuardedString.cs:34:26:34:26 | 0 | GuardedString.cs:35:31:35:31 | access to local variable s |
|
||||
| NullAlwaysBad.cs:7:29:7:29 | SSA param(s) | NullAlwaysBad.cs:9:30:9:30 | access to parameter s |
|
||||
| NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o |
|
||||
| Params.cs:20:12:20:15 | null | Params.cs:14:17:14:20 | access to parameter args |
|
||||
| StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:15:16:15:16 | access to local variable s |
|
||||
| StringConcatenation.cs:15:16:15:16 | access to local variable s | StringConcatenation.cs:16:17:16:17 | access to local variable s |
|
||||
#select
|
||||
|
@ -918,4 +921,5 @@ edges
|
|||
| E.cs:417:34:417:34 | access to parameter i | E.cs:417:24:417:40 | SSA capture def(i) | E.cs:417:34:417:34 | access to parameter i | Variable $@ may be null at this access because it has a nullable type. | E.cs:415:27:415:27 | i | i | E.cs:415:27:415:27 | i | this |
|
||||
| GuardedString.cs:35:31:35:31 | access to local variable s | GuardedString.cs:7:16:7:32 | SSA def(s) | GuardedString.cs:35:31:35:31 | access to local variable s | Variable $@ may be null at this access because of $@ assignment. | GuardedString.cs:7:16:7:16 | s | s | GuardedString.cs:7:16:7:32 | String s = ... | this |
|
||||
| NullMaybeBad.cs:7:27:7:27 | access to parameter o | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | Variable $@ may be null at this access because of $@ null argument. | NullMaybeBad.cs:5:25:5:25 | o | o | NullMaybeBad.cs:13:17:13:20 | null | this |
|
||||
| Params.cs:14:17:14:20 | access to parameter args | Params.cs:20:12:20:15 | null | Params.cs:14:17:14:20 | access to parameter args | Variable $@ may be null at this access because of $@ null argument. | Params.cs:12:36:12:39 | args | args | Params.cs:20:12:20:15 | null | this |
|
||||
| StringConcatenation.cs:16:17:16:17 | access to local variable s | StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:16:17:16:17 | access to local variable s | Variable $@ may be null at this access because of $@ assignment. | StringConcatenation.cs:14:16:14:16 | s | s | StringConcatenation.cs:14:16:14:23 | String s = ... | this |
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public class Params
|
||||
{
|
||||
public void M1(params string[] args)
|
||||
{
|
||||
var l = args.Length; // Good, true negative
|
||||
}
|
||||
|
||||
public void M2(params string[] args)
|
||||
{
|
||||
var l = args.Length; // Good
|
||||
}
|
||||
|
||||
public void M()
|
||||
{
|
||||
M1("a", "b", "c", null);
|
||||
M2(null);
|
||||
}
|
||||
}
|
|
@ -158,6 +158,14 @@ Dataflow Analysis
|
|||
|
||||
* The API for debugging flow using partial flow has changed slightly. Instead of using :code:`module Partial = FlowExploration<limit/0>` and choosing between :code:`Partial::partialFlow` and :code:`Partial::partialFlowRev`, you now choose between :code:`module Partial = FlowExplorationFwd<limit/0>` and :code:`module Partial = FlowExplorationRev<limit/0>`, and then always use :code:`Partial::partialFlow`.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Range Analysis
|
||||
""""""""""""""
|
||||
|
||||
* Initial release. Moves the range analysis library into its own qlpack.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -23,20 +23,19 @@ Bug Fixes
|
|||
~~~~~~~~~
|
||||
|
||||
* Fixed an internal error in the compiler when arguments to the :code:`codePointCount` string primitive were not bound.
|
||||
* Fixed a bug where :code:`codeql database finalize` would fail if a database under construction was moved between machines between
|
||||
:code:`codeql database init` and :code:`codeql database finalize`. This should now work, as long as both commands are run by the same *release* of the CodeQL CLI and the extractors used are the ones bundled with the CLI.
|
||||
* Fixed a bug where :code:`codeql database finalize` would fail if a database under construction was moved between machines between :code:`codeql database init` and :code:`codeql database finalize`.
|
||||
This should now work, as long as both commands are run by the same *release* of the CodeQL CLI and the extractors used are the ones bundled with the CLI.
|
||||
* Fixed a bug where :code:`codeql database run-queries` would fail in some circumstances when the database path included an :code:`@`.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* A new compilation flag (:code:`--fail-on-ambiguous-relation-name`) has been added to specify that compilation should fail if the compiler generates an ambiguous relation name.
|
||||
* :code:`codeql database analyze` now defaults to include markdown query help for all custom queries with help files available. To change the default behaviour you can pass the new flag :code:`--sarif-include-query-help`, which provides the options :code:`always` (which includes query help for all queries), :code:`custom_queries_only` (the default) and :code:`never` (which does not include query help for any query). The existing flag
|
||||
:code:`--sarif-add-query-help` has been deprecated and will be removed in a future release.
|
||||
* The new (advanced) command-line option :code:`--[no-]linkage-aware-import` disables the linkage-awareness phase of :code:`codeql dataset import`, as a quick fix (at the expense of database completeness) for C++ projects where this part of database creation consumes too much memory. This option is available in the commands :code:`database create`,
|
||||
:code:`database finalize`, :code:`database import`, :code:`dataset import`, :code:`test extract`, and
|
||||
:code:`test run`.
|
||||
* The CodeQL language server now provides basic support for Rename, and you can now use the Rename Symbol functionality in Visual Studio Code for CodeQL. The current Rename support is less a refactoring tool and more a labor-saving device. You may have to perform some manual edits after using Rename, but it should still be faster and less work than renaming a symbol manually.
|
||||
* :code:`codeql database analyze` now defaults to include markdown query help for all custom queries with help files available. To change the default behaviour you can pass the new flag :code:`--sarif-include-query-help`, which provides the options :code:`always` (which includes query help for all queries), :code:`custom_queries_only` (the default) and :code:`never` (which does not include query help for any query). The existing flag
|
||||
:code:`--sarif-add-query-help` has been deprecated and will be removed in a future release.
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
|
@ -84,7 +83,7 @@ Swift
|
|||
"""""
|
||||
|
||||
* Added new query "System command built from user-controlled sources" (:code:`swift/command-line-injection`) for Swift. This query detects system commands built from user-controlled sources without sufficient validation. The query was previously `contributed to the 'experimental' directory by @maikypedia <https://github.com/github/codeql/pull/13726>`__ but will now run by default for all code scanning users.
|
||||
* Added a nw query "Missing regular expression anchor" (:code:`swift/missing-regexp-anchor`) for Swift. This query detects regular expressions without anchors that can be vulnerable to bypassing.
|
||||
* Added a new query "Missing regular expression anchor" (:code:`swift/missing-regexp-anchor`) for Swift. This query detects regular expressions without anchors that can be vulnerable to bypassing.
|
||||
|
||||
Query Metadata Changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -92,8 +91,8 @@ Query Metadata Changes
|
|||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* Lower the severity of log-injection to medium.
|
||||
* Increase the severity of XSS to high.
|
||||
* Lower the security severity of log-injection to medium.
|
||||
* Increase the security severity of XSS to high.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
@ -192,7 +191,7 @@ C#
|
|||
Golang
|
||||
""""""
|
||||
|
||||
* Added the `gin cors <https://github.com/gin-contrib/cors>`__ library to the CorsMisconfiguration.ql query
|
||||
* Added the `gin-contrib/cors <https://github.com/gin-contrib/cors>`__ library to the experimental query "CORS misconfiguration" (:code:`go/cors-misconfiguration`).
|
||||
|
||||
Java
|
||||
""""
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
.. _codeql-cli-2.15.4:
|
||||
|
||||
==========================
|
||||
CodeQL 2.15.4 (2023-12-11)
|
||||
==========================
|
||||
|
||||
.. contents:: Contents
|
||||
:depth: 2
|
||||
:local:
|
||||
:backlinks: none
|
||||
|
||||
This is an overview of changes in the CodeQL CLI and relevant CodeQL query and library packs. For additional updates on changes to the CodeQL code scanning experience, check out the `code scanning section on the GitHub blog <https://github.blog/tag/code-scanning/>`__, `relevant GitHub Changelog updates <https://github.blog/changelog/label/code-scanning/>`__, `changes in the CodeQL extension for Visual Studio Code <https://marketplace.visualstudio.com/items/GitHub.vscode-codeql/changelog>`__, and the `CodeQL Action changelog <https://github.com/github/codeql-action/blob/main/CHANGELOG.md>`__.
|
||||
|
||||
CodeQL CLI
|
||||
----------
|
||||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Parallelism in the evaluator has been improved, resulting in faster analysis when running with many threads, particularly for large databases.
|
||||
|
||||
Query Packs
|
||||
-----------
|
||||
|
||||
Breaking Changes
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* The :code:`cpp/tainted-format-string-through-global` query has been deleted. This does not lead to a loss of relevant alerts, as the query duplicated a subset of the alerts from :code:`cpp/tainted-format-string`.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C#
|
||||
""
|
||||
|
||||
* Modelled additional flow steps to track flow from a :code:`View` call in an MVC controller to the corresponding Razor View (:code:`.cshtml`) file, which may result in additional results for queries such as :code:`cs/web/xss`.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* Added django URLs to detected "safe" URL patterns in :code:`js/unsafe-external-link`.
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* Added additional sinks for the "Uncontrolled format string" (:code:`swift/uncontrolled-format-string`) query. Some of these sinks are heuristic (imprecise) in nature.
|
||||
* Added heuristic (imprecise) sinks for the "Database query built from user-controlled sources" (:code:`swift/sql-injection`) query.
|
||||
|
||||
New Queries
|
||||
~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added a new query, :code:`cpp/use-of-string-after-lifetime-ends`, to detect calls to :code:`c_str` on strings that will be destroyed immediately.
|
||||
|
||||
Language Libraries
|
||||
------------------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
Golang
|
||||
""""""
|
||||
|
||||
* A bug has been fixed that meant that value flow through a slice expression was not tracked correctly. Taint flow was tracked correctly.
|
||||
|
||||
Minor Analysis Improvements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Java
|
||||
""""
|
||||
|
||||
* The diagnostic query :code:`java/diagnostics/successfully-extracted-files`, and therefore the Code Scanning UI measure of scanned Java files, now considers any Java file seen during extraction, even one with some errors, to be extracted / scanned.
|
||||
* Switch cases using binding patterns and :code:`case null[, default]` are now supported. Classes :code:`PatternCase` and :code:`NullDefaultCase` are introduced to represent new kinds of case statement.
|
||||
* Both switch cases and instanceof expressions using record patterns are now supported. The new class :code:`RecordPatternExpr` is introduced to represent record patterns, and :code:`InstanceOfExpr` gains :code:`getPattern` to replace :code:`getLocalVariableDeclExpr`.
|
||||
* The control-flow graph and therefore dominance information regarding switch blocks in statement context but with an expression rule (e.g. :code:`switch(...) { case 1 -> System.out.println("Hello world!") }`) has been fixed. This reduces false positives and negatives from various queries relating to functions featuring such statements.
|
||||
|
||||
JavaScript/TypeScript
|
||||
"""""""""""""""""""""
|
||||
|
||||
* Added models for the :code:`sqlite` and :code:`better-sqlite3` npm packages.
|
||||
* TypeScript 5.3 is now supported.
|
||||
|
||||
Python
|
||||
""""""
|
||||
|
||||
* Added support for tarfile extraction filters as defined in `PEP-706 <https://peps.python.org/pep-0706>`__. In particular, calls to :code:`TarFile.extract`, and :code:`TarFile.extractall` are no longer considered to be sinks for the :code:`py/tarslip` query if a sufficiently safe filter is provided.
|
||||
* Added modeling of :code:`*args` and :code:`**kwargs` as routed-parameters in request handlers for django/flask/FastAPI/tornado.
|
||||
* Added support for type parameters in function and class definitions, as well as the new Python 3.12 type alias statement.
|
||||
* Added taint-flow modeling for regular expressions with :code:`re` module from the standard library.
|
||||
|
||||
Ruby
|
||||
""""
|
||||
|
||||
* Improved modeling for :code:`ActiveRecord`\ s :code:`update_all` method
|
||||
|
||||
Swift
|
||||
"""""
|
||||
|
||||
* Extracts Swift's :code:`DiscardStmt` and :code:`MaterizliePackExpr`
|
||||
* Expanded and improved flow models for :code:`Set` and :code:`Sequence`.
|
||||
* Added imprecise flow sources matching initializers such as :code:`init(contentsOfFile:)`.
|
||||
* Extracts :code:`MacroDecl` and some related information
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
C/C++
|
||||
"""""
|
||||
|
||||
* Added an :code:`isPrototyped` predicate to :code:`Function` that holds when the function has a prototype.
|
|
@ -9,6 +9,7 @@ This is an overview of changes in the CodeQL CLI and relevant CodeQL query and l
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
codeql-cli-2.15.4
|
||||
codeql-cli-2.15.3
|
||||
codeql-cli-2.15.2
|
||||
codeql-cli-2.15.1
|
||||
|
|
|
@ -123,4 +123,20 @@ You could give the predicate a more descriptive name as follows:
|
|||
|
||||
.. code-block:: ql
|
||||
|
||||
predicate lessThanTen = isSmall/1;
|
||||
predicate lessThanTen = isSmall/1;
|
||||
|
||||
.. _weak_strong_aliases:
|
||||
|
||||
Strong and weak aliases
|
||||
=======================
|
||||
|
||||
Every alias definition is either **strong** or **weak**.
|
||||
An alias definition is **strong** if and only if it is a :ref:`type alias <type-aliases>` definition with
|
||||
:ref:`annotation <annotations>` ``final``.
|
||||
During :ref:`name resolution <name-resolution>`, ambiguity between aliases from **weak** alias definitions
|
||||
for the same module/type/predicate is allowed, but ambiguity between between aliases from distinct **strong**
|
||||
alias definitions is invalid QL.
|
||||
Likewise, for the purpose of applicative instantiation of :ref:`parameterised modules <parameterized-modules>`
|
||||
and `:ref:`parameterised module signatures <parameterized-module-signatures>`, aliases from **weak** alias
|
||||
definitions for instantiation arguments do not result in separate instantiations, but aliases from **strong**
|
||||
alias definitions for instantiation arguments do.
|
||||
|
|
|
@ -180,7 +180,8 @@ For example, in the previous two snippets, we relied on the predicate signature
|
|||
signature int transformer(int x);
|
||||
|
||||
The instantiation of parameterized modules is applicative.
|
||||
That is, if you instantiate a parameterized module twice with identical arguments, the resulting object is the same.
|
||||
That is, if you instantiate a parameterized module twice with equivalent arguments, the resulting object is the same.
|
||||
Arguments are considered equivalent in this context if they differ only by :ref:`weak aliasing <weak_strong_aliases>`.
|
||||
This is particularly relevant for type definitions inside parameterized modules as :ref:`classes <classes>`
|
||||
or via :ref:`newtype <algebraic-datatypes>`, because the duplication of such type definitions would result in
|
||||
incompatible types.
|
||||
|
|
|
@ -115,7 +115,7 @@ Environments may be combined as follows:
|
|||
- *Union*. This takes the union of the entry sets of the two environments.
|
||||
- *Overriding union*. This takes the union of two environments, but if there are entries for a key in the first map, then no additional entries for that key are included from the second map.
|
||||
|
||||
A *definite* environment has at most one entry for each key. Resolution is unique in a definite environment.
|
||||
A *definite* environment has only values that are *equal modulo weak aliasing* for each key.
|
||||
|
||||
Global environments
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -334,7 +334,7 @@ For a *completely uninstantiated* parameter, the *bottom-up instantiation-resolu
|
|||
|
||||
An entity is called *fully instantiated* if none of the *bottom-up instantiation-resolutions* of the parameters in the *relevant set of parameters* of the entity's *underlying completely uninstantiated* entity are parameters.
|
||||
|
||||
Two *instantiated modules* or two *instantiation-nested* entities are considered *equivalent* if they have the same *underlying completely uninstantiated* entity and each parameter in its *relevant set of parameters* has the same *bottom-up instantiation-resolution* relative to either *instantiated module*.
|
||||
Two *instantiated modules* or two *instantiation-nested* entities are considered *equivalent* if they have the same *underlying completely uninstantiated* entity and each parameter in its *relevant set of parameters* has *bottom-up instantiation-resolution*s relative both *instantiated module*s that are *equivalent modulo weak aliases*.
|
||||
|
||||
Module instantiation is applicative, meaning that *equivalent* *instantiated modules* and *equivalent* *instantiation-nested* entities are indistinguishable.
|
||||
|
||||
|
@ -1763,7 +1763,7 @@ The grammar given in this section is disambiguated first by precedence, and seco
|
|||
Aliases
|
||||
-------
|
||||
|
||||
Aliases define new names for existing QL entities.
|
||||
Aliases define new names for existing QL bindings.
|
||||
|
||||
::
|
||||
|
||||
|
@ -1772,7 +1772,19 @@ Aliases define new names for existing QL entities.
|
|||
| qldoc? annotations "module" modulename "=" moduleExpr ";"
|
||||
|
||||
|
||||
An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively.
|
||||
An alias introduces a binding from the new name to the binding referred to by the right-hand side in the current module's visible predicate, type, or module environment respectively.
|
||||
|
||||
An alias is called a *strong alias* if and only if it has the ``final`` annotation. Otherwise, it is called a *weak alias*.
|
||||
|
||||
Two bindings `A`, `B` are called *equal modulo weak aliasing* if and only if one of the following conditions are satisfied:
|
||||
|
||||
- `A` and `B` are the same binding or
|
||||
|
||||
- `A`` is introduced by a *weak alias* for `C`, where `B` and `C` are *equal modulo weak aliasing* (or vice versa) or
|
||||
|
||||
- `A` and `B` are introduced by the same strong alias and they are aliases for bindings that are *equal modulo weak aliasing*.
|
||||
|
||||
Note that the third condition is only relevant in :ref:`Parameterized modules`, where the binding introduced by the alias can depend on instantiation parameters.
|
||||
|
||||
Built-ins
|
||||
---------
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
.NET 5, .NET 6, .NET 7","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
|
||||
Go (aka Golang), "Go up to 1.21", "Go 1.11 or more recent", ``.go``
|
||||
Java,"Java 7 to 20 [5]_","javac (OpenJDK and Oracle JDK),
|
||||
Java,"Java 7 to 21 [5]_","javac (OpenJDK and Oracle JDK),
|
||||
|
||||
Eclipse compiler for Java (ECJ) [6]_",``.java``
|
||||
Kotlin [7]_,"Kotlin 1.5.0 to 1.9.20","kotlinc",``.kt``
|
||||
|
@ -33,7 +33,7 @@
|
|||
.. [2] Objective-C, Objective-C++, C++/CLI, and C++/CX are not supported.
|
||||
.. [3] Support for the clang-cl compiler is preliminary.
|
||||
.. [4] Support for the Arm Compiler (armcc) is preliminary.
|
||||
.. [5] Builds that execute on Java 7 to 20 can be analyzed. The analysis understands Java 20 standard language features.
|
||||
.. [5] Builds that execute on Java 7 to 21 can be analyzed. The analysis understands Java 21 standard language features.
|
||||
.. [6] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin.
|
||||
.. [7] Kotlin support is currently in beta.
|
||||
.. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.
|
||||
|
|
|
@ -588,18 +588,17 @@ However, joining the virtual dispatch relation with itself in this way is
|
|||
usually way too big to be feasible. Instead, the relation above should only be
|
||||
defined for those values of `call` for which the set of resulting dispatch
|
||||
targets might be reduced. To do this, define the set of `call`s that might for
|
||||
some reason benefit from a call context as the following predicate (the `c`
|
||||
column should be `call.getEnclosingCallable()`):
|
||||
some reason benefit from a call context as the following predicate:
|
||||
```ql
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c)
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call)
|
||||
```
|
||||
And then define `DataFlowCallable viableImplInCallContext(DataFlowCall call,
|
||||
DataFlowCall ctx)` as sketched above, but restricted to
|
||||
`mayBenefitFromCallContext(call, _)`.
|
||||
`mayBenefitFromCallContext(call)`.
|
||||
|
||||
The shared implementation will then compare counts of virtual dispatch targets
|
||||
using `viableCallable` and `viableImplInCallContext` for each `call` in
|
||||
`mayBenefitFromCallContext(call, _)` and track call contexts during flow
|
||||
`mayBenefitFromCallContext(call)` and track call contexts during flow
|
||||
calculation when differences in these counts show an improved precision in
|
||||
further calls.
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ Alert queries (`@kind problem` or `path-problem`) support two further properties
|
|||
* `medium`
|
||||
* `high`
|
||||
* `very-high`
|
||||
* `@problem.severity`–defines the level of severity of non-security alerts:
|
||||
* `@problem.severity`–defines the likelihood that an alert, either security-related or not, causes an actual problem such as incorrect program behavior:
|
||||
* `error`–an issue that is likely to cause incorrect program behavior, for example a crash or vulnerability.
|
||||
* `warning`–an issue that indicates a potential problem in the code, or makes the code fragile if another (unrelated) part of code is changed.
|
||||
* `recommendation`–an issue where the code behaves correctly, but it could be improved.
|
||||
|
|
|
@ -34,7 +34,7 @@ encoding/pem,,3,,3,
|
|||
encoding/xml,,23,,23,
|
||||
errors,,3,,3,
|
||||
expvar,,6,,6,
|
||||
fmt,,5,,5,
|
||||
fmt,,16,,16,
|
||||
github.com/astaxie/beego,,7,,7,
|
||||
github.com/astaxie/beego/context,,1,,1,
|
||||
github.com/astaxie/beego/utils,,13,,13,
|
||||
|
|
|
|
@ -15,7 +15,7 @@ Go framework & library support
|
|||
`Macaron <https://gopkg.in/macaron.v1>`_,``gopkg.in/macaron*``,,1,
|
||||
`Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",,20,
|
||||
`SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1,
|
||||
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",8,566,
|
||||
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",8,577,
|
||||
`beego <https://beego.me/>`_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",,42,
|
||||
`go-pg <https://pg.uptrace.dev/>`_,``github.com/go-pg/pg*``,,6,
|
||||
`golang.org/x/net <https://pkg.go.dev/golang.org/x/net>`_,``golang.org/x/net*``,,21,
|
||||
|
@ -25,5 +25,5 @@ Go framework & library support
|
|||
`protobuf <https://pkg.go.dev/google.golang.org/protobuf>`_,"``github.com/golang/protobuf*``, ``google.golang.org/protobuf*``",,16,
|
||||
`yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9,
|
||||
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,
|
||||
Totals,,8,826,
|
||||
Totals,,8,837,
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The class `Fmt::AppenderOrSprinter` of the `Fmt.qll` module has been deprecated. Use the new `Fmt::AppenderOrSprinterFunc` class instead. Its taint flow features have been migrated to models-as-data.
|
|
@ -8,3 +8,14 @@ extensions:
|
|||
- ["fmt", "ScanState", True, "Token", "", "", "Argument[-1]", "ReturnValue[0]", "taint", "manual"]
|
||||
- ["fmt", "State", True, "Write", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"]
|
||||
- ["fmt", "Stringer", True, "String", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Append", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Append", "", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Appendf", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Appendf", "", "", "Argument[1]", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Appendf", "", "", "Argument[2].ArrayElement", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Appendln", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Appendln", "", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Sprint", "", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Sprintf", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Sprintf", "", "", "Argument[1].ArrayElement", "ReturnValue", "taint", "manual"]
|
||||
- ["fmt", "", True, "Sprintln", "", "", "Argument[0].ArrayElement", "ReturnValue", "taint", "manual"]
|
||||
|
|
|
@ -104,18 +104,6 @@ DataFlowCallable viableCallable(DataFlowCall ma) {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
|
||||
|
||||
private int parameterPosition() {
|
||||
result = [-1 .. any(DataFlowCallable c).getType().getNumParameter()]
|
||||
}
|
||||
|
|
|
@ -7,8 +7,12 @@ import go
|
|||
// Some TaintTracking::FunctionModel subclasses remain because varargs functions don't work with Models-as-Data sumamries yet.
|
||||
/** Provides models of commonly used functions in the `fmt` package. */
|
||||
module Fmt {
|
||||
/** The `Sprint` or `Append` functions or one of their variants. */
|
||||
class AppenderOrSprinter extends TaintTracking::FunctionModel {
|
||||
/**
|
||||
* The `Sprint` or `Append` functions or one of their variants.
|
||||
*
|
||||
* DEPRECATED: Use AppenderOrSprinterFunc instead.
|
||||
*/
|
||||
deprecated class AppenderOrSprinter extends TaintTracking::FunctionModel {
|
||||
AppenderOrSprinter() { this.hasQualifiedName("fmt", ["Append", "Sprint"] + ["", "f", "ln"]) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
|
||||
|
@ -16,8 +20,15 @@ module Fmt {
|
|||
}
|
||||
}
|
||||
|
||||
/** The `Sprint` or `Append` functions or one of their variants. */
|
||||
class AppenderOrSprinterFunc extends Function {
|
||||
AppenderOrSprinterFunc() {
|
||||
this.hasQualifiedName("fmt", ["Append", "Sprint"] + ["", "f", "ln"])
|
||||
}
|
||||
}
|
||||
|
||||
/** The `Sprint` function or one of its variants. */
|
||||
class Sprinter extends AppenderOrSprinter {
|
||||
class Sprinter extends AppenderOrSprinterFunc {
|
||||
Sprinter() { this.getName().matches("Sprint%") }
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,21 @@ import go
|
|||
/** Provides models of commonly used functions in the `log` package. */
|
||||
module Log {
|
||||
private class LogFunction extends Function {
|
||||
int firstPrintedArg;
|
||||
|
||||
LogFunction() {
|
||||
exists(string fn | fn.matches(["Fatal%", "Panic%", "Print%"]) |
|
||||
exists(string fn |
|
||||
fn.matches(["Fatal%", "Panic%", "Print%"]) and firstPrintedArg = 0
|
||||
or
|
||||
fn = "Output" and firstPrintedArg = 1
|
||||
|
|
||||
this.hasQualifiedName("log", fn)
|
||||
or
|
||||
this.(Method).hasQualifiedName("log", "Logger", fn)
|
||||
)
|
||||
}
|
||||
|
||||
int getFirstPrintedArg() { result = firstPrintedArg }
|
||||
}
|
||||
|
||||
private class LogFormatter extends StringOps::Formatting::Range instanceof LogFunction {
|
||||
|
@ -23,9 +31,13 @@ module Log {
|
|||
}
|
||||
|
||||
private class LogCall extends LoggerCall::Range, DataFlow::CallNode {
|
||||
LogCall() { this = any(LogFunction f).getACall() }
|
||||
LogFunction target;
|
||||
|
||||
override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() }
|
||||
LogCall() { this = target.getACall() }
|
||||
|
||||
override DataFlow::Node getAMessageComponent() {
|
||||
result = this.getSyntacticArgument(any(int i | i >= target.getFirstPrintedArg()))
|
||||
}
|
||||
}
|
||||
|
||||
/** A fatal log function, which calls `os.Exit`. */
|
||||
|
|
|
@ -74,6 +74,8 @@ module CleartextLogging {
|
|||
)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
// A taint propagating data-flow edge through structs: a tainted write taints the entire struct.
|
||||
exists(Write write |
|
||||
|
|
|
@ -35,7 +35,7 @@ module HeuristicNames {
|
|||
*/
|
||||
string maybePassword() {
|
||||
result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or
|
||||
result = "(?is).*(auth(entication|ori[sz]ation)?|api)key.*"
|
||||
result = "(?is).*(auth(entication|ori[sz]ation)?|api|secret)key.*"
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -99,7 +99,7 @@ module PrivateUrlFlowsToAuthCodeUrlCallConfig implements DataFlow::ConfigSig {
|
|||
or
|
||||
// Propagate across Sprintf and similar calls
|
||||
exists(DataFlow::CallNode cn |
|
||||
cn.getACalleeIncludingExternals().asFunction() instanceof Fmt::AppenderOrSprinter
|
||||
cn.getACalleeIncludingExternals().asFunction() instanceof Fmt::AppenderOrSprinterFunc
|
||||
|
|
||||
pred = cn.getASyntacticArgument() and succ = cn.getResult()
|
||||
)
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added more sources and sinks to the query `go/clear-text-logging`.
|
|
@ -1,9 +1,12 @@
|
|||
edges
|
||||
| Dsn.go:47:10:47:30 | call to FormValue | Dsn.go:49:102:49:105 | name |
|
||||
| Dsn.go:49:11:49:106 | []type{args} [array] | Dsn.go:49:11:49:106 | call to Sprintf |
|
||||
| Dsn.go:49:11:49:106 | call to Sprintf | Dsn.go:50:29:50:33 | dbDSN |
|
||||
| Dsn.go:49:102:49:105 | name | Dsn.go:49:11:49:106 | []type{args} [array] |
|
||||
| Dsn.go:49:102:49:105 | name | Dsn.go:49:11:49:106 | call to Sprintf |
|
||||
nodes
|
||||
| Dsn.go:47:10:47:30 | call to FormValue | semmle.label | call to FormValue |
|
||||
| Dsn.go:49:11:49:106 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| Dsn.go:49:11:49:106 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| Dsn.go:49:102:49:105 | name | semmle.label | name |
|
||||
| Dsn.go:50:29:50:33 | dbDSN | semmle.label | dbDSN |
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
edges
|
||||
| Dsn.go:26:11:26:17 | selection of Args | Dsn.go:28:102:28:109 | index expression |
|
||||
| Dsn.go:28:11:28:110 | []type{args} [array] | Dsn.go:28:11:28:110 | call to Sprintf |
|
||||
| Dsn.go:28:11:28:110 | call to Sprintf | Dsn.go:29:29:29:33 | dbDSN |
|
||||
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | []type{args} [array] |
|
||||
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | call to Sprintf |
|
||||
| Dsn.go:62:2:62:4 | definition of cfg [pointer] | Dsn.go:63:9:63:11 | cfg [pointer] |
|
||||
| Dsn.go:62:2:62:4 | definition of cfg [pointer] | Dsn.go:67:102:67:104 | cfg [pointer] |
|
||||
|
@ -10,13 +12,16 @@ edges
|
|||
| Dsn.go:63:9:63:11 | implicit dereference | Dsn.go:67:102:67:108 | selection of dsn |
|
||||
| Dsn.go:63:19:63:25 | selection of Args | Dsn.go:63:19:63:29 | slice expression |
|
||||
| Dsn.go:63:19:63:29 | slice expression | Dsn.go:63:9:63:11 | implicit dereference |
|
||||
| Dsn.go:67:11:67:109 | []type{args} [array] | Dsn.go:67:11:67:109 | call to Sprintf |
|
||||
| Dsn.go:67:11:67:109 | call to Sprintf | Dsn.go:68:29:68:33 | dbDSN |
|
||||
| Dsn.go:67:102:67:104 | cfg [pointer] | Dsn.go:67:102:67:104 | implicit dereference |
|
||||
| Dsn.go:67:102:67:104 | implicit dereference | Dsn.go:63:9:63:11 | implicit dereference |
|
||||
| Dsn.go:67:102:67:104 | implicit dereference | Dsn.go:67:102:67:108 | selection of dsn |
|
||||
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | []type{args} [array] |
|
||||
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | call to Sprintf |
|
||||
nodes
|
||||
| Dsn.go:26:11:26:17 | selection of Args | semmle.label | selection of Args |
|
||||
| Dsn.go:28:11:28:110 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| Dsn.go:28:11:28:110 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| Dsn.go:28:102:28:109 | index expression | semmle.label | index expression |
|
||||
| Dsn.go:29:29:29:33 | dbDSN | semmle.label | dbDSN |
|
||||
|
@ -25,6 +30,7 @@ nodes
|
|||
| Dsn.go:63:9:63:11 | implicit dereference | semmle.label | implicit dereference |
|
||||
| Dsn.go:63:19:63:25 | selection of Args | semmle.label | selection of Args |
|
||||
| Dsn.go:63:19:63:29 | slice expression | semmle.label | slice expression |
|
||||
| Dsn.go:67:11:67:109 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| Dsn.go:67:11:67:109 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| Dsn.go:67:102:67:104 | cfg [pointer] | semmle.label | cfg [pointer] |
|
||||
| Dsn.go:67:102:67:104 | implicit dereference | semmle.label | implicit dereference |
|
||||
|
|
|
@ -7,8 +7,14 @@ edges
|
|||
| new-tests.go:26:26:26:30 | &... | new-tests.go:31:48:31:56 | selection of word |
|
||||
| new-tests.go:26:26:26:30 | &... | new-tests.go:32:48:32:56 | selection of safe |
|
||||
| new-tests.go:26:26:26:30 | &... | new-tests.go:35:49:35:57 | selection of word |
|
||||
| new-tests.go:31:11:31:57 | []type{args} [array] | new-tests.go:31:11:31:57 | call to Sprintf |
|
||||
| new-tests.go:31:48:31:56 | selection of word | new-tests.go:31:11:31:57 | []type{args} [array] |
|
||||
| new-tests.go:31:48:31:56 | selection of word | new-tests.go:31:11:31:57 | call to Sprintf |
|
||||
| new-tests.go:32:11:32:57 | []type{args} [array] | new-tests.go:32:11:32:57 | call to Sprintf |
|
||||
| new-tests.go:32:48:32:56 | selection of safe | new-tests.go:32:11:32:57 | []type{args} [array] |
|
||||
| new-tests.go:32:48:32:56 | selection of safe | new-tests.go:32:11:32:57 | call to Sprintf |
|
||||
| new-tests.go:35:12:35:58 | []type{args} [array] | new-tests.go:35:12:35:58 | call to Sprintf |
|
||||
| new-tests.go:35:49:35:57 | selection of word | new-tests.go:35:12:35:58 | []type{args} [array] |
|
||||
| new-tests.go:35:49:35:57 | selection of word | new-tests.go:35:12:35:58 | call to Sprintf |
|
||||
| new-tests.go:39:18:39:30 | call to Param | new-tests.go:47:11:47:46 | ...+... |
|
||||
| new-tests.go:49:18:49:30 | call to Query | new-tests.go:50:11:50:46 | ...+... |
|
||||
|
@ -18,8 +24,14 @@ edges
|
|||
| new-tests.go:63:26:63:30 | &... | new-tests.go:68:48:68:56 | selection of word |
|
||||
| new-tests.go:63:26:63:30 | &... | new-tests.go:69:48:69:56 | selection of safe |
|
||||
| new-tests.go:63:26:63:30 | &... | new-tests.go:74:49:74:57 | selection of word |
|
||||
| new-tests.go:68:11:68:57 | []type{args} [array] | new-tests.go:68:11:68:57 | call to Sprintf |
|
||||
| new-tests.go:68:48:68:56 | selection of word | new-tests.go:68:11:68:57 | []type{args} [array] |
|
||||
| new-tests.go:68:48:68:56 | selection of word | new-tests.go:68:11:68:57 | call to Sprintf |
|
||||
| new-tests.go:69:11:69:57 | []type{args} [array] | new-tests.go:69:11:69:57 | call to Sprintf |
|
||||
| new-tests.go:69:48:69:56 | selection of safe | new-tests.go:69:11:69:57 | []type{args} [array] |
|
||||
| new-tests.go:69:48:69:56 | selection of safe | new-tests.go:69:11:69:57 | call to Sprintf |
|
||||
| new-tests.go:74:12:74:58 | []type{args} [array] | new-tests.go:74:12:74:58 | call to Sprintf |
|
||||
| new-tests.go:74:49:74:57 | selection of word | new-tests.go:74:12:74:58 | []type{args} [array] |
|
||||
| new-tests.go:74:49:74:57 | selection of word | new-tests.go:74:12:74:58 | call to Sprintf |
|
||||
| new-tests.go:78:18:78:24 | selection of URL | new-tests.go:78:18:78:32 | call to Query |
|
||||
| new-tests.go:78:18:78:32 | call to Query | new-tests.go:78:18:78:46 | call to Get |
|
||||
|
@ -41,10 +53,13 @@ nodes
|
|||
| builtin.go:129:21:129:31 | call to Referer | semmle.label | call to Referer |
|
||||
| builtin.go:132:38:132:51 | untrustedInput | semmle.label | untrustedInput |
|
||||
| new-tests.go:26:26:26:30 | &... | semmle.label | &... |
|
||||
| new-tests.go:31:11:31:57 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| new-tests.go:31:11:31:57 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| new-tests.go:31:48:31:56 | selection of word | semmle.label | selection of word |
|
||||
| new-tests.go:32:11:32:57 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| new-tests.go:32:11:32:57 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| new-tests.go:32:48:32:56 | selection of safe | semmle.label | selection of safe |
|
||||
| new-tests.go:35:12:35:58 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| new-tests.go:35:12:35:58 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| new-tests.go:35:49:35:57 | selection of word | semmle.label | selection of word |
|
||||
| new-tests.go:39:18:39:30 | call to Param | semmle.label | call to Param |
|
||||
|
@ -55,10 +70,13 @@ nodes
|
|||
| new-tests.go:62:31:62:38 | selection of Body | semmle.label | selection of Body |
|
||||
| new-tests.go:63:17:63:23 | reqBody | semmle.label | reqBody |
|
||||
| new-tests.go:63:26:63:30 | &... | semmle.label | &... |
|
||||
| new-tests.go:68:11:68:57 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| new-tests.go:68:11:68:57 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| new-tests.go:68:48:68:56 | selection of word | semmle.label | selection of word |
|
||||
| new-tests.go:69:11:69:57 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| new-tests.go:69:11:69:57 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| new-tests.go:69:48:69:56 | selection of safe | semmle.label | selection of safe |
|
||||
| new-tests.go:74:12:74:58 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| new-tests.go:74:12:74:58 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| new-tests.go:74:49:74:57 | selection of word | semmle.label | selection of word |
|
||||
| new-tests.go:78:18:78:24 | selection of URL | semmle.label | selection of URL |
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
| file://:0:0:0:0 | [summary param] 0 in Append | file://:0:0:0:0 | [summary] to write: ReturnValue in Append |
|
||||
| file://:0:0:0:0 | [summary param] 0 in AppendQuote | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendQuote |
|
||||
| file://:0:0:0:0 | [summary param] 0 in AppendQuoteToASCII | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendQuoteToASCII |
|
||||
| file://:0:0:0:0 | [summary param] 0 in AppendQuoteToGraphic | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendQuoteToGraphic |
|
||||
| file://:0:0:0:0 | [summary param] 0 in AppendSlice | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendSlice |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Appendf | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendf |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Appendln | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendln |
|
||||
| file://:0:0:0:0 | [summary param] 0 in As | file://:0:0:0:0 | [summary] to write: Argument[1] in As |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Base | file://:0:0:0:0 | [summary] to write: ReturnValue in Base |
|
||||
| file://:0:0:0:0 | [summary param] 0 in BytePtrFromString | file://:0:0:0:0 | [summary] to write: ReturnValue in BytePtrFromString |
|
||||
|
@ -67,6 +70,7 @@
|
|||
| file://:0:0:0:0 | [summary param] 0 in SplitAfter | file://:0:0:0:0 | [summary] to write: ReturnValue in SplitAfter |
|
||||
| file://:0:0:0:0 | [summary param] 0 in SplitAfterN | file://:0:0:0:0 | [summary] to write: ReturnValue in SplitAfterN |
|
||||
| file://:0:0:0:0 | [summary param] 0 in SplitN | file://:0:0:0:0 | [summary] to write: ReturnValue in SplitN |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Sprintf | file://:0:0:0:0 | [summary] to write: ReturnValue in Sprintf |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: Argument[-1] in Store |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: Argument[-1] in Store |
|
||||
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: Argument[-1] in Store |
|
||||
|
@ -133,6 +137,7 @@
|
|||
| file://:0:0:0:0 | [summary param] 1 in AppendQuoteToASCII | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendQuoteToASCII |
|
||||
| file://:0:0:0:0 | [summary param] 1 in AppendQuoteToGraphic | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendQuoteToGraphic |
|
||||
| file://:0:0:0:0 | [summary param] 1 in AppendSlice | file://:0:0:0:0 | [summary] to write: ReturnValue in AppendSlice |
|
||||
| file://:0:0:0:0 | [summary param] 1 in Appendf | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendf |
|
||||
| file://:0:0:0:0 | [summary param] 1 in Copy | file://:0:0:0:0 | [summary] to write: Argument[0] in Copy |
|
||||
| file://:0:0:0:0 | [summary param] 1 in Copy | file://:0:0:0:0 | [summary] to write: Argument[0] in Copy |
|
||||
| file://:0:0:0:0 | [summary param] 1 in CopyBuffer | file://:0:0:0:0 | [summary] to write: Argument[0] in CopyBuffer |
|
||||
|
@ -287,6 +292,12 @@
|
|||
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: Argument[0] in WriteTo |
|
||||
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: Argument[0] in WriteTo |
|
||||
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: Argument[0] in WriteTo |
|
||||
| file://:0:0:0:0 | [summary] read: Argument[0].ArrayElement in Sprint | file://:0:0:0:0 | [summary] to write: ReturnValue in Sprint |
|
||||
| file://:0:0:0:0 | [summary] read: Argument[0].ArrayElement in Sprintln | file://:0:0:0:0 | [summary] to write: ReturnValue in Sprintln |
|
||||
| file://:0:0:0:0 | [summary] read: Argument[1].ArrayElement in Append | file://:0:0:0:0 | [summary] to write: ReturnValue in Append |
|
||||
| file://:0:0:0:0 | [summary] read: Argument[1].ArrayElement in Appendln | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendln |
|
||||
| file://:0:0:0:0 | [summary] read: Argument[1].ArrayElement in Sprintf | file://:0:0:0:0 | [summary] to write: ReturnValue in Sprintf |
|
||||
| file://:0:0:0:0 | [summary] read: Argument[2].ArrayElement in Appendf | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendf |
|
||||
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[0] |
|
||||
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[1] |
|
||||
| main.go:38:13:38:13 | 1 | main.go:38:7:38:20 | slice literal |
|
||||
|
|
|
@ -318,9 +318,14 @@
|
|||
| errors.As | file://:0:0:0:0 | [summary param] 0 in As | file://:0:0:0:0 | [summary] to write: Argument[1] in As |
|
||||
| errors.New | file://:0:0:0:0 | [summary param] 0 in New | file://:0:0:0:0 | [summary] to write: ReturnValue in New |
|
||||
| errors.Unwrap | file://:0:0:0:0 | [summary param] 0 in Unwrap | file://:0:0:0:0 | [summary] to write: ReturnValue in Unwrap |
|
||||
| fmt.Append | file://:0:0:0:0 | [summary param] 0 in Append | file://:0:0:0:0 | [summary] to write: ReturnValue in Append |
|
||||
| fmt.Appendf | file://:0:0:0:0 | [summary param] 0 in Appendf | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendf |
|
||||
| fmt.Appendf | file://:0:0:0:0 | [summary param] 1 in Appendf | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendf |
|
||||
| fmt.Appendln | file://:0:0:0:0 | [summary param] 0 in Appendln | file://:0:0:0:0 | [summary] to write: ReturnValue in Appendln |
|
||||
| fmt.GoStringer.GoString | file://:0:0:0:0 | [summary param] -1 in GoString | file://:0:0:0:0 | [summary] to write: ReturnValue in GoString |
|
||||
| fmt.ScanState.Read | file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: Argument[0] in Read |
|
||||
| fmt.ScanState.Token | file://:0:0:0:0 | [summary param] -1 in Token | file://:0:0:0:0 | [summary] to write: ReturnValue in Token |
|
||||
| fmt.Sprintf | file://:0:0:0:0 | [summary param] 0 in Sprintf | file://:0:0:0:0 | [summary] to write: ReturnValue in Sprintf |
|
||||
| fmt.State.Write | file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: Argument[-1] in Write |
|
||||
| fmt.Stringer.String | file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: ReturnValue in String |
|
||||
| fmt.pp.Write | file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: Argument[-1] in Write |
|
||||
|
|
|
@ -13,9 +13,13 @@ edges
|
|||
| reflectedxsstest.go:31:2:31:44 | ... := ...[1] | reflectedxsstest.go:34:46:34:60 | selection of Filename |
|
||||
| reflectedxsstest.go:32:2:32:38 | ... := ...[0] | reflectedxsstest.go:33:49:33:55 | content |
|
||||
| reflectedxsstest.go:32:34:32:37 | file | reflectedxsstest.go:32:2:32:38 | ... := ...[0] |
|
||||
| reflectedxsstest.go:33:17:33:56 | []type{args} [array] | reflectedxsstest.go:33:17:33:56 | call to Sprintf |
|
||||
| reflectedxsstest.go:33:17:33:56 | call to Sprintf | reflectedxsstest.go:33:10:33:57 | type conversion |
|
||||
| reflectedxsstest.go:33:49:33:55 | content | reflectedxsstest.go:33:17:33:56 | []type{args} [array] |
|
||||
| reflectedxsstest.go:33:49:33:55 | content | reflectedxsstest.go:33:17:33:56 | call to Sprintf |
|
||||
| reflectedxsstest.go:34:17:34:61 | []type{args} [array] | reflectedxsstest.go:34:17:34:61 | call to Sprintf |
|
||||
| reflectedxsstest.go:34:17:34:61 | call to Sprintf | reflectedxsstest.go:34:10:34:62 | type conversion |
|
||||
| reflectedxsstest.go:34:46:34:60 | selection of Filename | reflectedxsstest.go:34:17:34:61 | []type{args} [array] |
|
||||
| reflectedxsstest.go:34:46:34:60 | selection of Filename | reflectedxsstest.go:34:17:34:61 | call to Sprintf |
|
||||
| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | reflectedxsstest.go:39:16:39:21 | reader |
|
||||
| reflectedxsstest.go:39:2:39:32 | ... := ...[0] | reflectedxsstest.go:40:14:40:17 | part |
|
||||
|
@ -25,7 +29,9 @@ edges
|
|||
| reflectedxsstest.go:40:14:40:28 | call to FileName | reflectedxsstest.go:44:46:44:53 | partName |
|
||||
| reflectedxsstest.go:41:2:41:10 | definition of byteSlice | reflectedxsstest.go:45:10:45:18 | byteSlice |
|
||||
| reflectedxsstest.go:42:2:42:5 | part | reflectedxsstest.go:41:2:41:10 | definition of byteSlice |
|
||||
| reflectedxsstest.go:44:17:44:54 | []type{args} [array] | reflectedxsstest.go:44:17:44:54 | call to Sprintf |
|
||||
| reflectedxsstest.go:44:17:44:54 | call to Sprintf | reflectedxsstest.go:44:10:44:55 | type conversion |
|
||||
| reflectedxsstest.go:44:46:44:53 | partName | reflectedxsstest.go:44:17:44:54 | []type{args} [array] |
|
||||
| reflectedxsstest.go:44:46:44:53 | partName | reflectedxsstest.go:44:17:44:54 | call to Sprintf |
|
||||
| reflectedxsstest.go:51:14:51:18 | selection of URL | reflectedxsstest.go:51:14:51:26 | call to Query |
|
||||
| reflectedxsstest.go:51:14:51:26 | call to Query | reflectedxsstest.go:54:11:54:21 | type conversion |
|
||||
|
@ -64,9 +70,11 @@ nodes
|
|||
| reflectedxsstest.go:32:2:32:38 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| reflectedxsstest.go:32:34:32:37 | file | semmle.label | file |
|
||||
| reflectedxsstest.go:33:10:33:57 | type conversion | semmle.label | type conversion |
|
||||
| reflectedxsstest.go:33:17:33:56 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| reflectedxsstest.go:33:17:33:56 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| reflectedxsstest.go:33:49:33:55 | content | semmle.label | content |
|
||||
| reflectedxsstest.go:34:10:34:62 | type conversion | semmle.label | type conversion |
|
||||
| reflectedxsstest.go:34:17:34:61 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| reflectedxsstest.go:34:17:34:61 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| reflectedxsstest.go:34:46:34:60 | selection of Filename | semmle.label | selection of Filename |
|
||||
| reflectedxsstest.go:38:2:38:35 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
|
@ -77,6 +85,7 @@ nodes
|
|||
| reflectedxsstest.go:41:2:41:10 | definition of byteSlice | semmle.label | definition of byteSlice |
|
||||
| reflectedxsstest.go:42:2:42:5 | part | semmle.label | part |
|
||||
| reflectedxsstest.go:44:10:44:55 | type conversion | semmle.label | type conversion |
|
||||
| reflectedxsstest.go:44:17:44:54 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| reflectedxsstest.go:44:17:44:54 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| reflectedxsstest.go:44:46:44:53 | partName | semmle.label | partName |
|
||||
| reflectedxsstest.go:45:10:45:18 | byteSlice | semmle.label | byteSlice |
|
||||
|
|
|
@ -1,40 +1,54 @@
|
|||
edges
|
||||
| SqlInjection.go:10:7:11:30 | []type{args} [array] | SqlInjection.go:10:7:11:30 | call to Sprintf |
|
||||
| SqlInjection.go:10:7:11:30 | call to Sprintf | SqlInjection.go:12:11:12:11 | q |
|
||||
| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query |
|
||||
| SqlInjection.go:11:3:11:17 | call to Query | SqlInjection.go:11:3:11:29 | index expression |
|
||||
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | []type{args} [array] |
|
||||
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | call to Sprintf |
|
||||
| issue48.go:17:2:17:33 | ... := ...[0] | issue48.go:18:17:18:17 | b |
|
||||
| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] |
|
||||
| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... |
|
||||
| issue48.go:18:20:18:39 | &... | issue48.go:21:3:21:33 | index expression |
|
||||
| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf |
|
||||
| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 |
|
||||
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | []type{args} [array] |
|
||||
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | call to Sprintf |
|
||||
| issue48.go:27:2:27:34 | ... := ...[0] | issue48.go:28:17:28:18 | b2 |
|
||||
| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] |
|
||||
| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... |
|
||||
| issue48.go:28:21:28:41 | &... | issue48.go:31:3:31:31 | selection of Category |
|
||||
| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf |
|
||||
| issue48.go:30:8:31:32 | call to Sprintf | issue48.go:32:11:32:12 | q4 |
|
||||
| issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | []type{args} [array] |
|
||||
| issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | call to Sprintf |
|
||||
| issue48.go:37:17:37:50 | type conversion | issue48.go:37:53:37:73 | &... |
|
||||
| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query |
|
||||
| issue48.go:37:24:37:38 | call to Query | issue48.go:37:17:37:50 | type conversion |
|
||||
| issue48.go:37:53:37:73 | &... | issue48.go:40:3:40:31 | selection of Category |
|
||||
| issue48.go:39:8:40:32 | []type{args} [array] | issue48.go:39:8:40:32 | call to Sprintf |
|
||||
| issue48.go:39:8:40:32 | call to Sprintf | issue48.go:41:11:41:12 | q5 |
|
||||
| issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | []type{args} [array] |
|
||||
| issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | call to Sprintf |
|
||||
| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression |
|
||||
| main.go:15:11:15:84 | []type{args} [array] | main.go:15:11:15:84 | call to Sprintf |
|
||||
| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query |
|
||||
| main.go:15:63:15:75 | call to Query | main.go:15:63:15:83 | index expression |
|
||||
| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | []type{args} [array] |
|
||||
| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | call to Sprintf |
|
||||
| main.go:16:11:16:85 | []type{args} [array] | main.go:16:11:16:85 | call to Sprintf |
|
||||
| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get |
|
||||
| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | []type{args} [array] |
|
||||
| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | call to Sprintf |
|
||||
| main.go:28:17:31:2 | &... [pointer, Category] | main.go:34:3:34:13 | RequestData [pointer, Category] |
|
||||
| main.go:28:18:31:2 | struct literal [Category] | main.go:28:17:31:2 | &... [pointer, Category] |
|
||||
| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query |
|
||||
| main.go:30:13:30:27 | call to Query | main.go:30:13:30:39 | index expression |
|
||||
| main.go:30:13:30:39 | index expression | main.go:28:18:31:2 | struct literal [Category] |
|
||||
| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf |
|
||||
| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q |
|
||||
| main.go:34:3:34:13 | RequestData [pointer, Category] | main.go:34:3:34:13 | implicit dereference [Category] |
|
||||
| main.go:34:3:34:13 | implicit dereference [Category] | main.go:34:3:34:22 | selection of Category |
|
||||
| main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | []type{args} [array] |
|
||||
| main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | call to Sprintf |
|
||||
| main.go:39:2:39:12 | definition of RequestData [pointer, Category] | main.go:40:2:40:12 | RequestData [pointer, Category] |
|
||||
| main.go:39:2:39:12 | definition of RequestData [pointer, Category] | main.go:43:3:43:13 | RequestData [pointer, Category] |
|
||||
|
@ -43,9 +57,11 @@ edges
|
|||
| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query |
|
||||
| main.go:40:25:40:39 | call to Query | main.go:40:25:40:51 | index expression |
|
||||
| main.go:40:25:40:51 | index expression | main.go:40:2:40:12 | implicit dereference [Category] |
|
||||
| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf |
|
||||
| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q |
|
||||
| main.go:43:3:43:13 | RequestData [pointer, Category] | main.go:43:3:43:13 | implicit dereference [Category] |
|
||||
| main.go:43:3:43:13 | implicit dereference [Category] | main.go:43:3:43:22 | selection of Category |
|
||||
| main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | []type{args} [array] |
|
||||
| main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | call to Sprintf |
|
||||
| main.go:48:2:48:12 | definition of RequestData [pointer, Category] | main.go:49:4:49:14 | RequestData [pointer, Category] |
|
||||
| main.go:48:2:48:12 | definition of RequestData [pointer, Category] | main.go:52:3:52:13 | RequestData [pointer, Category] |
|
||||
|
@ -54,9 +70,11 @@ edges
|
|||
| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query |
|
||||
| main.go:49:28:49:42 | call to Query | main.go:49:28:49:54 | index expression |
|
||||
| main.go:49:28:49:54 | index expression | main.go:49:3:49:14 | star expression [Category] |
|
||||
| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf |
|
||||
| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q |
|
||||
| main.go:52:3:52:13 | RequestData [pointer, Category] | main.go:52:3:52:13 | implicit dereference [Category] |
|
||||
| main.go:52:3:52:13 | implicit dereference [Category] | main.go:52:3:52:22 | selection of Category |
|
||||
| main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | []type{args} [array] |
|
||||
| main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | call to Sprintf |
|
||||
| main.go:57:2:57:12 | definition of RequestData [pointer, Category] | main.go:58:4:58:14 | RequestData [pointer, Category] |
|
||||
| main.go:57:2:57:12 | definition of RequestData [pointer, Category] | main.go:61:5:61:15 | RequestData [pointer, Category] |
|
||||
|
@ -65,7 +83,9 @@ edges
|
|||
| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query |
|
||||
| main.go:58:28:58:42 | call to Query | main.go:58:28:58:54 | index expression |
|
||||
| main.go:58:28:58:54 | index expression | main.go:58:3:58:14 | star expression [Category] |
|
||||
| main.go:60:7:61:26 | []type{args} [array] | main.go:60:7:61:26 | call to Sprintf |
|
||||
| main.go:60:7:61:26 | call to Sprintf | main.go:62:11:62:11 | q |
|
||||
| main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | []type{args} [array] |
|
||||
| main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | call to Sprintf |
|
||||
| main.go:61:4:61:15 | star expression [Category] | main.go:61:3:61:25 | selection of Category |
|
||||
| main.go:61:5:61:15 | RequestData [pointer, Category] | main.go:61:4:61:15 | star expression [Category] |
|
||||
|
@ -88,6 +108,7 @@ edges
|
|||
| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:81:18:81:25 | pipeline |
|
||||
| mongoDB.go:50:34:50:39 | filter | mongoDB.go:50:23:50:40 | struct literal |
|
||||
nodes
|
||||
| SqlInjection.go:10:7:11:30 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| SqlInjection.go:10:7:11:30 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| SqlInjection.go:11:3:11:9 | selection of URL | semmle.label | selection of URL |
|
||||
| SqlInjection.go:11:3:11:17 | call to Query | semmle.label | call to Query |
|
||||
|
@ -97,6 +118,7 @@ nodes
|
|||
| issue48.go:17:25:17:32 | selection of Body | semmle.label | selection of Body |
|
||||
| issue48.go:18:17:18:17 | b | semmle.label | b |
|
||||
| issue48.go:18:20:18:39 | &... | semmle.label | &... |
|
||||
| issue48.go:20:8:21:34 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| issue48.go:20:8:21:34 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| issue48.go:21:3:21:33 | index expression | semmle.label | index expression |
|
||||
| issue48.go:22:11:22:12 | q3 | semmle.label | q3 |
|
||||
|
@ -104,6 +126,7 @@ nodes
|
|||
| issue48.go:27:26:27:33 | selection of Body | semmle.label | selection of Body |
|
||||
| issue48.go:28:17:28:18 | b2 | semmle.label | b2 |
|
||||
| issue48.go:28:21:28:41 | &... | semmle.label | &... |
|
||||
| issue48.go:30:8:31:32 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| issue48.go:30:8:31:32 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| issue48.go:31:3:31:31 | selection of Category | semmle.label | selection of Category |
|
||||
| issue48.go:32:11:32:12 | q4 | semmle.label | q4 |
|
||||
|
@ -111,15 +134,18 @@ nodes
|
|||
| issue48.go:37:24:37:30 | selection of URL | semmle.label | selection of URL |
|
||||
| issue48.go:37:24:37:38 | call to Query | semmle.label | call to Query |
|
||||
| issue48.go:37:53:37:73 | &... | semmle.label | &... |
|
||||
| issue48.go:39:8:40:32 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| issue48.go:39:8:40:32 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| issue48.go:40:3:40:31 | selection of Category | semmle.label | selection of Category |
|
||||
| issue48.go:41:11:41:12 | q5 | semmle.label | q5 |
|
||||
| main.go:11:11:11:16 | selection of Form | semmle.label | selection of Form |
|
||||
| main.go:11:11:11:28 | index expression | semmle.label | index expression |
|
||||
| main.go:15:11:15:84 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| main.go:15:11:15:84 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| main.go:15:63:15:67 | selection of URL | semmle.label | selection of URL |
|
||||
| main.go:15:63:15:75 | call to Query | semmle.label | call to Query |
|
||||
| main.go:15:63:15:83 | index expression | semmle.label | index expression |
|
||||
| main.go:16:11:16:85 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| main.go:16:11:16:85 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| main.go:16:63:16:70 | selection of Header | semmle.label | selection of Header |
|
||||
| main.go:16:63:16:84 | call to Get | semmle.label | call to Get |
|
||||
|
@ -128,6 +154,7 @@ nodes
|
|||
| main.go:30:13:30:19 | selection of URL | semmle.label | selection of URL |
|
||||
| main.go:30:13:30:27 | call to Query | semmle.label | call to Query |
|
||||
| main.go:30:13:30:39 | index expression | semmle.label | index expression |
|
||||
| main.go:33:7:34:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| main.go:33:7:34:23 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| main.go:34:3:34:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
||||
| main.go:34:3:34:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] |
|
||||
|
@ -139,6 +166,7 @@ nodes
|
|||
| main.go:40:25:40:31 | selection of URL | semmle.label | selection of URL |
|
||||
| main.go:40:25:40:39 | call to Query | semmle.label | call to Query |
|
||||
| main.go:40:25:40:51 | index expression | semmle.label | index expression |
|
||||
| main.go:42:7:43:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| main.go:42:7:43:23 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| main.go:43:3:43:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
||||
| main.go:43:3:43:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] |
|
||||
|
@ -150,6 +178,7 @@ nodes
|
|||
| main.go:49:28:49:34 | selection of URL | semmle.label | selection of URL |
|
||||
| main.go:49:28:49:42 | call to Query | semmle.label | call to Query |
|
||||
| main.go:49:28:49:54 | index expression | semmle.label | index expression |
|
||||
| main.go:51:7:52:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| main.go:51:7:52:23 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| main.go:52:3:52:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
||||
| main.go:52:3:52:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] |
|
||||
|
@ -161,6 +190,7 @@ nodes
|
|||
| main.go:58:28:58:34 | selection of URL | semmle.label | selection of URL |
|
||||
| main.go:58:28:58:42 | call to Query | semmle.label | call to Query |
|
||||
| main.go:58:28:58:54 | index expression | semmle.label | index expression |
|
||||
| main.go:60:7:61:26 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| main.go:60:7:61:26 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| main.go:61:3:61:25 | selection of Category | semmle.label | selection of Category |
|
||||
| main.go:61:4:61:15 | star expression [Category] | semmle.label | star expression [Category] |
|
||||
|
|
|
@ -6,8 +6,6 @@ edges
|
|||
| klog.go:21:11:21:16 | definition of header | klog.go:22:15:22:20 | header |
|
||||
| klog.go:21:27:21:33 | headers | klog.go:21:4:24:4 | range statement[1] |
|
||||
| klog.go:28:13:28:20 | selection of Header | klog.go:28:13:28:41 | call to Get |
|
||||
| main.go:20:2:20:7 | definition of fields | main.go:22:29:22:34 | fields |
|
||||
| main.go:21:19:21:26 | password | main.go:20:2:20:7 | definition of fields |
|
||||
| overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String |
|
||||
| passwords.go:8:12:8:12 | definition of x | passwords.go:9:14:9:14 | x |
|
||||
| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | definition of x |
|
||||
|
@ -53,7 +51,6 @@ edges
|
|||
| protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] |
|
||||
| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description |
|
||||
| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] |
|
||||
| util.go:16:9:16:18 | selection of password | passwords.go:28:14:28:28 | call to getPassword |
|
||||
nodes
|
||||
| klog.go:20:3:25:3 | range statement[1] | semmle.label | range statement[1] |
|
||||
| klog.go:20:13:20:19 | definition of headers | semmle.label | definition of headers |
|
||||
|
@ -64,13 +61,35 @@ nodes
|
|||
| klog.go:22:15:22:20 | header | semmle.label | header |
|
||||
| klog.go:28:13:28:20 | selection of Header | semmle.label | selection of Header |
|
||||
| klog.go:28:13:28:41 | call to Get | semmle.label | call to Get |
|
||||
| main.go:15:14:15:21 | password | semmle.label | password |
|
||||
| main.go:17:12:17:19 | password | semmle.label | password |
|
||||
| main.go:18:17:18:24 | password | semmle.label | password |
|
||||
| main.go:20:2:20:7 | definition of fields | semmle.label | definition of fields |
|
||||
| main.go:21:19:21:26 | password | semmle.label | password |
|
||||
| main.go:22:29:22:34 | fields | semmle.label | fields |
|
||||
| main.go:25:35:25:42 | password | semmle.label | password |
|
||||
| main.go:15:12:15:19 | password | semmle.label | password |
|
||||
| main.go:16:17:16:24 | password | semmle.label | password |
|
||||
| main.go:17:13:17:20 | password | semmle.label | password |
|
||||
| main.go:18:14:18:21 | password | semmle.label | password |
|
||||
| main.go:19:12:19:19 | password | semmle.label | password |
|
||||
| main.go:20:17:20:24 | password | semmle.label | password |
|
||||
| main.go:21:13:21:20 | password | semmle.label | password |
|
||||
| main.go:22:14:22:21 | password | semmle.label | password |
|
||||
| main.go:23:12:23:19 | password | semmle.label | password |
|
||||
| main.go:24:17:24:24 | password | semmle.label | password |
|
||||
| main.go:25:13:25:20 | password | semmle.label | password |
|
||||
| main.go:26:14:26:21 | password | semmle.label | password |
|
||||
| main.go:27:16:27:23 | password | semmle.label | password |
|
||||
| main.go:30:10:30:17 | password | semmle.label | password |
|
||||
| main.go:31:15:31:22 | password | semmle.label | password |
|
||||
| main.go:32:11:32:18 | password | semmle.label | password |
|
||||
| main.go:33:12:33:19 | password | semmle.label | password |
|
||||
| main.go:34:10:34:17 | password | semmle.label | password |
|
||||
| main.go:35:15:35:22 | password | semmle.label | password |
|
||||
| main.go:36:11:36:18 | password | semmle.label | password |
|
||||
| main.go:37:12:37:19 | password | semmle.label | password |
|
||||
| main.go:38:10:38:17 | password | semmle.label | password |
|
||||
| main.go:39:15:39:22 | password | semmle.label | password |
|
||||
| main.go:40:11:40:18 | password | semmle.label | password |
|
||||
| main.go:41:12:41:19 | password | semmle.label | password |
|
||||
| main.go:42:14:42:21 | password | semmle.label | password |
|
||||
| main.go:44:12:44:19 | password | semmle.label | password |
|
||||
| main.go:45:17:45:24 | password | semmle.label | password |
|
||||
| main.go:52:35:52:42 | password | semmle.label | password |
|
||||
| overrides.go:9:9:9:16 | password | semmle.label | password |
|
||||
| overrides.go:13:14:13:23 | call to String | semmle.label | call to String |
|
||||
| passwords.go:8:12:8:12 | definition of x | semmle.label | definition of x |
|
||||
|
@ -135,24 +154,46 @@ nodes
|
|||
| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | semmle.label | implicit dereference [Description] |
|
||||
| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | semmle.label | x [pointer, Description] |
|
||||
| protos/query/query.pb.go:119:10:119:22 | selection of Description | semmle.label | selection of Description |
|
||||
| util.go:16:9:16:18 | selection of password | semmle.label | selection of password |
|
||||
subpaths
|
||||
| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | definition of x [pointer, Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | protobuf.go:14:14:14:35 | call to GetDescription |
|
||||
#select
|
||||
| klog.go:22:15:22:20 | header | klog.go:20:30:20:37 | selection of Header | klog.go:22:15:22:20 | header | $@ flows to a logging call. | klog.go:20:30:20:37 | selection of Header | Sensitive data returned by HTTP request headers |
|
||||
| klog.go:28:13:28:41 | call to Get | klog.go:28:13:28:20 | selection of Header | klog.go:28:13:28:41 | call to Get | $@ flows to a logging call. | klog.go:28:13:28:20 | selection of Header | Sensitive data returned by HTTP request headers |
|
||||
| main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | main.go:15:14:15:21 | password | $@ flows to a logging call. | main.go:15:14:15:21 | password | Sensitive data returned by an access to password |
|
||||
| main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | main.go:17:12:17:19 | password | $@ flows to a logging call. | main.go:17:12:17:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | main.go:18:17:18:24 | password | $@ flows to a logging call. | main.go:18:17:18:24 | password | Sensitive data returned by an access to password |
|
||||
| main.go:22:29:22:34 | fields | main.go:21:19:21:26 | password | main.go:22:29:22:34 | fields | $@ flows to a logging call. | main.go:21:19:21:26 | password | Sensitive data returned by an access to password |
|
||||
| main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | main.go:25:35:25:42 | password | $@ flows to a logging call. | main.go:25:35:25:42 | password | Sensitive data returned by an access to password |
|
||||
| main.go:15:12:15:19 | password | main.go:15:12:15:19 | password | main.go:15:12:15:19 | password | $@ flows to a logging call. | main.go:15:12:15:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:16:17:16:24 | password | main.go:16:17:16:24 | password | main.go:16:17:16:24 | password | $@ flows to a logging call. | main.go:16:17:16:24 | password | Sensitive data returned by an access to password |
|
||||
| main.go:17:13:17:20 | password | main.go:17:13:17:20 | password | main.go:17:13:17:20 | password | $@ flows to a logging call. | main.go:17:13:17:20 | password | Sensitive data returned by an access to password |
|
||||
| main.go:18:14:18:21 | password | main.go:18:14:18:21 | password | main.go:18:14:18:21 | password | $@ flows to a logging call. | main.go:18:14:18:21 | password | Sensitive data returned by an access to password |
|
||||
| main.go:19:12:19:19 | password | main.go:19:12:19:19 | password | main.go:19:12:19:19 | password | $@ flows to a logging call. | main.go:19:12:19:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:20:17:20:24 | password | main.go:20:17:20:24 | password | main.go:20:17:20:24 | password | $@ flows to a logging call. | main.go:20:17:20:24 | password | Sensitive data returned by an access to password |
|
||||
| main.go:21:13:21:20 | password | main.go:21:13:21:20 | password | main.go:21:13:21:20 | password | $@ flows to a logging call. | main.go:21:13:21:20 | password | Sensitive data returned by an access to password |
|
||||
| main.go:22:14:22:21 | password | main.go:22:14:22:21 | password | main.go:22:14:22:21 | password | $@ flows to a logging call. | main.go:22:14:22:21 | password | Sensitive data returned by an access to password |
|
||||
| main.go:23:12:23:19 | password | main.go:23:12:23:19 | password | main.go:23:12:23:19 | password | $@ flows to a logging call. | main.go:23:12:23:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:24:17:24:24 | password | main.go:24:17:24:24 | password | main.go:24:17:24:24 | password | $@ flows to a logging call. | main.go:24:17:24:24 | password | Sensitive data returned by an access to password |
|
||||
| main.go:25:13:25:20 | password | main.go:25:13:25:20 | password | main.go:25:13:25:20 | password | $@ flows to a logging call. | main.go:25:13:25:20 | password | Sensitive data returned by an access to password |
|
||||
| main.go:26:14:26:21 | password | main.go:26:14:26:21 | password | main.go:26:14:26:21 | password | $@ flows to a logging call. | main.go:26:14:26:21 | password | Sensitive data returned by an access to password |
|
||||
| main.go:27:16:27:23 | password | main.go:27:16:27:23 | password | main.go:27:16:27:23 | password | $@ flows to a logging call. | main.go:27:16:27:23 | password | Sensitive data returned by an access to password |
|
||||
| main.go:30:10:30:17 | password | main.go:30:10:30:17 | password | main.go:30:10:30:17 | password | $@ flows to a logging call. | main.go:30:10:30:17 | password | Sensitive data returned by an access to password |
|
||||
| main.go:31:15:31:22 | password | main.go:31:15:31:22 | password | main.go:31:15:31:22 | password | $@ flows to a logging call. | main.go:31:15:31:22 | password | Sensitive data returned by an access to password |
|
||||
| main.go:32:11:32:18 | password | main.go:32:11:32:18 | password | main.go:32:11:32:18 | password | $@ flows to a logging call. | main.go:32:11:32:18 | password | Sensitive data returned by an access to password |
|
||||
| main.go:33:12:33:19 | password | main.go:33:12:33:19 | password | main.go:33:12:33:19 | password | $@ flows to a logging call. | main.go:33:12:33:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:34:10:34:17 | password | main.go:34:10:34:17 | password | main.go:34:10:34:17 | password | $@ flows to a logging call. | main.go:34:10:34:17 | password | Sensitive data returned by an access to password |
|
||||
| main.go:35:15:35:22 | password | main.go:35:15:35:22 | password | main.go:35:15:35:22 | password | $@ flows to a logging call. | main.go:35:15:35:22 | password | Sensitive data returned by an access to password |
|
||||
| main.go:36:11:36:18 | password | main.go:36:11:36:18 | password | main.go:36:11:36:18 | password | $@ flows to a logging call. | main.go:36:11:36:18 | password | Sensitive data returned by an access to password |
|
||||
| main.go:37:12:37:19 | password | main.go:37:12:37:19 | password | main.go:37:12:37:19 | password | $@ flows to a logging call. | main.go:37:12:37:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:38:10:38:17 | password | main.go:38:10:38:17 | password | main.go:38:10:38:17 | password | $@ flows to a logging call. | main.go:38:10:38:17 | password | Sensitive data returned by an access to password |
|
||||
| main.go:39:15:39:22 | password | main.go:39:15:39:22 | password | main.go:39:15:39:22 | password | $@ flows to a logging call. | main.go:39:15:39:22 | password | Sensitive data returned by an access to password |
|
||||
| main.go:40:11:40:18 | password | main.go:40:11:40:18 | password | main.go:40:11:40:18 | password | $@ flows to a logging call. | main.go:40:11:40:18 | password | Sensitive data returned by an access to password |
|
||||
| main.go:41:12:41:19 | password | main.go:41:12:41:19 | password | main.go:41:12:41:19 | password | $@ flows to a logging call. | main.go:41:12:41:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:42:14:42:21 | password | main.go:42:14:42:21 | password | main.go:42:14:42:21 | password | $@ flows to a logging call. | main.go:42:14:42:21 | password | Sensitive data returned by an access to password |
|
||||
| main.go:44:12:44:19 | password | main.go:44:12:44:19 | password | main.go:44:12:44:19 | password | $@ flows to a logging call. | main.go:44:12:44:19 | password | Sensitive data returned by an access to password |
|
||||
| main.go:45:17:45:24 | password | main.go:45:17:45:24 | password | main.go:45:17:45:24 | password | $@ flows to a logging call. | main.go:45:17:45:24 | password | Sensitive data returned by an access to password |
|
||||
| main.go:52:35:52:42 | password | main.go:52:35:52:42 | password | main.go:52:35:52:42 | password | $@ flows to a logging call. | main.go:52:35:52:42 | password | Sensitive data returned by an access to password |
|
||||
| overrides.go:13:14:13:23 | call to String | overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | $@ flows to a logging call. | overrides.go:9:9:9:16 | password | Sensitive data returned by an access to password |
|
||||
| passwords.go:9:14:9:14 | x | passwords.go:30:8:30:15 | password | passwords.go:9:14:9:14 | x | $@ flows to a logging call. | passwords.go:30:8:30:15 | password | Sensitive data returned by an access to password |
|
||||
| passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | passwords.go:25:14:25:21 | password | $@ flows to a logging call. | passwords.go:25:14:25:21 | password | Sensitive data returned by an access to password |
|
||||
| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||
| passwords.go:28:14:28:28 | call to getPassword | util.go:16:9:16:18 | selection of password | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | util.go:16:9:16:18 | selection of password | Sensitive data returned by an access to password |
|
||||
| passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | passwords.go:32:12:32:19 | password | $@ flows to a logging call. | passwords.go:32:12:32:19 | password | Sensitive data returned by an access to password |
|
||||
| passwords.go:34:14:34:35 | ...+... | passwords.go:34:28:34:35 | password | passwords.go:34:14:34:35 | ...+... | $@ flows to a logging call. | passwords.go:34:28:34:35 | password | Sensitive data returned by an access to password |
|
||||
| passwords.go:39:14:39:17 | obj1 | passwords.go:37:13:37:13 | x | passwords.go:39:14:39:17 | obj1 | $@ flows to a logging call. | passwords.go:37:13:37:13 | x | Sensitive data returned by an access to password |
|
||||
|
|
|
@ -12,7 +12,34 @@ import (
|
|||
func main() {
|
||||
password := "P4ssw0rd"
|
||||
|
||||
log.Print(password)
|
||||
log.Printf("", password)
|
||||
log.Printf(password, "")
|
||||
log.Println(password)
|
||||
log.Fatal(password)
|
||||
log.Fatalf("", password)
|
||||
log.Fatalf(password, "")
|
||||
log.Fatalln(password)
|
||||
log.Panic(password)
|
||||
log.Panicf("", password)
|
||||
log.Panicf(password, "")
|
||||
log.Panicln(password)
|
||||
log.Output(0, password)
|
||||
|
||||
l := log.Default()
|
||||
l.Print(password)
|
||||
l.Printf("", password)
|
||||
l.Printf(password, "")
|
||||
l.Println(password)
|
||||
l.Fatal(password)
|
||||
l.Fatalf("", password)
|
||||
l.Fatalf(password, "")
|
||||
l.Fatalln(password)
|
||||
l.Panic(password)
|
||||
l.Panicf("", password)
|
||||
l.Panicf(password, "")
|
||||
l.Panicln(password)
|
||||
l.Output(0, password)
|
||||
|
||||
glog.Info(password)
|
||||
logrus.Warning(password)
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
edges
|
||||
| sample.go:15:10:15:64 | call to Sum256 | sample.go:16:9:16:15 | slice expression |
|
||||
| sample.go:15:24:15:63 | type conversion | sample.go:15:10:15:64 | call to Sum256 |
|
||||
| sample.go:15:31:15:62 | []type{args} [array] | sample.go:15:31:15:62 | call to Sprintf |
|
||||
| sample.go:15:31:15:62 | call to Sprintf | sample.go:15:24:15:63 | type conversion |
|
||||
| sample.go:15:49:15:61 | call to Uint32 | sample.go:15:31:15:62 | []type{args} [array] |
|
||||
| sample.go:15:49:15:61 | call to Uint32 | sample.go:15:31:15:62 | call to Sprintf |
|
||||
| sample.go:16:9:16:15 | slice expression | sample.go:26:25:26:30 | call to Guid |
|
||||
| sample.go:33:2:33:6 | definition of nonce | sample.go:37:25:37:29 | nonce |
|
||||
|
@ -12,6 +14,7 @@ nodes
|
|||
| InsecureRandomness.go:12:18:12:40 | call to Intn | semmle.label | call to Intn |
|
||||
| sample.go:15:10:15:64 | call to Sum256 | semmle.label | call to Sum256 |
|
||||
| sample.go:15:24:15:63 | type conversion | semmle.label | type conversion |
|
||||
| sample.go:15:31:15:62 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||
| sample.go:15:31:15:62 | call to Sprintf | semmle.label | call to Sprintf |
|
||||
| sample.go:15:49:15:61 | call to Uint32 | semmle.label | call to Uint32 |
|
||||
| sample.go:16:9:16:15 | slice expression | semmle.label | slice expression |
|
||||
|
|
|
@ -1,251 +1,253 @@
|
|||
package,sink,source,summary,sink:bean-validation,sink:command-injection,sink:credentials-key,sink:credentials-password,sink:credentials-username,sink:encryption-iv,sink:encryption-salt,sink:file-content-store,sink:fragment-injection,sink:groovy-injection,sink:hostname-verification,sink:html-injection,sink:information-leak,sink:intent-redirection,sink:jexl-injection,sink:jndi-injection,sink:js-injection,sink:ldap-injection,sink:log-injection,sink:mvel-injection,sink:ognl-injection,sink:path-injection,sink:pending-intents,sink:regex-use,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:request-forgery,sink:response-splitting,sink:sql-injection,sink:template-injection,sink:trust-boundary-violation,sink:url-redirection,sink:xpath-injection,sink:xslt-injection,source:android-external-storage-dir,source:contentprovider,source:database,source:environment,source:file,source:remote,summary:taint,summary:value
|
||||
actions.osgi,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
android.app,35,,103,,,,,,,,,11,,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,18,85
|
||||
android.content,24,31,154,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,8,,,,,,4,27,,,,,63,91
|
||||
android.database,59,,41,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,41,
|
||||
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15
|
||||
android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,41,81
|
||||
android.support.v4.app,11,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
android.util,6,16,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,16,,
|
||||
android.webkit,3,2,,,,,,,,,,,,,2,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,
|
||||
android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,
|
||||
androidx.core.app,6,,95,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,12,83
|
||||
androidx.fragment.app,11,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
androidx.slice,2,5,88,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,5,,,,,27,61
|
||||
antlr,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
ch.ethz.ssh2,2,,,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.alibaba.druid.sql,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,1,
|
||||
com.alibaba.fastjson2,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.amazonaws.auth,2,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.auth0.jwt.algorithms,6,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.azure.identity,3,,,,,1,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.databind,2,,6,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
com.google.common.base,4,,87,,,,,,,,,,,,,,,,,,,,,,,,,,3,1,,,,,,,,,,,,,,,,,,63,24
|
||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17
|
||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551
|
||||
com.google.common.flogger,29,,,,,,,,,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.google.common.io,10,,73,,,,,,,,1,,,,,,,,,,,,,,9,,,,,,,,,,,,,,,,,,,,,,,72,1
|
||||
com.google.gson,,,44,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30,14
|
||||
com.hubspot.jinjava,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
com.jcraft.jsch,5,,1,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,1,
|
||||
com.microsoft.sqlserver.jdbc,4,,,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.mitchellbosecke.pebble,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
com.mongodb,10,,,,,,4,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.opensymphony.xwork2,56,,961,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,867,94
|
||||
com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7,
|
||||
com.sshtools.j2ssh.authentication,3,,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.crypto.provider,19,,,,,17,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.jndi.ldap,4,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.net.httpserver,3,,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.net.ssl,3,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.rowset,3,,,,,,2,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.security.auth.module,2,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.security.ntlm,5,,,,,,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.security.sasl.digest,3,,,,,,2,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.thoughtworks.xstream,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.trilead.ssh2,13,,,,,2,4,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.unboundid.ldap.sdk,17,,,,,,,,,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.zaxxer.hikari,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,
|
||||
freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,
|
||||
groovy.lang,26,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.text,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.util,5,,,,,,,,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
hudson,71,9,2648,,4,,,,,,3,,,,4,,,,,,,,,,54,,,,,,,,,6,,,,,,,,,,,,5,4,2572,76
|
||||
io.jsonwebtoken,,2,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,4,
|
||||
io.netty.bootstrap,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,
|
||||
io.netty.buffer,,,207,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,130,77
|
||||
io.netty.channel,9,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,,2,,
|
||||
io.netty.handler.codec,4,13,259,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,3,,,,,,,,,,,,,13,143,116
|
||||
io.netty.handler.ssl,4,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
io.netty.handler.stream,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
io.netty.resolver,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
io.netty.util,2,,23,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,21,2
|
||||
jakarta.activation,2,,2,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,2,
|
||||
jakarta.faces.context,2,7,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,
|
||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
jakarta.persistence,2,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,1,
|
||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55
|
||||
jakarta.xml.bind.attachment,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,
|
||||
java.awt,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3
|
||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
java.io,50,1,46,,,,,,,,22,,,,,,,,,,,,,,28,,,,,,,,,,,,,,,,,,,,,1,,44,2
|
||||
java.lang,32,3,94,,13,,,,,,,,,,,,,,,,,8,,,6,,,4,,,1,,,,,,,,,,,,,,3,,,57,37
|
||||
java.net,16,3,23,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,,3,23,
|
||||
java.nio,49,,36,,,,,,,,5,,,,,,,,,,,,,,43,,,,,,,,,1,,,,,,,,,,,,,,36,
|
||||
java.security,21,,,,,11,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
java.sql,15,1,2,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,4,,9,,,,,,,,1,,,,2,
|
||||
java.util,47,2,519,,,,,,,,1,,,,,,,,,,,34,,,2,,,,5,2,,1,2,,,,,,,,,,,,2,,,45,474
|
||||
javafx.scene.web,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
javax.activation,2,,7,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,7,
|
||||
javax.crypto,19,,4,,,12,3,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,
|
||||
javax.faces.context,2,7,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,
|
||||
javax.imageio.stream,1,,1,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57,
|
||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
javax.management,2,,1,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
javax.naming,7,,1,,,,,,,,,,,,,,,,6,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
javax.net.ssl,4,,,,,,2,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.portlet,,,61,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,
|
||||
javax.print.attribute.standard,2,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.script,1,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.security.auth.callback,1,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.security.auth.kerberos,6,,,,,4,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.servlet,7,21,2,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,3,,,2,,,,,,,,,21,2,
|
||||
javax.sql,7,,,,,,4,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,
|
||||
javax.ws.rs.client,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
javax.ws.rs.core,3,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,2,,,,,,,,,94,55
|
||||
javax.xml.bind.attachment,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,
|
||||
javax.xml.transform,2,,6,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,1,,,,,,,6,
|
||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,
|
||||
jenkins,,,523,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,500,23
|
||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
kotlin,16,,1849,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,2,,,,,,,,,,,,,,1836,13
|
||||
liquibase.database.jvm,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
liquibase.statement.core,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
net.schmizz.sshj,4,,,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
net.sf.json,2,,338,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,321,17
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,,,
|
||||
ognl,6,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
okhttp3,4,,50,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,23,27
|
||||
org.acegisecurity,,,49,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,49,
|
||||
org.antlr.runtime,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.compress.archivers.tar,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,
|
||||
org.apache.commons.exec,6,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.httpclient.util,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.commons.io,117,,562,,,,,,,,4,,,,,,,,,,,,,,98,,,,,,,,,15,,,,,,,,,,,,,,548,14
|
||||
org.apache.commons.jelly,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl2,15,,,,,,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl3,15,,,,,,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.lang,,,767,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,596,171
|
||||
org.apache.commons.lang3,6,,425,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,294,131
|
||||
org.apache.commons.logging,6,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.net,13,12,,,,,2,2,,,,,,,,,,,,,,,,,3,,,,,,,,,6,,,,,,,,,,,,,12,,
|
||||
org.apache.commons.ognl,6,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52
|
||||
org.apache.cxf.catalog,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.common.classloader,3,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.common.jaxb,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.common.logging,6,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.configuration.jsse,2,,,,,,,,,,,,,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.helpers,10,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,,,,,,,,,,5,,,,,,,,,
|
||||
org.apache.cxf.resource,9,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,5,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.staxutils,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.tools.corba.utils,4,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.tools.util,10,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.transform,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,
|
||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hadoop.fs,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,
|
||||
org.apache.hadoop.hive.metastore,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,
|
||||
org.apache.hadoop.hive.ql.exec,1,,1,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hadoop.hive.ql.metadata,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.async.methods,84,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,84,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.classic.methods,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.fluent,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.benchmark,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,73,2,45,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,72,,,,,,,,,,,,,2,45,
|
||||
org.apache.hc.core5.net,,,18,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.hive.hcatalog.templeton,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
org.apache.http,48,3,95,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,46,,,,,,,,,,,,,3,86,9
|
||||
org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,57,
|
||||
org.apache.ibatis.mapping,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.log4j,11,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.logging.log4j,359,,8,,,,,,,,,,,,,,,,,,,359,,,,,,,,,,,,,,,,,,,,,,,,,,4,4
|
||||
org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.shiro.jndi,1,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.shiro.mgt,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.sshd.client.session,3,,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.struts.beanvalidation.validation.interceptor,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,
|
||||
org.apache.struts2,14,,3873,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,3,,,,,,,,,,3839,34
|
||||
org.apache.tools.ant,12,,,,1,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.tools.zip,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.velocity.app,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,
|
||||
org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,
|
||||
org.codehaus.cargo.container.installer,3,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.codehaus.groovy.control,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,,,
|
||||
org.eclipse.jetty.client,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.fusesource.leveldbjni,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.geogebra.web.full.main,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,
|
||||
org.gradle.api.file,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,
|
||||
org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,,
|
||||
org.influxdb,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.jboss.logging,324,,,,,,,,,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.jdbi.v3.core,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.jenkins.ui.icon,,,49,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48,1
|
||||
org.jenkins.ui.symbol,,,33,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,8
|
||||
org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38
|
||||
org.keycloak.models.map.storage,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
org.kohsuke.stapler,20,24,363,,,,,,,,,,,,2,,,,,,,,,,9,,,,,,,,,4,,,,,5,,,,,,,,24,352,11
|
||||
org.mvel2,16,,,,,,,,,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.openjdk.jmh.runner.options,1,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.owasp.esapi,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.scijava.log,13,,,,,,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.slf4j,55,,6,,,,,,,,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,2,4
|
||||
org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30
|
||||
org.springframework.boot.jdbc,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.core.io,3,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
org.springframework.http,14,,77,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,67,10
|
||||
org.springframework.jdbc.core,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,
|
||||
org.springframework.jdbc.datasource,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,
|
||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,,
|
||||
org.springframework.jndi,1,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.ldap,47,,,,,,,,,,,,,,,,,,33,,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.core.userdetails,2,,,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,3,,142,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,90,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,13,
|
||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
org.springframework.web.util,,9,157,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,132,25
|
||||
org.thymeleaf,2,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,2,
|
||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
org.yaml.snakeyaml,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
play.libs.ws,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
play.mvc,1,13,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,13,24,
|
||||
ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48
|
||||
ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
retrofit2,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,1,
|
||||
sun.jvmstat.perfdata.monitor.protocol.local,3,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.jvmstat.perfdata.monitor.protocol.rmi,1,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.misc,3,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.net.ftp,5,,,,,,2,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.net.www.protocol.http,3,,,,,,2,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.acl,1,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.jgss.krb5,2,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.krb5,9,,,,,3,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.pkcs,4,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.pkcs11,3,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.provider,2,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.ssl,3,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.x509,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.tools.jconsole,28,,,,,,13,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
package,sink,source,summary,sink:bean-validation,sink:command-injection,sink:credentials-key,sink:credentials-password,sink:credentials-username,sink:encryption-iv,sink:encryption-salt,sink:environment-injection,sink:file-content-store,sink:fragment-injection,sink:groovy-injection,sink:hostname-verification,sink:html-injection,sink:information-leak,sink:intent-redirection,sink:jexl-injection,sink:jndi-injection,sink:js-injection,sink:ldap-injection,sink:log-injection,sink:mvel-injection,sink:ognl-injection,sink:path-injection,sink:pending-intents,sink:regex-use,sink:regex-use[-1],sink:regex-use[0],sink:regex-use[],sink:regex-use[f-1],sink:regex-use[f1],sink:regex-use[f],sink:request-forgery,sink:response-splitting,sink:sql-injection,sink:template-injection,sink:trust-boundary-violation,sink:url-redirection,sink:xpath-injection,sink:xslt-injection,source:android-external-storage-dir,source:contentprovider,source:database,source:environment,source:file,source:remote,summary:taint,summary:value
|
||||
actions.osgi,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
android.app,35,,103,,,,,,,,,,11,,,,,7,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,18,85
|
||||
android.content,24,31,154,,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,8,,,,,,4,27,,,,,63,91
|
||||
android.database,59,,41,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,59,,,,,,,,,,,,41,
|
||||
android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,45,15
|
||||
android.os,,2,122,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,41,81
|
||||
android.support.v4.app,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
android.util,6,16,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,16,,
|
||||
android.webkit,3,2,,,,,,,,,,,,,,2,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,
|
||||
android.widget,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,
|
||||
androidx.core.app,6,,95,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,12,83
|
||||
androidx.fragment.app,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
androidx.slice,2,5,88,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,5,,,,,27,61
|
||||
antlr,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
ch.ethz.ssh2,2,,,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.alibaba.druid.sql,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,1,
|
||||
com.alibaba.fastjson2,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.amazonaws.auth,2,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.auth0.jwt.algorithms,6,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.azure.identity,3,,,,,1,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
com.fasterxml.jackson.databind,2,,6,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
com.google.common.base,4,,87,,,,,,,,,,,,,,,,,,,,,,,,,,,3,1,,,,,,,,,,,,,,,,,,63,24
|
||||
com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17
|
||||
com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,551
|
||||
com.google.common.flogger,29,,,,,,,,,,,,,,,,,,,,,,29,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.google.common.io,10,,73,,,,,,,,,1,,,,,,,,,,,,,,9,,,,,,,,,,,,,,,,,,,,,,,72,1
|
||||
com.google.gson,,,52,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,38,14
|
||||
com.hubspot.jinjava,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
com.jcraft.jsch,5,,1,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,1,
|
||||
com.microsoft.sqlserver.jdbc,4,,,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.mitchellbosecke.pebble,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,
|
||||
com.mongodb,10,,,,,,4,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.opensymphony.xwork2,56,,961,,,,,,,,,,,,,,,,,,,,,,56,,,,,,,,,,,,,,,,,,,,,,,,867,94
|
||||
com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7,
|
||||
com.sshtools.j2ssh.authentication,3,,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.crypto.provider,19,,,,,17,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.jndi.ldap,4,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.net.httpserver,3,,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.net.ssl,3,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.rowset,3,,,,,,2,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.security.auth.module,2,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.security.ntlm,5,,,,,,3,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.sun.security.sasl.digest,3,,,,,,2,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.thoughtworks.xstream,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.trilead.ssh2,13,,,,,2,4,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.unboundid.ldap.sdk,17,,,,,,,,,,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
com.zaxxer.hikari,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,
|
||||
freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,
|
||||
groovy.lang,26,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.text,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
groovy.util,5,,,,,,,,,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
hudson,74,9,2648,,4,,,,,,3,3,,,,4,,,,,,,,,,54,,,,,,,,,6,,,,,,,,,,,,5,4,2572,76
|
||||
io.jsonwebtoken,,2,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,4,
|
||||
io.netty.bootstrap,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,
|
||||
io.netty.buffer,,,207,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,130,77
|
||||
io.netty.channel,9,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,,2,,
|
||||
io.netty.handler.codec,4,13,259,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,3,,,,,,,,,,,,,13,143,116
|
||||
io.netty.handler.ssl,4,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
io.netty.handler.stream,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
io.netty.resolver,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
io.netty.util,2,,23,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,21,2
|
||||
jakarta.activation,2,,2,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,2,
|
||||
jakarta.faces.context,2,7,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,
|
||||
jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
jakarta.persistence,2,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,1,
|
||||
jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55
|
||||
jakarta.xml.bind.attachment,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,
|
||||
java.awt,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3
|
||||
java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
java.io,50,1,46,,,,,,,,,22,,,,,,,,,,,,,,28,,,,,,,,,,,,,,,,,,,,,1,,44,2
|
||||
java.lang,33,3,94,,13,,,,,,1,,,,,,,,,,,,8,,,6,,,4,,,1,,,,,,,,,,,,,,3,,,57,37
|
||||
java.net,16,3,23,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,,3,23,
|
||||
java.nio,49,,36,,,,,,,,,5,,,,,,,,,,,,,,43,,,,,,,,,1,,,,,,,,,,,,,,36,
|
||||
java.security,21,,,,,11,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
java.sql,15,1,2,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,9,,,,,,,,1,,,,2,
|
||||
java.util,47,2,519,,,,,,,,,1,,,,,,,,,,,34,,,2,,,,5,2,,1,2,,,,,,,,,,,,2,,,45,474
|
||||
javafx.scene.web,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
javax.activation,2,,7,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,,,,,7,
|
||||
javax.crypto,19,,4,,,12,3,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,
|
||||
javax.faces.context,2,7,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,
|
||||
javax.imageio.stream,1,,1,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57,
|
||||
javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23
|
||||
javax.management,2,,1,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
javax.naming,7,,1,,,,,,,,,,,,,,,,,6,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
javax.net.ssl,4,,,,,,2,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.portlet,,,61,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,61,
|
||||
javax.print.attribute.standard,2,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.script,1,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.security.auth.callback,1,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.security.auth.kerberos,6,,,,,4,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.servlet,7,21,2,,,,,,,,,,,,,,1,,,,,,,,,1,,,,,,,,,,3,,,2,,,,,,,,,21,2,
|
||||
javax.sql,7,,,,,,4,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,
|
||||
javax.ws.rs.client,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,
|
||||
javax.ws.rs.core,3,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,2,,,,,,,,,94,55
|
||||
javax.xml.bind.attachment,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,
|
||||
javax.xml.transform,2,,6,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,1,,,,,,,6,
|
||||
javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,
|
||||
jenkins,,,523,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,500,23
|
||||
jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
kotlin,16,,1849,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,2,,,,,,,,,,,,,,1836,13
|
||||
liquibase.database.jvm,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
liquibase.statement.core,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
net.schmizz.sshj,4,,,,,,2,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
net.sf.json,2,,338,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,321,17
|
||||
net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,,,
|
||||
ognl,6,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
okhttp3,4,,50,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,23,27
|
||||
org.acegisecurity,,,49,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,49,
|
||||
org.antlr.runtime,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,
|
||||
org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783
|
||||
org.apache.commons.compress.archivers.tar,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,
|
||||
org.apache.commons.exec,10,,,,6,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.httpclient.util,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.commons.io,117,,562,,,,,,,,,4,,,,,,,,,,,,,,98,,,,,,,,,15,,,,,,,,,,,,,,548,14
|
||||
org.apache.commons.jelly,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl2,15,,,,,,,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.jexl3,15,,,,,,,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.lang,,,767,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,596,171
|
||||
org.apache.commons.lang3,6,,425,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,294,131
|
||||
org.apache.commons.logging,6,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.net,13,12,,,,,2,2,,,,,,,,,,,,,,,,,,3,,,,,,,,,6,,,,,,,,,,,,,12,,
|
||||
org.apache.commons.ognl,6,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,220,52
|
||||
org.apache.cxf.catalog,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.common.classloader,3,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.common.jaxb,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.common.logging,6,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.configuration.jsse,2,,,,,,,,,,,,,,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.helpers,10,,,,,,,,,,,,,,,,,,,,,,,,,5,,,,,,,,,,,,,,,5,,,,,,,,,
|
||||
org.apache.cxf.resource,9,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,5,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.staxutils,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.tools.corba.utils,4,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.tools.util,10,,,,,,,,,,,,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.cxf.transform,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,
|
||||
org.apache.directory.ldap.client.api,1,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hadoop.fs,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,
|
||||
org.apache.hadoop.hive.metastore,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,
|
||||
org.apache.hadoop.hive.ql.exec,1,,1,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hadoop.hive.ql.metadata,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.async.methods,84,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,84,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.classic.methods,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,
|
||||
org.apache.hc.client5.http.fluent,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.benchmark,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.hc.core5.http,73,2,45,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,72,,,,,,,,,,,,,2,45,
|
||||
org.apache.hc.core5.net,,,18,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,
|
||||
org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6
|
||||
org.apache.hive.hcatalog.templeton,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
org.apache.http,48,3,95,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,46,,,,,,,,,,,,,3,86,9
|
||||
org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,57,
|
||||
org.apache.ibatis.mapping,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.log4j,11,,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.logging.log4j,359,,8,,,,,,,,,,,,,,,,,,,,359,,,,,,,,,,,,,,,,,,,,,,,,,,4,4
|
||||
org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.shiro.jndi,1,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.shiro.mgt,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.sshd.client.session,3,,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.struts.beanvalidation.validation.interceptor,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,
|
||||
org.apache.struts2,14,,3873,,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,3,,,,,,,,,,3839,34
|
||||
org.apache.tools.ant,12,,,,1,,,,,,,,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.apache.tools.zip,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.apache.velocity.app,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,
|
||||
org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,
|
||||
org.codehaus.cargo.container.installer,3,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.codehaus.groovy.control,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,,,
|
||||
org.eclipse.jetty.client,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.fusesource.leveldbjni,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.geogebra.web.full.main,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,
|
||||
org.gradle.api.file,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,
|
||||
org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,,
|
||||
org.influxdb,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.jboss.logging,324,,,,,,,,,,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.jdbi.v3.core,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,
|
||||
org.jenkins.ui.icon,,,49,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48,1
|
||||
org.jenkins.ui.symbol,,,33,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,25,8
|
||||
org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38
|
||||
org.keycloak.models.map.storage,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
|
||||
org.kohsuke.stapler,20,24,363,,,,,,,,,,,,,2,,,,,,,,,,9,,,,,,,,,4,,,,,5,,,,,,,,24,352,11
|
||||
org.mvel2,16,,,,,,,,,,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.openjdk.jmh.runner.options,1,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.owasp.esapi,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.pac4j.jwt.config.encryption,4,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.pac4j.jwt.config.signature,4,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.scijava.log,13,,,,,,,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.slf4j,55,,6,,,,,,,,,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,2,4
|
||||
org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30
|
||||
org.springframework.boot.jdbc,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13
|
||||
org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
org.springframework.core.io,3,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
org.springframework.data.repository,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
org.springframework.http,14,,77,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,67,10
|
||||
org.springframework.jdbc.core,19,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19,,,,,,,,,,,,,
|
||||
org.springframework.jdbc.datasource,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,
|
||||
org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,,
|
||||
org.springframework.jndi,1,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.ldap,47,,,,,,,,,,,,,,,,,,,33,,14,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.core.userdetails,2,,,,,,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,,
|
||||
org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32
|
||||
org.springframework.util,3,,142,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,90,52
|
||||
org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,
|
||||
org.springframework.web.client,13,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,13,,,,,,,,,,,,,3,,
|
||||
org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,,
|
||||
org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,12,13,
|
||||
org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
org.springframework.web.util,,9,157,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,132,25
|
||||
org.thymeleaf,2,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,2,
|
||||
org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,
|
||||
org.yaml.snakeyaml,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,
|
||||
play.libs.ws,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,
|
||||
play.mvc,1,13,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,13,24,
|
||||
ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,48
|
||||
ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,
|
||||
ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6,4,
|
||||
ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10,10,
|
||||
ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35
|
||||
retrofit2,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,1,
|
||||
sun.jvmstat.perfdata.monitor.protocol.local,3,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.jvmstat.perfdata.monitor.protocol.rmi,1,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.misc,3,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.net.ftp,5,,,,,,2,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.net.www.protocol.http,3,,,,,,2,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.acl,1,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.jgss.krb5,2,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.krb5,9,,,,,3,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.pkcs,4,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.pkcs11,3,,,,,1,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.provider,2,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.ssl,3,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.security.x509,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
sun.tools.jconsole,28,,,,,,13,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
|
|
|
|
@ -18,10 +18,10 @@ Java framework & library support
|
|||
`Google Guava <https://guava.dev/>`_,``com.google.common.*``,,730,43,9,,,,,
|
||||
JBoss Logging,``org.jboss.logging``,,,324,,,,,,
|
||||
`JSON-java <https://github.com/stleary/JSON-java>`_,``org.json``,,236,,,,,,,
|
||||
Java Standard Library,``java.*``,10,724,230,79,,9,,,19
|
||||
Java Standard Library,``java.*``,10,724,231,79,,9,,,19
|
||||
Java extensions,"``javax.*``, ``jakarta.*``",67,687,80,5,4,2,1,1,4
|
||||
Kotlin Standard Library,``kotlin*``,,1849,16,14,,,,,2
|
||||
`Spring <https://spring.io/>`_,``org.springframework.*``,38,481,118,5,,28,14,,35
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.google.gson``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.mongodb``, ``com.opensymphony.xwork2``, ``com.rabbitmq.client``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.text``, ``groovy.util``, ``hudson``, ``io.jsonwebtoken``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.struts.beanvalidation.validation.interceptor``, ``org.apache.struts2``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.hibernate``, ``org.influxdb``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.jooq``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``org.yaml.snakeyaml``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",131,10506,874,121,6,22,18,,208
|
||||
Totals,,308,18927,2446,331,16,128,33,1,402
|
||||
Others,"``actions.osgi``, ``antlr``, ``ch.ethz.ssh2``, ``cn.hutool.core.codec``, ``com.alibaba.druid.sql``, ``com.alibaba.fastjson2``, ``com.amazonaws.auth``, ``com.auth0.jwt.algorithms``, ``com.azure.identity``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.google.gson``, ``com.hubspot.jinjava``, ``com.jcraft.jsch``, ``com.microsoft.sqlserver.jdbc``, ``com.mitchellbosecke.pebble``, ``com.mongodb``, ``com.opensymphony.xwork2``, ``com.rabbitmq.client``, ``com.sshtools.j2ssh.authentication``, ``com.sun.crypto.provider``, ``com.sun.jndi.ldap``, ``com.sun.net.httpserver``, ``com.sun.net.ssl``, ``com.sun.rowset``, ``com.sun.security.auth.module``, ``com.sun.security.ntlm``, ``com.sun.security.sasl.digest``, ``com.thoughtworks.xstream``, ``com.trilead.ssh2``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.text``, ``groovy.util``, ``hudson``, ``io.jsonwebtoken``, ``io.netty.bootstrap``, ``io.netty.buffer``, ``io.netty.channel``, ``io.netty.handler.codec``, ``io.netty.handler.ssl``, ``io.netty.handler.stream``, ``io.netty.resolver``, ``io.netty.util``, ``javafx.scene.web``, ``jenkins``, ``jodd.json``, ``liquibase.database.jvm``, ``liquibase.statement.core``, ``net.schmizz.sshj``, ``net.sf.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.acegisecurity``, ``org.antlr.runtime``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.exec``, ``org.apache.commons.httpclient.util``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.lang``, ``org.apache.commons.logging``, ``org.apache.commons.net``, ``org.apache.commons.ognl``, ``org.apache.cxf.catalog``, ``org.apache.cxf.common.classloader``, ``org.apache.cxf.common.jaxb``, ``org.apache.cxf.common.logging``, ``org.apache.cxf.configuration.jsse``, ``org.apache.cxf.helpers``, ``org.apache.cxf.resource``, ``org.apache.cxf.staxutils``, ``org.apache.cxf.tools.corba.utils``, ``org.apache.cxf.tools.util``, ``org.apache.cxf.transform``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.fs``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hadoop.hive.ql.exec``, ``org.apache.hadoop.hive.ql.metadata``, ``org.apache.hc.client5.http.async.methods``, ``org.apache.hc.client5.http.classic.methods``, ``org.apache.hc.client5.http.fluent``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.ibatis.mapping``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.shiro.mgt``, ``org.apache.sshd.client.session``, ``org.apache.struts.beanvalidation.validation.interceptor``, ``org.apache.struts2``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.eclipse.jetty.client``, ``org.fusesource.leveldbjni``, ``org.geogebra.web.full.main``, ``org.gradle.api.file``, ``org.hibernate``, ``org.influxdb``, ``org.jdbi.v3.core``, ``org.jenkins.ui.icon``, ``org.jenkins.ui.symbol``, ``org.jooq``, ``org.keycloak.models.map.storage``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.owasp.esapi``, ``org.pac4j.jwt.config.encryption``, ``org.pac4j.jwt.config.signature``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``org.yaml.snakeyaml``, ``play.libs.ws``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``, ``sun.jvmstat.perfdata.monitor.protocol.local``, ``sun.jvmstat.perfdata.monitor.protocol.rmi``, ``sun.misc``, ``sun.net.ftp``, ``sun.net.www.protocol.http``, ``sun.security.acl``, ``sun.security.jgss.krb5``, ``sun.security.krb5``, ``sun.security.pkcs``, ``sun.security.pkcs11``, ``sun.security.provider``, ``sun.security.ssl``, ``sun.security.x509``, ``sun.tools.jconsole``",131,10514,889,121,6,22,18,,208
|
||||
Totals,,308,18935,2462,331,16,128,33,1,402
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ def version_string_to_version(version):
|
|||
# Version number used by CI.
|
||||
ci_version = '1.9.0'
|
||||
|
||||
many_versions = [ '1.5.0', '1.5.10', '1.5.20', '1.5.30', '1.6.0', '1.6.20', '1.7.0', '1.7.20', '1.8.0', '1.9.0-Beta', '1.9.20-Beta', '2.0.0-Beta1' ]
|
||||
many_versions = [ '1.5.0', '1.5.10', '1.5.20', '1.5.30', '1.6.0', '1.6.20', '1.7.0', '1.7.20', '1.8.0', '1.9.0-Beta', '1.9.20-Beta', '2.0.0-Beta1', '2.0.255-SNAPSHOT' ]
|
||||
|
||||
many_versions_versions = [version_string_to_version(v) for v in many_versions]
|
||||
many_versions_versions_asc = sorted(many_versions_versions, key = lambda v: v.toTupleWithTag())
|
||||
|
|
|
@ -3,18 +3,26 @@ package com.github.codeql
|
|||
import com.github.codeql.utils.isExternalFileClassMember
|
||||
import com.semmle.extractor.java.OdasaOutput
|
||||
import com.semmle.util.data.StringDigestor
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.isFileClass
|
||||
import org.jetbrains.kotlin.ir.util.packageFqName
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
import java.util.HashSet
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
class ExternalDeclExtractor(val logger: FileLogger, val compression: Compression, val invocationTrapFile: String, val sourceFilePath: String, val primitiveTypeMapping: PrimitiveTypeMapping, val pluginContext: IrPluginContext, val globalExtensionState: KotlinExtractorGlobalState, val diagnosticTrapWriter: DiagnosticTrapWriter) {
|
||||
class ExternalDeclExtractor(
|
||||
val logger: FileLogger,
|
||||
val compression: Compression,
|
||||
val invocationTrapFile: String,
|
||||
val sourceFilePath: String,
|
||||
val primitiveTypeMapping: PrimitiveTypeMapping,
|
||||
val pluginContext: IrPluginContext,
|
||||
val globalExtensionState: KotlinExtractorGlobalState,
|
||||
val diagnosticTrapWriter: DiagnosticTrapWriter
|
||||
) {
|
||||
|
||||
val declBinaryNames = HashMap<IrDeclaration, String>()
|
||||
val externalDeclsDone = HashSet<Pair<String, String>>()
|
||||
|
@ -23,13 +31,17 @@ class ExternalDeclExtractor(val logger: FileLogger, val compression: Compression
|
|||
val propertySignature = ";property"
|
||||
val fieldSignature = ";field"
|
||||
|
||||
val output = OdasaOutput(false, compression, logger).also {
|
||||
it.setCurrentSourceFile(File(sourceFilePath))
|
||||
}
|
||||
val output =
|
||||
OdasaOutput(false, compression, logger).also {
|
||||
it.setCurrentSourceFile(File(sourceFilePath))
|
||||
}
|
||||
|
||||
fun extractLater(d: IrDeclarationWithName, signature: String): Boolean {
|
||||
if (d !is IrClass && !isExternalFileClassMember(d)) {
|
||||
logger.errorElement("External declaration is neither a class, nor a top-level declaration", d)
|
||||
logger.errorElement(
|
||||
"External declaration is neither a class, nor a top-level declaration",
|
||||
d
|
||||
)
|
||||
return false
|
||||
}
|
||||
val declBinaryName = declBinaryNames.getOrPut(d) { getIrElementBinaryName(d) }
|
||||
|
@ -37,34 +49,54 @@ class ExternalDeclExtractor(val logger: FileLogger, val compression: Compression
|
|||
if (ret) externalDeclWorkList.add(Pair(d, signature))
|
||||
return ret
|
||||
}
|
||||
|
||||
fun extractLater(c: IrClass) = extractLater(c, "")
|
||||
|
||||
fun writeStubTrapFile(e: IrElement, signature: String = "") {
|
||||
extractElement(e, signature, true) { trapFileBW, _, _ ->
|
||||
trapFileBW.write("// Trap file stubbed because this declaration was extracted from source in $sourceFilePath\n")
|
||||
trapFileBW.write(
|
||||
"// Trap file stubbed because this declaration was extracted from source in $sourceFilePath\n"
|
||||
)
|
||||
trapFileBW.write("// Part of invocation $invocationTrapFile\n")
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractElement(element: IrElement, possiblyLongSignature: String, fromSource: Boolean, extractorFn: (BufferedWriter, String, OdasaOutput.TrapFileManager) -> Unit) {
|
||||
// In order to avoid excessively long signatures which can lead to trap file names longer than the filesystem
|
||||
private fun extractElement(
|
||||
element: IrElement,
|
||||
possiblyLongSignature: String,
|
||||
fromSource: Boolean,
|
||||
extractorFn: (BufferedWriter, String, OdasaOutput.TrapFileManager) -> Unit
|
||||
) {
|
||||
// In order to avoid excessively long signatures which can lead to trap file names longer
|
||||
// than the filesystem
|
||||
// limit, we truncate and add a hash to preserve uniqueness if necessary.
|
||||
val signature = if (possiblyLongSignature.length > 100) {
|
||||
possiblyLongSignature.substring(0, 92) + "#" + StringDigestor.digest(possiblyLongSignature).substring(0, 8)
|
||||
} else { possiblyLongSignature }
|
||||
val signature =
|
||||
if (possiblyLongSignature.length > 100) {
|
||||
possiblyLongSignature.substring(0, 92) +
|
||||
"#" +
|
||||
StringDigestor.digest(possiblyLongSignature).substring(0, 8)
|
||||
} else {
|
||||
possiblyLongSignature
|
||||
}
|
||||
output.getTrapLockerForDecl(element, signature, fromSource).useAC { locker ->
|
||||
locker.trapFileManager.useAC { manager ->
|
||||
val shortName = when(element) {
|
||||
is IrDeclarationWithName -> element.name.asString()
|
||||
is IrFile -> element.name
|
||||
else -> "(unknown name)"
|
||||
}
|
||||
val shortName =
|
||||
when (element) {
|
||||
is IrDeclarationWithName -> element.name.asString()
|
||||
is IrFile -> element.name
|
||||
else -> "(unknown name)"
|
||||
}
|
||||
if (manager == null) {
|
||||
logger.info("Skipping extracting external decl $shortName")
|
||||
} else {
|
||||
val trapFile = manager.file
|
||||
logger.info("Will write TRAP file $trapFile")
|
||||
val trapTmpFile = File.createTempFile("${trapFile.nameWithoutExtension}.", ".${trapFile.extension}.tmp", trapFile.parentFile)
|
||||
val trapTmpFile =
|
||||
File.createTempFile(
|
||||
"${trapFile.nameWithoutExtension}.",
|
||||
".${trapFile.extension}.tmp",
|
||||
trapFile.parentFile
|
||||
)
|
||||
logger.debug("Writing temporary TRAP file $trapTmpFile")
|
||||
try {
|
||||
compression.bufferedWriter(trapTmpFile).use {
|
||||
|
@ -77,7 +109,10 @@ class ExternalDeclExtractor(val logger: FileLogger, val compression: Compression
|
|||
logger.info("Finished writing TRAP file $trapFile")
|
||||
} catch (e: Exception) {
|
||||
manager.setHasError()
|
||||
logger.error("Failed to extract '$shortName'. Partial TRAP file location is $trapTmpFile", e)
|
||||
logger.error(
|
||||
"Failed to extract '$shortName'. Partial TRAP file location is $trapTmpFile",
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,37 +125,75 @@ class ExternalDeclExtractor(val logger: FileLogger, val compression: Compression
|
|||
externalDeclWorkList.clear()
|
||||
nextBatch.forEach { workPair ->
|
||||
val (irDecl, possiblyLongSignature) = workPair
|
||||
extractElement(irDecl, possiblyLongSignature, false) { trapFileBW, signature, manager ->
|
||||
extractElement(irDecl, possiblyLongSignature, false) {
|
||||
trapFileBW,
|
||||
signature,
|
||||
manager ->
|
||||
val binaryPath = getIrDeclarationBinaryPath(irDecl)
|
||||
if (binaryPath == null) {
|
||||
logger.errorElement("Unable to get binary path", irDecl)
|
||||
} else {
|
||||
// We want our comments to be the first thing in the file,
|
||||
// so start off with a PlainTrapWriter
|
||||
val tw = PlainTrapWriter(logger.loggerBase, TrapLabelManager(), trapFileBW, diagnosticTrapWriter)
|
||||
tw.writeComment("Generated by the CodeQL Kotlin extractor for external dependencies")
|
||||
val tw =
|
||||
PlainTrapWriter(
|
||||
logger.loggerBase,
|
||||
TrapLabelManager(),
|
||||
trapFileBW,
|
||||
diagnosticTrapWriter
|
||||
)
|
||||
tw.writeComment(
|
||||
"Generated by the CodeQL Kotlin extractor for external dependencies"
|
||||
)
|
||||
tw.writeComment("Part of invocation $invocationTrapFile")
|
||||
if (signature != possiblyLongSignature) {
|
||||
tw.writeComment("Function signature abbreviated; full signature is: $possiblyLongSignature")
|
||||
tw.writeComment(
|
||||
"Function signature abbreviated; full signature is: $possiblyLongSignature"
|
||||
)
|
||||
}
|
||||
// Now elevate to a SourceFileTrapWriter, and populate the
|
||||
// file information if needed:
|
||||
val ftw = tw.makeFileTrapWriter(binaryPath, true)
|
||||
|
||||
val fileExtractor = KotlinFileExtractor(logger, ftw, null, binaryPath, manager, this, primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), globalExtensionState)
|
||||
val fileExtractor =
|
||||
KotlinFileExtractor(
|
||||
logger,
|
||||
ftw,
|
||||
null,
|
||||
binaryPath,
|
||||
manager,
|
||||
this,
|
||||
primitiveTypeMapping,
|
||||
pluginContext,
|
||||
KotlinFileExtractor.DeclarationStack(),
|
||||
globalExtensionState
|
||||
)
|
||||
|
||||
if (irDecl is IrClass) {
|
||||
// Populate a location and compilation-unit package for the file. This is similar to
|
||||
// the beginning of `KotlinFileExtractor.extractFileContents` but without an `IrFile`
|
||||
// Populate a location and compilation-unit package for the file. This
|
||||
// is similar to
|
||||
// the beginning of `KotlinFileExtractor.extractFileContents` but
|
||||
// without an `IrFile`
|
||||
// to start from.
|
||||
val pkg = irDecl.packageFqName?.asString() ?: ""
|
||||
val pkgId = fileExtractor.extractPackage(pkg)
|
||||
ftw.writeHasLocation(ftw.fileId, ftw.getWholeFileLocation())
|
||||
ftw.writeCupackage(ftw.fileId, pkgId)
|
||||
|
||||
fileExtractor.extractClassSource(irDecl, extractDeclarations = !irDecl.isFileClass, extractStaticInitializer = false, extractPrivateMembers = false, extractFunctionBodies = false)
|
||||
fileExtractor.extractClassSource(
|
||||
irDecl,
|
||||
extractDeclarations = !irDecl.isFileClass,
|
||||
extractStaticInitializer = false,
|
||||
extractPrivateMembers = false,
|
||||
extractFunctionBodies = false
|
||||
)
|
||||
} else {
|
||||
fileExtractor.extractDeclaration(irDecl, extractPrivateMembers = false, extractFunctionBodies = false, extractAnnotations = true)
|
||||
fileExtractor.extractDeclaration(
|
||||
irDecl,
|
||||
extractPrivateMembers = false,
|
||||
extractFunctionBodies = false,
|
||||
extractAnnotations = true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,5 +201,4 @@ class ExternalDeclExtractor(val logger: FileLogger, val compression: Compression
|
|||
} while (externalDeclWorkList.isNotEmpty())
|
||||
output.writeTrapSet()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,66 +11,90 @@ import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
|||
class KotlinExtractorCommandLineProcessor : CommandLineProcessor {
|
||||
override val pluginId = "kotlin-extractor"
|
||||
|
||||
override val pluginOptions = listOf(
|
||||
CliOption(
|
||||
optionName = OPTION_INVOCATION_TRAP_FILE,
|
||||
valueDescription = "Invocation TRAP file",
|
||||
description = "Extractor will append invocation-related TRAP to this file",
|
||||
required = true,
|
||||
allowMultipleOccurrences = false
|
||||
),
|
||||
CliOption(
|
||||
optionName = OPTION_CHECK_TRAP_IDENTICAL,
|
||||
valueDescription = "Check whether different invocations produce identical TRAP",
|
||||
description = "Check whether different invocations produce identical TRAP",
|
||||
required = false,
|
||||
allowMultipleOccurrences = false
|
||||
),
|
||||
CliOption(
|
||||
optionName = OPTION_COMPILATION_STARTTIME,
|
||||
valueDescription = "The start time of the compilation as a Unix timestamp",
|
||||
description = "The start time of the compilation as a Unix timestamp",
|
||||
required = false,
|
||||
allowMultipleOccurrences = false
|
||||
),
|
||||
CliOption(
|
||||
optionName = OPTION_EXIT_AFTER_EXTRACTION,
|
||||
valueDescription = "Specify whether to call exitProcess after the extraction has completed",
|
||||
description = "Specify whether to call exitProcess after the extraction has completed",
|
||||
required = false,
|
||||
allowMultipleOccurrences = false
|
||||
override val pluginOptions =
|
||||
listOf(
|
||||
CliOption(
|
||||
optionName = OPTION_INVOCATION_TRAP_FILE,
|
||||
valueDescription = "Invocation TRAP file",
|
||||
description = "Extractor will append invocation-related TRAP to this file",
|
||||
required = true,
|
||||
allowMultipleOccurrences = false
|
||||
),
|
||||
CliOption(
|
||||
optionName = OPTION_CHECK_TRAP_IDENTICAL,
|
||||
valueDescription = "Check whether different invocations produce identical TRAP",
|
||||
description = "Check whether different invocations produce identical TRAP",
|
||||
required = false,
|
||||
allowMultipleOccurrences = false
|
||||
),
|
||||
CliOption(
|
||||
optionName = OPTION_COMPILATION_STARTTIME,
|
||||
valueDescription = "The start time of the compilation as a Unix timestamp",
|
||||
description = "The start time of the compilation as a Unix timestamp",
|
||||
required = false,
|
||||
allowMultipleOccurrences = false
|
||||
),
|
||||
CliOption(
|
||||
optionName = OPTION_EXIT_AFTER_EXTRACTION,
|
||||
valueDescription =
|
||||
"Specify whether to call exitProcess after the extraction has completed",
|
||||
description =
|
||||
"Specify whether to call exitProcess after the extraction has completed",
|
||||
required = false,
|
||||
allowMultipleOccurrences = false
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
override fun processOption(
|
||||
option: AbstractCliOption,
|
||||
value: String,
|
||||
configuration: CompilerConfiguration
|
||||
) = when (option.optionName) {
|
||||
OPTION_INVOCATION_TRAP_FILE -> configuration.put(KEY_INVOCATION_TRAP_FILE, value)
|
||||
OPTION_CHECK_TRAP_IDENTICAL -> processBooleanOption(value, OPTION_CHECK_TRAP_IDENTICAL, KEY_CHECK_TRAP_IDENTICAL, configuration)
|
||||
OPTION_EXIT_AFTER_EXTRACTION -> processBooleanOption(value, OPTION_EXIT_AFTER_EXTRACTION, KEY_EXIT_AFTER_EXTRACTION, configuration)
|
||||
OPTION_COMPILATION_STARTTIME ->
|
||||
when (val v = value.toLongOrNull()) {
|
||||
is Long -> configuration.put(KEY_COMPILATION_STARTTIME, v)
|
||||
else -> error("kotlin extractor: Bad argument $value for $OPTION_COMPILATION_STARTTIME")
|
||||
}
|
||||
else -> error("kotlin extractor: Bad option: ${option.optionName}")
|
||||
}
|
||||
) =
|
||||
when (option.optionName) {
|
||||
OPTION_INVOCATION_TRAP_FILE -> configuration.put(KEY_INVOCATION_TRAP_FILE, value)
|
||||
OPTION_CHECK_TRAP_IDENTICAL ->
|
||||
processBooleanOption(
|
||||
value,
|
||||
OPTION_CHECK_TRAP_IDENTICAL,
|
||||
KEY_CHECK_TRAP_IDENTICAL,
|
||||
configuration
|
||||
)
|
||||
OPTION_EXIT_AFTER_EXTRACTION ->
|
||||
processBooleanOption(
|
||||
value,
|
||||
OPTION_EXIT_AFTER_EXTRACTION,
|
||||
KEY_EXIT_AFTER_EXTRACTION,
|
||||
configuration
|
||||
)
|
||||
OPTION_COMPILATION_STARTTIME ->
|
||||
when (val v = value.toLongOrNull()) {
|
||||
is Long -> configuration.put(KEY_COMPILATION_STARTTIME, v)
|
||||
else ->
|
||||
error(
|
||||
"kotlin extractor: Bad argument $value for $OPTION_COMPILATION_STARTTIME"
|
||||
)
|
||||
}
|
||||
else -> error("kotlin extractor: Bad option: ${option.optionName}")
|
||||
}
|
||||
|
||||
private fun processBooleanOption(value: String, optionName: String, configKey: CompilerConfigurationKey<Boolean>, configuration: CompilerConfiguration) =
|
||||
private fun processBooleanOption(
|
||||
value: String,
|
||||
optionName: String,
|
||||
configKey: CompilerConfigurationKey<Boolean>,
|
||||
configuration: CompilerConfiguration
|
||||
) =
|
||||
when (value) {
|
||||
"true" -> configuration.put(configKey, true)
|
||||
"false" -> configuration.put(configKey, false)
|
||||
else -> error("kotlin extractor: Bad argument $value for $optionName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val OPTION_INVOCATION_TRAP_FILE = "invocationTrapFile"
|
||||
val KEY_INVOCATION_TRAP_FILE = CompilerConfigurationKey<String>(OPTION_INVOCATION_TRAP_FILE)
|
||||
private val OPTION_CHECK_TRAP_IDENTICAL = "checkTrapIdentical"
|
||||
val KEY_CHECK_TRAP_IDENTICAL= CompilerConfigurationKey<Boolean>(OPTION_CHECK_TRAP_IDENTICAL)
|
||||
val KEY_CHECK_TRAP_IDENTICAL = CompilerConfigurationKey<Boolean>(OPTION_CHECK_TRAP_IDENTICAL)
|
||||
private val OPTION_COMPILATION_STARTTIME = "compilationStartTime"
|
||||
val KEY_COMPILATION_STARTTIME= CompilerConfigurationKey<Long>(OPTION_COMPILATION_STARTTIME)
|
||||
val KEY_COMPILATION_STARTTIME = CompilerConfigurationKey<Long>(OPTION_COMPILATION_STARTTIME)
|
||||
private val OPTION_EXIT_AFTER_EXTRACTION = "exitAfterExtraction"
|
||||
val KEY_EXIT_AFTER_EXTRACTION= CompilerConfigurationKey<Boolean>(OPTION_EXIT_AFTER_EXTRACTION)
|
||||
val KEY_EXIT_AFTER_EXTRACTION = CompilerConfigurationKey<Boolean>(OPTION_EXIT_AFTER_EXTRACTION)
|
||||
|
|
|
@ -3,12 +3,9 @@
|
|||
|
||||
package com.github.codeql
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
|
||||
import com.intellij.mock.MockProject
|
||||
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import com.github.codeql.Kotlin2ComponentRegistrar
|
||||
|
||||
class KotlinExtractorComponentRegistrar : Kotlin2ComponentRegistrar() {
|
||||
override fun registerProjectComponents(
|
||||
|
@ -19,10 +16,14 @@ class KotlinExtractorComponentRegistrar : Kotlin2ComponentRegistrar() {
|
|||
if (invocationTrapFile == null) {
|
||||
throw Exception("Required argument for TRAP invocation file not given")
|
||||
}
|
||||
IrGenerationExtension.registerExtension(project, KotlinExtractorExtension(
|
||||
invocationTrapFile,
|
||||
configuration[KEY_CHECK_TRAP_IDENTICAL] ?: false,
|
||||
configuration[KEY_COMPILATION_STARTTIME],
|
||||
configuration[KEY_EXIT_AFTER_EXTRACTION] ?: false))
|
||||
IrGenerationExtension.registerExtension(
|
||||
project,
|
||||
KotlinExtractorExtension(
|
||||
invocationTrapFile,
|
||||
configuration[KEY_CHECK_TRAP_IDENTICAL] ?: false,
|
||||
configuration[KEY_COMPILATION_STARTTIME],
|
||||
configuration[KEY_EXIT_AFTER_EXTRACTION] ?: false
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
package com.github.codeql
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import java.io.BufferedReader
|
||||
import java.io.BufferedWriter
|
||||
import com.github.codeql.utils.versions.usesK2
|
||||
import com.semmle.util.files.FileUtil
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.BufferedReader
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
|
@ -20,9 +16,12 @@ import java.nio.file.Files
|
|||
import java.nio.file.Paths
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import com.github.codeql.utils.versions.usesK2
|
||||
import com.semmle.util.files.FileUtil
|
||||
import kotlin.system.exitProcess
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
|
||||
/*
|
||||
* KotlinExtractorExtension is the main entry point of the CodeQL Kotlin
|
||||
|
@ -55,8 +54,8 @@ class KotlinExtractorExtension(
|
|||
// can be set to true to make the plugin terminate the kotlinc
|
||||
// invocation when it has finished. This means that kotlinc will not
|
||||
// write any `.class` files etc.
|
||||
private val exitAfterExtraction: Boolean)
|
||||
: IrGenerationExtension {
|
||||
private val exitAfterExtraction: Boolean
|
||||
) : IrGenerationExtension {
|
||||
|
||||
// This is the main entry point to the extractor.
|
||||
// It will be called by kotlinc with the IR for the files being
|
||||
|
@ -65,10 +64,10 @@ class KotlinExtractorExtension(
|
|||
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
|
||||
try {
|
||||
runExtractor(moduleFragment, pluginContext)
|
||||
// We catch Throwable rather than Exception, as we want to
|
||||
// continue trying to extract everything else even if we get a
|
||||
// stack overflow or an assertion failure in one file.
|
||||
} catch(e: Throwable) {
|
||||
// We catch Throwable rather than Exception, as we want to
|
||||
// continue trying to extract everything else even if we get a
|
||||
// stack overflow or an assertion failure in one file.
|
||||
} catch (e: Throwable) {
|
||||
// If we get an exception at the top level, then something's
|
||||
// gone very wrong. Don't try to be too fancy, but try to
|
||||
// log a simple message.
|
||||
|
@ -80,7 +79,8 @@ class KotlinExtractorExtension(
|
|||
// We use a slightly different filename pattern compared
|
||||
// to normal logs. Just the existence of a `-top` log is
|
||||
// a sign that something's gone very wrong.
|
||||
val logFile = File.createTempFile("kotlin-extractor-top.", ".log", File(extractorLogDir))
|
||||
val logFile =
|
||||
File.createTempFile("kotlin-extractor-top.", ".log", File(extractorLogDir))
|
||||
logFile.writeText(msg)
|
||||
// Now we've got that out, let's see if we can append a stack trace too
|
||||
logFile.appendText(e.stackTraceToString())
|
||||
|
@ -99,12 +99,18 @@ class KotlinExtractorExtension(
|
|||
private fun runExtractor(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
|
||||
val startTimeMs = System.currentTimeMillis()
|
||||
val usesK2 = usesK2(pluginContext)
|
||||
// This default should be kept in sync with com.semmle.extractor.java.interceptors.KotlinInterceptor.initializeExtractionContext
|
||||
val trapDir = File(System.getenv("CODEQL_EXTRACTOR_JAVA_TRAP_DIR").takeUnless { it.isNullOrEmpty() } ?: "kotlin-extractor/trap")
|
||||
// This default should be kept in sync with
|
||||
// com.semmle.extractor.java.interceptors.KotlinInterceptor.initializeExtractionContext
|
||||
val trapDir =
|
||||
File(
|
||||
System.getenv("CODEQL_EXTRACTOR_JAVA_TRAP_DIR").takeUnless { it.isNullOrEmpty() }
|
||||
?: "kotlin-extractor/trap"
|
||||
)
|
||||
// The invocation TRAP file will already have been started
|
||||
// before the plugin is run, so we always use no compression
|
||||
// and we open it in append mode.
|
||||
FileOutputStream(File(invocationTrapFile), true).bufferedWriter().use { invocationTrapFileBW ->
|
||||
FileOutputStream(File(invocationTrapFile), true).bufferedWriter().use { invocationTrapFileBW
|
||||
->
|
||||
val invocationExtractionProblems = ExtractionProblems()
|
||||
val lm = TrapLabelManager()
|
||||
val logCounter = LogCounter()
|
||||
|
@ -113,12 +119,21 @@ class KotlinExtractorExtension(
|
|||
// The interceptor has already defined #compilation = *
|
||||
val compilation: Label<DbCompilation> = StringLabel("compilation")
|
||||
tw.writeCompilation_started(compilation)
|
||||
tw.writeCompilation_info(compilation, "Kotlin Compiler Version", KotlinCompilerVersion.getVersion() ?: "<unknown>")
|
||||
val extractor_name = this::class.java.getResource("extractor.name")?.readText() ?: "<unknown>"
|
||||
tw.writeCompilation_info(
|
||||
compilation,
|
||||
"Kotlin Compiler Version",
|
||||
KotlinCompilerVersion.getVersion() ?: "<unknown>"
|
||||
)
|
||||
val extractor_name =
|
||||
this::class.java.getResource("extractor.name")?.readText() ?: "<unknown>"
|
||||
tw.writeCompilation_info(compilation, "Kotlin Extractor Name", extractor_name)
|
||||
tw.writeCompilation_info(compilation, "Uses Kotlin 2", usesK2.toString())
|
||||
if (compilationStartTime != null) {
|
||||
tw.writeCompilation_compiler_times(compilation, -1.0, (System.currentTimeMillis()-compilationStartTime)/1000.0)
|
||||
tw.writeCompilation_compiler_times(
|
||||
compilation,
|
||||
-1.0,
|
||||
(System.currentTimeMillis() - compilationStartTime) / 1000.0
|
||||
)
|
||||
}
|
||||
tw.flush()
|
||||
val logger = Logger(loggerBase, tw)
|
||||
|
@ -138,23 +153,54 @@ class KotlinExtractorExtension(
|
|||
// FIXME: FileUtil expects a static global logger
|
||||
// which should be provided by SLF4J's factory facility. For now we set it here.
|
||||
FileUtil.logger = logger
|
||||
val srcDir = File(System.getenv("CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR").takeUnless { it.isNullOrEmpty() } ?: "kotlin-extractor/src")
|
||||
val srcDir =
|
||||
File(
|
||||
System.getenv("CODEQL_EXTRACTOR_JAVA_SOURCE_ARCHIVE_DIR").takeUnless {
|
||||
it.isNullOrEmpty()
|
||||
} ?: "kotlin-extractor/src"
|
||||
)
|
||||
srcDir.mkdirs()
|
||||
val globalExtensionState = KotlinExtractorGlobalState()
|
||||
moduleFragment.files.mapIndexed { index: Int, file: IrFile ->
|
||||
val fileExtractionProblems = FileExtractionProblems(invocationExtractionProblems)
|
||||
val fileTrapWriter = tw.makeSourceFileTrapWriter(file, true)
|
||||
loggerBase.setFileNumber(index)
|
||||
fileTrapWriter.writeCompilation_compiling_files(compilation, index, fileTrapWriter.fileId)
|
||||
doFile(compression, fileExtractionProblems, invocationTrapFile, fileTrapWriter, checkTrapIdentical, loggerBase, trapDir, srcDir, file, primitiveTypeMapping, pluginContext, globalExtensionState)
|
||||
fileTrapWriter.writeCompilation_compiling_files_completed(compilation, index, fileExtractionProblems.extractionResult())
|
||||
fileTrapWriter.writeCompilation_compiling_files(
|
||||
compilation,
|
||||
index,
|
||||
fileTrapWriter.fileId
|
||||
)
|
||||
doFile(
|
||||
compression,
|
||||
fileExtractionProblems,
|
||||
invocationTrapFile,
|
||||
fileTrapWriter,
|
||||
checkTrapIdentical,
|
||||
loggerBase,
|
||||
trapDir,
|
||||
srcDir,
|
||||
file,
|
||||
primitiveTypeMapping,
|
||||
pluginContext,
|
||||
globalExtensionState
|
||||
)
|
||||
fileTrapWriter.writeCompilation_compiling_files_completed(
|
||||
compilation,
|
||||
index,
|
||||
fileExtractionProblems.extractionResult()
|
||||
)
|
||||
}
|
||||
loggerBase.printLimitedDiagnosticCounts(tw)
|
||||
logPeakMemoryUsage(logger, "after extractor")
|
||||
logger.info("Extraction completed")
|
||||
logger.flush()
|
||||
val compilationTimeMs = System.currentTimeMillis() - startTimeMs
|
||||
tw.writeCompilation_finished(compilation, -1.0, compilationTimeMs.toDouble() / 1000, invocationExtractionProblems.extractionResult())
|
||||
tw.writeCompilation_finished(
|
||||
compilation,
|
||||
-1.0,
|
||||
compilationTimeMs.toDouble() / 1000,
|
||||
invocationExtractionProblems.extractionResult()
|
||||
)
|
||||
tw.flush()
|
||||
loggerBase.close()
|
||||
}
|
||||
|
@ -168,16 +214,19 @@ class KotlinExtractorExtension(
|
|||
return defaultCompression
|
||||
} else {
|
||||
try {
|
||||
@OptIn(kotlin.ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
|
||||
val compression_option_upper = compression_option.uppercase()
|
||||
if (compression_option_upper == "BROTLI") {
|
||||
logger.warn("Kotlin extractor doesn't support Brotli compression. Using GZip instead.")
|
||||
logger.warn(
|
||||
"Kotlin extractor doesn't support Brotli compression. Using GZip instead."
|
||||
)
|
||||
return Compression.GZIP
|
||||
} else {
|
||||
return Compression.valueOf(compression_option_upper)
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
logger.warn("Unsupported compression type (\$$compression_env_var) \"$compression_option\". Supported values are ${Compression.values().joinToString()}.")
|
||||
logger.warn(
|
||||
"Unsupported compression type (\$$compression_env_var) \"$compression_option\". Supported values are ${Compression.values().joinToString()}."
|
||||
)
|
||||
return defaultCompression
|
||||
}
|
||||
}
|
||||
|
@ -191,11 +240,18 @@ class KotlinExtractorExtension(
|
|||
var nonheap: Long = 0
|
||||
for (bean in beans) {
|
||||
val peak = bean.getPeakUsage().getUsed()
|
||||
val kind = when (bean.getType()) {
|
||||
MemoryType.HEAP -> { heap += peak; "heap" }
|
||||
MemoryType.NON_HEAP -> { nonheap += peak; "non-heap" }
|
||||
else -> "unknown"
|
||||
}
|
||||
val kind =
|
||||
when (bean.getType()) {
|
||||
MemoryType.HEAP -> {
|
||||
heap += peak
|
||||
"heap"
|
||||
}
|
||||
MemoryType.NON_HEAP -> {
|
||||
nonheap += peak
|
||||
"non-heap"
|
||||
}
|
||||
else -> "unknown"
|
||||
}
|
||||
logger.info("Peak memory: * Peak for $kind bean ${bean.getName()} is $peak")
|
||||
}
|
||||
logger.info("Peak memory: * Total heap peak: $heap")
|
||||
|
@ -204,9 +260,12 @@ class KotlinExtractorExtension(
|
|||
}
|
||||
|
||||
class KotlinExtractorGlobalState {
|
||||
// These three record mappings of classes, functions and fields that should be replaced wherever they are found.
|
||||
// As of now these are only used to fix IR generated by the Gradle Android Extensions plugin, hence e.g. IrProperty
|
||||
// doesn't have a map as that plugin doesn't generate them. If and when these are used more widely additional maps
|
||||
// These three record mappings of classes, functions and fields that should be replaced wherever
|
||||
// they are found.
|
||||
// As of now these are only used to fix IR generated by the Gradle Android Extensions plugin,
|
||||
// hence e.g. IrProperty
|
||||
// doesn't have a map as that plugin doesn't generate them. If and when these are used more
|
||||
// widely additional maps
|
||||
// should be added here.
|
||||
val syntheticToRealClassMap = HashMap<IrClass, IrClass?>()
|
||||
val syntheticToRealFunctionMap = HashMap<IrFunction, IrFunction?>()
|
||||
|
@ -228,13 +287,15 @@ open class ExtractionProblems {
|
|||
open fun setRecoverableProblem() {
|
||||
recoverableProblem = true
|
||||
}
|
||||
|
||||
open fun setNonRecoverableProblem() {
|
||||
nonRecoverableProblem = true
|
||||
}
|
||||
|
||||
fun extractionResult(): Int {
|
||||
if(nonRecoverableProblem) {
|
||||
if (nonRecoverableProblem) {
|
||||
return 2
|
||||
} else if(recoverableProblem) {
|
||||
} else if (recoverableProblem) {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
|
@ -247,11 +308,13 @@ The `FileExtractionProblems` is analogous to `ExtractionProblems`,
|
|||
except it records whether there were any problems while extracting a
|
||||
particular source file.
|
||||
*/
|
||||
class FileExtractionProblems(val invocationExtractionProblems: ExtractionProblems): ExtractionProblems() {
|
||||
class FileExtractionProblems(val invocationExtractionProblems: ExtractionProblems) :
|
||||
ExtractionProblems() {
|
||||
override fun setRecoverableProblem() {
|
||||
super.setRecoverableProblem()
|
||||
invocationExtractionProblems.setRecoverableProblem()
|
||||
}
|
||||
|
||||
override fun setNonRecoverableProblem() {
|
||||
super.setNonRecoverableProblem()
|
||||
invocationExtractionProblems.setNonRecoverableProblem()
|
||||
|
@ -266,7 +329,7 @@ identical.
|
|||
private fun equivalentTrap(r1: BufferedReader, r2: BufferedReader): Boolean {
|
||||
r1.use { br1 ->
|
||||
r2.use { br2 ->
|
||||
while(true) {
|
||||
while (true) {
|
||||
val l1 = br1.readLine()
|
||||
val l2 = br2.readLine()
|
||||
if (l1 == null && l2 == null) {
|
||||
|
@ -295,7 +358,8 @@ private fun doFile(
|
|||
srcFile: IrFile,
|
||||
primitiveTypeMapping: PrimitiveTypeMapping,
|
||||
pluginContext: IrPluginContext,
|
||||
globalExtensionState: KotlinExtractorGlobalState) {
|
||||
globalExtensionState: KotlinExtractorGlobalState
|
||||
) {
|
||||
val srcFilePath = srcFile.path
|
||||
val logger = FileLogger(loggerBase, fileTrapWriter)
|
||||
logger.info("Extracting file $srcFilePath")
|
||||
|
@ -312,10 +376,13 @@ private fun doFile(
|
|||
val dbSrcFilePath = Paths.get("$dbSrcDir/$srcFileRelativePath")
|
||||
val dbSrcDirPath = dbSrcFilePath.parent
|
||||
Files.createDirectories(dbSrcDirPath)
|
||||
val srcTmpFile = File.createTempFile(dbSrcFilePath.fileName.toString() + ".", ".src.tmp", dbSrcDirPath.toFile())
|
||||
srcTmpFile.outputStream().use {
|
||||
Files.copy(Paths.get(srcFilePath), it)
|
||||
}
|
||||
val srcTmpFile =
|
||||
File.createTempFile(
|
||||
dbSrcFilePath.fileName.toString() + ".",
|
||||
".src.tmp",
|
||||
dbSrcDirPath.toFile()
|
||||
)
|
||||
srcTmpFile.outputStream().use { Files.copy(Paths.get(srcFilePath), it) }
|
||||
srcTmpFile.renameTo(dbSrcFilePath.toFile())
|
||||
|
||||
val trapFileName = "$dbTrapDir/$srcFileRelativePath.trap"
|
||||
|
@ -328,22 +395,52 @@ private fun doFile(
|
|||
trapFileWriter.getTempWriter().use { trapFileBW ->
|
||||
// We want our comments to be the first thing in the file,
|
||||
// so start off with a mere TrapWriter
|
||||
val tw = PlainTrapWriter(loggerBase, TrapLabelManager(), trapFileBW, fileTrapWriter.getDiagnosticTrapWriter())
|
||||
val tw =
|
||||
PlainTrapWriter(
|
||||
loggerBase,
|
||||
TrapLabelManager(),
|
||||
trapFileBW,
|
||||
fileTrapWriter.getDiagnosticTrapWriter()
|
||||
)
|
||||
tw.writeComment("Generated by the CodeQL Kotlin extractor for kotlin source code")
|
||||
tw.writeComment("Part of invocation $invocationTrapFile")
|
||||
// Now elevate to a SourceFileTrapWriter, and populate the
|
||||
// file information
|
||||
val sftw = tw.makeSourceFileTrapWriter(srcFile, true)
|
||||
val externalDeclExtractor = ExternalDeclExtractor(logger, compression, invocationTrapFile, srcFilePath, primitiveTypeMapping, pluginContext, globalExtensionState, fileTrapWriter.getDiagnosticTrapWriter())
|
||||
val externalDeclExtractor =
|
||||
ExternalDeclExtractor(
|
||||
logger,
|
||||
compression,
|
||||
invocationTrapFile,
|
||||
srcFilePath,
|
||||
primitiveTypeMapping,
|
||||
pluginContext,
|
||||
globalExtensionState,
|
||||
fileTrapWriter.getDiagnosticTrapWriter()
|
||||
)
|
||||
val linesOfCode = LinesOfCode(logger, sftw, srcFile)
|
||||
val fileExtractor = KotlinFileExtractor(logger, sftw, linesOfCode, srcFilePath, null, externalDeclExtractor, primitiveTypeMapping, pluginContext, KotlinFileExtractor.DeclarationStack(), globalExtensionState)
|
||||
val fileExtractor =
|
||||
KotlinFileExtractor(
|
||||
logger,
|
||||
sftw,
|
||||
linesOfCode,
|
||||
srcFilePath,
|
||||
null,
|
||||
externalDeclExtractor,
|
||||
primitiveTypeMapping,
|
||||
pluginContext,
|
||||
KotlinFileExtractor.DeclarationStack(),
|
||||
globalExtensionState
|
||||
)
|
||||
|
||||
fileExtractor.extractFileContents(srcFile, sftw.fileId)
|
||||
externalDeclExtractor.extractExternalClasses()
|
||||
}
|
||||
|
||||
if (checkTrapIdentical && trapFileWriter.exists()) {
|
||||
if (equivalentTrap(trapFileWriter.getTempReader(), trapFileWriter.getRealReader())) {
|
||||
if (
|
||||
equivalentTrap(trapFileWriter.getTempReader(), trapFileWriter.getRealReader())
|
||||
) {
|
||||
trapFileWriter.deleteTemp()
|
||||
} else {
|
||||
trapFileWriter.renameTempToDifferent()
|
||||
|
@ -351,9 +448,9 @@ private fun doFile(
|
|||
} else {
|
||||
trapFileWriter.renameTempToReal()
|
||||
}
|
||||
// We catch Throwable rather than Exception, as we want to
|
||||
// continue trying to extract everything else even if we get a
|
||||
// stack overflow or an assertion failure in one file.
|
||||
// We catch Throwable rather than Exception, as we want to
|
||||
// continue trying to extract everything else even if we get a
|
||||
// stack overflow or an assertion failure in one file.
|
||||
} catch (e: Throwable) {
|
||||
logger.error("Failed to extract '$srcFilePath'. " + trapFileWriter.debugInfo(), e)
|
||||
context.clear()
|
||||
|
@ -373,17 +470,26 @@ enum class Compression(val extension: String) {
|
|||
return GZIPOutputStream(file.outputStream()).bufferedWriter()
|
||||
}
|
||||
};
|
||||
|
||||
abstract fun bufferedWriter(file: File): BufferedWriter
|
||||
}
|
||||
|
||||
private fun getTrapFileWriter(compression: Compression, logger: FileLogger, trapFileName: String): TrapFileWriter {
|
||||
private fun getTrapFileWriter(
|
||||
compression: Compression,
|
||||
logger: FileLogger,
|
||||
trapFileName: String
|
||||
): TrapFileWriter {
|
||||
return when (compression) {
|
||||
Compression.NONE -> NonCompressedTrapFileWriter(logger, trapFileName)
|
||||
Compression.GZIP -> GZipCompressedTrapFileWriter(logger, trapFileName)
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class TrapFileWriter(val logger: FileLogger, trapName: String, val extension: String) {
|
||||
private abstract class TrapFileWriter(
|
||||
val logger: FileLogger,
|
||||
trapName: String,
|
||||
val extension: String
|
||||
) {
|
||||
private val realFile = File(trapName + extension)
|
||||
private val parentDir = realFile.parentFile
|
||||
lateinit private var tempFile: File
|
||||
|
@ -405,6 +511,7 @@ private abstract class TrapFileWriter(val logger: FileLogger, trapName: String,
|
|||
}
|
||||
|
||||
abstract protected fun getReader(file: File): BufferedReader
|
||||
|
||||
abstract protected fun getWriter(file: File): BufferedWriter
|
||||
|
||||
fun getRealReader(): BufferedReader {
|
||||
|
@ -432,7 +539,8 @@ private abstract class TrapFileWriter(val logger: FileLogger, trapName: String,
|
|||
}
|
||||
|
||||
fun renameTempToDifferent() {
|
||||
val trapDifferentFile = File.createTempFile(realFile.getName() + ".", ".trap.different" + extension, parentDir)
|
||||
val trapDifferentFile =
|
||||
File.createTempFile(realFile.getName() + ".", ".trap.different" + extension, parentDir)
|
||||
if (tempFile.renameTo(trapDifferentFile)) {
|
||||
logger.warn("TRAP difference: $realFile vs $trapDifferentFile")
|
||||
} else {
|
||||
|
@ -448,7 +556,8 @@ private abstract class TrapFileWriter(val logger: FileLogger, trapName: String,
|
|||
}
|
||||
}
|
||||
|
||||
private class NonCompressedTrapFileWriter(logger: FileLogger, trapName: String): TrapFileWriter(logger, trapName, "") {
|
||||
private class NonCompressedTrapFileWriter(logger: FileLogger, trapName: String) :
|
||||
TrapFileWriter(logger, trapName, "") {
|
||||
override protected fun getReader(file: File): BufferedReader {
|
||||
return file.bufferedReader()
|
||||
}
|
||||
|
@ -458,12 +567,17 @@ private class NonCompressedTrapFileWriter(logger: FileLogger, trapName: String):
|
|||
}
|
||||
}
|
||||
|
||||
private class GZipCompressedTrapFileWriter(logger: FileLogger, trapName: String): TrapFileWriter(logger, trapName, ".gz") {
|
||||
private class GZipCompressedTrapFileWriter(logger: FileLogger, trapName: String) :
|
||||
TrapFileWriter(logger, trapName, ".gz") {
|
||||
override protected fun getReader(file: File): BufferedReader {
|
||||
return BufferedReader(InputStreamReader(GZIPInputStream(BufferedInputStream(FileInputStream(file)))))
|
||||
return BufferedReader(
|
||||
InputStreamReader(GZIPInputStream(BufferedInputStream(FileInputStream(file))))
|
||||
)
|
||||
}
|
||||
|
||||
override protected fun getWriter(file: File): BufferedWriter {
|
||||
return BufferedWriter(OutputStreamWriter(GZIPOutputStream(BufferedOutputStream(FileOutputStream(file)))))
|
||||
return BufferedWriter(
|
||||
OutputStreamWriter(GZIPOutputStream(BufferedOutputStream(FileOutputStream(file))))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,31 +1,21 @@
|
|||
package com.github.codeql
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
|
||||
/**
|
||||
* This represents a label (`#...`) in a TRAP file.
|
||||
*/
|
||||
interface Label<T: AnyDbType> {
|
||||
fun <U: AnyDbType> cast(): Label<U> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return this as Label<U>
|
||||
/** This represents a label (`#...`) in a TRAP file. */
|
||||
interface Label<T : AnyDbType> {
|
||||
fun <U : AnyDbType> cast(): Label<U> {
|
||||
@Suppress("UNCHECKED_CAST") return this as Label<U>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The label `#i`, e.g. `#123`. Most labels we generate are of this
|
||||
* form.
|
||||
*/
|
||||
class IntLabel<T: AnyDbType>(val i: Int): Label<T> {
|
||||
/** The label `#i`, e.g. `#123`. Most labels we generate are of this form. */
|
||||
class IntLabel<T : AnyDbType>(val i: Int) : Label<T> {
|
||||
override fun toString(): String = "#$i"
|
||||
}
|
||||
|
||||
/**
|
||||
* The label `#name`, e.g. `#compilation`. This is used when labels are
|
||||
* shared between different components (e.g. when both the interceptor
|
||||
* and the extractor need to refer to the same label).
|
||||
* The label `#name`, e.g. `#compilation`. This is used when labels are shared between different
|
||||
* components (e.g. when both the interceptor and the extractor need to refer to the same label).
|
||||
*/
|
||||
class StringLabel<T: AnyDbType>(val name: String): Label<T> {
|
||||
class StringLabel<T : AnyDbType>(val name: String) : Label<T> {
|
||||
override fun toString(): String = "#$name"
|
||||
}
|
||||
|
|
|
@ -2,11 +2,7 @@ package com.github.codeql
|
|||
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
|
||||
class LinesOfCode(
|
||||
val logger: FileLogger,
|
||||
val tw: FileTrapWriter,
|
||||
val file: IrFile
|
||||
) {
|
||||
class LinesOfCode(val logger: FileLogger, val tw: FileTrapWriter, val file: IrFile) {
|
||||
val linesOfCodePSI = LinesOfCodePSI(logger, tw, file)
|
||||
val linesOfCodeLighterAST = LinesOfCodeLighterAST(logger, tw, file)
|
||||
|
||||
|
@ -14,7 +10,10 @@ class LinesOfCode(
|
|||
val psiExtracted = linesOfCodePSI.linesOfCodeInFile(id)
|
||||
val lighterASTExtracted = linesOfCodeLighterAST.linesOfCodeInFile(id)
|
||||
if (psiExtracted && lighterASTExtracted) {
|
||||
logger.warnElement("Both PSI and LighterAST number-of-lines-in-file information for ${file.path}.", file)
|
||||
logger.warnElement(
|
||||
"Both PSI and LighterAST number-of-lines-in-file information for ${file.path}.",
|
||||
file
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +21,10 @@ class LinesOfCode(
|
|||
val psiExtracted = linesOfCodePSI.linesOfCodeInDeclaration(d, id)
|
||||
val lighterASTExtracted = linesOfCodeLighterAST.linesOfCodeInDeclaration(d, id)
|
||||
if (psiExtracted && lighterASTExtracted) {
|
||||
logger.warnElement("Both PSI and LighterAST number-of-lines-in-file information for declaration.", d)
|
||||
logger.warnElement(
|
||||
"Both PSI and LighterAST number-of-lines-in-file information for declaration.",
|
||||
d
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,20 +7,17 @@ import com.intellij.psi.PsiWhiteSpace
|
|||
import org.jetbrains.kotlin.config.KotlinCompilerVersion
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.kdoc.psi.api.KDocElement
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtVisitor
|
||||
|
||||
class LinesOfCodePSI(
|
||||
val logger: FileLogger,
|
||||
val tw: FileTrapWriter,
|
||||
val file: IrFile
|
||||
) {
|
||||
val psi2Ir = getPsi2Ir().also {
|
||||
if (it == null) {
|
||||
logger.warn("Lines of code will not be populated as Kotlin version is too old (${KotlinCompilerVersion.getVersion()})")
|
||||
class LinesOfCodePSI(val logger: FileLogger, val tw: FileTrapWriter, val file: IrFile) {
|
||||
val psi2Ir =
|
||||
getPsi2Ir().also {
|
||||
if (it == null) {
|
||||
logger.warn(
|
||||
"Lines of code will not be populated as Kotlin version is too old (${KotlinCompilerVersion.getVersion()})"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun linesOfCodeInFile(id: Label<DbFile>): Boolean {
|
||||
if (psi2Ir == null) {
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.github.codeql
|
|||
import com.github.codeql.utils.versions.copyParameterToFunction
|
||||
import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||
import com.github.codeql.utils.versions.getAnnotationType
|
||||
import java.lang.annotation.ElementType
|
||||
import java.util.HashSet
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
|
@ -48,10 +50,12 @@ import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
|||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.lang.annotation.ElementType
|
||||
import java.util.HashSet
|
||||
|
||||
class MetaAnnotationSupport(private val logger: FileLogger, private val pluginContext: IrPluginContext, private val extractor: KotlinFileExtractor) {
|
||||
class MetaAnnotationSupport(
|
||||
private val logger: FileLogger,
|
||||
private val pluginContext: IrPluginContext,
|
||||
private val extractor: KotlinFileExtractor
|
||||
) {
|
||||
|
||||
// Taken from AdditionalIrUtils.kt (not available in Kotlin < 1.6)
|
||||
private val IrConstructorCall.annotationClass
|
||||
|
@ -82,8 +86,7 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
wrapAnnotationEntriesInContainer(annotationClass, containerClass, grouped)?.let {
|
||||
result.add(it)
|
||||
}
|
||||
else
|
||||
logger.warnElement("Failed to find an annotation container class", annotationClass)
|
||||
else logger.warnElement("Failed to find an annotation container class", annotationClass)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -91,9 +94,14 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
// Adapted from RepeatedAnnotationLowering.kt
|
||||
private fun getOrCreateContainerClass(annotationClass: IrClass): IrClass? {
|
||||
val metaAnnotations = annotationClass.annotations
|
||||
val jvmRepeatable = metaAnnotations.find { it.symbol.owner.parentAsClass.fqNameWhenAvailable == JvmAnnotationNames.REPEATABLE_ANNOTATION }
|
||||
val jvmRepeatable =
|
||||
metaAnnotations.find {
|
||||
it.symbol.owner.parentAsClass.fqNameWhenAvailable ==
|
||||
JvmAnnotationNames.REPEATABLE_ANNOTATION
|
||||
}
|
||||
return if (jvmRepeatable != null) {
|
||||
((jvmRepeatable.getValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol)?.owner
|
||||
((jvmRepeatable.getValueArgument(0) as? IrClassReference)?.symbol as? IrClassSymbol)
|
||||
?.owner
|
||||
} else {
|
||||
getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass)
|
||||
}
|
||||
|
@ -108,20 +116,28 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
val annotationType = annotationClass.typeWith()
|
||||
val containerConstructor = containerClass.primaryConstructor
|
||||
if (containerConstructor == null) {
|
||||
logger.warnElement("Expected container class to have a primary constructor", containerClass)
|
||||
logger.warnElement(
|
||||
"Expected container class to have a primary constructor",
|
||||
containerClass
|
||||
)
|
||||
return null
|
||||
} else {
|
||||
return IrConstructorCallImpl.fromSymbolOwner(containerClass.defaultType, containerConstructor.symbol).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrVarargImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.arrayClass.typeWith(annotationType),
|
||||
annotationType,
|
||||
entries
|
||||
)
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
containerClass.defaultType,
|
||||
containerConstructor.symbol
|
||||
)
|
||||
}
|
||||
.apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrVarargImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.arrayClass.typeWith(annotationType),
|
||||
annotationType,
|
||||
entries
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,14 +150,19 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTarget>? {
|
||||
val valueArgument = targetEntry.getValueArgument(0) as? IrVararg ?: return null
|
||||
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
|
||||
KotlinTarget.valueOrNull(it.symbol.owner.name.asString())
|
||||
}.toSet()
|
||||
return valueArgument.elements
|
||||
.filterIsInstance<IrGetEnumValue>()
|
||||
.mapNotNull { KotlinTarget.valueOrNull(it.symbol.owner.name.asString()) }
|
||||
.toSet()
|
||||
}
|
||||
|
||||
private val javaAnnotationTargetElementType by lazy { extractor.referenceExternalClass("java.lang.annotation.ElementType") }
|
||||
private val javaAnnotationTargetElementType by lazy {
|
||||
extractor.referenceExternalClass("java.lang.annotation.ElementType")
|
||||
}
|
||||
|
||||
private val javaAnnotationTarget by lazy { extractor.referenceExternalClass("java.lang.annotation.Target") }
|
||||
private val javaAnnotationTarget by lazy {
|
||||
extractor.referenceExternalClass("java.lang.annotation.Target")
|
||||
}
|
||||
|
||||
private fun findEnumEntry(c: IrClass, name: String) =
|
||||
c.declarations.filterIsInstance<IrEnumEntry>().find { it.name.asString() == name }
|
||||
|
@ -168,10 +189,11 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
private val jvm8TargetMap by lazy {
|
||||
javaAnnotationTargetElementType?.let {
|
||||
jvm6TargetMap?.let { j6Map ->
|
||||
j6Map + mapOf(
|
||||
KotlinTarget.TYPE_PARAMETER to findEnumEntry(it, "TYPE_PARAMETER"),
|
||||
KotlinTarget.TYPE to findEnumEntry(it, "TYPE_USE")
|
||||
)
|
||||
j6Map +
|
||||
mapOf(
|
||||
KotlinTarget.TYPE_PARAMETER to findEnumEntry(it, "TYPE_PARAMETER"),
|
||||
KotlinTarget.TYPE to findEnumEntry(it, "TYPE_USE")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,45 +201,59 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
private fun getAnnotationTargetMap() =
|
||||
if (pluginContext.platform?.any { it.targetPlatformVersion == JvmTarget.JVM_1_6 } == true)
|
||||
jvm6TargetMap
|
||||
else
|
||||
jvm8TargetMap
|
||||
else jvm8TargetMap
|
||||
|
||||
// Adapted from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateTargetAnnotation(c: IrClass): IrConstructorCall? {
|
||||
if (c.hasAnnotation(JvmAnnotationNames.TARGET_ANNOTATION))
|
||||
return null
|
||||
if (c.hasAnnotation(JvmAnnotationNames.TARGET_ANNOTATION)) return null
|
||||
val elementType = javaAnnotationTargetElementType ?: return null
|
||||
val targetType = javaAnnotationTarget ?: return null
|
||||
val targetConstructor = targetType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
val targetConstructor =
|
||||
targetType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
val targets = getApplicableTargetSet(c) ?: return null
|
||||
val annotationTargetMap = getAnnotationTargetMap() ?: return null
|
||||
|
||||
val javaTargets = targets.mapNotNullTo(HashSet()) { annotationTargetMap[it] }.sortedBy {
|
||||
ElementType.valueOf(it.symbol.owner.name.asString())
|
||||
}
|
||||
val vararg = IrVarargImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
type = pluginContext.irBuiltIns.arrayClass.typeWith(elementType.defaultType),
|
||||
varargElementType = elementType.defaultType
|
||||
)
|
||||
val javaTargets =
|
||||
targets
|
||||
.mapNotNullTo(HashSet()) { annotationTargetMap[it] }
|
||||
.sortedBy { ElementType.valueOf(it.symbol.owner.name.asString()) }
|
||||
val vararg =
|
||||
IrVarargImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
type = pluginContext.irBuiltIns.arrayClass.typeWith(elementType.defaultType),
|
||||
varargElementType = elementType.defaultType
|
||||
)
|
||||
for (target in javaTargets) {
|
||||
vararg.elements.add(
|
||||
IrGetEnumValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, elementType.defaultType, target.symbol
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
elementType.defaultType,
|
||||
target.symbol
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol, 0
|
||||
).apply {
|
||||
putValueArgument(0, vararg)
|
||||
}
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
targetConstructor.returnType,
|
||||
targetConstructor.symbol,
|
||||
0
|
||||
)
|
||||
.apply { putValueArgument(0, vararg) }
|
||||
}
|
||||
|
||||
private val javaAnnotationRetention by lazy { extractor.referenceExternalClass("java.lang.annotation.Retention") }
|
||||
private val javaAnnotationRetentionPolicy by lazy { extractor.referenceExternalClass("java.lang.annotation.RetentionPolicy") }
|
||||
private val javaAnnotationRetentionPolicyRuntime by lazy { javaAnnotationRetentionPolicy?.let { findEnumEntry(it, "RUNTIME") } }
|
||||
private val javaAnnotationRetention by lazy {
|
||||
extractor.referenceExternalClass("java.lang.annotation.Retention")
|
||||
}
|
||||
private val javaAnnotationRetentionPolicy by lazy {
|
||||
extractor.referenceExternalClass("java.lang.annotation.RetentionPolicy")
|
||||
}
|
||||
private val javaAnnotationRetentionPolicyRuntime by lazy {
|
||||
javaAnnotationRetentionPolicy?.let { findEnumEntry(it, "RUNTIME") }
|
||||
}
|
||||
|
||||
private val annotationRetentionMap by lazy {
|
||||
javaAnnotationRetentionPolicy?.let {
|
||||
|
@ -232,118 +268,164 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
// Taken from AnnotationCodegen.kt (not available in Kotlin < 1.6.20)
|
||||
private fun IrClass.getAnnotationRetention(): KotlinRetention? {
|
||||
val retentionArgument =
|
||||
getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(0)
|
||||
as? IrGetEnumValue ?: return null
|
||||
getAnnotation(StandardNames.FqNames.retention)?.getValueArgument(0) as? IrGetEnumValue
|
||||
?: return null
|
||||
val retentionArgumentValue = retentionArgument.symbol.owner
|
||||
return KotlinRetention.valueOf(retentionArgumentValue.name.asString())
|
||||
}
|
||||
|
||||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateRetentionAnnotation(irClass: IrClass): IrConstructorCall? {
|
||||
if (irClass.hasAnnotation(JvmAnnotationNames.RETENTION_ANNOTATION))
|
||||
return null
|
||||
if (irClass.hasAnnotation(JvmAnnotationNames.RETENTION_ANNOTATION)) return null
|
||||
val retentionMap = annotationRetentionMap ?: return null
|
||||
val kotlinRetentionPolicy = irClass.getAnnotationRetention()
|
||||
val javaRetentionPolicy = kotlinRetentionPolicy?.let { retentionMap[it] } ?: javaAnnotationRetentionPolicyRuntime ?: return null
|
||||
val javaRetentionPolicy =
|
||||
kotlinRetentionPolicy?.let { retentionMap[it] }
|
||||
?: javaAnnotationRetentionPolicyRuntime
|
||||
?: return null
|
||||
val retentionPolicyType = javaAnnotationRetentionPolicy ?: return null
|
||||
val retentionType = javaAnnotationRetention ?: return null
|
||||
val targetConstructor = retentionType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
val targetConstructor =
|
||||
retentionType.declarations.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol, 0
|
||||
).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrGetEnumValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionPolicyType.defaultType, javaRetentionPolicy.symbol
|
||||
)
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
targetConstructor.returnType,
|
||||
targetConstructor.symbol,
|
||||
0
|
||||
)
|
||||
}
|
||||
.apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
IrGetEnumValueImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
retentionPolicyType.defaultType,
|
||||
javaRetentionPolicy.symbol
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val javaAnnotationRepeatable by lazy { extractor.referenceExternalClass("java.lang.annotation.Repeatable") }
|
||||
private val kotlinAnnotationRepeatableContainer by lazy { extractor.referenceExternalClass("kotlin.jvm.internal.RepeatableContainer") }
|
||||
private val javaAnnotationRepeatable by lazy {
|
||||
extractor.referenceExternalClass("java.lang.annotation.Repeatable")
|
||||
}
|
||||
private val kotlinAnnotationRepeatableContainer by lazy {
|
||||
extractor.referenceExternalClass("kotlin.jvm.internal.RepeatableContainer")
|
||||
}
|
||||
|
||||
// Taken from declarationBuilders.kt (not available in Kotlin < 1.6):
|
||||
private fun addDefaultGetter(p: IrProperty, parentClass: IrClass) {
|
||||
val field = p.backingField ?:
|
||||
run { logger.warnElement("Expected property to have a backing field", p); return }
|
||||
val field =
|
||||
p.backingField
|
||||
?: run {
|
||||
logger.warnElement("Expected property to have a backing field", p)
|
||||
return
|
||||
}
|
||||
p.addGetter {
|
||||
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
returnType = field.type
|
||||
}.apply {
|
||||
val thisReceiever = parentClass.thisReceiver ?:
|
||||
run { logger.warnElement("Expected property's parent class to have a receiver parameter", parentClass); return }
|
||||
val newParam = copyParameterToFunction(thisReceiever, this)
|
||||
dispatchReceiverParameter = newParam
|
||||
body = factory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET).apply({
|
||||
this.statements.add(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.nothingType,
|
||||
symbol,
|
||||
IrGetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
field.symbol,
|
||||
field.type,
|
||||
IrGetValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
newParam.type,
|
||||
newParam.symbol
|
||||
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
returnType = field.type
|
||||
}
|
||||
.apply {
|
||||
val thisReceiever =
|
||||
parentClass.thisReceiver
|
||||
?: run {
|
||||
logger.warnElement(
|
||||
"Expected property's parent class to have a receiver parameter",
|
||||
parentClass
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
val newParam = copyParameterToFunction(thisReceiever, this)
|
||||
dispatchReceiverParameter = newParam
|
||||
body =
|
||||
factory
|
||||
.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||
.apply({
|
||||
this.statements.add(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.nothingType,
|
||||
symbol,
|
||||
IrGetFieldImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
field.symbol,
|
||||
field.type,
|
||||
IrGetValueImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
newParam.type,
|
||||
newParam.symbol
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from JvmCachedDeclarations.kt
|
||||
private fun getOrCreateSyntheticRepeatableAnnotationContainer(annotationClass: IrClass) =
|
||||
extractor.globalExtensionState.syntheticRepeatableAnnotationContainers.getOrPut(annotationClass) {
|
||||
val containerClass = pluginContext.irFactory.buildClass {
|
||||
kind = ClassKind.ANNOTATION_CLASS
|
||||
name = Name.identifier("Container")
|
||||
}.apply {
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
parent = annotationClass
|
||||
superTypes = listOf(getAnnotationType(pluginContext))
|
||||
}
|
||||
extractor.globalExtensionState.syntheticRepeatableAnnotationContainers.getOrPut(
|
||||
annotationClass
|
||||
) {
|
||||
val containerClass =
|
||||
pluginContext.irFactory
|
||||
.buildClass {
|
||||
kind = ClassKind.ANNOTATION_CLASS
|
||||
name = Name.identifier("Container")
|
||||
}
|
||||
.apply {
|
||||
createImplicitParameterDeclarationWithWrappedDescriptor()
|
||||
parent = annotationClass
|
||||
superTypes = listOf(getAnnotationType(pluginContext))
|
||||
}
|
||||
|
||||
val propertyName = Name.identifier("value")
|
||||
val propertyType = pluginContext.irBuiltIns.arrayClass.typeWith(annotationClass.typeWith())
|
||||
val propertyType =
|
||||
pluginContext.irBuiltIns.arrayClass.typeWith(annotationClass.typeWith())
|
||||
|
||||
containerClass.addConstructor {
|
||||
isPrimary = true
|
||||
}.apply {
|
||||
addValueParameter(propertyName.identifier, propertyType)
|
||||
}
|
||||
containerClass
|
||||
.addConstructor { isPrimary = true }
|
||||
.apply { addValueParameter(propertyName.identifier, propertyType) }
|
||||
|
||||
containerClass.addProperty {
|
||||
name = propertyName
|
||||
}.apply property@{
|
||||
backingField = pluginContext.irFactory.buildField {
|
||||
name = propertyName
|
||||
type = propertyType
|
||||
}.apply {
|
||||
parent = containerClass
|
||||
correspondingPropertySymbol = this@property.symbol
|
||||
containerClass
|
||||
.addProperty { name = propertyName }
|
||||
.apply property@{
|
||||
backingField =
|
||||
pluginContext.irFactory
|
||||
.buildField {
|
||||
name = propertyName
|
||||
type = propertyType
|
||||
}
|
||||
.apply {
|
||||
parent = containerClass
|
||||
correspondingPropertySymbol = this@property.symbol
|
||||
}
|
||||
addDefaultGetter(this, containerClass)
|
||||
}
|
||||
addDefaultGetter(this, containerClass)
|
||||
}
|
||||
|
||||
val repeatableContainerAnnotation = kotlinAnnotationRepeatableContainer?.constructors?.single()
|
||||
val repeatableContainerAnnotation =
|
||||
kotlinAnnotationRepeatableContainer?.constructors?.single()
|
||||
|
||||
containerClass.annotations = annotationClass.annotations
|
||||
.filter {
|
||||
it.isAnnotationWithEqualFqName(StandardNames.FqNames.retention) ||
|
||||
containerClass.annotations =
|
||||
annotationClass.annotations
|
||||
.filter {
|
||||
it.isAnnotationWithEqualFqName(StandardNames.FqNames.retention) ||
|
||||
it.isAnnotationWithEqualFqName(StandardNames.FqNames.target)
|
||||
}
|
||||
.map { it.deepCopyWithSymbols(containerClass) } +
|
||||
}
|
||||
.map { it.deepCopyWithSymbols(containerClass) } +
|
||||
listOfNotNull(
|
||||
repeatableContainerAnnotation?.let {
|
||||
IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, it.returnType, it.symbol, 0
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
it.returnType,
|
||||
it.symbol,
|
||||
0
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -352,45 +434,80 @@ class MetaAnnotationSupport(private val logger: FileLogger, private val pluginCo
|
|||
}
|
||||
|
||||
// Adapted from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateRepeatableAnnotation(irClass: IrClass, extractAnnotationTypeAccesses: Boolean): IrConstructorCall? {
|
||||
if (!irClass.hasAnnotation(StandardNames.FqNames.repeatable) ||
|
||||
irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION)
|
||||
) return null
|
||||
private fun generateRepeatableAnnotation(
|
||||
irClass: IrClass,
|
||||
extractAnnotationTypeAccesses: Boolean
|
||||
): IrConstructorCall? {
|
||||
if (
|
||||
!irClass.hasAnnotation(StandardNames.FqNames.repeatable) ||
|
||||
irClass.hasAnnotation(JvmAnnotationNames.REPEATABLE_ANNOTATION)
|
||||
)
|
||||
return null
|
||||
|
||||
val repeatableConstructor = javaAnnotationRepeatable?.declarations?.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
val repeatableConstructor =
|
||||
javaAnnotationRepeatable?.declarations?.firstIsInstanceOrNull<IrConstructor>()
|
||||
?: return null
|
||||
|
||||
val containerClass = getOrCreateSyntheticRepeatableAnnotationContainer(irClass)
|
||||
// Whenever a repeatable annotation with a Kotlin-synthesised container is extracted, extract the synthetic container to the same trap file.
|
||||
extractor.extractClassSource(containerClass, extractDeclarations = true, extractStaticInitializer = true, extractPrivateMembers = true, extractFunctionBodies = extractAnnotationTypeAccesses)
|
||||
|
||||
val containerReference = IrClassReferenceImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, pluginContext.irBuiltIns.kClassClass.typeWith(containerClass.defaultType),
|
||||
containerClass.symbol, containerClass.defaultType
|
||||
// Whenever a repeatable annotation with a Kotlin-synthesised container is extracted,
|
||||
// extract the synthetic container to the same trap file.
|
||||
extractor.extractClassSource(
|
||||
containerClass,
|
||||
extractDeclarations = true,
|
||||
extractStaticInitializer = true,
|
||||
extractPrivateMembers = true,
|
||||
extractFunctionBodies = extractAnnotationTypeAccesses
|
||||
)
|
||||
|
||||
val containerReference =
|
||||
IrClassReferenceImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
pluginContext.irBuiltIns.kClassClass.typeWith(containerClass.defaultType),
|
||||
containerClass.symbol,
|
||||
containerClass.defaultType
|
||||
)
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, repeatableConstructor.returnType, repeatableConstructor.symbol, 0
|
||||
).apply {
|
||||
putValueArgument(0, containerReference)
|
||||
}
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
repeatableConstructor.returnType,
|
||||
repeatableConstructor.symbol,
|
||||
0
|
||||
)
|
||||
.apply { putValueArgument(0, containerReference) }
|
||||
}
|
||||
|
||||
private val javaAnnotationDocumented by lazy { extractor.referenceExternalClass("java.lang.annotation.Documented") }
|
||||
private val javaAnnotationDocumented by lazy {
|
||||
extractor.referenceExternalClass("java.lang.annotation.Documented")
|
||||
}
|
||||
|
||||
// Taken from AdditionalClassAnnotationLowering.kt
|
||||
private fun generateDocumentedAnnotation(irClass: IrClass): IrConstructorCall? {
|
||||
if (!irClass.hasAnnotation(StandardNames.FqNames.mustBeDocumented) ||
|
||||
irClass.hasAnnotation(JvmAnnotationNames.DOCUMENTED_ANNOTATION)
|
||||
) return null
|
||||
if (
|
||||
!irClass.hasAnnotation(StandardNames.FqNames.mustBeDocumented) ||
|
||||
irClass.hasAnnotation(JvmAnnotationNames.DOCUMENTED_ANNOTATION)
|
||||
)
|
||||
return null
|
||||
|
||||
val documentedConstructor = javaAnnotationDocumented?.declarations?.firstIsInstanceOrNull<IrConstructor>() ?: return null
|
||||
val documentedConstructor =
|
||||
javaAnnotationDocumented?.declarations?.firstIsInstanceOrNull<IrConstructor>()
|
||||
?: return null
|
||||
|
||||
return IrConstructorCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, documentedConstructor.returnType, documentedConstructor.symbol, 0
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
documentedConstructor.returnType,
|
||||
documentedConstructor.symbol,
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
fun generateJavaMetaAnnotations(c: IrClass, extractAnnotationTypeAccesses: Boolean) =
|
||||
// This is essentially AdditionalClassAnnotationLowering adapted to run outside the backend.
|
||||
listOfNotNull(generateTargetAnnotation(c), generateRetentionAnnotation(c), generateRepeatableAnnotation(c, extractAnnotationTypeAccesses), generateDocumentedAnnotation(c))
|
||||
listOfNotNull(
|
||||
generateTargetAnnotation(c),
|
||||
generateRetentionAnnotation(c),
|
||||
generateRepeatableAnnotation(c, extractAnnotationTypeAccesses),
|
||||
generateDocumentedAnnotation(c)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,93 +1,105 @@
|
|||
package com.github.codeql
|
||||
|
||||
import com.github.codeql.utils.*
|
||||
import com.github.codeql.utils.versions.*
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import com.github.codeql.utils.*
|
||||
import com.github.codeql.utils.versions.*
|
||||
|
||||
class PrimitiveTypeMapping(val logger: Logger, val pluginContext: IrPluginContext) {
|
||||
fun getPrimitiveInfo(s: IrSimpleType) =
|
||||
s.classOrNull?.let {
|
||||
if ((it.owner.parent as? IrPackageFragment)?.packageFqName == StandardNames.BUILT_INS_PACKAGE_FQ_NAME)
|
||||
if (
|
||||
(it.owner.parent as? IrPackageFragment)?.packageFqName ==
|
||||
StandardNames.BUILT_INS_PACKAGE_FQ_NAME
|
||||
)
|
||||
mapping[it.owner.name]
|
||||
else
|
||||
null
|
||||
else null
|
||||
}
|
||||
|
||||
data class PrimitiveTypeInfo(
|
||||
val primitiveName: String?,
|
||||
val otherIsPrimitive: Boolean,
|
||||
val javaClass: IrClass,
|
||||
val kotlinPackageName: String, val kotlinClassName: String
|
||||
val kotlinPackageName: String,
|
||||
val kotlinClassName: String
|
||||
)
|
||||
|
||||
private fun findClass(fqName: String, fallback: IrClass): IrClass {
|
||||
val symbol = getClassByFqName(pluginContext, fqName)
|
||||
if(symbol == null) {
|
||||
if (symbol == null) {
|
||||
logger.warn("Can't find $fqName")
|
||||
// Do the best we can
|
||||
return fallback
|
||||
} else {
|
||||
return symbol.owner
|
||||
return symbol.owner
|
||||
}
|
||||
}
|
||||
|
||||
private val mapping = {
|
||||
val kotlinByte = pluginContext.irBuiltIns.byteClass.owner
|
||||
val javaLangByte = findClass("java.lang.Byte", kotlinByte)
|
||||
val kotlinShort = pluginContext.irBuiltIns.shortClass.owner
|
||||
val javaLangShort = findClass("java.lang.Short", kotlinShort)
|
||||
val kotlinInt = pluginContext.irBuiltIns.intClass.owner
|
||||
val javaLangInteger = findClass("java.lang.Integer", kotlinInt)
|
||||
val kotlinLong = pluginContext.irBuiltIns.longClass.owner
|
||||
val javaLangLong = findClass("java.lang.Long", kotlinLong)
|
||||
private val mapping =
|
||||
{
|
||||
val kotlinByte = pluginContext.irBuiltIns.byteClass.owner
|
||||
val javaLangByte = findClass("java.lang.Byte", kotlinByte)
|
||||
val kotlinShort = pluginContext.irBuiltIns.shortClass.owner
|
||||
val javaLangShort = findClass("java.lang.Short", kotlinShort)
|
||||
val kotlinInt = pluginContext.irBuiltIns.intClass.owner
|
||||
val javaLangInteger = findClass("java.lang.Integer", kotlinInt)
|
||||
val kotlinLong = pluginContext.irBuiltIns.longClass.owner
|
||||
val javaLangLong = findClass("java.lang.Long", kotlinLong)
|
||||
|
||||
val kotlinUByte = findClass("kotlin.UByte", kotlinByte)
|
||||
val kotlinUShort = findClass("kotlin.UShort", kotlinShort)
|
||||
val kotlinUInt = findClass("kotlin.UInt", kotlinInt)
|
||||
val kotlinULong = findClass("kotlin.ULong", kotlinLong)
|
||||
val kotlinUByte = findClass("kotlin.UByte", kotlinByte)
|
||||
val kotlinUShort = findClass("kotlin.UShort", kotlinShort)
|
||||
val kotlinUInt = findClass("kotlin.UInt", kotlinInt)
|
||||
val kotlinULong = findClass("kotlin.ULong", kotlinLong)
|
||||
|
||||
val kotlinDouble = pluginContext.irBuiltIns.doubleClass.owner
|
||||
val javaLangDouble = findClass("java.lang.Double", kotlinDouble)
|
||||
val kotlinFloat = pluginContext.irBuiltIns.floatClass.owner
|
||||
val javaLangFloat = findClass("java.lang.Float", kotlinFloat)
|
||||
val kotlinDouble = pluginContext.irBuiltIns.doubleClass.owner
|
||||
val javaLangDouble = findClass("java.lang.Double", kotlinDouble)
|
||||
val kotlinFloat = pluginContext.irBuiltIns.floatClass.owner
|
||||
val javaLangFloat = findClass("java.lang.Float", kotlinFloat)
|
||||
|
||||
val kotlinBoolean = pluginContext.irBuiltIns.booleanClass.owner
|
||||
val javaLangBoolean = findClass("java.lang.Boolean", kotlinBoolean)
|
||||
val kotlinBoolean = pluginContext.irBuiltIns.booleanClass.owner
|
||||
val javaLangBoolean = findClass("java.lang.Boolean", kotlinBoolean)
|
||||
|
||||
val kotlinChar = pluginContext.irBuiltIns.charClass.owner
|
||||
val javaLangCharacter = findClass("java.lang.Character", kotlinChar)
|
||||
val kotlinChar = pluginContext.irBuiltIns.charClass.owner
|
||||
val javaLangCharacter = findClass("java.lang.Character", kotlinChar)
|
||||
|
||||
val kotlinUnit = pluginContext.irBuiltIns.unitClass.owner
|
||||
val kotlinUnit = pluginContext.irBuiltIns.unitClass.owner
|
||||
|
||||
val kotlinNothing = pluginContext.irBuiltIns.nothingClass.owner
|
||||
val javaLangVoid = findClass("java.lang.Void", kotlinNothing)
|
||||
val kotlinNothing = pluginContext.irBuiltIns.nothingClass.owner
|
||||
val javaLangVoid = findClass("java.lang.Void", kotlinNothing)
|
||||
|
||||
mapOf(
|
||||
StandardNames.FqNames._byte.shortName() to PrimitiveTypeInfo("byte", true, javaLangByte, "kotlin", "Byte"),
|
||||
StandardNames.FqNames._short.shortName() to PrimitiveTypeInfo("short", true, javaLangShort, "kotlin", "Short"),
|
||||
StandardNames.FqNames._int.shortName() to PrimitiveTypeInfo("int", true, javaLangInteger, "kotlin", "Int"),
|
||||
StandardNames.FqNames._long.shortName() to PrimitiveTypeInfo("long", true, javaLangLong, "kotlin", "Long"),
|
||||
|
||||
StandardNames.FqNames.uByteFqName.shortName() to PrimitiveTypeInfo("byte", true, kotlinUByte, "kotlin", "UByte"),
|
||||
StandardNames.FqNames.uShortFqName.shortName() to PrimitiveTypeInfo("short", true, kotlinUShort, "kotlin", "UShort"),
|
||||
StandardNames.FqNames.uIntFqName.shortName() to PrimitiveTypeInfo("int", true, kotlinUInt, "kotlin", "UInt"),
|
||||
StandardNames.FqNames.uLongFqName.shortName() to PrimitiveTypeInfo("long", true, kotlinULong, "kotlin", "ULong"),
|
||||
|
||||
StandardNames.FqNames._double.shortName() to PrimitiveTypeInfo("double", true, javaLangDouble, "kotlin", "Double"),
|
||||
StandardNames.FqNames._float.shortName() to PrimitiveTypeInfo("float", true, javaLangFloat, "kotlin", "Float"),
|
||||
|
||||
StandardNames.FqNames._boolean.shortName() to PrimitiveTypeInfo("boolean", true, javaLangBoolean, "kotlin", "Boolean"),
|
||||
|
||||
StandardNames.FqNames._char.shortName() to PrimitiveTypeInfo("char", true, javaLangCharacter, "kotlin", "Char"),
|
||||
|
||||
StandardNames.FqNames.unit.shortName() to PrimitiveTypeInfo("void", false, kotlinUnit, "kotlin", "Unit"),
|
||||
StandardNames.FqNames.nothing.shortName() to PrimitiveTypeInfo(null, true, javaLangVoid, "kotlin", "Nothing"),
|
||||
)
|
||||
}()
|
||||
mapOf(
|
||||
StandardNames.FqNames._byte.shortName() to
|
||||
PrimitiveTypeInfo("byte", true, javaLangByte, "kotlin", "Byte"),
|
||||
StandardNames.FqNames._short.shortName() to
|
||||
PrimitiveTypeInfo("short", true, javaLangShort, "kotlin", "Short"),
|
||||
StandardNames.FqNames._int.shortName() to
|
||||
PrimitiveTypeInfo("int", true, javaLangInteger, "kotlin", "Int"),
|
||||
StandardNames.FqNames._long.shortName() to
|
||||
PrimitiveTypeInfo("long", true, javaLangLong, "kotlin", "Long"),
|
||||
StandardNames.FqNames.uByteFqName.shortName() to
|
||||
PrimitiveTypeInfo("byte", true, kotlinUByte, "kotlin", "UByte"),
|
||||
StandardNames.FqNames.uShortFqName.shortName() to
|
||||
PrimitiveTypeInfo("short", true, kotlinUShort, "kotlin", "UShort"),
|
||||
StandardNames.FqNames.uIntFqName.shortName() to
|
||||
PrimitiveTypeInfo("int", true, kotlinUInt, "kotlin", "UInt"),
|
||||
StandardNames.FqNames.uLongFqName.shortName() to
|
||||
PrimitiveTypeInfo("long", true, kotlinULong, "kotlin", "ULong"),
|
||||
StandardNames.FqNames._double.shortName() to
|
||||
PrimitiveTypeInfo("double", true, javaLangDouble, "kotlin", "Double"),
|
||||
StandardNames.FqNames._float.shortName() to
|
||||
PrimitiveTypeInfo("float", true, javaLangFloat, "kotlin", "Float"),
|
||||
StandardNames.FqNames._boolean.shortName() to
|
||||
PrimitiveTypeInfo("boolean", true, javaLangBoolean, "kotlin", "Boolean"),
|
||||
StandardNames.FqNames._char.shortName() to
|
||||
PrimitiveTypeInfo("char", true, javaLangCharacter, "kotlin", "Char"),
|
||||
StandardNames.FqNames.unit.shortName() to
|
||||
PrimitiveTypeInfo("void", false, kotlinUnit, "kotlin", "Unit"),
|
||||
StandardNames.FqNames.nothing.shortName() to
|
||||
PrimitiveTypeInfo(null, true, javaLangVoid, "kotlin", "Nothing"),
|
||||
)
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -1,92 +1,87 @@
|
|||
package com.github.codeql
|
||||
|
||||
import com.github.codeql.KotlinUsesExtractor.LocallyVisibleFunctionLabels
|
||||
import com.semmle.extractor.java.PopulateFile
|
||||
import com.semmle.util.unicode.UTF8Util
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.path
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.path
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
|
||||
|
||||
import com.semmle.extractor.java.PopulateFile
|
||||
import com.semmle.util.unicode.UTF8Util
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
|
||||
/**
|
||||
* Each `.trap` file has a `TrapLabelManager` while we are writing it.
|
||||
* It provides fresh TRAP label names, and maintains a mapping from keys
|
||||
* (`@"..."`) to labels.
|
||||
* Each `.trap` file has a `TrapLabelManager` while we are writing it. It provides fresh TRAP label
|
||||
* names, and maintains a mapping from keys (`@"..."`) to labels.
|
||||
*/
|
||||
class TrapLabelManager {
|
||||
/** The next integer to use as a label name. */
|
||||
private var nextInt: Int = 100
|
||||
|
||||
/** Returns a fresh label. */
|
||||
fun <T: AnyDbType> getFreshLabel(): Label<T> {
|
||||
fun <T : AnyDbType> getFreshLabel(): Label<T> {
|
||||
return IntLabel(nextInt++)
|
||||
}
|
||||
|
||||
/**
|
||||
* A mapping from a key (`@"..."`) to the label defined to be that
|
||||
* key, if any.
|
||||
*/
|
||||
/** A mapping from a key (`@"..."`) to the label defined to be that key, if any. */
|
||||
val labelMapping: MutableMap<String, Label<*>> = mutableMapOf<String, Label<*>>()
|
||||
|
||||
val anonymousTypeMapping: MutableMap<IrClass, TypeResults> = mutableMapOf()
|
||||
|
||||
val locallyVisibleFunctionLabelMapping: MutableMap<IrFunction, LocallyVisibleFunctionLabels> = mutableMapOf()
|
||||
val locallyVisibleFunctionLabelMapping: MutableMap<IrFunction, LocallyVisibleFunctionLabels> =
|
||||
mutableMapOf()
|
||||
|
||||
/**
|
||||
* The set of labels of generic specialisations that we have extracted
|
||||
* in this TRAP file.
|
||||
* We can't easily avoid duplication between TRAP files, as the labels
|
||||
* contain references to other labels, so we just accept this
|
||||
* duplication.
|
||||
* The set of labels of generic specialisations that we have extracted in this TRAP file. We
|
||||
* can't easily avoid duplication between TRAP files, as the labels contain references to other
|
||||
* labels, so we just accept this duplication.
|
||||
*/
|
||||
val genericSpecialisationsExtracted = HashSet<String>()
|
||||
|
||||
/**
|
||||
* Sometimes, when we extract a file class we don't have the IrFile
|
||||
* for it, so we are not able to give it a location. This means that
|
||||
* the location is written outside of the label creation.
|
||||
* This allows us to keep track of whether we've written the location
|
||||
* already in this TRAP file, to avoid duplication.
|
||||
* Sometimes, when we extract a file class we don't have the IrFile for it, so we are not able
|
||||
* to give it a location. This means that the location is written outside of the label creation.
|
||||
* This allows us to keep track of whether we've written the location already in this TRAP file,
|
||||
* to avoid duplication.
|
||||
*/
|
||||
val fileClassLocationsExtracted = HashSet<IrFile>()
|
||||
}
|
||||
|
||||
/**
|
||||
* A `TrapWriter` is used to write TRAP to a particular TRAP file.
|
||||
* There may be multiple `TrapWriter`s for the same file, as different
|
||||
* instances will have different additional state, but they must all
|
||||
* share the same `TrapLabelManager` and `BufferedWriter`.
|
||||
* A `TrapWriter` is used to write TRAP to a particular TRAP file. There may be multiple
|
||||
* `TrapWriter`s for the same file, as different instances will have different additional state, but
|
||||
* they must all share the same `TrapLabelManager` and `BufferedWriter`.
|
||||
*/
|
||||
// TODO lm was `protected` before anonymousTypeMapping and locallyVisibleFunctionLabelMapping moved into it. Should we re-protect it and provide accessors?
|
||||
abstract class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLabelManager, private val bw: BufferedWriter) {
|
||||
// TODO lm was `protected` before anonymousTypeMapping and locallyVisibleFunctionLabelMapping moved
|
||||
// into it. Should we re-protect it and provide accessors?
|
||||
abstract class TrapWriter(
|
||||
protected val loggerBase: LoggerBase,
|
||||
val lm: TrapLabelManager,
|
||||
private val bw: BufferedWriter
|
||||
) {
|
||||
abstract fun getDiagnosticTrapWriter(): DiagnosticTrapWriter
|
||||
|
||||
/**
|
||||
* Returns the label that is defined to be the given key, if such
|
||||
* a label exists, and `null` otherwise. Most users will want to use
|
||||
* `getLabelFor` instead, which allows non-existent labels to be
|
||||
* initialised.
|
||||
* Returns the label that is defined to be the given key, if such a label exists, and `null`
|
||||
* otherwise. Most users will want to use `getLabelFor` instead, which allows non-existent
|
||||
* labels to be initialised.
|
||||
*/
|
||||
fun <T: AnyDbType> getExistingLabelFor(key: String): Label<T>? {
|
||||
fun <T : AnyDbType> getExistingLabelFor(key: String): Label<T>? {
|
||||
return lm.labelMapping.get(key)?.cast<T>()
|
||||
}
|
||||
/**
|
||||
* Returns the label for the given key, if one exists.
|
||||
* Otherwise, a fresh label is bound to that key, `initialise`
|
||||
* is run on it, and it is returned.
|
||||
* Returns the label for the given key, if one exists. Otherwise, a fresh label is bound to that
|
||||
* key, `initialise` is run on it, and it is returned.
|
||||
*/
|
||||
@JvmOverloads // Needed so Java can call a method with an optional argument
|
||||
fun <T: AnyDbType> getLabelFor(key: String, initialise: (Label<T>) -> Unit = {}): Label<T> {
|
||||
fun <T : AnyDbType> getLabelFor(key: String, initialise: (Label<T>) -> Unit = {}): Label<T> {
|
||||
val maybeLabel: Label<T>? = getExistingLabelFor(key)
|
||||
if(maybeLabel == null) {
|
||||
if (maybeLabel == null) {
|
||||
val label: Label<T> = lm.getFreshLabel()
|
||||
lm.labelMapping.put(key, label)
|
||||
writeTrap("$label = $key\n")
|
||||
|
@ -97,30 +92,24 @@ abstract class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLab
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a label for a fresh ID (i.e. a new label bound to `*`).
|
||||
*/
|
||||
fun <T: AnyDbType> getFreshIdLabel(): Label<T> {
|
||||
/** Returns a label for a fresh ID (i.e. a new label bound to `*`). */
|
||||
fun <T : AnyDbType> getFreshIdLabel(): Label<T> {
|
||||
val label: Label<T> = lm.getFreshLabel()
|
||||
writeTrap("$label = *\n")
|
||||
return label
|
||||
}
|
||||
|
||||
/**
|
||||
* It is not easy to assign keys to local variables, so they get
|
||||
* given `*` IDs. However, the same variable may be referred to
|
||||
* from distant places in the IR, so we need a way to find out
|
||||
* which label is used for a given local variable. This information
|
||||
* is stored in this mapping.
|
||||
*/
|
||||
private val variableLabelMapping: MutableMap<IrVariable, Label<out DbLocalvar>> = mutableMapOf<IrVariable, Label<out DbLocalvar>>()
|
||||
/**
|
||||
* This returns the label used for a local variable, creating one
|
||||
* if none currently exists.
|
||||
* It is not easy to assign keys to local variables, so they get given `*` IDs. However, the
|
||||
* same variable may be referred to from distant places in the IR, so we need a way to find out
|
||||
* which label is used for a given local variable. This information is stored in this mapping.
|
||||
*/
|
||||
private val variableLabelMapping: MutableMap<IrVariable, Label<out DbLocalvar>> =
|
||||
mutableMapOf<IrVariable, Label<out DbLocalvar>>()
|
||||
/** This returns the label used for a local variable, creating one if none currently exists. */
|
||||
fun <T> getVariableLabelFor(v: IrVariable): Label<out DbLocalvar> {
|
||||
val maybeLabel = variableLabelMapping.get(v)
|
||||
if(maybeLabel == null) {
|
||||
if (maybeLabel == null) {
|
||||
val label = getFreshIdLabel<DbLocalvar>()
|
||||
variableLabelMapping.put(v, label)
|
||||
return label
|
||||
|
@ -134,43 +123,41 @@ abstract class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLab
|
|||
}
|
||||
|
||||
/**
|
||||
* This returns a label for the location described by its arguments.
|
||||
* Typically users will not want to call this directly, but instead
|
||||
* use `unknownLocation`, or overloads of this defined by subclasses.
|
||||
* This returns a label for the location described by its arguments. Typically users will not
|
||||
* want to call this directly, but instead use `unknownLocation`, or overloads of this defined
|
||||
* by subclasses.
|
||||
*/
|
||||
fun getLocation(fileId: Label<DbFile>, startLine: Int, startColumn: Int, endLine: Int, endColumn: Int): Label<DbLocation> {
|
||||
fun getLocation(
|
||||
fileId: Label<DbFile>,
|
||||
startLine: Int,
|
||||
startColumn: Int,
|
||||
endLine: Int,
|
||||
endColumn: Int
|
||||
): Label<DbLocation> {
|
||||
return getLabelFor("@\"loc,{$fileId},$startLine,$startColumn,$endLine,$endColumn\"") {
|
||||
writeLocations_default(it, fileId, startLine, startColumn, endLine, endColumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The label for the 'unknown' file ID.
|
||||
* Users will want to use `unknownLocation` instead.
|
||||
* This is lazy, as we don't want to define it in a TRAP file unless
|
||||
* the TRAP file actually contains something in the 'unknown' file.
|
||||
* The label for the 'unknown' file ID. Users will want to use `unknownLocation` instead. This
|
||||
* is lazy, as we don't want to define it in a TRAP file unless the TRAP file actually contains
|
||||
* something in the 'unknown' file.
|
||||
*/
|
||||
protected val unknownFileId: Label<DbFile> by lazy {
|
||||
val unknownFileLabel = "@\";sourcefile\""
|
||||
getLabelFor(unknownFileLabel, {
|
||||
writeFiles(it, "")
|
||||
})
|
||||
getLabelFor(unknownFileLabel, { writeFiles(it, "") })
|
||||
}
|
||||
|
||||
/**
|
||||
* The label for the 'unknown' location.
|
||||
* This is lazy, as we don't want to define it in a TRAP file unless
|
||||
* the TRAP file actually contains something with an 'unknown'
|
||||
* location.
|
||||
* The label for the 'unknown' location. This is lazy, as we don't want to define it in a TRAP
|
||||
* file unless the TRAP file actually contains something with an 'unknown' location.
|
||||
*/
|
||||
val unknownLocation: Label<DbLocation> by lazy {
|
||||
getWholeFileLocation(unknownFileId)
|
||||
}
|
||||
val unknownLocation: Label<DbLocation> by lazy { getWholeFileLocation(unknownFileId) }
|
||||
|
||||
/**
|
||||
* Returns the label for the file `filePath`.
|
||||
* If `populateFileTables` is true, then this also adds rows to the
|
||||
* `files` and `folders` tables for this file.
|
||||
* Returns the label for the file `filePath`. If `populateFileTables` is true, then this also
|
||||
* adds rows to the `files` and `folders` tables for this file.
|
||||
*/
|
||||
fun mkFileId(filePath: String, populateFileTables: Boolean): Label<DbFile> {
|
||||
// If a file is in a jar, then the Kotlin compiler gives
|
||||
|
@ -178,65 +165,65 @@ abstract class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLab
|
|||
// it as appropriate, to make the right file ID.
|
||||
val populateFile = PopulateFile(this)
|
||||
val splitFilePath = filePath.split("!/")
|
||||
if(splitFilePath.size == 1) {
|
||||
if (splitFilePath.size == 1) {
|
||||
return populateFile.getFileLabel(File(filePath), populateFileTables)
|
||||
} else {
|
||||
return populateFile.getFileInJarLabel(File(splitFilePath.get(0)), splitFilePath.get(1), populateFileTables)
|
||||
return populateFile.getFileInJarLabel(
|
||||
File(splitFilePath.get(0)),
|
||||
splitFilePath.get(1),
|
||||
populateFileTables
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If you have an ID for a file, then this gets a label for the
|
||||
* location representing the whole of that file.
|
||||
* If you have an ID for a file, then this gets a label for the location representing the whole
|
||||
* of that file.
|
||||
*/
|
||||
fun getWholeFileLocation(fileId: Label<DbFile>): Label<DbLocation> {
|
||||
return getLocation(fileId, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a raw string into the TRAP file. Users should call one of
|
||||
* the wrapper functions instead.
|
||||
* Write a raw string into the TRAP file. Users should call one of the wrapper functions
|
||||
* instead.
|
||||
*/
|
||||
fun writeTrap(trap: String) {
|
||||
bw.write(trap)
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a comment into the TRAP file.
|
||||
*/
|
||||
/** Write a comment into the TRAP file. */
|
||||
fun writeComment(comment: String) {
|
||||
writeTrap("// ${comment.replace("\n", "\n// ")}\n")
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the TRAP file.
|
||||
*/
|
||||
/** Flush the TRAP file. */
|
||||
fun flush() {
|
||||
bw.flush()
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string so that it can be used in a TRAP string literal,
|
||||
* i.e. with `"` escaped as `""`.
|
||||
*/
|
||||
* Escape a string so that it can be used in a TRAP string literal, i.e. with `"` escaped as
|
||||
* `""`.
|
||||
*/
|
||||
fun escapeTrapString(str: String) = str.replace("\"", "\"\"")
|
||||
|
||||
/**
|
||||
* TRAP string literals are limited to 1 megabyte.
|
||||
*/
|
||||
/** TRAP string literals are limited to 1 megabyte. */
|
||||
private val MAX_STRLEN = 1.shl(20)
|
||||
|
||||
/**
|
||||
* Truncate a string, if necessary, so that it can be used as a TRAP
|
||||
* string literal. TRAP string literals are limited to 1 megabyte.
|
||||
* Truncate a string, if necessary, so that it can be used as a TRAP string literal. TRAP string
|
||||
* literals are limited to 1 megabyte.
|
||||
*/
|
||||
fun truncateString(str: String): String {
|
||||
val len = str.length
|
||||
val newLen = UTF8Util.encodablePrefixLength(str, MAX_STRLEN)
|
||||
if (newLen < len) {
|
||||
loggerBase.warn(this.getDiagnosticTrapWriter(),
|
||||
loggerBase.warn(
|
||||
this.getDiagnosticTrapWriter(),
|
||||
"Truncated string of length $len",
|
||||
"Truncated string of length $len, starting '${str.take(100)}', ending '${str.takeLast(100)}'")
|
||||
"Truncated string of length $len, starting '${str.take(100)}', ending '${str.takeLast(100)}'"
|
||||
)
|
||||
return str.take(newLen)
|
||||
} else {
|
||||
return str
|
||||
|
@ -244,69 +231,75 @@ abstract class TrapWriter (protected val loggerBase: LoggerBase, val lm: TrapLab
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets a FileTrapWriter like this one (using the same label manager,
|
||||
* writer etc), but using the given `filePath` for locations.
|
||||
* Gets a FileTrapWriter like this one (using the same label manager, writer etc), but using the
|
||||
* given `filePath` for locations.
|
||||
*/
|
||||
fun makeFileTrapWriter(filePath: String, populateFileTables: Boolean) =
|
||||
FileTrapWriter(loggerBase, lm, bw, this.getDiagnosticTrapWriter(), filePath, populateFileTables)
|
||||
FileTrapWriter(
|
||||
loggerBase,
|
||||
lm,
|
||||
bw,
|
||||
this.getDiagnosticTrapWriter(),
|
||||
filePath,
|
||||
populateFileTables
|
||||
)
|
||||
|
||||
/**
|
||||
* Gets a FileTrapWriter like this one (using the same label manager,
|
||||
* writer etc), but using the given `IrFile` for locations.
|
||||
* Gets a FileTrapWriter like this one (using the same label manager, writer etc), but using the
|
||||
* given `IrFile` for locations.
|
||||
*/
|
||||
fun makeSourceFileTrapWriter(file: IrFile, populateFileTables: Boolean) =
|
||||
SourceFileTrapWriter(loggerBase, lm, bw, this.getDiagnosticTrapWriter(), file, populateFileTables)
|
||||
SourceFileTrapWriter(
|
||||
loggerBase,
|
||||
lm,
|
||||
bw,
|
||||
this.getDiagnosticTrapWriter(),
|
||||
file,
|
||||
populateFileTables
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `PlainTrapWriter` has no additional context of its own.
|
||||
*/
|
||||
class PlainTrapWriter (
|
||||
/** A `PlainTrapWriter` has no additional context of its own. */
|
||||
class PlainTrapWriter(
|
||||
loggerBase: LoggerBase,
|
||||
lm: TrapLabelManager,
|
||||
bw: BufferedWriter,
|
||||
val dtw: DiagnosticTrapWriter
|
||||
): TrapWriter (loggerBase, lm, bw) {
|
||||
) : TrapWriter(loggerBase, lm, bw) {
|
||||
override fun getDiagnosticTrapWriter(): DiagnosticTrapWriter {
|
||||
return dtw
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `DiagnosticTrapWriter` is a TrapWriter that diagnostics can be
|
||||
* written to; i.e. it has the #compilation label defined. In practice,
|
||||
* this means that it is a TrapWriter for the invocation TRAP file.
|
||||
* A `DiagnosticTrapWriter` is a TrapWriter that diagnostics can be written to; i.e. it has
|
||||
* the #compilation label defined. In practice, this means that it is a TrapWriter for the
|
||||
* invocation TRAP file.
|
||||
*/
|
||||
class DiagnosticTrapWriter (
|
||||
loggerBase: LoggerBase,
|
||||
lm: TrapLabelManager,
|
||||
bw: BufferedWriter
|
||||
): TrapWriter (loggerBase, lm, bw) {
|
||||
class DiagnosticTrapWriter(loggerBase: LoggerBase, lm: TrapLabelManager, bw: BufferedWriter) :
|
||||
TrapWriter(loggerBase, lm, bw) {
|
||||
override fun getDiagnosticTrapWriter(): DiagnosticTrapWriter {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `FileTrapWriter` is used when we know which file we are extracting
|
||||
* entities from, so we can at least give the right file as a location.
|
||||
* A `FileTrapWriter` is used when we know which file we are extracting entities from, so we can at
|
||||
* least give the right file as a location.
|
||||
*
|
||||
* An ID for the file will be created, and if `populateFileTables` is
|
||||
* true then we will also add rows to the `files` and `folders` tables
|
||||
* for it.
|
||||
* An ID for the file will be created, and if `populateFileTables` is true then we will also add
|
||||
* rows to the `files` and `folders` tables for it.
|
||||
*/
|
||||
open class FileTrapWriter (
|
||||
open class FileTrapWriter(
|
||||
loggerBase: LoggerBase,
|
||||
lm: TrapLabelManager,
|
||||
bw: BufferedWriter,
|
||||
val dtw: DiagnosticTrapWriter,
|
||||
val filePath: String,
|
||||
populateFileTables: Boolean
|
||||
): TrapWriter (loggerBase, lm, bw) {
|
||||
) : TrapWriter(loggerBase, lm, bw) {
|
||||
|
||||
/**
|
||||
* The ID for the file that we are extracting from.
|
||||
*/
|
||||
/** The ID for the file that we are extracting from. */
|
||||
val fileId = mkFileId(filePath, populateFileTables)
|
||||
|
||||
override fun getDiagnosticTrapWriter(): DiagnosticTrapWriter {
|
||||
|
@ -320,7 +313,12 @@ open class FileTrapWriter (
|
|||
|
||||
var currentMin = default
|
||||
for (option in options) {
|
||||
if (option != null && option != UNDEFINED_OFFSET && option != SYNTHETIC_OFFSET && option < currentMin) {
|
||||
if (
|
||||
option != null &&
|
||||
option != UNDEFINED_OFFSET &&
|
||||
option != SYNTHETIC_OFFSET &&
|
||||
option < currentMin
|
||||
) {
|
||||
currentMin = option
|
||||
}
|
||||
}
|
||||
|
@ -344,15 +342,13 @@ open class FileTrapWriter (
|
|||
return e.endOffset
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a label for the location of `e`.
|
||||
*/
|
||||
/** Gets a label for the location of `e`. */
|
||||
fun getLocation(e: IrElement): Label<DbLocation> {
|
||||
return getLocation(getStartOffset(e), getEndOffset(e))
|
||||
}
|
||||
/**
|
||||
* Gets a label for the location corresponding to `startOffset` and
|
||||
* `endOffset` within this file.
|
||||
* Gets a label for the location corresponding to `startOffset` and `endOffset` within this
|
||||
* file.
|
||||
*/
|
||||
open fun getLocation(startOffset: Int, endOffset: Int): Label<DbLocation> {
|
||||
// We don't have a FileEntry to look up the offsets in, so all
|
||||
|
@ -360,8 +356,8 @@ open class FileTrapWriter (
|
|||
return getWholeFileLocation()
|
||||
}
|
||||
/**
|
||||
* Gets the location of `e` as a human-readable string. Only used in
|
||||
* log messages and exception messages.
|
||||
* Gets the location of `e` as a human-readable string. Only used in log messages and exception
|
||||
* messages.
|
||||
*/
|
||||
open fun getLocationString(e: IrElement): String {
|
||||
// We don't have a FileEntry to look up the offsets in, so all
|
||||
|
@ -371,50 +367,54 @@ open class FileTrapWriter (
|
|||
// to be 0.
|
||||
return "file://$filePath"
|
||||
}
|
||||
/**
|
||||
* Gets a label for the location representing the whole of this file.
|
||||
*/
|
||||
/** Gets a label for the location representing the whole of this file. */
|
||||
fun getWholeFileLocation(): Label<DbLocation> {
|
||||
return getWholeFileLocation(fileId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `SourceFileTrapWriter` is used when not only do we know which file
|
||||
* we are extracting entities from, but we also have an `IrFileEntry`
|
||||
* (from an `IrFile`) which allows us to map byte offsets to line
|
||||
* and column numbers.
|
||||
* A `SourceFileTrapWriter` is used when not only do we know which file we are extracting entities
|
||||
* from, but we also have an `IrFileEntry` (from an `IrFile`) which allows us to map byte offsets to
|
||||
* line and column numbers.
|
||||
*
|
||||
* An ID for the file will be created, and if `populateFileTables` is
|
||||
* true then we will also add rows to the `files` and `folders` tables
|
||||
* for it.
|
||||
* An ID for the file will be created, and if `populateFileTables` is true then we will also add
|
||||
* rows to the `files` and `folders` tables for it.
|
||||
*/
|
||||
class SourceFileTrapWriter (
|
||||
class SourceFileTrapWriter(
|
||||
loggerBase: LoggerBase,
|
||||
lm: TrapLabelManager,
|
||||
bw: BufferedWriter,
|
||||
dtw: DiagnosticTrapWriter,
|
||||
val irFile: IrFile,
|
||||
populateFileTables: Boolean) :
|
||||
FileTrapWriter(loggerBase, lm, bw, dtw, irFile.path, populateFileTables) {
|
||||
populateFileTables: Boolean
|
||||
) : FileTrapWriter(loggerBase, lm, bw, dtw, irFile.path, populateFileTables) {
|
||||
|
||||
/**
|
||||
* The file entry for the file that we are extracting from.
|
||||
* Used to map offsets to line/column numbers.
|
||||
* The file entry for the file that we are extracting from. Used to map offsets to line/column
|
||||
* numbers.
|
||||
*/
|
||||
private val fileEntry = irFile.fileEntry
|
||||
|
||||
override fun getLocation(startOffset: Int, endOffset: Int): Label<DbLocation> {
|
||||
if (startOffset == UNDEFINED_OFFSET || endOffset == UNDEFINED_OFFSET) {
|
||||
if (startOffset != endOffset) {
|
||||
loggerBase.warn(dtw, "Location with inconsistent offsets (start $startOffset, end $endOffset)", null)
|
||||
loggerBase.warn(
|
||||
dtw,
|
||||
"Location with inconsistent offsets (start $startOffset, end $endOffset)",
|
||||
null
|
||||
)
|
||||
}
|
||||
return getWholeFileLocation()
|
||||
}
|
||||
|
||||
if (startOffset == SYNTHETIC_OFFSET || endOffset == SYNTHETIC_OFFSET) {
|
||||
if (startOffset != endOffset) {
|
||||
loggerBase.warn(dtw, "Location with inconsistent offsets (start $startOffset, end $endOffset)", null)
|
||||
loggerBase.warn(
|
||||
dtw,
|
||||
"Location with inconsistent offsets (start $startOffset, end $endOffset)",
|
||||
null
|
||||
)
|
||||
}
|
||||
return getWholeFileLocation()
|
||||
}
|
||||
|
@ -428,28 +428,37 @@ class SourceFileTrapWriter (
|
|||
fileEntry.getLineNumber(startOffset) + 1,
|
||||
fileEntry.getColumnNumber(startOffset) + 1,
|
||||
fileEntry.getLineNumber(endOffset) + 1,
|
||||
fileEntry.getColumnNumber(endOffset) + endColumnOffset)
|
||||
fileEntry.getColumnNumber(endOffset) + endColumnOffset
|
||||
)
|
||||
}
|
||||
|
||||
override fun getLocationString(e: IrElement): String {
|
||||
if (e.startOffset == UNDEFINED_OFFSET || e.endOffset == UNDEFINED_OFFSET) {
|
||||
if (e.startOffset != e.endOffset) {
|
||||
loggerBase.warn(dtw, "Location with inconsistent offsets (start ${e.startOffset}, end ${e.endOffset})", null)
|
||||
loggerBase.warn(
|
||||
dtw,
|
||||
"Location with inconsistent offsets (start ${e.startOffset}, end ${e.endOffset})",
|
||||
null
|
||||
)
|
||||
}
|
||||
return "<unknown location while processing $filePath>"
|
||||
}
|
||||
|
||||
if (e.startOffset == SYNTHETIC_OFFSET || e.endOffset == SYNTHETIC_OFFSET) {
|
||||
if (e.startOffset != e.endOffset) {
|
||||
loggerBase.warn(dtw, "Location with inconsistent offsets (start ${e.startOffset}, end ${e.endOffset})", null)
|
||||
loggerBase.warn(
|
||||
dtw,
|
||||
"Location with inconsistent offsets (start ${e.startOffset}, end ${e.endOffset})",
|
||||
null
|
||||
)
|
||||
}
|
||||
return "<synthetic location while processing $filePath>"
|
||||
}
|
||||
|
||||
val startLine = fileEntry.getLineNumber(e.startOffset) + 1
|
||||
val startLine = fileEntry.getLineNumber(e.startOffset) + 1
|
||||
val startColumn = fileEntry.getColumnNumber(e.startOffset) + 1
|
||||
val endLine = fileEntry.getLineNumber(e.endOffset) + 1
|
||||
val endColumn = fileEntry.getColumnNumber(e.endOffset)
|
||||
val endLine = fileEntry.getLineNumber(e.endOffset) + 1
|
||||
val endColumn = fileEntry.getColumnNumber(e.endOffset)
|
||||
return "file://$filePath:$startLine:$startColumn:$endLine:$endColumn"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,16 @@ import org.jetbrains.kotlin.ir.expressions.IrBody
|
|||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
|
||||
open class CommentExtractor(protected val fileExtractor: KotlinFileExtractor, protected val file: IrFile, protected val fileLabel: Label<out DbFile>) {
|
||||
open class CommentExtractor(
|
||||
protected val fileExtractor: KotlinFileExtractor,
|
||||
protected val file: IrFile,
|
||||
protected val fileLabel: Label<out DbFile>
|
||||
) {
|
||||
protected val tw = fileExtractor.tw
|
||||
protected val logger = fileExtractor.logger
|
||||
|
||||
protected fun getLabel(element: IrElement): Label<out DbTop>? {
|
||||
if (element == file)
|
||||
return fileLabel
|
||||
if (element == file) return fileLabel
|
||||
|
||||
if (element is IrValueParameter && element.index == -1) {
|
||||
// Don't attribute comments to the implicit `this` parameter of a function.
|
||||
|
@ -22,18 +25,21 @@ open class CommentExtractor(protected val fileExtractor: KotlinFileExtractor, pr
|
|||
}
|
||||
|
||||
val label: String
|
||||
val existingLabel = if (element is IrVariable) {
|
||||
// local variables are not named globally, so we need to get them from the variable label cache
|
||||
label = "variable ${element.name.asString()}"
|
||||
tw.getExistingVariableLabelFor(element)
|
||||
} else if (element is IrFunction && element.isLocalFunction()) {
|
||||
// local functions are not named globally, so we need to get them from the local function label cache
|
||||
label = "local function ${element.name.asString()}"
|
||||
fileExtractor.getExistingLocallyVisibleFunctionLabel(element)
|
||||
} else {
|
||||
label = getLabelForNamedElement(element) ?: return null
|
||||
tw.getExistingLabelFor<DbTop>(label)
|
||||
}
|
||||
val existingLabel =
|
||||
if (element is IrVariable) {
|
||||
// local variables are not named globally, so we need to get them from the variable
|
||||
// label cache
|
||||
label = "variable ${element.name.asString()}"
|
||||
tw.getExistingVariableLabelFor(element)
|
||||
} else if (element is IrFunction && element.isLocalFunction()) {
|
||||
// local functions are not named globally, so we need to get them from the local
|
||||
// function label cache
|
||||
label = "local function ${element.name.asString()}"
|
||||
fileExtractor.getExistingLocallyVisibleFunctionLabel(element)
|
||||
} else {
|
||||
label = getLabelForNamedElement(element) ?: return null
|
||||
tw.getExistingLabelFor<DbTop>(label)
|
||||
}
|
||||
if (existingLabel == null) {
|
||||
logger.warn("Couldn't get existing label for $label")
|
||||
return null
|
||||
|
@ -41,7 +47,7 @@ open class CommentExtractor(protected val fileExtractor: KotlinFileExtractor, pr
|
|||
return existingLabel
|
||||
}
|
||||
|
||||
private fun getLabelForNamedElement(element: IrElement) : String? {
|
||||
private fun getLabelForNamedElement(element: IrElement): String? {
|
||||
when (element) {
|
||||
is IrClass -> return fileExtractor.getClassLabel(element, listOf()).classLabel
|
||||
is IrTypeParameter -> return fileExtractor.getTypeParameterLabel(element)
|
||||
|
@ -57,14 +63,14 @@ open class CommentExtractor(protected val fileExtractor: KotlinFileExtractor, pr
|
|||
is IrField -> return fileExtractor.getFieldLabel(element)
|
||||
is IrEnumEntry -> return fileExtractor.getEnumEntryLabel(element)
|
||||
is IrTypeAlias -> return fileExtractor.getTypeAliasLabel(element)
|
||||
|
||||
is IrAnonymousInitializer -> {
|
||||
val parentClass = element.parentClassOrNull
|
||||
if (parentClass == null) {
|
||||
logger.warnElement("Parent of anonymous initializer is not a class", element)
|
||||
return null
|
||||
}
|
||||
// Assign the comment to the class. The content of the `init` blocks might be extracted in multiple constructors.
|
||||
// Assign the comment to the class. The content of the `init` blocks might be
|
||||
// extracted in multiple constructors.
|
||||
return getLabelForNamedElement(parentClass)
|
||||
}
|
||||
|
||||
|
@ -74,7 +80,10 @@ open class CommentExtractor(protected val fileExtractor: KotlinFileExtractor, pr
|
|||
|
||||
// todo add others:
|
||||
else -> {
|
||||
logger.warnElement("Unhandled element type found during comment extraction: ${element::class}", element)
|
||||
logger.warnElement(
|
||||
"Unhandled element type found during comment extraction: ${element::class}",
|
||||
element
|
||||
)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,18 @@ import org.jetbrains.kotlin.psi.KtVisitor
|
|||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
|
||||
class CommentExtractorPSI(fileExtractor: KotlinFileExtractor, file: IrFile, fileLabel: Label<out DbFile>): CommentExtractor(fileExtractor, file, fileLabel) {
|
||||
class CommentExtractorPSI(
|
||||
fileExtractor: KotlinFileExtractor,
|
||||
file: IrFile,
|
||||
fileLabel: Label<out DbFile>
|
||||
) : CommentExtractor(fileExtractor, file, fileLabel) {
|
||||
// Returns true if it extracted the comments; false otherwise.
|
||||
fun extract(): Boolean {
|
||||
val psi2Ir = getPsi2Ir()
|
||||
if (psi2Ir == null) {
|
||||
logger.warn("Comments will not be extracted as Kotlin version is too old (${KotlinCompilerVersion.getVersion()})")
|
||||
logger.warn(
|
||||
"Comments will not be extracted as Kotlin version is too old (${KotlinCompilerVersion.getVersion()})"
|
||||
)
|
||||
return false
|
||||
}
|
||||
val ktFile = psi2Ir.getKtFile(file)
|
||||
|
@ -37,28 +43,30 @@ class CommentExtractorPSI(fileExtractor: KotlinFileExtractor, file: IrFile, file
|
|||
override fun visitElement(element: PsiElement) {
|
||||
element.acceptChildren(this)
|
||||
|
||||
// Slightly hacky, but `visitComment` doesn't seem to visit comments with `tokenType` `KtTokens.DOC_COMMENT`
|
||||
if (element is PsiComment){
|
||||
// Slightly hacky, but `visitComment` doesn't seem to visit comments with
|
||||
// `tokenType` `KtTokens.DOC_COMMENT`
|
||||
if (element is PsiComment) {
|
||||
visitCommentElement(element)
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitCommentElement(comment: PsiComment) {
|
||||
val type: CommentType = when (comment.tokenType) {
|
||||
KtTokens.EOL_COMMENT -> {
|
||||
CommentType.SingleLine
|
||||
val type: CommentType =
|
||||
when (comment.tokenType) {
|
||||
KtTokens.EOL_COMMENT -> {
|
||||
CommentType.SingleLine
|
||||
}
|
||||
KtTokens.BLOCK_COMMENT -> {
|
||||
CommentType.Block
|
||||
}
|
||||
KtTokens.DOC_COMMENT -> {
|
||||
CommentType.Doc
|
||||
}
|
||||
else -> {
|
||||
logger.warn("Unhandled comment token type: ${comment.tokenType}")
|
||||
return
|
||||
}
|
||||
}
|
||||
KtTokens.BLOCK_COMMENT -> {
|
||||
CommentType.Block
|
||||
}
|
||||
KtTokens.DOC_COMMENT -> {
|
||||
CommentType.Doc
|
||||
}
|
||||
else -> {
|
||||
logger.warn("Unhandled comment token type: ${comment.tokenType}")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val commentLabel = tw.getFreshIdLabel<DbKtcomment>()
|
||||
tw.writeKtComments(commentLabel, type.value, comment.text)
|
||||
|
@ -101,10 +109,12 @@ class CommentExtractorPSI(fileExtractor: KotlinFileExtractor, file: IrFile, file
|
|||
}
|
||||
}
|
||||
|
||||
private fun getKDocOwner(comment: KDoc) : PsiElement? {
|
||||
private fun getKDocOwner(comment: KDoc): PsiElement? {
|
||||
val owner = comment.owner
|
||||
if (owner == null) {
|
||||
logger.warn("Couldn't get owner of KDoc. The comment is extracted without an owner.")
|
||||
logger.warn(
|
||||
"Couldn't get owner of KDoc. The comment is extracted without an owner."
|
||||
)
|
||||
}
|
||||
return owner
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче