Merge branch 'main' into docs-11486-security-severity

This commit is contained in:
Felicity Chapman 2024-01-11 22:28:30 +00:00 коммит произвёл GitHub
Родитель 8fdeb5691b 42f6dbe0b1
Коммит f06cca8eff
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
277 изменённых файлов: 12184 добавлений и 4325 удалений

12
.github/workflows/mad_modelDiff.yml поставляемый
Просмотреть файл

@ -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,

1 package source summary source:remote summary:taint summary:value
34 encoding/xml 23 23
35 errors 3 3
36 expvar 6 6
37 fmt 5 16 5 16
38 github.com/astaxie/beego 7 7
39 github.com/astaxie/beego/context 1 1
40 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,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

1 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
2 actions.osgi 6 6
3 android.app 35 103 11 7 17 18 85
4 android.content 24 31 154 16 8 4 27 63 91
5 android.database 59 41 59 41
6 android.net 60 45 15
7 android.os 2 122 2 41 81
8 android.support.v4.app 11 11
9 android.util 6 16 6 16
10 android.webkit 3 2 2 1 2
11 android.widget 1 1 1 1
12 androidx.core.app 6 95 6 12 83
13 androidx.fragment.app 11 11
14 androidx.slice 2 5 88 2 5 27 61
15 antlr 1 1
16 ch.ethz.ssh2 2 1 1
17 cn.hutool.core.codec 1 1
18 com.alibaba.druid.sql 1 1 1 1
19 com.alibaba.fastjson2 1 1
20 com.amazonaws.auth 2 2
21 com.auth0.jwt.algorithms 6 6
22 com.azure.identity 3 1 1 1
23 com.esotericsoftware.kryo.io 1 1
24 com.esotericsoftware.kryo5.io 1 1
25 com.fasterxml.jackson.core 1 1
26 com.fasterxml.jackson.databind 2 6 2 6
27 com.google.common.base 4 87 3 1 63 24
28 com.google.common.cache 17 17
29 com.google.common.collect 553 2 551
30 com.google.common.flogger 29 29
31 com.google.common.io 10 73 1 9 72 1
32 com.google.gson 44 52 30 38 14
33 com.hubspot.jinjava 2 2
34 com.jcraft.jsch 5 1 2 2 1 1
35 com.microsoft.sqlserver.jdbc 4 2 2
36 com.mitchellbosecke.pebble 2 2
37 com.mongodb 10 4 6
38 com.opensymphony.xwork2 56 961 56 867 94
39 com.rabbitmq.client 21 7 21 7
40 com.sshtools.j2ssh.authentication 3 1 2
41 com.sun.crypto.provider 19 17 2
42 com.sun.jndi.ldap 4 4
43 com.sun.net.httpserver 3 1 2
44 com.sun.net.ssl 3 3
45 com.sun.rowset 3 2 1
46 com.sun.security.auth.module 2 2
47 com.sun.security.ntlm 5 3 2
48 com.sun.security.sasl.digest 3 2 1
49 com.thoughtworks.xstream 1 1
50 com.trilead.ssh2 13 2 4 7
51 com.unboundid.ldap.sdk 17 17
52 com.zaxxer.hikari 2 2
53 flexjson 1 1
54 freemarker.cache 1 1
55 freemarker.template 7 7
56 groovy.lang 26 26
57 groovy.text 1 1
58 groovy.util 5 5
59 hudson 71 74 9 2648 4 3 3 4 54 6 5 4 2572 76
60 io.jsonwebtoken 2 4 2 4
61 io.netty.bootstrap 3 3
62 io.netty.buffer 207 130 77
63 io.netty.channel 9 2 9 2
64 io.netty.handler.codec 4 13 259 1 3 13 143 116
65 io.netty.handler.ssl 4 4
66 io.netty.handler.stream 1 1
67 io.netty.resolver 1 1
68 io.netty.util 2 23 1 1 21 2
69 jakarta.activation 2 2 1 1 2
70 jakarta.faces.context 2 7 2 7
71 jakarta.json 123 100 23
72 jakarta.persistence 2 1 2 1
73 jakarta.ws.rs.client 1 1
74 jakarta.ws.rs.container 9 9
75 jakarta.ws.rs.core 2 149 2 94 55
76 jakarta.xml.bind.attachment 2 2
77 java.awt 3 3
78 java.beans 1 1
79 java.io 50 1 46 22 28 1 44 2
80 java.lang 32 33 3 94 13 1 8 6 4 1 3 57 37
81 java.net 16 3 23 1 1 14 3 23
82 java.nio 49 36 5 43 1 36
83 java.security 21 11 10
84 java.sql 15 1 2 1 1 4 9 1 2
85 java.util 47 2 519 1 34 2 5 2 1 2 2 45 474
86 javafx.scene.web 1 1
87 javax.activation 2 7 1 1 7
88 javax.crypto 19 4 12 3 2 2 4
89 javax.faces.context 2 7 2 7
90 javax.imageio.stream 1 1 1 1
91 javax.jms 9 57 9 57
92 javax.json 123 100 23
93 javax.management 2 1 2 1
94 javax.naming 7 1 6 1 1
95 javax.net.ssl 4 2 2
96 javax.portlet 61 61
97 javax.print.attribute.standard 2 2
98 javax.script 1 1
99 javax.security.auth.callback 1 1
100 javax.security.auth.kerberos 6 4 2
101 javax.servlet 7 21 2 1 1 3 2 21 2
102 javax.sql 7 4 3
103 javax.validation 1 1 1 1
104 javax.ws.rs.client 1 1
105 javax.ws.rs.container 9 9
106 javax.ws.rs.core 3 149 1 2 94 55
107 javax.xml.bind.attachment 2 2
108 javax.xml.transform 2 6 1 1 6
109 javax.xml.xpath 3 3
110 jenkins 523 500 23
111 jodd.json 10 10
112 kotlin 16 1849 14 2 1836 13
113 liquibase.database.jvm 1 1
114 liquibase.statement.core 1 1
115 net.schmizz.sshj 4 2 2
116 net.sf.json 2 338 2 321 17
117 net.sf.saxon.s9api 5 5
118 ognl 6 6
119 okhttp3 4 50 4 23 27
120 org.acegisecurity 49 49
121 org.antlr.runtime 1 1
122 org.apache.commons.codec 6 6
123 org.apache.commons.collections 800 17 783
124 org.apache.commons.collections4 800 17 783
125 org.apache.commons.compress.archivers.tar 4 4
126 org.apache.commons.exec 6 10 6 4
127 org.apache.commons.httpclient.util 1 1
128 org.apache.commons.io 117 562 4 98 15 548 14
129 org.apache.commons.jelly 6 6
130 org.apache.commons.jexl2 15 15
131 org.apache.commons.jexl3 15 15
132 org.apache.commons.lang 767 596 171
133 org.apache.commons.lang3 6 425 6 294 131
134 org.apache.commons.logging 6 6
135 org.apache.commons.net 13 12 2 2 3 6 12
136 org.apache.commons.ognl 6 6
137 org.apache.commons.text 272 220 52
138 org.apache.cxf.catalog 1 1
139 org.apache.cxf.common.classloader 3 1 2
140 org.apache.cxf.common.jaxb 1 1
141 org.apache.cxf.common.logging 6 6
142 org.apache.cxf.configuration.jsse 2 1 1
143 org.apache.cxf.helpers 10 5 5
144 org.apache.cxf.resource 9 4 5
145 org.apache.cxf.staxutils 1 1
146 org.apache.cxf.tools.corba.utils 4 4
147 org.apache.cxf.tools.util 10 10
148 org.apache.cxf.transform 3 3
149 org.apache.directory.ldap.client.api 1 1
150 org.apache.hadoop.fs 10 10
151 org.apache.hadoop.hive.metastore 3 3
152 org.apache.hadoop.hive.ql.exec 1 1 1 1
153 org.apache.hadoop.hive.ql.metadata 1 1
154 org.apache.hc.client5.http.async.methods 84 84
155 org.apache.hc.client5.http.classic.methods 37 37
156 org.apache.hc.client5.http.fluent 19 19
157 org.apache.hc.core5.benchmark 1 1
158 org.apache.hc.core5.function 1 1
159 org.apache.hc.core5.http 73 2 45 1 72 2 45
160 org.apache.hc.core5.net 18 18
161 org.apache.hc.core5.util 24 18 6
162 org.apache.hive.hcatalog.templeton 1 1
163 org.apache.http 48 3 95 2 46 3 86 9
164 org.apache.ibatis.jdbc 6 57 6 57
165 org.apache.ibatis.mapping 1 1
166 org.apache.log4j 11 11
167 org.apache.logging.log4j 359 8 359 4 4
168 org.apache.shiro.codec 1 1
169 org.apache.shiro.jndi 1 1
170 org.apache.shiro.mgt 1 1
171 org.apache.sshd.client.session 3 1 2
172 org.apache.struts.beanvalidation.validation.interceptor 4 4
173 org.apache.struts2 14 3873 11 3 3839 34
174 org.apache.tools.ant 12 1 11
175 org.apache.tools.zip 1 1
176 org.apache.velocity.app 4 4
177 org.apache.velocity.runtime 4 4
178 org.codehaus.cargo.container.installer 3 2 1
179 org.codehaus.groovy.control 1 1
180 org.dom4j 20 20
181 org.eclipse.jetty.client 1 1
182 org.fusesource.leveldbjni 1 1
183 org.geogebra.web.full.main 1 1
184 org.gradle.api.file 2 2
185 org.hibernate 7 7
186 org.influxdb 1 1
187 org.jboss.logging 324 324
188 org.jdbi.v3.core 6 6
189 org.jenkins.ui.icon 49 48 1
190 org.jenkins.ui.symbol 33 25 8
191 org.jooq 1 1
192 org.json 236 198 38
193 org.keycloak.models.map.storage 1 1
194 org.kohsuke.stapler 20 24 363 2 9 4 5 24 352 11
195 org.mvel2 16 16
196 org.openjdk.jmh.runner.options 1 1
197 org.owasp.esapi 1 1
198 org.scijava.log org.pac4j.jwt.config.encryption 13 4 4 13
199 org.slf4j org.pac4j.jwt.config.signature 55 4 6 4 55 2 4
200 org.springframework.beans org.scijava.log 13 30 13 30
201 org.springframework.boot.jdbc org.slf4j 1 55 6 55 1 2 4
202 org.springframework.cache org.springframework.beans 13 30 13 30
203 org.springframework.context org.springframework.boot.jdbc 1 3 1 3
204 org.springframework.core.io org.springframework.cache 3 13 2 1 13
205 org.springframework.data.repository org.springframework.context 1 3 3 1
206 org.springframework.http org.springframework.core.io 14 3 77 2 14 1 67 10
207 org.springframework.jdbc.core org.springframework.data.repository 19 1 19 1
208 org.springframework.jdbc.datasource org.springframework.http 4 14 77 4 14 67 10
209 org.springframework.jdbc.object org.springframework.jdbc.core 9 19 9 19
210 org.springframework.jndi org.springframework.jdbc.datasource 1 4 1 4
211 org.springframework.ldap org.springframework.jdbc.object 47 9 33 14 9
212 org.springframework.security.core.userdetails org.springframework.jndi 2 1 1 1 1
213 org.springframework.security.web.savedrequest org.springframework.ldap 47 6 33 14 6
214 org.springframework.ui org.springframework.security.core.userdetails 2 32 1 1 32
215 org.springframework.util org.springframework.security.web.savedrequest 3 6 142 3 6 90 52
216 org.springframework.validation org.springframework.ui 13 32 13 32
217 org.springframework.web.client org.springframework.util 13 3 3 142 3 13 3 90 52
218 org.springframework.web.context.request org.springframework.validation 8 13 8 13
219 org.springframework.web.multipart org.springframework.web.client 13 12 3 13 13 12 3 13
220 org.springframework.web.reactive.function.client org.springframework.web.context.request 2 8 2 8
221 org.springframework.web.util org.springframework.web.multipart 9 12 157 13 9 12 132 13 25
222 org.thymeleaf org.springframework.web.reactive.function.client 2 2 2 2 2
223 org.xml.sax org.springframework.web.util 9 1 157 9 1 132 25
224 org.xmlpull.v1 org.thymeleaf 2 3 2 2 3 2
225 org.yaml.snakeyaml org.xml.sax 1 1
226 play.libs.ws org.xmlpull.v1 2 3 2 3
227 play.mvc org.yaml.snakeyaml 1 13 24 1 1 13 24 1
228 ratpack.core.form play.libs.ws 2 3 2 3
229 ratpack.core.handling play.mvc 1 6 13 4 24 1 6 13 4 24
230 ratpack.core.http ratpack.core.form 10 10 3 10 10 3
231 ratpack.exec ratpack.core.handling 6 48 4 6 4 48
232 ratpack.form ratpack.core.http 10 3 10 10 3 10
233 ratpack.func ratpack.exec 35 48 35 48
234 ratpack.handling ratpack.form 6 4 3 6 4 3
235 ratpack.http ratpack.func 10 10 35 10 10 35
236 ratpack.util ratpack.handling 6 35 4 6 4 35
237 retrofit2 ratpack.http 1 10 1 10 1 10 1 10
238 sun.jvmstat.perfdata.monitor.protocol.local ratpack.util 3 35 3 35
239 sun.jvmstat.perfdata.monitor.protocol.rmi retrofit2 1 1 1 1 1
240 sun.misc sun.jvmstat.perfdata.monitor.protocol.local 3 3
241 sun.net.ftp sun.jvmstat.perfdata.monitor.protocol.rmi 5 1 2 3 1
242 sun.net.www.protocol.http sun.misc 3 2 1 3
243 sun.security.acl sun.net.ftp 1 5 2 1 3
244 sun.security.jgss.krb5 sun.net.www.protocol.http 2 3 2 2 1
245 sun.security.krb5 sun.security.acl 9 1 3 6 1
246 sun.security.pkcs sun.security.jgss.krb5 4 2 4 2
247 sun.security.pkcs11 sun.security.krb5 3 9 1 3 2 6
248 sun.security.provider sun.security.pkcs 2 4 4 2
249 sun.security.ssl sun.security.pkcs11 3 1 3 2
250 sun.security.x509 sun.security.provider 1 2 1 2
251 sun.tools.jconsole sun.security.ssl 28 3 13 3 15
252 sun.security.x509 1 1
253 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
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше