diff --git a/MODULE.bazel b/MODULE.bazel index 2b37719584cd..29e0308462a6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -20,18 +20,18 @@ bazel_dep(name = "rules_go", version = "0.59.0") bazel_dep(name = "rules_java", version = "9.0.3") bazel_dep(name = "rules_pkg", version = "1.0.1") bazel_dep(name = "rules_nodejs", version = "6.7.3") -bazel_dep(name = "rules_python", version = "0.40.0") -bazel_dep(name = "rules_shell", version = "0.5.0") +bazel_dep(name = "rules_python", version = "1.9.0") +bazel_dep(name = "rules_shell", version = "0.6.1") bazel_dep(name = "bazel_skylib", version = "1.8.1") -bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl") +bazel_dep(name = "abseil-cpp", version = "20260107.1", repo_name = "absl") bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json") bazel_dep(name = "fmt", version = "12.1.0-codeql.1") bazel_dep(name = "rules_kotlin", version = "2.2.2-codeql.1") bazel_dep(name = "gazelle", version = "0.47.0") bazel_dep(name = "rules_dotnet", version = "0.21.5-codeql.1") -bazel_dep(name = "googletest", version = "1.14.0.bcr.1") +bazel_dep(name = "googletest", version = "1.17.0.bcr.2") bazel_dep(name = "rules_rust", version = "0.68.1.codeql.1") -bazel_dep(name = "zstd", version = "1.5.5.bcr.1") +bazel_dep(name = "zstd", version = "1.5.7.bcr.1") bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True) diff --git a/actions/ql/lib/qlpack.yml b/actions/ql/lib/qlpack.yml index 6c1865d96de5..58daff358aed 100644 --- a/actions/ql/lib/qlpack.yml +++ b/actions/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-all -version: 0.4.29 +version: 0.4.30-dev library: true warnOnImplicitThis: true dependencies: diff --git a/actions/ql/src/qlpack.yml b/actions/ql/src/qlpack.yml index 64c2c528fe5a..cb88235175f7 100644 --- a/actions/ql/src/qlpack.yml +++ b/actions/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/actions-queries -version: 0.6.21 +version: 0.6.22-dev library: false warnOnImplicitThis: true groups: [actions, queries] diff --git a/config/add-overlay-annotations.py b/config/add-overlay-annotations.py index 0a30eee5799b..4fbd9a2b7fce 100644 --- a/config/add-overlay-annotations.py +++ b/config/add-overlay-annotations.py @@ -199,6 +199,7 @@ def annotate_as_appropriate(filename, lines): # as overlay[local?]. It is not clear that these heuristics are exactly what we want, # but they seem to work well enough for now (as determined by speed and accuracy numbers). if (filename.endswith("Test.qll") or + re.search(r"go/ql/lib/semmle/go/security/[^/]+[.]qll$", filename.replace(os.sep, "/")) or ((filename.endswith("Query.qll") or filename.endswith("Config.qll")) and any("implements DataFlow::ConfigSig" in line for line in lines))): return None diff --git a/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/in_trap.ql b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/in_trap.ql new file mode 100644 index 000000000000..5ea4f67776b4 --- /dev/null +++ b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/in_trap.ql @@ -0,0 +1,21 @@ +class Element extends @element { + string toString() { none() } +} + +class Trap extends @trap { + string toString() { none() } +} + +class Tag extends @tag { + string toString() { none() } +} + +from Element e, Trap trap +where + in_trap_or_tag(e, trap) + or + exists(Tag tag | + in_trap_or_tag(e, tag) and + trap_uses_tag(trap, tag) + ) +select e, trap diff --git a/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/old.dbscheme b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/old.dbscheme new file mode 100644 index 000000000000..770002bb0232 --- /dev/null +++ b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/old.dbscheme @@ -0,0 +1,2545 @@ + +/*- Compilations -*/ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * Optionally, record the build mode for each compilation. + */ +compilation_build_mode( + unique int id : @compilation ref, + int mode : int ref +); + +/* +case @compilation_build_mode.mode of + 0 = @build_mode_none +| 1 = @build_mode_manual +| 2 = @build_mode_auto +; +*/ + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- C++ dbscheme -*/ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +/** + * Gives the TRAP filename that `trap` is associated with. + * For debugging only. + */ +trap_filename( + int trap: @trap, + string filename: string ref +); + +/** + * Gives the tag name for `tag`. + * For debugging only. + */ +tag_name( + int tag: @tag, + string name: string ref +); + +@trap_or_tag = @tag | @trap; + +/** + * Gives the name for the source file. + */ +source_file_name( + int sf: @source_file, + string name: string ref +); + +/** + * In `build-mode: none` overlay mode, indicates that `source_file` + * (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the + * TRAP file corresponding to `foo.c`, something it transitively + * includes, or a template instantiation it transitively uses. + */ +source_file_uses_trap( + int source_file: @source_file ref, + int trap_file: @trap ref +); + +/** + * In `build-mode: none` overlay mode, indicates that the TRAP file + * `trap_file` uses tag `tag`. + */ +trap_uses_tag( + int trap_file: @trap ref, + int tag: @tag ref +); + +/** + * Holds if there is a definition of `element` in TRAP file or tag `t`. + */ +in_trap_or_tag( + int element: @element ref, + int t: @trap_or_tag ref +); + +pch_uses( + int pch: @pch ref, + int compilation: @compilation ref, + int id: @file ref +) + +#keyset[pch, compilation] +pch_creations( + int pch: @pch, + int compilation: @compilation ref, + int from: @file ref +) + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +case @macroinvocation.kind of + 1 = @macro_expansion +| 2 = @other_macro_reference +; + +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location_default ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +case @function.kind of + 0 = @unknown_function +| 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +// ... 6 = @builtin_function deprecated // GCC built-in functions, e.g. __builtin___memcpy_chk +| 7 = @user_defined_literal +| 8 = @deduction_guide +; + +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +builtin_functions( + int id: @function ref +) + +function_entry_point( + int id: @function ref, + unique int entry_point: @stmt ref +); + +function_return_type( + int id: @function ref, + int return_type: @type ref +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref +); + +/* +case @coroutine_placeholder_variable.kind of + 1 = @handle +| 2 = @promise +| 3 = @init_await_resume +; +*/ + +coroutine_placeholder_variable( + unique int placeholder_variable: @variable ref, + int kind: int ref, + int function: @function ref +) + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +function_prototyped(unique int id: @function ref) + +deduction_guide_for_class( + int id: @function ref, + int class_template: @usertype ref +) + +member_function_this_type( + unique int id: @function ref, + int this_type: @type ref +); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +/* +case @fun_requires.kind of + 1 = @template_attached +| 2 = @function_attached +; +*/ + +fun_requires( + int id: @fun_decl ref, + int kind: int ref, + int constraint: @expr ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_specialized(int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable ref); +var_requires( + int id: @var_decl ref, + int constraint: @expr ref +); + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); +type_requires( + int id: @type_decl ref, + int constraint: @expr ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +case @using.kind of + 1 = @using_declaration +| 2 = @using_directive +| 3 = @using_enum_declaration +; + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref, + int kind: int ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @parameterized_element ref, + int index: int ref, + int type_id: @type ref +); + +overrides( + int new: @function ref, + int old: @function ref +); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function ref +) + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/** + * Built-in types are the fundamental types, e.g., integral, floating, and void. + */ +case @builtintype.kind of + 1 = @errortype +| 2 = @unknowntype +| 3 = @void +| 4 = @boolean +| 5 = @char +| 6 = @unsigned_char +| 7 = @signed_char +| 8 = @short +| 9 = @unsigned_short +| 10 = @signed_short +| 11 = @int +| 12 = @unsigned_int +| 13 = @signed_int +| 14 = @long +| 15 = @unsigned_long +| 16 = @signed_long +| 17 = @long_long +| 18 = @unsigned_long_long +| 19 = @signed_long_long +// ... 20 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +// ... 40 _Decimal32 +// ... 41 _Decimal64 +// ... 42 _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +// ... 50 _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +| 54 = @fp16 // __fp16 +| 55 = @std_bfloat16 // __bf16 +| 56 = @std_float16 // std::float16_t +| 57 = @complex_std_float32 // _Complex _Float32 +| 58 = @complex_float32x // _Complex _Float32x +| 59 = @complex_std_float64 // _Complex _Float64 +| 60 = @complex_float64x // _Complex _Float64x +| 61 = @complex_std_float128 // _Complex _Float128 +| 62 = @mfp8 // __mfp8 +| 63 = @scalable_vector_count // __SVCount_t +| 64 = @complex_fp16 // _Complex __fp16 +| 65 = @complex_std_bfloat16 // _Complex __bf16 +| 66 = @complex_std_float16 // _Complex std::float16_t +; + +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/** + * Derived types are types that are directly derived from existing types and + * point to, refer to, transform type data to return a new type. + */ +case @derivedtype.kind of + 1 = @pointer +| 2 = @reference +| 3 = @type_with_specifiers +| 4 = @array +| 5 = @gnu_vector +| 6 = @routineptr +| 7 = @routinereference +| 8 = @rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated +| 10 = @block +| 11 = @scalable_vector // Arm SVE +; + +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +tupleelements( + unique int id: @derivedtype ref, + int num_elements: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator or C23 `typeof`/`typeof_unqual` + * operator taking an expression as its argument. For example: + * ``` + * int a; + * decltype(1+a) b; + * typeof(1+a) c; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * changes the semantics of the decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ + +/* +case @decltype.kind of +| 0 = @decltype +| 1 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +; +*/ + +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int kind: int ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +case @type_operator.kind of + 0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +| 1 = @underlying_type +| 2 = @bases +| 3 = @direct_bases +| 4 = @add_lvalue_reference +| 5 = @add_pointer +| 6 = @add_rvalue_reference +| 7 = @decay +| 8 = @make_signed +| 9 = @make_unsigned +| 10 = @remove_all_extents +| 11 = @remove_const +| 12 = @remove_cv +| 13 = @remove_cvref +| 14 = @remove_extent +| 15 = @remove_pointer +| 16 = @remove_reference_t +| 17 = @remove_restrict +| 18 = @remove_volatile +| 19 = @remove_reference +; + +type_operators( + unique int id: @type_operator, + int arg_type: @type ref, + int kind: int ref, + int base_type: @type ref +) + +case @usertype.kind of + 0 = @unknown_usertype +| 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +// ... 5 = @typedef deprecated // classic C: typedef typedef type name +// ... 6 = @template deprecated +| 7 = @template_parameter +| 8 = @template_template_parameter +| 9 = @proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated +| 13 = @scoped_enum +// ... 14 = @using_alias deprecated // a using name = type style typedef +| 15 = @template_struct +| 16 = @template_class +| 17 = @template_union +| 18 = @alias +; + +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + string uuid: string ref +); + +/* +case @usertype.alias_kind of +| 0 = @typedef +| 1 = @alias +*/ + +usertype_alias_kind( + int id: @usertype ref, + int alias_kind: int ref +) + +nontype_template_parameters( + int id: @expr ref +); + +type_template_type_constraint( + int id: @usertype ref, + int constraint: @expr ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname, + boolean is_complete: boolean ref +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@user_or_decltype = @usertype | @decltype; + +is_proxy_class_for( + unique int id: @usertype ref, + int templ_param_id: @user_or_decltype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location_default ref, + // a_symbol_reference_kind from the frontend. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +template_template_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +template_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +template_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@concept = @concept_template | @concept_id; + +concept_templates( + unique int concept_id: @concept_template, + string name: string ref, + int location: @location_default ref +); +concept_instantiation( + unique int to: @concept_id ref, + int from: @concept_template ref +); +is_type_constraint(int concept_id: @concept_id ref); +concept_template_argument( + int concept_id: @concept ref, + int index: int ref, + int arg_type: @type ref +); +concept_template_argument_value( + int concept_id: @concept ref, + int index: int ref, + int arg_value: @expr ref +); + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +explicit_specifier_exprs( + unique int func_id: @function ref, + int constant: @expr ref +) + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +| 4 = @attribute_arg_constant_expr +| 5 = @attribute_arg_expr +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_constant( + unique int arg: @attribute_arg ref, + int constant: @expr ref +) +attribute_arg_expr( + unique int arg: @attribute_arg ref, + int expr: @expr ref +) +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +namespaceattributes( + int namespace_id: @namespace ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + | @routinetype + | @ptrtomember + | @decltype + | @type_operator; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl + | @concept_template; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + | @c11_generic + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall( + unique int caller: @funbindexpr ref, + int kind: int ref +); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype + | @decltype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + ; + +@assign_pointer_expr = @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr + | @assign_bitwise_expr + | @assign_pointer_expr + ; + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + Binary encoding of the allocator form. + + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + Binary encoding of the deallocator form. + + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 4 = destroying_delete + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_default ref +); + +braced_initialisers( + int init: @initialiser ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_default ref +); + +expr_reuse( + int reuse: @expr ref, + int original: @expr ref, + int value_category: int ref +) + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // frontend internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +| 363 = @reuseexpr +| 364 = @istriviallycopyassignable +| 365 = @isassignablenopreconditioncheck +| 366 = @referencebindstotemporary +| 367 = @issameas +| 368 = @builtinhasattribute +| 369 = @ispointerinterconvertiblewithclass +| 370 = @builtinispointerinterconvertiblewithclass +| 371 = @iscorrespondingmember +| 372 = @builtiniscorrespondingmember +| 373 = @isboundedarray +| 374 = @isunboundedarray +| 375 = @isreferenceable +| 378 = @isnothrowconvertible +| 379 = @referenceconstructsfromtemporary +| 380 = @referenceconvertsfromtemporary +| 381 = @isconvertible +| 382 = @isvalidwinrttype +| 383 = @iswinclass +| 384 = @iswininterface +| 385 = @istriviallyequalitycomparable +| 386 = @isscopedenum +| 387 = @istriviallyrelocatable +| 388 = @datasizeof +| 389 = @c11_generic +| 390 = @requires_expr +| 391 = @nested_requirement +| 392 = @compound_requirement +| 393 = @concept_id +| 394 = @isinvocable +| 395 = @isnothrowinvocable +| 396 = @isbitwisecloneable +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @istrivialexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + | @istriviallycopyassignable + | @isassignablenopreconditioncheck + | @referencebindstotemporary + | @issameas + | @builtinhasattribute + | @ispointerinterconvertiblewithclass + | @builtinispointerinterconvertiblewithclass + | @iscorrespondingmember + | @builtiniscorrespondingmember + | @isboundedarray + | @isunboundedarray + | @isreferenceable + | @isnothrowconvertible + | @referenceconstructsfromtemporary + | @referenceconvertsfromtemporary + | @isconvertible + | @isvalidwinrttype + | @iswinclass + | @iswininterface + | @istriviallyequalitycomparable + | @isscopedenum + | @istriviallyrelocatable + | @isinvocable + | @isnothrowinvocable + | @isbitwisecloneable + ; + +compound_requirement_is_noexcept( + int expr: @compound_requirement ref +); + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +param_ref_to_this( + int expr: @param_ref ref +) + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref, + int position: int ref, + boolean is_designated: boolean ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref, + int position: int ref, + boolean is_designated: boolean ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof | @sizeof_pack; + +sizeof_bind( + unique int expr: @sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref, + boolean has_explicit_parameter_list: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_default ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +| 38 = @stmt_consteval_if +| 39 = @stmt_not_consteval_if +| 40 = @stmt_leave +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +type_is_vla(unique int type_id: @derivedtype ref) + +if_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +@stmt_consteval_or_not_consteval_if = @stmt_consteval_if | @stmt_not_consteval_if; + +consteval_if_then( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int then_id: @stmt ref +); + +consteval_if_else( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +@stmt_for_or_range_based_for = @stmt_for + | @stmt_range_based_for; + +for_initialization( + unique int for_stmt: @stmt_for_or_range_based_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@parameterized_element = @function | @stmt_block | @requires_expr; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @parameterized_element ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue | @stmt_leave; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 14 = @ppd_ms_import +| 15 = @ppd_elifdef +| 16 = @ppd_elifndef +| 17 = @ppd_embed +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +embeds( + unique int id: @ppd_embed ref, + int included: @file ref +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/*- Database metadata -*/ + +/** + * The CLI will automatically emit applicable tuples for this table, + * such as `databaseMetadata("isOverlay", "true")` when building an + * overlay database. + */ +databaseMetadata( + string metadataKey: string ref, + string value: string ref +); + +/*- Overlay support -*/ + +/** + * The CLI will automatically emit tuples for each new/modified/deleted file + * when building an overlay database. + */ +overlayChangedFiles( + string path: string ref +); + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; diff --git a/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/semmlecode.dbscheme b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/semmlecode.dbscheme new file mode 100644 index 000000000000..7e7c2f55670f --- /dev/null +++ b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/semmlecode.dbscheme @@ -0,0 +1,2517 @@ + +/*- Compilations -*/ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * Optionally, record the build mode for each compilation. + */ +compilation_build_mode( + unique int id : @compilation ref, + int mode : int ref +); + +/* +case @compilation_build_mode.mode of + 0 = @build_mode_none +| 1 = @build_mode_manual +| 2 = @build_mode_auto +; +*/ + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- C++ dbscheme -*/ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +/** + * Gives the TRAP filename that `trap` is associated with. + * For debugging only. + */ +trap_filename( + int trap: @trap, + string filename: string ref +); + +/** + * In `build-mode: none` overlay mode, indicates that `source_file` + * (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the + * TRAP file corresponding to `foo.c`, something it transitively + * includes, or a template instantiation it transitively uses. + */ +source_file_uses_trap( + string source_file: string ref, + int trap_file: @trap ref +); + +/** + * Holds if there is a definition of `element` in TRAP file `trap_file`. + */ +in_trap( + int element: @element ref, + int trap_file: @trap ref +); + +pch_uses( + int pch: @pch ref, + int compilation: @compilation ref, + int id: @file ref +) + +#keyset[pch, compilation] +pch_creations( + int pch: @pch, + int compilation: @compilation ref, + int from: @file ref +) + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +case @macroinvocation.kind of + 1 = @macro_expansion +| 2 = @other_macro_reference +; + +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location_default ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +case @function.kind of + 0 = @unknown_function +| 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +// ... 6 = @builtin_function deprecated // GCC built-in functions, e.g. __builtin___memcpy_chk +| 7 = @user_defined_literal +| 8 = @deduction_guide +; + +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +builtin_functions( + int id: @function ref +) + +function_entry_point( + int id: @function ref, + unique int entry_point: @stmt ref +); + +function_return_type( + int id: @function ref, + int return_type: @type ref +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref +); + +/* +case @coroutine_placeholder_variable.kind of + 1 = @handle +| 2 = @promise +| 3 = @init_await_resume +; +*/ + +coroutine_placeholder_variable( + unique int placeholder_variable: @variable ref, + int kind: int ref, + int function: @function ref +) + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +function_prototyped(unique int id: @function ref) + +deduction_guide_for_class( + int id: @function ref, + int class_template: @usertype ref +) + +member_function_this_type( + unique int id: @function ref, + int this_type: @type ref +); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +/* +case @fun_requires.kind of + 1 = @template_attached +| 2 = @function_attached +; +*/ + +fun_requires( + int id: @fun_decl ref, + int kind: int ref, + int constraint: @expr ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_specialized(int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable ref); +var_requires( + int id: @var_decl ref, + int constraint: @expr ref +); + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); +type_requires( + int id: @type_decl ref, + int constraint: @expr ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +case @using.kind of + 1 = @using_declaration +| 2 = @using_directive +| 3 = @using_enum_declaration +; + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref, + int kind: int ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @parameterized_element ref, + int index: int ref, + int type_id: @type ref +); + +overrides( + int new: @function ref, + int old: @function ref +); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function ref +) + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/** + * Built-in types are the fundamental types, e.g., integral, floating, and void. + */ +case @builtintype.kind of + 1 = @errortype +| 2 = @unknowntype +| 3 = @void +| 4 = @boolean +| 5 = @char +| 6 = @unsigned_char +| 7 = @signed_char +| 8 = @short +| 9 = @unsigned_short +| 10 = @signed_short +| 11 = @int +| 12 = @unsigned_int +| 13 = @signed_int +| 14 = @long +| 15 = @unsigned_long +| 16 = @signed_long +| 17 = @long_long +| 18 = @unsigned_long_long +| 19 = @signed_long_long +// ... 20 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +// ... 40 _Decimal32 +// ... 41 _Decimal64 +// ... 42 _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +// ... 50 _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +| 54 = @fp16 // __fp16 +| 55 = @std_bfloat16 // __bf16 +| 56 = @std_float16 // std::float16_t +| 57 = @complex_std_float32 // _Complex _Float32 +| 58 = @complex_float32x // _Complex _Float32x +| 59 = @complex_std_float64 // _Complex _Float64 +| 60 = @complex_float64x // _Complex _Float64x +| 61 = @complex_std_float128 // _Complex _Float128 +| 62 = @mfp8 // __mfp8 +| 63 = @scalable_vector_count // __SVCount_t +| 64 = @complex_fp16 // _Complex __fp16 +| 65 = @complex_std_bfloat16 // _Complex __bf16 +| 66 = @complex_std_float16 // _Complex std::float16_t +; + +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/** + * Derived types are types that are directly derived from existing types and + * point to, refer to, transform type data to return a new type. + */ +case @derivedtype.kind of + 1 = @pointer +| 2 = @reference +| 3 = @type_with_specifiers +| 4 = @array +| 5 = @gnu_vector +| 6 = @routineptr +| 7 = @routinereference +| 8 = @rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated +| 10 = @block +| 11 = @scalable_vector // Arm SVE +; + +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +tupleelements( + unique int id: @derivedtype ref, + int num_elements: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator or C23 `typeof`/`typeof_unqual` + * operator taking an expression as its argument. For example: + * ``` + * int a; + * decltype(1+a) b; + * typeof(1+a) c; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * changes the semantics of the decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ + +/* +case @decltype.kind of +| 0 = @decltype +| 1 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +; +*/ + +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int kind: int ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +case @type_operator.kind of + 0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +| 1 = @underlying_type +| 2 = @bases +| 3 = @direct_bases +| 4 = @add_lvalue_reference +| 5 = @add_pointer +| 6 = @add_rvalue_reference +| 7 = @decay +| 8 = @make_signed +| 9 = @make_unsigned +| 10 = @remove_all_extents +| 11 = @remove_const +| 12 = @remove_cv +| 13 = @remove_cvref +| 14 = @remove_extent +| 15 = @remove_pointer +| 16 = @remove_reference_t +| 17 = @remove_restrict +| 18 = @remove_volatile +| 19 = @remove_reference +; + +type_operators( + unique int id: @type_operator, + int arg_type: @type ref, + int kind: int ref, + int base_type: @type ref +) + +case @usertype.kind of + 0 = @unknown_usertype +| 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +// ... 5 = @typedef deprecated // classic C: typedef typedef type name +// ... 6 = @template deprecated +| 7 = @template_parameter +| 8 = @template_template_parameter +| 9 = @proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated +| 13 = @scoped_enum +// ... 14 = @using_alias deprecated // a using name = type style typedef +| 15 = @template_struct +| 16 = @template_class +| 17 = @template_union +| 18 = @alias +; + +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + string uuid: string ref +); + +/* +case @usertype.alias_kind of +| 0 = @typedef +| 1 = @alias +*/ + +usertype_alias_kind( + int id: @usertype ref, + int alias_kind: int ref +) + +nontype_template_parameters( + int id: @expr ref +); + +type_template_type_constraint( + int id: @usertype ref, + int constraint: @expr ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname, + boolean is_complete: boolean ref +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@user_or_decltype = @usertype | @decltype; + +is_proxy_class_for( + unique int id: @usertype ref, + int templ_param_id: @user_or_decltype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location_default ref, + // a_symbol_reference_kind from the frontend. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +template_template_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +template_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +template_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@concept = @concept_template | @concept_id; + +concept_templates( + unique int concept_id: @concept_template, + string name: string ref, + int location: @location_default ref +); +concept_instantiation( + unique int to: @concept_id ref, + int from: @concept_template ref +); +is_type_constraint(int concept_id: @concept_id ref); +concept_template_argument( + int concept_id: @concept ref, + int index: int ref, + int arg_type: @type ref +); +concept_template_argument_value( + int concept_id: @concept ref, + int index: int ref, + int arg_value: @expr ref +); + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +explicit_specifier_exprs( + unique int func_id: @function ref, + int constant: @expr ref +) + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +| 4 = @attribute_arg_constant_expr +| 5 = @attribute_arg_expr +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_constant( + unique int arg: @attribute_arg ref, + int constant: @expr ref +) +attribute_arg_expr( + unique int arg: @attribute_arg ref, + int expr: @expr ref +) +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +namespaceattributes( + int namespace_id: @namespace ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + | @routinetype + | @ptrtomember + | @decltype + | @type_operator; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl + | @concept_template; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + | @c11_generic + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall( + unique int caller: @funbindexpr ref, + int kind: int ref +); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype + | @decltype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + ; + +@assign_pointer_expr = @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr + | @assign_bitwise_expr + | @assign_pointer_expr + ; + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + Binary encoding of the allocator form. + + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + Binary encoding of the deallocator form. + + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 4 = destroying_delete + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_default ref +); + +braced_initialisers( + int init: @initialiser ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_default ref +); + +expr_reuse( + int reuse: @expr ref, + int original: @expr ref, + int value_category: int ref +) + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // frontend internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +| 363 = @reuseexpr +| 364 = @istriviallycopyassignable +| 365 = @isassignablenopreconditioncheck +| 366 = @referencebindstotemporary +| 367 = @issameas +| 368 = @builtinhasattribute +| 369 = @ispointerinterconvertiblewithclass +| 370 = @builtinispointerinterconvertiblewithclass +| 371 = @iscorrespondingmember +| 372 = @builtiniscorrespondingmember +| 373 = @isboundedarray +| 374 = @isunboundedarray +| 375 = @isreferenceable +| 378 = @isnothrowconvertible +| 379 = @referenceconstructsfromtemporary +| 380 = @referenceconvertsfromtemporary +| 381 = @isconvertible +| 382 = @isvalidwinrttype +| 383 = @iswinclass +| 384 = @iswininterface +| 385 = @istriviallyequalitycomparable +| 386 = @isscopedenum +| 387 = @istriviallyrelocatable +| 388 = @datasizeof +| 389 = @c11_generic +| 390 = @requires_expr +| 391 = @nested_requirement +| 392 = @compound_requirement +| 393 = @concept_id +| 394 = @isinvocable +| 395 = @isnothrowinvocable +| 396 = @isbitwisecloneable +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @istrivialexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + | @istriviallycopyassignable + | @isassignablenopreconditioncheck + | @referencebindstotemporary + | @issameas + | @builtinhasattribute + | @ispointerinterconvertiblewithclass + | @builtinispointerinterconvertiblewithclass + | @iscorrespondingmember + | @builtiniscorrespondingmember + | @isboundedarray + | @isunboundedarray + | @isreferenceable + | @isnothrowconvertible + | @referenceconstructsfromtemporary + | @referenceconvertsfromtemporary + | @isconvertible + | @isvalidwinrttype + | @iswinclass + | @iswininterface + | @istriviallyequalitycomparable + | @isscopedenum + | @istriviallyrelocatable + | @isinvocable + | @isnothrowinvocable + | @isbitwisecloneable + ; + +compound_requirement_is_noexcept( + int expr: @compound_requirement ref +); + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +param_ref_to_this( + int expr: @param_ref ref +) + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref, + int position: int ref, + boolean is_designated: boolean ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref, + int position: int ref, + boolean is_designated: boolean ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof | @sizeof_pack; + +sizeof_bind( + unique int expr: @sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref, + boolean has_explicit_parameter_list: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_default ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +| 38 = @stmt_consteval_if +| 39 = @stmt_not_consteval_if +| 40 = @stmt_leave +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +type_is_vla(unique int type_id: @derivedtype ref) + +if_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +@stmt_consteval_or_not_consteval_if = @stmt_consteval_if | @stmt_not_consteval_if; + +consteval_if_then( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int then_id: @stmt ref +); + +consteval_if_else( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +@stmt_for_or_range_based_for = @stmt_for + | @stmt_range_based_for; + +for_initialization( + unique int for_stmt: @stmt_for_or_range_based_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@parameterized_element = @function | @stmt_block | @requires_expr; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @parameterized_element ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue | @stmt_leave; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 14 = @ppd_ms_import +| 15 = @ppd_elifdef +| 16 = @ppd_elifndef +| 17 = @ppd_embed +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +embeds( + unique int id: @ppd_embed ref, + int included: @file ref +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/*- Database metadata -*/ + +/** + * The CLI will automatically emit applicable tuples for this table, + * such as `databaseMetadata("isOverlay", "true")` when building an + * overlay database. + */ +databaseMetadata( + string metadataKey: string ref, + string value: string ref +); + +/*- Overlay support -*/ + +/** + * The CLI will automatically emit tuples for each new/modified/deleted file + * when building an overlay database. + */ +overlayChangedFiles( + string path: string ref +); + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; diff --git a/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/source_file_uses_trap.ql b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/source_file_uses_trap.ql new file mode 100644 index 000000000000..7e91f4e0b86a --- /dev/null +++ b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/source_file_uses_trap.ql @@ -0,0 +1,13 @@ +class SourceFile extends @source_file { + string toString() { none() } +} + +class Trap extends @trap { + string toString() { none() } +} + +from SourceFile source_file, string name, Trap trap +where + source_file_uses_trap(source_file, trap) and + source_file_name(source_file, name) +select name, trap diff --git a/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/upgrade.properties b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/upgrade.properties new file mode 100644 index 000000000000..8b75a52f182a --- /dev/null +++ b/cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/upgrade.properties @@ -0,0 +1,8 @@ +description: Add source_file_name +compatibility: backwards +source_file_uses_trap.rel: run source_file_uses_trap.ql +source_file_name.rel: delete +tag_name.rel: delete +trap_uses_tag.rel: delete +in_trap.rel: run in_trap.ql +in_trap_or_tag.rel: delete diff --git a/cpp/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md b/cpp/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md new file mode 100644 index 000000000000..23fdce9b6159 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol. diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 3682af828fc8..f58f85ad9434 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 8.0.0 +version: 8.0.1-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll index 211be2aa4326..dad011d93912 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll @@ -1663,7 +1663,7 @@ private module Cached { private predicate compares_ge( ValueNumber test, Operand left, Operand right, int k, boolean isGe, GuardValue value ) { - exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, value)) + compares_lt(test, right, left, 1 - k, isGe, value) } /** Rearrange various simple comparisons into `left < right + k` form. */ diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll index cf8f01e69442..7cf3b937ac51 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll @@ -353,12 +353,26 @@ module CsvValidation { ) } + private string getIncorrectConstructorSummaryOutput() { + exists(string namespace, string type, string name, string output | + type = name or + type = name + "<" + any(string s) + | + summaryModel(namespace, type, _, name, _, _, _, output, _, _, _) and + output.matches("ReturnValue%") and + result = + "Constructor model for " + namespace + "." + type + + " should use `Argument[this]` in the output, not `ReturnValue`." + ) + } + /** Holds if some row in a CSV-based flow model appears to contain typos. */ query predicate invalidModelRow(string msg) { msg = [ getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(), - getInvalidModelSubtype(), getInvalidModelColumnCount(), KindVal::getInvalidModelKind() + getInvalidModelSubtype(), getInvalidModelColumnCount(), KindVal::getInvalidModelKind(), + getIncorrectConstructorSummaryOutput() ] } } @@ -555,6 +569,7 @@ private Locatable getSupportedFunctionTemplateArgument(Function templateFunction * Normalize the `n`'th parameter of `f` by replacing template names * with `func:N` (where `N` is the index of the template). */ +pragma[nomagic] private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) { exists(Function templateFunction | templateFunction = getFullyTemplatedFunction(f) and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll index af3e25ba7344..cce1b80e7fcb 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll @@ -201,7 +201,7 @@ module SourceSinkInterpretationInput implements string toString() { result = this.asElement().toString() or - result = this.asNode().toString() + result = this.asNode().toStringImpl() or result = this.asCall().toString() } diff --git a/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll b/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll index 3dea144bbf67..e93bf578921d 100644 --- a/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll +++ b/cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll @@ -6,117 +6,67 @@ private import OverlayXml /** * Holds always for the overlay variant and never for the base variant. - * This local predicate is used to define local predicates that behave - * differently for the base and overlay variant. */ overlay[local] predicate isOverlay() { databaseMetadata("isOverlay", "true") } -overlay[local] -private string getLocationFilePath(@location_default loc) { - exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result)) -} - -/** - * Gets the file path for an element with a single location. - */ -overlay[local] -private string getSingleLocationFilePath(@element e) { - exists(@location_default loc | - var_decls(e, _, _, _, loc) - or - fun_decls(e, _, _, _, loc) - or - type_decls(e, _, loc) - or - namespace_decls(e, _, loc, _) - or - macroinvocations(e, _, loc, _) - or - preprocdirects(e, _, loc) - or - diagnostics(e, _, _, _, _, loc) - or - usings(e, _, loc, _) - or - static_asserts(e, _, _, loc, _) - or - derivations(e, _, _, _, loc) - or - frienddecls(e, _, _, loc) - or - comments(e, _, loc) - or - exprs(e, _, loc) - or - stmts(e, _, loc) - or - initialisers(e, _, _, loc) - or - attributes(e, _, _, _, loc) - or - attribute_args(e, _, _, _, loc) - or - namequalifiers(e, _, _, loc) - or - enumconstants(e, _, _, _, _, loc) - or - type_mentions(e, _, loc, _) - or - lambda_capture(e, _, _, _, _, _, loc) - or - concept_templates(e, _, loc) - | - result = getLocationFilePath(loc) - ) -} - /** - * Gets the file path for an element with potentially multiple locations. + * Holds if the TRAP file or tag `t` is reachable from source file `sourceFile` + * in the base (isOverlayVariant=false) or overlay (isOverlayVariant=true) variant. */ overlay[local] -private string getMultiLocationFilePath(@element e) { - exists(@location_default loc | - var_decls(_, e, _, _, loc) - or - fun_decls(_, e, _, _, loc) - or - type_decls(_, e, loc) - or - namespace_decls(_, e, loc, _) - | - result = getLocationFilePath(loc) +private predicate locallyReachableTrapOrTag( + boolean isOverlayVariant, string sourceFile, @trap_or_tag t +) { + exists(@source_file sf, @trap trap | + (if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and + source_file_uses_trap(sf, trap) and + source_file_name(sf, sourceFile) and + (t = trap or trap_uses_tag(trap, t)) ) } /** - * A local helper predicate that holds in the base variant and never in the - * overlay variant. - */ -overlay[local] -private predicate isBase() { not isOverlay() } - -/** - * Holds if `path` was extracted in the overlay database. + * Holds if element `e` is in TRAP file or tag `t` + * in the base (isOverlayVariant=false) or overlay (isOverlayVariant=true) variant. */ overlay[local] -private predicate overlayHasFile(string path) { - isOverlay() and - files(_, path) and - path != "" +private predicate locallyInTrapOrTag(boolean isOverlayVariant, @element e, @trap_or_tag t) { + (if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and + in_trap_or_tag(e, t) } /** * Discards an element from the base variant if: - * - It has a single location in a file extracted in the overlay, or - * - All of its locations are in files extracted in the overlay. + * - We have knowledge about what TRAP file or tag it is in (in the base). + * - It is not in any overlay TRAP file or tag that is reachable from an overlay source file. + * - For every base TRAP file or tag that contains it and is reachable from a base source file, + * either the source file has changed, or the overlay has redefined the TRAP file or tag, + * or the overlay runner has re-extracted the same source file. */ overlay[discard_entity] private predicate discardElement(@element e) { - isBase() and - ( - overlayHasFile(getSingleLocationFilePath(e)) - or - forex(string path | path = getMultiLocationFilePath(e) | overlayHasFile(path)) + // If we don't have any knowledge about what TRAP file something + // is in, then we don't want to discard it, so we only consider + // entities that are known to be in a base TRAP file or tag. + locallyInTrapOrTag(false, e, _) and + // Anything that is reachable from an overlay source file should + // not be discarded. + not exists(@trap_or_tag t | locallyInTrapOrTag(true, e, t) | + locallyReachableTrapOrTag(true, _, t) + ) and + // Finally, we have to make sure the base variant does not retain it. + // If it is reachable from a base source file, then that is + // sufficient unless either the base source file has changed (in + // particular, been deleted), or the overlay has redefined the TRAP + // file or tag it is in, or the overlay runner has re-extracted the same + // source file (e.g. because a header it includes has changed). + forall(@trap_or_tag t, string sourceFile | + locallyInTrapOrTag(false, e, t) and + locallyReachableTrapOrTag(false, sourceFile, t) + | + overlayChangedFiles(sourceFile) or + locallyReachableTrapOrTag(true, _, t) or + locallyReachableTrapOrTag(true, sourceFile, _) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll new file mode 100644 index 000000000000..fe954c640d1b --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -0,0 +1,1823 @@ +private import cpp +private import semmle.code.cpp.ir.ValueNumbering +private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.models.interfaces.DataFlow +private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl +private import DataFlowPrivate +private import DataFlowUtil +private import ModelUtil +private import SsaImpl as SsaImpl +private import DataFlowImplCommon as DataFlowImplCommon +private import codeql.util.Unit +private import Node0ToString + +/** + * A canonical representation of a field. + * + * For performance reasons we want a unique `Content` that represents + * a given field across any template instantiation of a class. + * + * This is possible in _almost_ all cases, but there are cases where it is + * not possible to map between a field in the uninstantiated template to a + * field in the instantiated template. This happens in the case of local class + * definitions (because the local class is not the template that constructs + * the instantiation - it is the enclosing function). So this abstract class + * has two implementations: a non-local case (where we can represent a + * canonical field as the field declaration from an uninstantiated class + * template or a non-templated class), and a local case (where we simply use + * the field from the instantiated class). + */ +abstract class CanonicalField extends Field { + /** Gets a field represented by this canonical field. */ + abstract Field getAField(); + + /** + * Gets a class that declares a field represented by this canonical field. + */ + abstract Class getADeclaringType(); + + /** + * Gets a type that this canonical field may have. Note that this may + * not be a unique type. For example, consider this case: + * ``` + * template + * struct S { T x; }; + * + * S s1; + * S s2; + * ``` + * In this case the canonical field corresponding to `S::x` has two types: + * `int` and `char`. + */ + Type getAType() { result = this.getAField().getType() } + + Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() } +} + +private class NonLocalCanonicalField extends CanonicalField { + Class declaringType; + + NonLocalCanonicalField() { + declaringType = this.getDeclaringType() and + not declaringType.isFromTemplateInstantiation(_) and + not declaringType.isLocal() // handled in LocalCanonicalField + } + + override Field getAField() { + exists(Class c | result.getDeclaringType() = c | + // Either the declaring class of the field is a template instantiation + // that has been constructed from this canonical declaration + c.isConstructedFrom(declaringType) and + pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName()) + or + // or this canonical declaration is not a template. + not c.isConstructedFrom(_) and + result = this + ) + } + + override Class getADeclaringType() { + result = this.getDeclaringType() + or + result.isConstructedFrom(this.getDeclaringType()) + } +} + +private class LocalCanonicalField extends CanonicalField { + Class declaringType; + + LocalCanonicalField() { + declaringType = this.getDeclaringType() and + declaringType.isLocal() + } + + override Field getAField() { result = this } + + override Class getADeclaringType() { result = declaringType } +} + +/** + * A canonical representation of a `Union`. See `CanonicalField` for the explanation for + * why we need a canonical representation. + */ +abstract class CanonicalUnion extends Union { + /** Gets a union represented by this canonical union. */ + abstract Union getAUnion(); + + /** Gets a canonical field of this canonical union. */ + CanonicalField getACanonicalField() { result.getDeclaringType() = this } +} + +private class NonLocalCanonicalUnion extends CanonicalUnion { + NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() } + + override Union getAUnion() { + result = this + or + result.isConstructedFrom(this) + } +} + +private class LocalCanonicalUnion extends CanonicalUnion { + LocalCanonicalUnion() { this.isLocal() } + + override Union getAUnion() { result = this } +} + +bindingset[f] +pragma[inline_late] +int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) } + +/** + * Gets a field in the union `u` whose size + * is `bytes` number of bytes. + */ +private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) { + result = u.getACanonicalField() and + bytes = getFieldSize(result) +} + +cached +private module Cached { + cached + newtype TContent = + TNonUnionContent(CanonicalField f, int indirectionIndex) { + // the indirection index for field content starts at 1 (because `TNonUnionContent` is thought of as + // the address of the field, `FieldAddress` in the IR). + indirectionIndex = [1 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and + // Reads and writes of union fields are tracked using `UnionContent`. + not f.getDeclaringType() instanceof Union + } or + TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) { + exists(CanonicalField f | + f = u.getACanonicalField() and + bytes = getFieldSize(f) and + // We key `UnionContent` by the union instead of its fields since a write to one + // field can be read by any read of the union's fields. Again, the indirection index + // is 1-based (because 0 is considered the address). + indirectionIndex = + [1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes) + .getAnUnspecifiedType()) + )] + ) + } or + TElementContent(int indirectionIndex) { + indirectionIndex = [1 .. getMaxElementContentIndirectionIndex()] + } + + /** + * The IR dataflow graph consists of the following nodes: + * - `Node0`, which injects most instructions and operands directly into the + * dataflow graph. + * - `VariableNode`, which is used to model flow through global variables. + * - `PostUpdateNodeImpl`, which is used to model the state of an object after + * an update after a number of loads. + * - `SsaSynthNode`, which represents synthesized nodes as computed by the shared SSA + * library. + * - `RawIndirectOperand`, which represents the value of `operand` after + * loading the address a number of times. + * - `RawIndirectInstruction`, which represents the value of `instr` after + * loading the address a number of times. + */ + cached + newtype TIRDataFlowNode = + TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or + TGlobalLikeVariableNode(GlobalLikeVariable var, int indirectionIndex) { + indirectionIndex = + [getMinIndirectionsForType(var.getUnspecifiedType()) .. SsaImpl::getMaxIndirectionsForType(var.getUnspecifiedType())] + } or + TPostUpdateNodeImpl(Operand operand, int indirectionIndex) { + isPostUpdateNodeImpl(operand, indirectionIndex) + } or + TSsaSynthNode(SsaImpl::SynthNode n) or + TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or + TRawIndirectOperand0(Node0Impl node, int indirectionIndex) { + SsaImpl::hasRawIndirectOperand(node.asOperand(), indirectionIndex) + } or + TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) { + not exists(node.asOperand()) and + SsaImpl::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex) + } or + TFinalParameterNode(Parameter p, int indirectionIndex) { + exists(SsaImpl::FinalParameterUse use | + use.getParameter() = p and + use.getIndirectionIndex() = indirectionIndex + ) + } or + TFinalGlobalValue(SsaImpl::GlobalUse globalUse) or + TInitialGlobalValue(SsaImpl::GlobalDef globalUse) or + TBodyLessParameterNodeImpl(Parameter p, int indirectionIndex) { + // Rule out parameters of catch blocks. + not exists(p.getCatchBlock()) and + // We subtract one because `getMaxIndirectionsForType` returns the maximum + // indirection for a glvalue of a given type, and this doesn't apply to + // parameters. + indirectionIndex = [0 .. SsaImpl::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1] and + not any(InitializeParameterInstruction init).getParameter() = p + } or + TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) +} + +import Cached + +/** + * An operand that is defined by a `FieldAddressInstruction`. + */ +class FieldAddress extends Operand { + FieldAddressInstruction fai; + + FieldAddress() { fai = this.getDef() and not SsaImpl::ignoreOperand(this) } + + /** Gets the field associated with this instruction. */ + Field getField() { result = fai.getField() } + + /** Gets the instruction whose result provides the address of the object containing the field. */ + Instruction getObjectAddress() { result = fai.getObjectAddress() } + + /** Gets the operand that provides the address of the object containing the field. */ + Operand getObjectAddressOperand() { result = fai.getObjectAddressOperand() } +} + +/** + * Holds if `opFrom` is an operand whose value flows to the result of `instrTo`. + * + * `isPointerArith` is `true` if `instrTo` is a `PointerArithmeticInstruction` and `opFrom` + * is the left operand. + * + * `additional` is `true` if the conversion is supplied by an implementation of the + * `Indirection` class. It is sometimes useful to exclude such conversions. + */ +predicate conversionFlow( + Operand opFrom, Instruction instrTo, boolean isPointerArith, boolean additional +) { + isPointerArith = false and + ( + additional = false and + ( + instrTo.(CopyValueInstruction).getSourceValueOperand() = opFrom + or + instrTo.(ConvertInstruction).getUnaryOperand() = opFrom + or + instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom + or + instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom + or + exists(BuiltInInstruction builtIn | + builtIn = instrTo and + // __builtin_bit_cast + builtIn.getBuiltInOperation() instanceof BuiltInBitCast and + opFrom = builtIn.getAnOperand() + ) + ) + or + additional = true and + SsaImpl::isAdditionalConversionFlow(opFrom, instrTo) + ) + or + isPointerArith = true and + additional = false and + instrTo.(PointerArithmeticInstruction).getLeftOperand() = opFrom +} + +module Public { + import ExprNodes + + /** + * A node in a data flow graph. + * + * A node can be either an expression, a parameter, or an uninitialized local + * variable. Such nodes are created with `DataFlow::exprNode`, + * `DataFlow::parameterNode`, and `DataFlow::uninitializedNode` respectively. + */ + class Node extends TIRDataFlowNode { + /** + * INTERNAL: Do not use. + */ + DataFlowCallable getEnclosingCallable() { none() } // overridden in subclasses + + /** Gets the function to which this node belongs, if any. */ + Declaration getFunction() { none() } // overridden in subclasses + + /** Holds if this node represents a glvalue. */ + predicate isGLValue() { none() } + + /** + * Gets the type of this node. + * + * If `isGLValue()` holds, then the type of this node + * should be thought of as "pointer to `getType()`". + */ + Type getType() { none() } // overridden in subclasses + + /** Gets the instruction corresponding to this node, if any. */ + Instruction asInstruction() { result = this.(InstructionNode).getInstruction() } + + /** Gets the operands corresponding to this node, if any. */ + Operand asOperand() { result = this.(OperandNode).getOperand() } + + /** + * Gets the operand that is indirectly tracked by this node behind `index` + * number of indirections. + */ + Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) } + + /** + * Holds if this node is at index `i` in basic block `block`. + * + * Note: Phi nodes are considered to be at index `-1`. + */ + final predicate hasIndexInBlock(IRBlock block, int i) { + this.asInstruction() = block.getInstruction(i) + or + this.asOperand().getUse() = block.getInstruction(i) + or + exists(SsaImpl::SynthNode ssaNode | + this.(SsaSynthNode).getSynthNode() = ssaNode and + ssaNode.getBasicBlock() = block and + ssaNode.getIndex() = i + ) + or + this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i) + or + this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i) + or + this.(PostUpdateNode).getPreUpdateNode().hasIndexInBlock(block, i) + } + + /** Gets the basic block of this node, if any. */ + final IRBlock getBasicBlock() { this.hasIndexInBlock(result, _) } + + /** + * Gets the non-conversion expression corresponding to this node, if any. + * This predicate only has a result on nodes that represent the value of + * evaluating the expression. For data flowing _out of_ an expression, like + * when an argument is passed by reference, use `asDefiningArgument` instead + * of `asExpr`. + * + * If this node strictly (in the sense of `asConvertedExpr`) corresponds to + * a `Conversion`, then the result is the underlying non-`Conversion` base + * expression. + */ + Expr asExpr() { result = this.asExpr(_) } + + /** + * INTERNAL: Do not use. + */ + Expr asExpr(int n) { result = this.(ExprNode).getExpr(n) } + + /** + * INTERNAL: Do not use. + */ + Expr asIndirectExpr(int n, int index) { result = this.(IndirectExprNode).getExpr(n, index) } + + /** + * Gets the non-conversion expression that's indirectly tracked by this node + * under `index` number of indirections. + */ + Expr asIndirectExpr(int index) { result = this.asIndirectExpr(_, index) } + + /** + * Gets the non-conversion expression that's indirectly tracked by this node + * behind a number of indirections. + */ + Expr asIndirectExpr() { result = this.asIndirectExpr(_) } + + /** + * Gets the expression corresponding to this node, if any. The returned + * expression may be a `Conversion`. + */ + Expr asConvertedExpr() { result = this.asConvertedExpr(_) } + + /** + * Gets the expression corresponding to this node, if any. The returned + * expression may be a `Conversion`. + */ + Expr asConvertedExpr(int n) { result = this.(ExprNode).getConvertedExpr(n) } + + private Expr asIndirectConvertedExpr(int n, int index) { + result = this.(IndirectExprNode).getConvertedExpr(n, index) + } + + /** + * Gets the expression that's indirectly tracked by this node + * behind `index` number of indirections. + */ + Expr asIndirectConvertedExpr(int index) { result = this.asIndirectConvertedExpr(_, index) } + + /** + * Gets the expression that's indirectly tracked by this node behind a + * number of indirections. + */ + Expr asIndirectConvertedExpr() { result = this.asIndirectConvertedExpr(_) } + + /** + * Gets the argument that defines this `DefinitionByReferenceNode`, if any. + * This predicate should be used instead of `asExpr` when referring to the + * value of a reference argument _after_ the call has returned. For example, + * in `f(&x)`, this predicate will have `&x` as its result for the `Node` + * that represents the new value of `x`. + */ + Expr asDefiningArgument() { result = this.asDefiningArgument(_) } + + /** + * Gets the definition associated with this node, if any. + * + * For example, consider the following example + * ```cpp + * int x = 42; // 1 + * x = 34; // 2 + * ++x; // 3 + * x++; // 4 + * x += 1; // 5 + * int y = x += 2; // 6 + * ``` + * - For (1) the result is `42`. + * - For (2) the result is `x = 34`. + * - For (3) the result is `++x`. + * - For (4) the result is `x++`. + * - For (5) the result is `x += 1`. + * - For (6) there are two results: + * - For the definition generated by `x += 2` the result is `x += 2` + * - For the definition generated by `int y = ...` the result is + * also `x += 2`. + * + * For assignments, `node.asDefinition()` and `node.asExpr()` will both exist + * for the same dataflow node. However, for expression such as `x++` that + * both write to `x` and read the current value of `x`, `node.asDefinition()` + * will give the node corresponding to the value after the increment, and + * `node.asExpr()` will give the node corresponding to the value before the + * increment. For an example of this, consider the following: + * + * ```cpp + * sink(x++); + * ``` + * in the above program, there will not be flow from a node `n` such that + * `n.asDefinition() instanceof IncrementOperation` to the argument of `sink` + * since the value passed to `sink` is the value before to the increment. + * However, there will be dataflow from a node `n` such that + * `n.asExpr() instanceof IncrementOperation` since the result of evaluating + * the expression `x++` is passed to `sink`. + */ + Expr asDefinition() { result = this.asDefinition(_) } + + private predicate isCertainStore() { + exists(SsaImpl::Definition def | + SsaImpl::defToNode(this, def, _) and + def.isCertain() + ) + } + + /** + * Gets the definition associated with this node, if any. + * + * For example, consider the following example + * ```cpp + * int x = 42; // 1 + * x = 34; // 2 + * ++x; // 3 + * x++; // 4 + * x += 1; // 5 + * int y = x += 2; // 6 + * ``` + * - For (1) the result is `42`. + * - For (2) the result is `x = 34`. + * - For (3) the result is `++x`. + * - For (4) the result is `x++`. + * - For (5) the result is `x += 1`. + * - For (6) there are two results: + * - For the definition generated by `x += 2` the result is `x += 2` + * - For the definition generated by `int y = ...` the result is + * also `x += 2`. + * + * For assignments, `node.asDefinition(_)` and `node.asExpr()` will both exist + * for the same dataflow node. However, for expression such as `x++` that + * both write to `x` and read the current value of `x`, `node.asDefinition(_)` + * will give the node corresponding to the value after the increment, and + * `node.asExpr()` will give the node corresponding to the value before the + * increment. For an example of this, consider the following: + * + * ```cpp + * sink(x++); + * ``` + * in the above program, there will not be flow from a node `n` such that + * `n.asDefinition(_) instanceof IncrementOperation` to the argument of `sink` + * since the value passed to `sink` is the value before to the increment. + * However, there will be dataflow from a node `n` such that + * `n.asExpr() instanceof IncrementOperation` since the result of evaluating + * the expression `x++` is passed to `sink`. + * + * If `uncertain = false` then the definition is guaranteed to overwrite + * the entire buffer pointed to by the destination address of the definition. + * Otherwise, `uncertain = true`. + * + * For example, the write `int x; x = 42;` is guaranteed to overwrite all the + * bytes allocated to `x`, while the assignment `int p[10]; p[3] = 42;` has + * `uncertain = true` since the write will not overwrite the entire buffer + * pointed to by `p`. + */ + Expr asDefinition(boolean uncertain) { + exists(StoreInstruction store | + store = this.asInstruction() and + result = asDefinitionImpl(store) and + if this.isCertainStore() then uncertain = false else uncertain = true + ) + } + + /** + * Gets the definition associated with this node, if this node is a certain definition. + * + * See `Node.asDefinition/1` for a description of certain and uncertain definitions. + */ + Expr asCertainDefinition() { result = this.asDefinition(false) } + + /** + * Gets the definition associated with this node, if this node is an uncertain definition. + * + * See `Node.asDefinition/1` for a description of certain and uncertain definitions. + */ + Expr asUncertainDefinition() { result = this.asDefinition(true) } + + /** + * Gets the indirect definition at a given indirection corresponding to this + * node, if any. + * + * See the comments on `Node.asDefinition` for examples. + */ + Expr asIndirectDefinition(int indirectionIndex) { + exists(StoreInstruction store | + this.(IndirectInstruction).hasInstructionAndIndirectionIndex(store, indirectionIndex) and + result = asDefinitionImpl(store) + ) + } + + /** + * Gets the indirect definition at some indirection corresponding to this + * node, if any. + */ + Expr asIndirectDefinition() { result = this.asIndirectDefinition(_) } + + /** + * Gets the argument that defines this `DefinitionByReferenceNode`, if any. + * + * Unlike `Node::asDefiningArgument/0`, this predicate gets the node representing + * the value of the `index`'th indirection after leaving a function. For example, + * in: + * ```cpp + * void f(int**); + * ... + * int** x = ...; + * f(x); + * ``` + * The node `n` such that `n.asDefiningArgument(1)` is the argument `x` will + * contain the value of `*x` after `f` has returned, and the node `n` such that + * `n.asDefiningArgument(2)` is the argument `x` will contain the value of `**x` + * after the `f` has returned. + */ + Expr asDefiningArgument(int index) { + this.(DefinitionByReferenceNode).getIndirectionIndex() = index and + result = this.(DefinitionByReferenceNode).getArgument() + } + + /** + * Gets the the argument going into a function for a node that represents + * the indirect value of the argument after `index` loads. For example, in: + * ```cpp + * void f(int**); + * ... + * int** x = ...; + * f(x); + * ``` + * The node `n` such that `n.asIndirectArgument(1)` represents the value of + * `*x` going into `f`, and the node `n` such that `n.asIndirectArgument(2)` + * represents the value of `**x` going into `f`. + */ + Expr asIndirectArgument(int index) { + this.(SideEffectOperandNode).hasAddressOperandAndIndirectionIndex(_, index) and + result = this.(SideEffectOperandNode).getArgument() + } + + /** + * Gets the the argument going into a function for a node that represents + * the indirect value of the argument after any non-zero number of loads. + */ + Expr asIndirectArgument() { result = this.asIndirectArgument(_) } + + /** Gets the positional parameter corresponding to this node, if any. */ + Parameter asParameter() { + exists(int indirectionIndex | result = this.asParameter(indirectionIndex) | + if result.getUnspecifiedType() instanceof ReferenceType + then indirectionIndex = 1 + else indirectionIndex = 0 + ) + } + + /** + * Gets the uninitialized local variable corresponding to this node, if + * any. + */ + LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } + + /** + * Gets the positional parameter corresponding to the node that represents + * the value of the parameter after `index` number of loads, if any. For + * example, in: + * ```cpp + * void f(int** x) { ... } + * ``` + * - The node `n` such that `n.asParameter(0)` is the parameter `x` represents + * the value of `x`. + * - The node `n` such that `n.asParameter(1)` is the parameter `x` represents + * the value of `*x`. + * - The node `n` such that `n.asParameter(2)` is the parameter `x` represents + * the value of `**x`. + */ + Parameter asParameter(int index) { + index = 0 and + result = this.(ExplicitParameterNode).getParameter() + or + this.(IndirectParameterNode).getIndirectionIndex() = index and + result = this.(IndirectParameterNode).getParameter() + } + + /** + * Holds if this node represents the `indirectionIndex`'th indirection of + * the value of an output parameter `p` just before reaching the end of a function. + */ + predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) { + exists(FinalParameterNode n | n = this | + p = n.getParameter() and + indirectionIndex = n.getIndirectionIndex() + ) + } + + /** + * Holds if this node represents the value of an output parameter `p` + * just before reaching the end of a function. + */ + predicate isFinalValueOfParameter(Parameter p) { this.isFinalValueOfParameter(p, _) } + + /** + * Gets the variable corresponding to this node, if any. This can be used for + * modeling flow in and out of global variables. + */ + Variable asVariable() { + this = TGlobalLikeVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType())) + } + + /** + * Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any. + * + * This can be used for modeling flow in and out of global variables. + */ + Variable asIndirectVariable(int indirectionIndex) { + indirectionIndex > getMinIndirectionsForType(result.getUnspecifiedType()) and + this = TGlobalLikeVariableNode(result, indirectionIndex) + } + + /** Gets an indirection of this node's underlying variable, if any. */ + Variable asIndirectVariable() { result = this.asIndirectVariable(_) } + + /** + * Gets the expression that is partially defined by this node, if any. + * + * Partial definitions are created for field stores (`x.y = taint();` is a partial + * definition of `x`), and for calls that may change the value of an object (so + * `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is + * a partial definition of `&x`). + */ + Expr asPartialDefinition() { + exists(PartialDefinitionNode pdn | this = pdn | + pdn.getIndirectionIndex() > 0 and + result = pdn.getDefinedExpr() + ) + } + + /** + * Gets an upper bound on the type of this node. + */ + Type getTypeBound() { result = this.getType() } + + /** Gets the location of this element. */ + final Location getLocation() { result = getLocationCached(this) } + + /** INTERNAL: Do not use. */ + Location getLocationImpl() { + none() // overridden by subclasses + } + + /** Gets a textual representation of this element. */ + final string toString() { result = toStringCached(this) } + + /** INTERNAL: Do not use. */ + string toStringImpl() { + none() // overridden by subclasses + } + } + + /** + * An instruction, viewed as a node in a data flow graph. + */ + class InstructionNode extends Node0 { + override InstructionNode0 node; + Instruction instr; + + InstructionNode() { instr = node.getInstruction() } + + /** Gets the instruction corresponding to this node. */ + Instruction getInstruction() { result = instr } + } + + /** + * An operand, viewed as a node in a data flow graph. + */ + class OperandNode extends Node, Node0 { + override OperandNode0 node; + Operand op; + + OperandNode() { op = node.getOperand() } + + /** Gets the operand corresponding to this node. */ + Operand getOperand() { result = op } + } + + /** + * A node associated with an object after an operation that might have + * changed its state. + * + * This can be either the argument to a callable after the callable returns + * (which might have mutated the argument), or the qualifier of a field after + * an update to the field. + * + * Nodes corresponding to AST elements, for example `ExprNode`, usually refer + * to the value before the update with the exception of `ClassInstanceExpr`, + * which represents the value after the constructor has run. + */ + abstract class PostUpdateNode extends Node { + /** + * Gets the node before the state update. + */ + abstract Node getPreUpdateNode(); + + final override Type getType() { result = this.getPreUpdateNode().getType() } + } + + /** + * The value of an uninitialized local variable, viewed as a node in a data + * flow graph. + */ + class UninitializedNode extends Node { + LocalVariable v; + + UninitializedNode() { + exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | + def.getIndirectionIndex() = 0 and + def.getValue().asInstruction() instanceof UninitializedInstruction and + SsaImpl::defToNode(this, def, sv) and + v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() + ) + } + + /** Gets the uninitialized local variable corresponding to this node. */ + LocalVariable getLocalVariable() { result = v } + } + + /** + * The value of a parameter at function entry, viewed as a node in a data + * flow graph. This includes both explicit parameters such as `x` in `f(x)` + * and implicit parameters such as `this` in `x.f()`. + * + * To match a specific kind of parameter, consider using one of the subclasses + * `ExplicitParameterNode`, `ThisParameterNode`, or + * `ParameterIndirectionNode`. + */ + final class ParameterNode = AbstractParameterNode; + + /** An explicit positional parameter, including `this`, but not `...`. */ + final class DirectParameterNode = AbstractDirectParameterNode; + + final class ExplicitParameterNode = AbstractExplicitParameterNode; + + /** An implicit `this` parameter. */ + class ThisParameterInstructionNode extends AbstractExplicitParameterNode, + InstructionDirectParameterNode + { + ThisParameterInstructionNode() { instr.getIRVariable() instanceof IRThisVariable } + + override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + pos.(DirectPosition).getArgumentIndex() = -1 and + instr.getEnclosingFunction() = f + } + + override string toStringImpl() { result = "this" } + } + + /** + * A node that represents the value of a variable after a function call that + * may have changed the variable because it's passed by reference. + * + * A typical example would be a call `f(&x)`. Firstly, there will be flow into + * `x` from previous definitions of `x`. Secondly, there will be a + * `DefinitionByReferenceNode` to represent the value of `x` after the call has + * returned. This node will have its `getArgument()` equal to `&x` and its + * `getVariableAccess()` equal to `x`. + */ + class DefinitionByReferenceNode extends IndirectArgumentOutNode { + DefinitionByReferenceNode() { this.getIndirectionIndex() > 0 } + + /** Gets the unconverted argument corresponding to this node. */ + Expr getArgument() { + result = this.getAddressOperand().getDef().getUnconvertedResultExpression() + } + + /** Gets the parameter through which this value is assigned. */ + Parameter getParameter() { + result = this.getCallInstruction().getStaticCallTarget().getParameter(this.getArgumentIndex()) + } + } + + /** + * A `Node` corresponding to a global (or `static` local) variable in the + * program, as opposed to the value of that variable at some particular point. + * This is used to model flow through global variables (and `static` local + * variables). + * + * There is no `VariableNode` for non-`static` local variables. + */ + class VariableNode extends Node, TGlobalLikeVariableNode { + Variable v; + int indirectionIndex; + + VariableNode() { this = TGlobalLikeVariableNode(v, indirectionIndex) } + + /** Gets the variable corresponding to this node. */ + Variable getVariable() { result = v } + + /** Gets the indirection index of this node. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Declaration getFunction() { none() } + + override DataFlowCallable getEnclosingCallable() { + // When flow crosses from one _enclosing callable_ to another, the + // interprocedural data-flow library discards call contexts and inserts a + // node in the big-step relation used for human-readable path explanations. + // Therefore we want a distinct enclosing callable for each `VariableNode`, + // and that can be the `Variable` itself. + result.asSourceCallable() = v + } + + override Type getType() { result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1) } + + final override Location getLocationImpl() { + // Certain variables (such as parameters) can have multiple locations. + // When there's a unique location we use that one, but if multiple locations + // exist we default to an unknown location. + result = unique( | | v.getLocation()) + or + not exists(unique( | | v.getLocation())) and + result instanceof UnknownLocation + } + + override string toStringImpl() { result = stars(this) + v.toString() } + } + + /** + * Gets the node corresponding to `instr`. + */ + InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } + + /** + * Gets the node corresponding to `operand`. + */ + OperandNode operandNode(Operand operand) { result.getOperand() = operand } + + /** + * Gets the `Node` corresponding to the value of evaluating `e` or any of its + * conversions. There is no result if `e` is a `Conversion`. For data flowing + * _out of_ an expression, like when an argument is passed by reference, use + * `definitionByReferenceNodeFromArgument` instead. + */ + ExprNode exprNode(Expr e) { result.getExpr(_) = e } + + /** + * Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may + * be a `Conversion`. For data flowing _out of_ an expression, like when an + * argument is passed by reference, use + * `definitionByReferenceNodeFromArgument` instead. + */ + ExprNode convertedExprNode(Expr e) { result.getConvertedExpr(_) = e } + + /** + * Gets the `Node` corresponding to the value of `p` at function entry. + */ + ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p } + + /** + * Gets the `Node` corresponding to a definition by reference of the variable + * that is passed as unconverted `argument` of a call. + */ + DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) { + result.getArgument() = argument + } + + /** Gets the `VariableNode` corresponding to the variable `v`. */ + VariableNode variableNode(Variable v) { + result.getVariable() = v and result.getIndirectionIndex() = 1 + } + + /** + * Gets the `Node` corresponding to the value of an uninitialized local + * variable `v`. + */ + Node uninitializedNode(LocalVariable v) { result.asUninitialized() = v } + + /** + * Holds if `indirectOperand` is the dataflow node that represents the + * indirection of `operand` with indirection index `indirectionIndex`. + */ + predicate hasOperandAndIndex( + IndirectOperand indirectOperand, Operand operand, int indirectionIndex + ) { + indirectOperand.hasOperandAndIndirectionIndex(operand, indirectionIndex) + } + + /** + * Holds if `indirectInstr` is the dataflow node that represents the + * indirection of `instr` with indirection index `indirectionIndex`. + */ + predicate hasInstructionAndIndex( + IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex + ) { + indirectInstr.hasInstructionAndIndirectionIndex(instr, indirectionIndex) + } +} + +private import Public + +/** + * A node representing an indirection of a parameter. + */ +final class IndirectParameterNode = AbstractIndirectParameterNode; + +/** + * A class that lifts pre-SSA dataflow nodes to regular dataflow nodes. + */ +private class Node0 extends Node, TNode0 { + Node0Impl node; + + Node0() { this = TNode0(node) } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = node.getEnclosingCallable() + } + + override Declaration getFunction() { result = node.getFunction() } + + override Location getLocationImpl() { result = node.getLocation() } + + override string toStringImpl() { result = node.toStringImpl() } + + override Type getType() { result = node.getType() } + + override predicate isGLValue() { node.isGLValue() } +} + +class PostUpdateNodeImpl extends PartialDefinitionNode, TPostUpdateNodeImpl { + int indirectionIndex; + Operand operand; + + PostUpdateNodeImpl() { this = TPostUpdateNodeImpl(operand, indirectionIndex) } + + override Declaration getFunction() { result = operand.getUse().getEnclosingFunction() } + + override DataFlowCallable getEnclosingCallable() { + result = this.getPreUpdateNode().getEnclosingCallable() + } + + /** Gets the operand associated with this node. */ + Operand getOperand() { result = operand } + + /** Gets the indirection index associated with this node. */ + override int getIndirectionIndex() { result = indirectionIndex } + + override Location getLocationImpl() { result = operand.getLocation() } + + final override Node getPreUpdateNode() { + indirectionIndex > 0 and + hasOperandAndIndex(result, operand, indirectionIndex) + or + indirectionIndex = 0 and + result.asOperand() = operand + } + + final override Expr getDefinedExpr() { + result = operand.getDef().getUnconvertedResultExpression() + } +} + +/** + * The node representing the value of a field after it has been updated. + */ +class PostFieldUpdateNode extends PostUpdateNodeImpl { + FieldAddress fieldAddress; + + PostFieldUpdateNode() { operand = fieldAddress.getObjectAddressOperand() } + + FieldAddress getFieldAddress() { result = fieldAddress } + + Field getUpdatedField() { result = this.getFieldAddress().getField() } + + override string toStringImpl() { + result = this.getPreUpdateNode().toStringImpl() + " [post update]" + } +} + +/** + * The base class for nodes that perform "partial definitions". + * + * In contrast to a normal "definition", which provides a new value for + * something, a partial definition is an expression that may affect a + * value, but does not necessarily replace it entirely. For example: + * ``` + * x.y = 1; // a partial definition of the object `x`. + * x.y.z = 1; // a partial definition of the object `x.y` and `x`. + * x.setY(1); // a partial definition of the object `x`. + * setY(&x); // a partial definition of the object `x`. + * ``` + */ +abstract private class PartialDefinitionNode extends PostUpdateNode { + /** Gets the indirection index of this node. */ + abstract int getIndirectionIndex(); + + /** Gets the expression that is partially defined by this node. */ + abstract Expr getDefinedExpr(); +} + +/** + * A node representing the indirection of a value after it + * has been returned from a function. + */ +class IndirectArgumentOutNode extends PostUpdateNodeImpl { + override ArgumentOperand operand; + + /** + * Gets the index of the argument that is associated with this post- + * update node. + */ + int getArgumentIndex() { + exists(CallInstruction call | call.getArgumentOperand(result) = operand) + } + + /** + * Gets the `Operand` that represents the address of the value that is being + * updated. + */ + Operand getAddressOperand() { result = operand } + + /** + * Gets the `CallInstruction` that represents the call that updated the + * argument. + */ + CallInstruction getCallInstruction() { result.getAnArgumentOperand() = operand } + + /** + * Gets the `Function` that the call targets, if this is statically known. + */ + Function getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() } + + override string toStringImpl() { + exists(string prefix | if indirectionIndex > 0 then prefix = "" else prefix = "pointer to " | + // This string should be unique enough to be helpful but common enough to + // avoid storing too many different strings. + result = prefix + this.getStaticCallTarget().getName() + " output argument" + or + not exists(this.getStaticCallTarget()) and + result = prefix + "output argument" + ) + } +} + +/** + * Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and + * `operand` represents a use of the fully converted value of `call`. + */ +private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) { + operandForFullyConvertedCall(operand, call) and + hasOperandAndIndex(node, operand, indirectionIndex) +} + +/** + * Holds if `node` is an indirect instruction with columns `(instr, indirectionIndex)`, and + * `instr` represents a use of the fully converted value of `call`. + * + * Note that `hasOperand(node, _, _, _)` implies `not hasInstruction(node, _, _, _)`. + */ +private predicate hasInstruction( + Node node, CallInstruction call, int indirectionIndex, Instruction instr +) { + instructionForFullyConvertedCall(instr, call) and + hasInstructionAndIndex(node, instr, indirectionIndex) +} + +/** + * A node representing the indirect value of a function call (i.e., a value hidden + * behind a number of indirections). + */ +class IndirectReturnOutNode extends Node { + CallInstruction call; + int indirectionIndex; + + IndirectReturnOutNode() { + // Annoyingly, we need to pick the fully converted value as the output of the function to + // make flow through in the shared dataflow library work correctly. + hasOperand(this, call, indirectionIndex, _) + or + hasInstruction(this, call, indirectionIndex, _) + } + + CallInstruction getCallInstruction() { result = call } + + int getIndirectionIndex() { result = indirectionIndex } + + /** Gets the operand associated with this node, if any. */ + Operand getOperand() { hasOperand(this, call, indirectionIndex, result) } + + /** Gets the instruction associated with this node, if any. */ + Instruction getInstruction() { hasInstruction(this, call, indirectionIndex, result) } +} + +/** + * An `IndirectReturnOutNode` which is used as a destination of a store operation. + * When it's used for a store operation it's useful to have this be a `PostUpdateNode` for + * the shared dataflow library's flow-through mechanism to detect flow in cases such as: + * ```cpp + * struct MyInt { + * int i; + * int& getRef() { return i; } + * }; + * ... + * MyInt mi; + * mi.getRef() = source(); // this is detected as a store to `i` via flow-through. + * sink(mi.i); + * ``` + */ +private class PostIndirectReturnOutNode extends IndirectReturnOutNode, PostUpdateNode { + PostIndirectReturnOutNode() { + any(StoreInstruction store).getDestinationAddressOperand() = this.getOperand() + } + + override Node getPreUpdateNode() { result = this } +} + +/** + * A node that represents the indirect value of an operand in the IR + * after `index` number of loads. + */ +private class RawIndirectOperand0 extends Node, TRawIndirectOperand0 { + Node0Impl node; + int indirectionIndex; + + RawIndirectOperand0() { this = TRawIndirectOperand0(node, indirectionIndex) } + + /** Gets the underlying instruction. */ + Operand getOperand() { result = node.asOperand() } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Declaration getFunction() { result = node.getFunction() } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = node.getEnclosingCallable() + } + + override predicate isGLValue() { this.getOperand().isGLValue() } + + override Type getType() { + exists(int sub, Type type, boolean isGLValue | + type = getOperandType(this.getOperand(), isGLValue) and + if isGLValue = true then sub = 1 else sub = 0 + | + result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub) + ) + } + + final override Location getLocationImpl() { + if exists(this.getOperand().getLocation()) + then result = this.getOperand().getLocation() + else result instanceof UnknownLocation + } + + override string toStringImpl() { result = stars(this) + operandToString(this.getOperand()) } +} + +/** + * A node that represents the indirect value of an instruction in the IR + * after `index` number of loads. + */ +private class RawIndirectInstruction0 extends Node, TRawIndirectInstruction0 { + Node0Impl node; + int indirectionIndex; + + RawIndirectInstruction0() { this = TRawIndirectInstruction0(node, indirectionIndex) } + + /** Gets the underlying instruction. */ + Instruction getInstruction() { result = node.asInstruction() } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Declaration getFunction() { result = node.getFunction() } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = node.getEnclosingCallable() + } + + override predicate isGLValue() { this.getInstruction().isGLValue() } + + override Type getType() { + exists(int sub, Type type, boolean isGLValue | + type = getInstructionType(this.getInstruction(), isGLValue) and + if isGLValue = true then sub = 1 else sub = 0 + | + result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub) + ) + } + + final override Location getLocationImpl() { + if exists(this.getInstruction().getLocation()) + then result = this.getInstruction().getLocation() + else result instanceof UnknownLocation + } + + override string toStringImpl() { + result = stars(this) + instructionToString(this.getInstruction()) + } +} + +/** + * A node that represents the indirect value of an operand in the IR + * after a number of loads. + */ +class RawIndirectOperand extends Node { + int indirectionIndex; + Operand operand; + + RawIndirectOperand() { + exists(Node0Impl node | operand = node.asOperand() | + this = TRawIndirectOperand0(node, indirectionIndex) + or + this = TRawIndirectInstruction0(node, indirectionIndex) + ) + } + + /** Gets the operand associated with this node. */ + Operand getOperand() { result = operand } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } +} + +/** + * A node that represents the indirect value of an instruction in the IR + * after a number of loads. + */ +class RawIndirectInstruction extends Node { + int indirectionIndex; + Instruction instr; + + RawIndirectInstruction() { + exists(Node0Impl node | instr = node.asInstruction() | + this = TRawIndirectOperand0(node, indirectionIndex) + or + this = TRawIndirectInstruction0(node, indirectionIndex) + ) + } + + /** Gets the instruction associated with this node. */ + Instruction getInstruction() { result = instr } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } +} + +/** + * A synthesized SSA node produced by the shared SSA library, viewed as a node + * in a data flow graph. + */ +class SsaSynthNode extends Node, TSsaSynthNode { + SsaImpl::SynthNode node; + + SsaSynthNode() { this = TSsaSynthNode(node) } + + /** Gets the synthesized SSA node associated with this node. */ + SsaImpl::SynthNode getSynthNode() { result = node } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = node.getBasicBlock().getEnclosingFunction() } + + override Type getType() { result = node.getSourceVariable().getType() } + + override predicate isGLValue() { node.getSourceVariable().isGLValue() } + + final override Location getLocationImpl() { result = node.getLocation() } + + override string toStringImpl() { result = node.toString() } +} + +/** + * Dataflow nodes necessary for iterator flow + */ +class SsaIteratorNode extends Node, TSsaIteratorNode { + IteratorFlow::IteratorFlowNode node; + + SsaIteratorNode() { this = TSsaIteratorNode(node) } + + /** Gets the phi node associated with this node. */ + IteratorFlow::IteratorFlowNode getIteratorFlowNode() { result = node } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = node.getFunction() } + + override Type getType() { result = node.getType() } + + final override Location getLocationImpl() { result = node.getLocation() } + + override string toStringImpl() { result = node.toString() } +} + +/** + * A node representing a value after leaving a function. + */ +class SideEffectOperandNode extends Node instanceof IndirectOperand { + CallInstruction call; + int argumentIndex; + ArgumentOperand arg; + + SideEffectOperandNode() { + arg = call.getArgumentOperand(argumentIndex) and + IndirectOperand.super.hasOperandAndIndirectionIndex(arg, _) + } + + CallInstruction getCallInstruction() { result = call } + + /** Gets the underlying operand and the underlying indirection index. */ + predicate hasAddressOperandAndIndirectionIndex(Operand operand, int indirectionIndex) { + IndirectOperand.super.hasOperandAndIndirectionIndex(operand, indirectionIndex) + } + + int getArgumentIndex() { result = argumentIndex } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = call.getEnclosingFunction() } + + Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() } +} + +/** + * A node representing the value of a global variable just before returning + * from a function body. + */ +class FinalGlobalValue extends Node, TFinalGlobalValue { + SsaImpl::GlobalUse globalUse; + + FinalGlobalValue() { this = TFinalGlobalValue(globalUse) } + + /** Gets the underlying SSA use. */ + SsaImpl::GlobalUse getGlobalUse() { result = globalUse } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() } + + override Type getType() { + exists(int indirectionIndex | + indirectionIndex = globalUse.getIndirectionIndex() and + result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex) + ) + } + + final override Location getLocationImpl() { result = globalUse.getLocation() } + + override string toStringImpl() { result = globalUse.toString() } +} + +/** + * A node representing the value of a global variable just after entering + * a function body. + */ +class InitialGlobalValue extends Node, TInitialGlobalValue { + SsaImpl::GlobalDef globalDef; + + InitialGlobalValue() { this = TInitialGlobalValue(globalDef) } + + /** Gets the underlying SSA definition. */ + SsaImpl::GlobalDef getGlobalDef() { result = globalDef } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = globalDef.getFunction() } + + final override predicate isGLValue() { globalDef.getIndirectionIndex() = 0 } + + override Type getType() { result = globalDef.getUnderlyingType() } + + final override Location getLocationImpl() { result = globalDef.getLocation() } + + override string toStringImpl() { result = globalDef.toString() } +} + +/** + * A node representing a parameter for a function with no body. + */ +class BodyLessParameterNodeImpl extends Node, TBodyLessParameterNodeImpl { + Parameter p; + int indirectionIndex; + + BodyLessParameterNodeImpl() { this = TBodyLessParameterNodeImpl(p, indirectionIndex) } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = p.getFunction() } + + /** Gets the indirection index of this node. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Type getType() { + result = getTypeImpl(p.getUnderlyingType(), this.getIndirectionIndex()) + } + + final override Location getLocationImpl() { + result = unique( | | p.getLocation()) + or + count(p.getLocation()) != 1 and + result instanceof UnknownLocation + } + + final override string toStringImpl() { + exists(string prefix | prefix = stars(this) | result = prefix + p.toString()) + } +} + +/** + * A data-flow node used to model flow summaries. That is, a dataflow node + * that is synthesized to represent a parameter, return value, or other part + * of a models-as-data modeled function. + */ +class FlowSummaryNode extends Node, TFlowSummaryNode { + /** + * Gets the models-as-data `SummaryNode` associated with this dataflow + * `FlowSummaryNode`. + */ + FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) } + + /** + * Gets the summarized callable that this node belongs to. + */ + FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() { + result = this.getSummaryNode().getSummarizedCallable() + } + + /** + * Gets the enclosing callable. For a `FlowSummaryNode` this is always the + * summarized function this node is part of. + */ + override DataFlowCallable getEnclosingCallable() { + result.asSummarizedCallable() = this.getSummarizedCallable() + } + + override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() } + + override string toStringImpl() { result = this.getSummaryNode().toString() } +} + +/** + * A node representing the indirection of a value that is + * about to be returned from a function. + */ +class IndirectReturnNode extends Node { + IndirectReturnNode() { + this instanceof FinalParameterNode + or + this.(IndirectOperand) + .hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _) + } + + override SourceCallable getEnclosingCallable() { result.asSourceCallable() = this.getFunction() } + + /** + * Holds if this node represents the value that is returned to the caller + * through a `return` statement. + */ + predicate isNormalReturn() { this instanceof IndirectOperand } + + /** + * Holds if this node represents the value that is returned to the caller + * by writing to the `argumentIndex`'th argument of the call. + */ + predicate isParameterReturn(int argumentIndex) { + this.(FinalParameterNode).getArgumentIndex() = argumentIndex + } + + /** Gets the indirection index of this indirect return node. */ + int getIndirectionIndex() { + result = this.(FinalParameterNode).getIndirectionIndex() + or + this.(IndirectOperand).hasOperandAndIndirectionIndex(_, result) + } +} + +/** + * A node representing the value of an output parameter + * just before reaching the end of a function. + */ +class FinalParameterNode extends Node, TFinalParameterNode { + Parameter p; + int indirectionIndex; + + FinalParameterNode() { this = TFinalParameterNode(p, indirectionIndex) } + + /** Gets the parameter associated with this final use. */ + Parameter getParameter() { result = p } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + /** Gets the argument index associated with this final use. */ + final int getArgumentIndex() { result = p.getIndex() } + + override Declaration getFunction() { result = p.getFunction() } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Type getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) } + + final override Location getLocationImpl() { + // Parameters can have multiple locations. When there's a unique location we use + // that one, but if multiple locations exist we default to an unknown location. + result = unique( | | p.getLocation()) + or + not exists(unique( | | p.getLocation())) and + result instanceof UnknownLocation + } + + override string toStringImpl() { result = stars(this) + p.toString() } +} + +abstract private class AbstractParameterNode extends Node { + /** + * Holds if this node is the parameter of `f` at the specified position. The + * implicit `this` parameter is considered to have position `-1`, and + * pointer-indirection parameters are at further negative positions. + */ + predicate isSourceParameterOf(Function f, ParameterPosition pos) { none() } + + /** + * Holds if this node is the parameter of `sc` at the specified position. The + * implicit `this` parameter is considered to have position `-1`, and + * pointer-indirection parameters are at further negative positions. + */ + predicate isSummaryParameterOf( + FlowSummaryImpl::Public::SummarizedCallable sc, ParameterPosition pos + ) { + none() + } + + /** + * Holds if this node is the parameter of `c` at the specified position. The + * implicit `this` parameter is considered to have position `-1`, and + * pointer-indirection parameters are at further negative positions. + */ + final predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.isSummaryParameterOf(c.asSummarizedCallable(), pos) + or + this.isSourceParameterOf(c.asSourceCallable(), pos) + } + + /** Gets the `Parameter` associated with this node, if it exists. */ + Parameter getParameter() { none() } // overridden by subclasses +} + +abstract private class AbstractIndirectParameterNode extends AbstractParameterNode { + /** Gets the indirection index of this parameter node. */ + abstract int getIndirectionIndex(); +} + +pragma[noinline] +private predicate indirectParameterNodeHasArgumentIndexAndIndex( + IndirectInstructionParameterNode node, int argumentIndex, int indirectionIndex +) { + node.hasInstructionAndIndirectionIndex(_, indirectionIndex) and + node.getArgumentIndex() = argumentIndex +} + +pragma[noinline] +private predicate indirectPositionHasArgumentIndexAndIndex( + IndirectionPosition pos, int argumentIndex, int indirectionIndex +) { + pos.getArgumentIndex() = argumentIndex and + pos.getIndirectionIndex() = indirectionIndex +} + +private class IndirectInstructionParameterNode extends AbstractIndirectParameterNode instanceof IndirectInstruction +{ + InitializeParameterInstruction init; + + IndirectInstructionParameterNode() { + IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) + } + + int getArgumentIndex() { init.hasIndex(result) } + + override string toStringImpl() { + exists(string prefix | prefix = stars(this) | + result = prefix + this.getParameter().toString() + or + not exists(this.getParameter()) and + result = prefix + "this" + ) + } + + /** Gets the parameter whose indirection is initialized. */ + override Parameter getParameter() { result = init.getParameter() } + + override DataFlowCallable getEnclosingCallable() { + result.asSourceCallable() = this.getFunction() + } + + override Declaration getFunction() { result = init.getEnclosingFunction() } + + override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + this.getFunction() = f and + exists(int argumentIndex, int indirectionIndex | + indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and + indirectParameterNodeHasArgumentIndexAndIndex(this, argumentIndex, indirectionIndex) + ) + } + + /** Gets the underlying operand and the underlying indirection index. */ + predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) { + IndirectInstruction.super.hasInstructionAndIndirectionIndex(instr, index) + } + + final override int getIndirectionIndex() { this.hasInstructionAndIndirectionIndex(init, result) } +} + +abstract private class AbstractDirectParameterNode extends AbstractParameterNode { } + +/** + * A non-indirect parameter node that is represented as an `Instruction`. + */ +abstract class InstructionDirectParameterNode extends InstructionNode, AbstractDirectParameterNode { + final override InitializeParameterInstruction instr; + + /** + * Gets the `IRVariable` that this parameter references. + */ + final IRVariable getIRVariable() { result = instr.getIRVariable() } +} + +abstract private class AbstractExplicitParameterNode extends AbstractDirectParameterNode { } + +/** An explicit positional parameter, not including `this` or `...`. */ +private class ExplicitParameterInstructionNode extends AbstractExplicitParameterNode, + InstructionDirectParameterNode +{ + ExplicitParameterInstructionNode() { exists(instr.getParameter()) } + + override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + f.getParameter(pos.(DirectPosition).getArgumentIndex()) = instr.getParameter() + } + + override string toStringImpl() { result = instr.getParameter().toString() } + + override Parameter getParameter() { result = instr.getParameter() } +} + +/** + * A parameter node that is part of a summary. + */ +class SummaryParameterNode extends AbstractParameterNode, FlowSummaryNode { + SummaryParameterNode() { + FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _) + } + + private ParameterPosition getPosition() { + FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result) + } + + override predicate isSummaryParameterOf( + FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition p + ) { + c = this.getSummarizedCallable() and + p = this.getPosition() + } +} + +private class DirectBodyLessParameterNode extends AbstractExplicitParameterNode, + BodyLessParameterNodeImpl +{ + DirectBodyLessParameterNode() { indirectionIndex = 0 } + + override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + this.getFunction() = f and + f.getParameter(pos.(DirectPosition).getArgumentIndex()) = p + } + + override Parameter getParameter() { result = p } +} + +private class IndirectBodyLessParameterNode extends AbstractIndirectParameterNode, + BodyLessParameterNodeImpl +{ + IndirectBodyLessParameterNode() { not this instanceof DirectBodyLessParameterNode } + + override predicate isSourceParameterOf(Function f, ParameterPosition pos) { + exists(int argumentPosition | + this.getFunction() = f and + f.getParameter(argumentPosition) = p and + indirectPositionHasArgumentIndexAndIndex(pos, argumentPosition, indirectionIndex) + ) + } + + override int getIndirectionIndex() { + result = BodyLessParameterNodeImpl.super.getIndirectionIndex() + } + + override Parameter getParameter() { result = p } +} + +/** + * A `PostUpdateNode` that is part of a flow summary. These are synthesized, + * for example, when a models-as-data summary models a write to a field since + * the write needs to target a `PostUpdateNode`. + */ +class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode { + SummaryPostUpdateNode() { + FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), _) + } + + override Node getPreUpdateNode() { + FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), + result.(FlowSummaryNode).getSummaryNode()) + } +} + +/** + * Returns `t`, but stripped of the outermost pointer, reference, etc. + * + * For example, `stripPointers(int*&)` is `int*` and `stripPointers(int*)` is `int`. + */ +private Type stripPointer(Type t) { + result = any(SsaImpl::Indirection ind | ind.getType() = t).getBaseType() + or + result = t.(PointerToMemberType).getBaseType() + or + result = t.(FunctionPointerIshType).getBaseType() +} + +/** + * Returns `t`, but stripped of the outer-most `indirectionIndex` number of indirections. + */ +private Type getTypeImpl0(Type t, int indirectionIndex) { + indirectionIndex = 0 and + result = t + or + indirectionIndex > 0 and + exists(Type stripped | + stripped = stripPointer(t.stripTopLevelSpecifiers()) and + stripped.getUnspecifiedType() != t.getUnspecifiedType() and + result = getTypeImpl0(stripped, indirectionIndex - 1) + ) +} + +/** + * Returns `t`, but stripped of the outer-most `indirectionIndex` number of indirections. + * + * If `indirectionIndex` cannot be stripped off `t`, an `UnknownType` is returned. + */ +bindingset[t, indirectionIndex] +pragma[inline_late] +Type getTypeImpl(Type t, int indirectionIndex) { + result = getTypeImpl0(t, indirectionIndex) + or + not exists(getTypeImpl0(t, indirectionIndex)) and + result instanceof UnknownType +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 88d7dd9faf19..6dd953b16ab5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1,5 +1,6 @@ private import cpp as Cpp private import DataFlowUtil +private import DataFlowNodes private import semmle.code.cpp.ir.IR private import DataFlowDispatch private import semmle.code.cpp.ir.internal.IRCppLanguage @@ -16,28 +17,42 @@ private import semmle.code.cpp.dataflow.ExternalFlow as External cached private module Cached { cached - module Nodes0 { - cached - newtype TIRDataFlowNode0 = - TInstructionNode0(Instruction i) { - not Ssa::ignoreInstruction(i) and - not exists(Operand op | - not Ssa::ignoreOperand(op) and i = Ssa::getIRRepresentationOfOperand(op) - ) and - // We exclude `void`-typed instructions because they cannot contain data. - // However, if the instruction is a glvalue, and their type is `void`, then the result - // type of the instruction is really `void*`, and thus we still want to have a dataflow - // node for it. - (not i.getResultType() instanceof VoidType or i.isGLValue()) - } or - TMultipleUseOperandNode0(Operand op) { - not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op)) - } or - TSingleUseOperandNode0(Operand op) { - not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op)) - } + newtype TIRDataFlowNode0 = + TInstructionNode0(Instruction i) { + not Ssa::ignoreInstruction(i) and + not exists(Operand op | + not Ssa::ignoreOperand(op) and i = Ssa::getIRRepresentationOfOperand(op) + ) and + // We exclude `void`-typed instructions because they cannot contain data. + // However, if the instruction is a glvalue, and their type is `void`, then the result + // type of the instruction is really `void*`, and thus we still want to have a dataflow + // node for it. + (not i.getResultType() instanceof VoidType or i.isGLValue()) + } or + TMultipleUseOperandNode0(Operand op) { + not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op)) + } or + TSingleUseOperandNode0(Operand op) { + not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op)) + } + + cached + string toStringCached(Node n) { + result = toExprString(n) + or + not exists(toExprString(n)) and + result = n.toStringImpl() } + cached + Location getLocationCached(Node n) { result = n.getLocationImpl() } + + cached + newtype TContentApprox = + TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or + TUnionApproxContent(string s) { unionHasApproxName(_, s) } or + TElementApproxContent() + /** * Gets an additional term that is added to the `join` and `branch` computations to reflect * an additional forward or backwards branching factor that is not taken into account @@ -59,38 +74,174 @@ private module Cached { result = countNumberOfBranchesUsingParameter(switch, p) ) } -} -import Cached -private import Nodes0 + cached + newtype TDataFlowCallable = + TSourceCallable(Cpp::Declaration decl) or + TSummarizedCallable(FlowSummaryImpl::Public::SummarizedCallable c) -/** - * A module for calculating the number of stars (i.e., `*`s) needed for various - * dataflow node `toString` predicates. - */ -module NodeStars { - private int getNumberOfIndirections(Node n) { - result = n.(RawIndirectOperand).getIndirectionIndex() - or - result = n.(RawIndirectInstruction).getIndirectionIndex() - or - result = n.(VariableNode).getIndirectionIndex() + cached + newtype TDataFlowCall = + TNormalCall(CallInstruction call) or + TSummaryCall( + FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver + ) { + FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) + } + + /** + * Holds if data can flow from `node1` to `node2` in a way that loses the + * calling context. For example, this would happen with flow through a + * global or static variable. + */ + cached + predicate jumpStep(Node n1, Node n2) { + exists(GlobalLikeVariable v | + exists(Ssa::GlobalUse globalUse | + v = globalUse.getVariable() and + n1.(FinalGlobalValue).getGlobalUse() = globalUse + | + globalUse.getIndirection() = getMinIndirectionForGlobalUse(globalUse) and + v = n2.asVariable() + or + v = n2.asIndirectVariable(globalUse.getIndirection()) + ) + or + exists(Ssa::GlobalDef globalDef | + v = globalDef.getVariable() and + n2.(InitialGlobalValue).getGlobalDef() = globalDef + | + globalDef.getIndirection() = getMinIndirectionForGlobalDef(globalDef) and + v = n1.asVariable() + or + v = n1.asIndirectVariable(globalDef.getIndirection()) + ) + ) or - result = n.(PostUpdateNodeImpl).getIndirectionIndex() + // models-as-data summarized flow + FlowSummaryImpl::Private::Steps::summaryJumpStep(n1.(FlowSummaryNode).getSummaryNode(), + n2.(FlowSummaryNode).getSummaryNode()) + } + + /** + * Holds if data can flow from `node1` to `node2` via an assignment to `f`. + * Thus, `node2` references an object with a field `f` that contains the + * value of `node1`. + * + * The boolean `certain` is true if the destination address does not involve + * any pointer arithmetic, and false otherwise. + */ + cached + predicate storeStepImpl(Node node1, Content c, Node node2, boolean certain) { + exists( + PostFieldUpdateNode postFieldUpdate, int indirectionIndex1, int numberOfLoads, + StoreInstruction store, FieldContent fc + | + postFieldUpdate = node2 and + fc = c and + nodeHasInstruction(node1, pragma[only_bind_into](store), + pragma[only_bind_into](indirectionIndex1)) and + postFieldUpdate.getIndirectionIndex() = 1 and + numberOfLoadsFromOperand(postFieldUpdate.getFieldAddress(), + store.getDestinationAddressOperand(), numberOfLoads, certain) and + fc.getAField() = postFieldUpdate.getUpdatedField() and + getIndirectionIndexLate(fc) = 1 + indirectionIndex1 + numberOfLoads + ) or - result = n.(FinalParameterNode).getIndirectionIndex() + // models-as-data summarized flow + FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c, + node2.(FlowSummaryNode).getSummaryNode()) and + certain = true + } + + /** + * Holds if data can flow from `node1` to `node2` via an assignment to `f`. + * Thus, `node2` references an object with a field `f` that contains the + * value of `node1`. + */ + cached + predicate storeStep(Node node1, ContentSet c, Node node2) { storeStepImpl(node1, c, node2, _) } + + /** + * Holds if data can flow from `node1` to `node2` via a read of `f`. + * Thus, `node1` references an object with a field `f` whose value ends up in + * `node2`. + */ + cached + predicate readStep(Node node1, ContentSet c, Node node2) { + exists( + FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2, FieldContent fc + | + fc = c and + nodeHasOperand(node2, operand, indirectionIndex2) and + // The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct + // in `storeStep`. + nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and + numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _) and + fc.getAField() = fa1.getField() and + getIndirectionIndexLate(fc) = indirectionIndex2 + numberOfLoads + ) or - result = n.(BodyLessParameterNodeImpl).getIndirectionIndex() + // models-as-data summarized flow + FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c, + node2.(FlowSummaryNode).getSummaryNode()) } /** - * Gets the number of stars (i.e., `*`s) needed to produce the `toString` - * output for `n`. + * Holds if values stored inside content `c` are cleared at node `n`. */ - string stars(Node n) { result = repeatStars(getNumberOfIndirections(n)) } + cached + predicate clearsContent(Node n, ContentSet c) { + n = + any(PostUpdateNode pun, Content d | + d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) + | + pun + ).getPreUpdateNode() and + ( + not exists(Operand op, Cpp::Operation p | + n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and + ( + p instanceof Cpp::AssignPointerAddExpr or + p instanceof Cpp::AssignPointerSubExpr or + p instanceof Cpp::CrementOperation + ) + | + p.getAnOperand() = op.getUse().getAst() + ) + or + forex(PostUpdateNode pun, Content d | + pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and + storeStepImpl(_, d, pun, true) and + pun.getPreUpdateNode() = n + | + c.(Content).getIndirectionIndex() = d.getIndirectionIndex() + ) + ) + } +} + +import Cached + +private int getNumberOfIndirections(Node n) { + result = n.(RawIndirectOperand).getIndirectionIndex() + or + result = n.(RawIndirectInstruction).getIndirectionIndex() + or + result = n.(VariableNode).getIndirectionIndex() + or + result = n.(PostUpdateNodeImpl).getIndirectionIndex() + or + result = n.(FinalParameterNode).getIndirectionIndex() + or + result = n.(BodyLessParameterNodeImpl).getIndirectionIndex() } -import NodeStars +/** + * Gets the number of stars (i.e., `*`s) needed to produce the `toString` + * output for `n`. + */ +string stars(Node n) { result = repeatStars(getNumberOfIndirections(n)) } /** * A cut-down `DataFlow::Node` class that does not depend on the output of SSA. @@ -828,85 +979,10 @@ private int getMinIndirectionForGlobalDef(Ssa::GlobalDef def) { result = getMinIndirectionsForType(def.getUnspecifiedType()) } -/** - * Holds if data can flow from `node1` to `node2` in a way that loses the - * calling context. For example, this would happen with flow through a - * global or static variable. - */ -predicate jumpStep(Node n1, Node n2) { - exists(GlobalLikeVariable v | - exists(Ssa::GlobalUse globalUse | - v = globalUse.getVariable() and - n1.(FinalGlobalValue).getGlobalUse() = globalUse - | - globalUse.getIndirection() = getMinIndirectionForGlobalUse(globalUse) and - v = n2.asVariable() - or - v = n2.asIndirectVariable(globalUse.getIndirection()) - ) - or - exists(Ssa::GlobalDef globalDef | - v = globalDef.getVariable() and - n2.(InitialGlobalValue).getGlobalDef() = globalDef - | - globalDef.getIndirection() = getMinIndirectionForGlobalDef(globalDef) and - v = n1.asVariable() - or - v = n1.asIndirectVariable(globalDef.getIndirection()) - ) - ) - or - // models-as-data summarized flow - FlowSummaryImpl::Private::Steps::summaryJumpStep(n1.(FlowSummaryNode).getSummaryNode(), - n2.(FlowSummaryNode).getSummaryNode()) -} - bindingset[c] pragma[inline_late] private int getIndirectionIndexLate(Content c) { result = c.getIndirectionIndex() } -/** - * Holds if data can flow from `node1` to `node2` via an assignment to `f`. - * Thus, `node2` references an object with a field `f` that contains the - * value of `node1`. - * - * The boolean `certain` is true if the destination address does not involve - * any pointer arithmetic, and false otherwise. This has to do with whether a - * store step can be used to clear a field (see `clearsContent`). - */ -predicate storeStepImpl(Node node1, Content c, Node node2, boolean certain) { - exists( - PostFieldUpdateNode postFieldUpdate, int indirectionIndex1, int numberOfLoads, - StoreInstruction store, FieldContent fc - | - postFieldUpdate = node2 and - fc = c and - nodeHasInstruction(node1, pragma[only_bind_into](store), - pragma[only_bind_into](indirectionIndex1)) and - postFieldUpdate.getIndirectionIndex() = 1 and - numberOfLoadsFromOperand(postFieldUpdate.getFieldAddress(), - store.getDestinationAddressOperand(), numberOfLoads, certain) and - fc.getAField() = postFieldUpdate.getUpdatedField() and - getIndirectionIndexLate(fc) = 1 + indirectionIndex1 + numberOfLoads - ) - or - // models-as-data summarized flow - FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c, - node2.(FlowSummaryNode).getSummaryNode()) and - certain = true -} - -/** - * Holds if data can flow from `node1` to `node2` via an assignment to `f`. - * Thus, `node2` references an object with a field `f` that contains the - * value of `node1`. - */ -predicate storeStep(Node node1, ContentSet c, Node node2) { storeStepImpl(node1, c, node2, _) } - -/** - * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like - * operations and exactly `n` `LoadInstruction` operations. - */ private predicate numberOfLoadsFromOperandRec( Operand operandFrom, Operand operandTo, int ind, boolean certain ) { @@ -957,63 +1033,6 @@ predicate nodeHasInstruction(Node node, Instruction instr, int indirectionIndex) hasInstructionAndIndex(node, instr, indirectionIndex) } -/** - * Holds if data can flow from `node1` to `node2` via a read of `f`. - * Thus, `node1` references an object with a field `f` whose value ends up in - * `node2`. - */ -predicate readStep(Node node1, ContentSet c, Node node2) { - exists( - FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2, FieldContent fc - | - fc = c and - nodeHasOperand(node2, operand, indirectionIndex2) and - // The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct - // in `storeStep`. - nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and - numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _) and - fc.getAField() = fa1.getField() and - getIndirectionIndexLate(fc) = indirectionIndex2 + numberOfLoads - ) - or - // models-as-data summarized flow - FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c, - node2.(FlowSummaryNode).getSummaryNode()) -} - -/** - * Holds if values stored inside content `c` are cleared at node `n`. - */ -predicate clearsContent(Node n, ContentSet c) { - n = - any(PostUpdateNode pun, Content d | d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) | pun) - .getPreUpdateNode() and - ( - // The crement operations and pointer addition and subtraction self-assign. We do not - // want to clear the contents if it is indirectly pointed at by any of these operations, - // as part of the contents might still be accessible afterwards. If there is no such - // indirection clearing the contents is safe. - not exists(Operand op, Cpp::Operation p | - n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and - ( - p instanceof Cpp::AssignPointerAddExpr or - p instanceof Cpp::AssignPointerSubExpr or - p instanceof Cpp::CrementOperation - ) - | - p.getAnOperand() = op.getUse().getAst() - ) - or - forex(PostUpdateNode pun, Content d | - pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and - storeStepImpl(_, d, pun, true) and - pun.getPreUpdateNode() = n - | - c.(Content).getIndirectionIndex() = d.getIndirectionIndex() - ) - ) -} - /** * Holds if the value that is being tracked is expected to be stored inside content `c` * at node `n`. @@ -1046,11 +1065,6 @@ class CastNode extends Node { CastNode() { none() } // stub implementation } -cached -private newtype TDataFlowCallable = - TSourceCallable(Cpp::Declaration decl) or - TSummarizedCallable(FlowSummaryImpl::Public::SummarizedCallable c) - /** * A callable, which may be: * - a function (that may contain code) @@ -1134,15 +1148,6 @@ class DataFlowType extends TypeFinal { string toString() { result = "" } } -cached -private newtype TDataFlowCall = - TNormalCall(CallInstruction call) or - TSummaryCall( - FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver - ) { - FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) - } - private predicate summarizedCallableIsManual(SummarizedCallable sc) { sc.asSummarizedCallable().hasManualModel() } @@ -1523,12 +1528,6 @@ private predicate fieldHasApproxName(Field f, string s) { private predicate unionHasApproxName(Cpp::Union u, string s) { s = u.getName().charAt(0) } -cached -private newtype TContentApprox = - TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or - TUnionApproxContent(string s) { unionHasApproxName(_, s) } or - TElementApproxContent() - /** An approximated `Content`. */ class ContentApprox extends TContentApprox { string toString() { none() } // overridden in subclasses diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index d704c7d56d65..d42d959f56ee 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -3,14 +3,12 @@ */ private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. private import semmle.code.cpp.ir.ValueNumbering private import semmle.code.cpp.ir.IR private import semmle.code.cpp.controlflow.IRGuards private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl +private import TaintTrackingUtil as TaintTrackingUtil private import DataFlowPrivate private import ModelUtil private import SsaImpl as SsaImpl @@ -18,1702 +16,8 @@ private import DataFlowImplCommon as DataFlowImplCommon private import codeql.util.Unit private import Node0ToString private import DataFlowDispatch as DataFlowDispatch -import ExprNodes - -/** - * The IR dataflow graph consists of the following nodes: - * - `Node0`, which injects most instructions and operands directly into the - * dataflow graph. - * - `VariableNode`, which is used to model flow through global variables. - * - `PostUpdateNodeImpl`, which is used to model the state of an object after - * an update after a number of loads. - * - `SsaSynthNode`, which represents synthesized nodes as computed by the shared SSA - * library. - * - `RawIndirectOperand`, which represents the value of `operand` after - * loading the address a number of times. - * - `RawIndirectInstruction`, which represents the value of `instr` after - * loading the address a number of times. - */ -cached -private newtype TIRDataFlowNode = - TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or - TGlobalLikeVariableNode(GlobalLikeVariable var, int indirectionIndex) { - indirectionIndex = - [getMinIndirectionsForType(var.getUnspecifiedType()) .. SsaImpl::getMaxIndirectionsForType(var.getUnspecifiedType())] - } or - TPostUpdateNodeImpl(Operand operand, int indirectionIndex) { - isPostUpdateNodeImpl(operand, indirectionIndex) - } or - TSsaSynthNode(SsaImpl::SynthNode n) or - TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or - TRawIndirectOperand0(Node0Impl node, int indirectionIndex) { - SsaImpl::hasRawIndirectOperand(node.asOperand(), indirectionIndex) - } or - TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) { - not exists(node.asOperand()) and - SsaImpl::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex) - } or - TFinalParameterNode(Parameter p, int indirectionIndex) { - exists(SsaImpl::FinalParameterUse use | - use.getParameter() = p and - use.getIndirectionIndex() = indirectionIndex - ) - } or - TFinalGlobalValue(SsaImpl::GlobalUse globalUse) or - TInitialGlobalValue(SsaImpl::GlobalDef globalUse) or - TBodyLessParameterNodeImpl(Parameter p, int indirectionIndex) { - // Rule out parameters of catch blocks. - not exists(p.getCatchBlock()) and - // We subtract one because `getMaxIndirectionsForType` returns the maximum - // indirection for a glvalue of a given type, and this doesn't apply to - // parameters. - indirectionIndex = [0 .. SsaImpl::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1] and - not any(InitializeParameterInstruction init).getParameter() = p - } or - TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) - -/** - * An operand that is defined by a `FieldAddressInstruction`. - */ -class FieldAddress extends Operand { - FieldAddressInstruction fai; - - FieldAddress() { fai = this.getDef() and not SsaImpl::ignoreOperand(this) } - - /** Gets the field associated with this instruction. */ - Field getField() { result = fai.getField() } - - /** Gets the instruction whose result provides the address of the object containing the field. */ - Instruction getObjectAddress() { result = fai.getObjectAddress() } - - /** Gets the operand that provides the address of the object containing the field. */ - Operand getObjectAddressOperand() { result = fai.getObjectAddressOperand() } -} - -/** - * Holds if `opFrom` is an operand whose value flows to the result of `instrTo`. - * - * `isPointerArith` is `true` if `instrTo` is a `PointerArithmeticInstruction` and `opFrom` - * is the left operand. - * - * `additional` is `true` if the conversion is supplied by an implementation of the - * `Indirection` class. It is sometimes useful to exclude such conversions. - */ -predicate conversionFlow( - Operand opFrom, Instruction instrTo, boolean isPointerArith, boolean additional -) { - isPointerArith = false and - ( - additional = false and - ( - instrTo.(CopyValueInstruction).getSourceValueOperand() = opFrom - or - instrTo.(ConvertInstruction).getUnaryOperand() = opFrom - or - instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom - or - instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom - or - exists(BuiltInInstruction builtIn | - builtIn = instrTo and - // __builtin_bit_cast - builtIn.getBuiltInOperation() instanceof BuiltInBitCast and - opFrom = builtIn.getAnOperand() - ) - ) - or - additional = true and - SsaImpl::isAdditionalConversionFlow(opFrom, instrTo) - ) - or - isPointerArith = true and - additional = false and - instrTo.(PointerArithmeticInstruction).getLeftOperand() = opFrom -} - -/** - * A node in a data flow graph. - * - * A node can be either an expression, a parameter, or an uninitialized local - * variable. Such nodes are created with `DataFlow::exprNode`, - * `DataFlow::parameterNode`, and `DataFlow::uninitializedNode` respectively. - */ -class Node extends TIRDataFlowNode { - /** - * INTERNAL: Do not use. - */ - DataFlowCallable getEnclosingCallable() { none() } // overridden in subclasses - - /** Gets the function to which this node belongs, if any. */ - Declaration getFunction() { none() } // overridden in subclasses - - /** Holds if this node represents a glvalue. */ - predicate isGLValue() { none() } - - /** - * Gets the type of this node. - * - * If `isGLValue()` holds, then the type of this node - * should be thought of as "pointer to `getType()`". - */ - Type getType() { none() } // overridden in subclasses - - /** Gets the instruction corresponding to this node, if any. */ - Instruction asInstruction() { result = this.(InstructionNode).getInstruction() } - - /** Gets the operands corresponding to this node, if any. */ - Operand asOperand() { result = this.(OperandNode).getOperand() } - - /** - * Gets the operand that is indirectly tracked by this node behind `index` - * number of indirections. - */ - Operand asIndirectOperand(int index) { hasOperandAndIndex(this, result, index) } - - /** - * Holds if this node is at index `i` in basic block `block`. - * - * Note: Phi nodes are considered to be at index `-1`. - */ - final predicate hasIndexInBlock(IRBlock block, int i) { - this.asInstruction() = block.getInstruction(i) - or - this.asOperand().getUse() = block.getInstruction(i) - or - exists(SsaImpl::SynthNode ssaNode | - this.(SsaSynthNode).getSynthNode() = ssaNode and - ssaNode.getBasicBlock() = block and - ssaNode.getIndex() = i - ) - or - this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i) - or - this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i) - or - this.(PostUpdateNode).getPreUpdateNode().hasIndexInBlock(block, i) - } - - /** Gets the basic block of this node, if any. */ - final IRBlock getBasicBlock() { this.hasIndexInBlock(result, _) } - - /** - * Gets the non-conversion expression corresponding to this node, if any. - * This predicate only has a result on nodes that represent the value of - * evaluating the expression. For data flowing _out of_ an expression, like - * when an argument is passed by reference, use `asDefiningArgument` instead - * of `asExpr`. - * - * If this node strictly (in the sense of `asConvertedExpr`) corresponds to - * a `Conversion`, then the result is the underlying non-`Conversion` base - * expression. - */ - Expr asExpr() { result = this.asExpr(_) } - - /** - * INTERNAL: Do not use. - */ - Expr asExpr(int n) { result = this.(ExprNode).getExpr(n) } - - /** - * INTERNAL: Do not use. - */ - Expr asIndirectExpr(int n, int index) { result = this.(IndirectExprNode).getExpr(n, index) } - - /** - * Gets the non-conversion expression that's indirectly tracked by this node - * under `index` number of indirections. - */ - Expr asIndirectExpr(int index) { result = this.asIndirectExpr(_, index) } - - /** - * Gets the non-conversion expression that's indirectly tracked by this node - * behind a number of indirections. - */ - Expr asIndirectExpr() { result = this.asIndirectExpr(_) } - - /** - * Gets the expression corresponding to this node, if any. The returned - * expression may be a `Conversion`. - */ - Expr asConvertedExpr() { result = this.asConvertedExpr(_) } - - /** - * Gets the expression corresponding to this node, if any. The returned - * expression may be a `Conversion`. - */ - Expr asConvertedExpr(int n) { result = this.(ExprNode).getConvertedExpr(n) } - - /** - * INTERNAL: Do not use. - */ - Expr asIndirectConvertedExpr(int n, int index) { - result = this.(IndirectExprNode).getConvertedExpr(n, index) - } - - /** - * Gets the expression that's indirectly tracked by this node - * behind `index` number of indirections. - */ - Expr asIndirectConvertedExpr(int index) { result = this.asIndirectConvertedExpr(_, index) } - - /** - * Gets the expression that's indirectly tracked by this node behind a - * number of indirections. - */ - Expr asIndirectConvertedExpr() { result = this.asIndirectConvertedExpr(_) } - - /** - * Gets the argument that defines this `DefinitionByReferenceNode`, if any. - * This predicate should be used instead of `asExpr` when referring to the - * value of a reference argument _after_ the call has returned. For example, - * in `f(&x)`, this predicate will have `&x` as its result for the `Node` - * that represents the new value of `x`. - */ - Expr asDefiningArgument() { result = this.asDefiningArgument(_) } - - /** - * Gets the definition associated with this node, if any. - * - * For example, consider the following example - * ```cpp - * int x = 42; // 1 - * x = 34; // 2 - * ++x; // 3 - * x++; // 4 - * x += 1; // 5 - * int y = x += 2; // 6 - * ``` - * - For (1) the result is `42`. - * - For (2) the result is `x = 34`. - * - For (3) the result is `++x`. - * - For (4) the result is `x++`. - * - For (5) the result is `x += 1`. - * - For (6) there are two results: - * - For the definition generated by `x += 2` the result is `x += 2` - * - For the definition generated by `int y = ...` the result is - * also `x += 2`. - * - * For assignments, `node.asDefinition()` and `node.asExpr()` will both exist - * for the same dataflow node. However, for expression such as `x++` that - * both write to `x` and read the current value of `x`, `node.asDefinition()` - * will give the node corresponding to the value after the increment, and - * `node.asExpr()` will give the node corresponding to the value before the - * increment. For an example of this, consider the following: - * - * ```cpp - * sink(x++); - * ``` - * in the above program, there will not be flow from a node `n` such that - * `n.asDefinition() instanceof IncrementOperation` to the argument of `sink` - * since the value passed to `sink` is the value before to the increment. - * However, there will be dataflow from a node `n` such that - * `n.asExpr() instanceof IncrementOperation` since the result of evaluating - * the expression `x++` is passed to `sink`. - */ - Expr asDefinition() { result = this.asDefinition(_) } - - private predicate isCertainStore() { - exists(SsaImpl::Definition def | - SsaImpl::defToNode(this, def, _) and - def.isCertain() - ) - } - - /** - * Gets the definition associated with this node, if any. - * - * For example, consider the following example - * ```cpp - * int x = 42; // 1 - * x = 34; // 2 - * ++x; // 3 - * x++; // 4 - * x += 1; // 5 - * int y = x += 2; // 6 - * ``` - * - For (1) the result is `42`. - * - For (2) the result is `x = 34`. - * - For (3) the result is `++x`. - * - For (4) the result is `x++`. - * - For (5) the result is `x += 1`. - * - For (6) there are two results: - * - For the definition generated by `x += 2` the result is `x += 2` - * - For the definition generated by `int y = ...` the result is - * also `x += 2`. - * - * For assignments, `node.asDefinition(_)` and `node.asExpr()` will both exist - * for the same dataflow node. However, for expression such as `x++` that - * both write to `x` and read the current value of `x`, `node.asDefinition(_)` - * will give the node corresponding to the value after the increment, and - * `node.asExpr()` will give the node corresponding to the value before the - * increment. For an example of this, consider the following: - * - * ```cpp - * sink(x++); - * ``` - * in the above program, there will not be flow from a node `n` such that - * `n.asDefinition(_) instanceof IncrementOperation` to the argument of `sink` - * since the value passed to `sink` is the value before to the increment. - * However, there will be dataflow from a node `n` such that - * `n.asExpr() instanceof IncrementOperation` since the result of evaluating - * the expression `x++` is passed to `sink`. - * - * If `uncertain = false` then the definition is guaranteed to overwrite - * the entire buffer pointed to by the destination address of the definition. - * Otherwise, `uncertain = true`. - * - * For example, the write `int x; x = 42;` is guaranteed to overwrite all the - * bytes allocated to `x`, while the assignment `int p[10]; p[3] = 42;` has - * `uncertain = true` since the write will not overwrite the entire buffer - * pointed to by `p`. - */ - Expr asDefinition(boolean uncertain) { - exists(StoreInstruction store | - store = this.asInstruction() and - result = asDefinitionImpl(store) and - if this.isCertainStore() then uncertain = false else uncertain = true - ) - } - - /** - * Gets the definition associated with this node, if this node is a certain definition. - * - * See `Node.asDefinition/1` for a description of certain and uncertain definitions. - */ - Expr asCertainDefinition() { result = this.asDefinition(false) } - - /** - * Gets the definition associated with this node, if this node is an uncertain definition. - * - * See `Node.asDefinition/1` for a description of certain and uncertain definitions. - */ - Expr asUncertainDefinition() { result = this.asDefinition(true) } - - /** - * Gets the indirect definition at a given indirection corresponding to this - * node, if any. - * - * See the comments on `Node.asDefinition` for examples. - */ - Expr asIndirectDefinition(int indirectionIndex) { - exists(StoreInstruction store | - this.(IndirectInstruction).hasInstructionAndIndirectionIndex(store, indirectionIndex) and - result = asDefinitionImpl(store) - ) - } - - /** - * Gets the indirect definition at some indirection corresponding to this - * node, if any. - */ - Expr asIndirectDefinition() { result = this.asIndirectDefinition(_) } - - /** - * Gets the argument that defines this `DefinitionByReferenceNode`, if any. - * - * Unlike `Node::asDefiningArgument/0`, this predicate gets the node representing - * the value of the `index`'th indirection after leaving a function. For example, - * in: - * ```cpp - * void f(int**); - * ... - * int** x = ...; - * f(x); - * ``` - * The node `n` such that `n.asDefiningArgument(1)` is the argument `x` will - * contain the value of `*x` after `f` has returned, and the node `n` such that - * `n.asDefiningArgument(2)` is the argument `x` will contain the value of `**x` - * after the `f` has returned. - */ - Expr asDefiningArgument(int index) { - this.(DefinitionByReferenceNode).getIndirectionIndex() = index and - result = this.(DefinitionByReferenceNode).getArgument() - } - - /** - * Gets the the argument going into a function for a node that represents - * the indirect value of the argument after `index` loads. For example, in: - * ```cpp - * void f(int**); - * ... - * int** x = ...; - * f(x); - * ``` - * The node `n` such that `n.asIndirectArgument(1)` represents the value of - * `*x` going into `f`, and the node `n` such that `n.asIndirectArgument(2)` - * represents the value of `**x` going into `f`. - */ - Expr asIndirectArgument(int index) { - this.(SideEffectOperandNode).hasAddressOperandAndIndirectionIndex(_, index) and - result = this.(SideEffectOperandNode).getArgument() - } - - /** - * Gets the the argument going into a function for a node that represents - * the indirect value of the argument after any non-zero number of loads. - */ - Expr asIndirectArgument() { result = this.asIndirectArgument(_) } - - /** Gets the positional parameter corresponding to this node, if any. */ - Parameter asParameter() { - exists(int indirectionIndex | result = this.asParameter(indirectionIndex) | - if result.getUnspecifiedType() instanceof ReferenceType - then indirectionIndex = 1 - else indirectionIndex = 0 - ) - } - - /** - * Gets the uninitialized local variable corresponding to this node, if - * any. - */ - LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } - - /** - * Gets the positional parameter corresponding to the node that represents - * the value of the parameter after `index` number of loads, if any. For - * example, in: - * ```cpp - * void f(int** x) { ... } - * ``` - * - The node `n` such that `n.asParameter(0)` is the parameter `x` represents - * the value of `x`. - * - The node `n` such that `n.asParameter(1)` is the parameter `x` represents - * the value of `*x`. - * - The node `n` such that `n.asParameter(2)` is the parameter `x` represents - * the value of `**x`. - */ - Parameter asParameter(int index) { - index = 0 and - result = this.(ExplicitParameterNode).getParameter() - or - this.(IndirectParameterNode).getIndirectionIndex() = index and - result = this.(IndirectParameterNode).getParameter() - } - - /** - * Holds if this node represents the `indirectionIndex`'th indirection of - * the value of an output parameter `p` just before reaching the end of a function. - */ - predicate isFinalValueOfParameter(Parameter p, int indirectionIndex) { - exists(FinalParameterNode n | n = this | - p = n.getParameter() and - indirectionIndex = n.getIndirectionIndex() - ) - } - - /** - * Holds if this node represents the value of an output parameter `p` - * just before reaching the end of a function. - */ - predicate isFinalValueOfParameter(Parameter p) { this.isFinalValueOfParameter(p, _) } - - /** - * Gets the variable corresponding to this node, if any. This can be used for - * modeling flow in and out of global variables. - */ - Variable asVariable() { - this = TGlobalLikeVariableNode(result, getMinIndirectionsForType(result.getUnspecifiedType())) - } - - /** - * Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any. - * - * This can be used for modeling flow in and out of global variables. - */ - Variable asIndirectVariable(int indirectionIndex) { - indirectionIndex > getMinIndirectionsForType(result.getUnspecifiedType()) and - this = TGlobalLikeVariableNode(result, indirectionIndex) - } - - /** Gets an indirection of this node's underlying variable, if any. */ - Variable asIndirectVariable() { result = this.asIndirectVariable(_) } - - /** - * Gets the expression that is partially defined by this node, if any. - * - * Partial definitions are created for field stores (`x.y = taint();` is a partial - * definition of `x`), and for calls that may change the value of an object (so - * `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is - * a partial definition of `&x`). - */ - Expr asPartialDefinition() { - exists(PartialDefinitionNode pdn | this = pdn | - pdn.getIndirectionIndex() > 0 and - result = pdn.getDefinedExpr() - ) - } - - /** - * Gets an upper bound on the type of this node. - */ - Type getTypeBound() { result = this.getType() } - - /** Gets the location of this element. */ - cached - final Location getLocation() { result = this.getLocationImpl() } - - /** INTERNAL: Do not use. */ - Location getLocationImpl() { - none() // overridden by subclasses - } - - /** Gets a textual representation of this element. */ - cached - final string toString() { - result = toExprString(this) - or - not exists(toExprString(this)) and - result = this.toStringImpl() - } - - /** INTERNAL: Do not use. */ - string toStringImpl() { - none() // overridden by subclasses - } -} - -/** - * A class that lifts pre-SSA dataflow nodes to regular dataflow nodes. - */ -private class Node0 extends Node, TNode0 { - Node0Impl node; - - Node0() { this = TNode0(node) } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = node.getEnclosingCallable() - } - - override Declaration getFunction() { result = node.getFunction() } - - override Location getLocationImpl() { result = node.getLocation() } - - override string toStringImpl() { result = node.toString() } - - override Type getType() { result = node.getType() } - - override predicate isGLValue() { node.isGLValue() } -} - -/** - * An instruction, viewed as a node in a data flow graph. - */ -class InstructionNode extends Node0 { - override InstructionNode0 node; - Instruction instr; - - InstructionNode() { instr = node.getInstruction() } - - /** Gets the instruction corresponding to this node. */ - Instruction getInstruction() { result = instr } -} - -/** - * An operand, viewed as a node in a data flow graph. - */ -class OperandNode extends Node, Node0 { - override OperandNode0 node; - Operand op; - - OperandNode() { op = node.getOperand() } - - /** Gets the operand corresponding to this node. */ - Operand getOperand() { result = op } -} - -/** - * INTERNAL: Do not use. - * - * Returns `t`, but stripped of the outermost pointer, reference, etc. - * - * For example, `stripPointers(int*&)` is `int*` and `stripPointers(int*)` is `int`. - */ -Type stripPointer(Type t) { - result = any(SsaImpl::Indirection ind | ind.getType() = t).getBaseType() - or - result = t.(PointerToMemberType).getBaseType() - or - result = t.(FunctionPointerIshType).getBaseType() -} - -/** - * INTERNAL: Do not use. - */ -class PostUpdateNodeImpl extends PartialDefinitionNode, TPostUpdateNodeImpl { - int indirectionIndex; - Operand operand; - - PostUpdateNodeImpl() { this = TPostUpdateNodeImpl(operand, indirectionIndex) } - - override Declaration getFunction() { result = operand.getUse().getEnclosingFunction() } - - override DataFlowCallable getEnclosingCallable() { - result = this.getPreUpdateNode().getEnclosingCallable() - } - - /** Gets the operand associated with this node. */ - Operand getOperand() { result = operand } - - /** Gets the indirection index associated with this node. */ - override int getIndirectionIndex() { result = indirectionIndex } - - override Location getLocationImpl() { result = operand.getLocation() } - - final override Node getPreUpdateNode() { - indirectionIndex > 0 and - hasOperandAndIndex(result, operand, indirectionIndex) - or - indirectionIndex = 0 and - result.asOperand() = operand - } - - final override Expr getDefinedExpr() { - result = operand.getDef().getUnconvertedResultExpression() - } -} - -/** - * INTERNAL: do not use. - * - * The node representing the value of a field after it has been updated. - */ -class PostFieldUpdateNode extends PostUpdateNodeImpl { - FieldAddress fieldAddress; - - PostFieldUpdateNode() { operand = fieldAddress.getObjectAddressOperand() } - - FieldAddress getFieldAddress() { result = fieldAddress } - - Field getUpdatedField() { result = this.getFieldAddress().getField() } - - override string toStringImpl() { result = this.getPreUpdateNode() + " [post update]" } -} - -/** - * INTERNAL: do not use. - * - * A synthesized SSA node produced by the shared SSA library, viewed as a node - * in a data flow graph. - */ -class SsaSynthNode extends Node, TSsaSynthNode { - SsaImpl::SynthNode node; - - SsaSynthNode() { this = TSsaSynthNode(node) } - - /** Gets the synthesized SSA node associated with this node. */ - SsaImpl::SynthNode getSynthNode() { result = node } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = node.getBasicBlock().getEnclosingFunction() } - - override Type getType() { result = node.getSourceVariable().getType() } - - override predicate isGLValue() { node.getSourceVariable().isGLValue() } - - final override Location getLocationImpl() { result = node.getLocation() } - - override string toStringImpl() { result = node.toString() } -} - -/** - * INTERNAL: do not use. - * - * Dataflow nodes necessary for iterator flow - */ -class SsaIteratorNode extends Node, TSsaIteratorNode { - IteratorFlow::IteratorFlowNode node; - - SsaIteratorNode() { this = TSsaIteratorNode(node) } - - /** Gets the phi node associated with this node. */ - IteratorFlow::IteratorFlowNode getIteratorFlowNode() { result = node } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = node.getFunction() } - - override Type getType() { result = node.getType() } - - final override Location getLocationImpl() { result = node.getLocation() } - - override string toStringImpl() { result = node.toString() } -} - -/** - * INTERNAL: do not use. - * - * A node representing a value after leaving a function. - */ -class SideEffectOperandNode extends Node instanceof IndirectOperand { - CallInstruction call; - int argumentIndex; - ArgumentOperand arg; - - SideEffectOperandNode() { - arg = call.getArgumentOperand(argumentIndex) and - IndirectOperand.super.hasOperandAndIndirectionIndex(arg, _) - } - - CallInstruction getCallInstruction() { result = call } - - /** Gets the underlying operand and the underlying indirection index. */ - predicate hasAddressOperandAndIndirectionIndex(Operand operand, int indirectionIndex) { - IndirectOperand.super.hasOperandAndIndirectionIndex(operand, indirectionIndex) - } - - int getArgumentIndex() { result = argumentIndex } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = call.getEnclosingFunction() } - - Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() } -} - -/** - * INTERNAL: do not use. - * - * A node representing the value of a global variable just before returning - * from a function body. - */ -class FinalGlobalValue extends Node, TFinalGlobalValue { - SsaImpl::GlobalUse globalUse; - - FinalGlobalValue() { this = TFinalGlobalValue(globalUse) } - - /** Gets the underlying SSA use. */ - SsaImpl::GlobalUse getGlobalUse() { result = globalUse } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() } - - override Type getType() { - exists(int indirectionIndex | - indirectionIndex = globalUse.getIndirectionIndex() and - result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex) - ) - } - - final override Location getLocationImpl() { result = globalUse.getLocation() } - - override string toStringImpl() { result = globalUse.toString() } -} - -/** - * INTERNAL: do not use. - * - * A node representing the value of a global variable just after entering - * a function body. - */ -class InitialGlobalValue extends Node, TInitialGlobalValue { - SsaImpl::GlobalDef globalDef; - - InitialGlobalValue() { this = TInitialGlobalValue(globalDef) } - - /** Gets the underlying SSA definition. */ - SsaImpl::GlobalDef getGlobalDef() { result = globalDef } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = globalDef.getFunction() } - - final override predicate isGLValue() { globalDef.getIndirectionIndex() = 0 } - - override Type getType() { result = globalDef.getUnderlyingType() } - - final override Location getLocationImpl() { result = globalDef.getLocation() } - - override string toStringImpl() { result = globalDef.toString() } -} - -/** - * INTERNAL: do not use. - * - * A node representing a parameter for a function with no body. - */ -class BodyLessParameterNodeImpl extends Node, TBodyLessParameterNodeImpl { - Parameter p; - int indirectionIndex; - - BodyLessParameterNodeImpl() { this = TBodyLessParameterNodeImpl(p, indirectionIndex) } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = p.getFunction() } - - /** Gets the indirection index of this node. */ - int getIndirectionIndex() { result = indirectionIndex } - - override Type getType() { - result = getTypeImpl(p.getUnderlyingType(), this.getIndirectionIndex()) - } - - final override Location getLocationImpl() { - result = unique( | | p.getLocation()) - or - count(p.getLocation()) != 1 and - result instanceof UnknownLocation - } - - final override string toStringImpl() { - exists(string prefix | prefix = stars(this) | result = prefix + p.toString()) - } -} - -/** - * A data-flow node used to model flow summaries. That is, a dataflow node - * that is synthesized to represent a parameter, return value, or other part - * of a models-as-data modeled function. - */ -class FlowSummaryNode extends Node, TFlowSummaryNode { - /** - * Gets the models-as-data `SummaryNode` associated with this dataflow - * `FlowSummaryNode`. - */ - FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) } - - /** - * Gets the summarized callable that this node belongs to. - */ - FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() { - result = this.getSummaryNode().getSummarizedCallable() - } - - /** - * Gets the enclosing callable. For a `FlowSummaryNode` this is always the - * summarized function this node is part of. - */ - override DataFlowCallable getEnclosingCallable() { - result.asSummarizedCallable() = this.getSummarizedCallable() - } - - override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() } - - override string toStringImpl() { result = this.getSummaryNode().toString() } -} - -/** - * INTERNAL: do not use. - * - * A node representing the indirection of a value that is - * about to be returned from a function. - */ -class IndirectReturnNode extends Node { - IndirectReturnNode() { - this instanceof FinalParameterNode - or - this.(IndirectOperand) - .hasOperandAndIndirectionIndex(any(ReturnValueInstruction ret).getReturnAddressOperand(), _) - } - - override SourceCallable getEnclosingCallable() { result.asSourceCallable() = this.getFunction() } - - /** - * Holds if this node represents the value that is returned to the caller - * through a `return` statement. - */ - predicate isNormalReturn() { this instanceof IndirectOperand } - - /** - * Holds if this node represents the value that is returned to the caller - * by writing to the `argumentIndex`'th argument of the call. - */ - predicate isParameterReturn(int argumentIndex) { - this.(FinalParameterNode).getArgumentIndex() = argumentIndex - } - - /** Gets the indirection index of this indirect return node. */ - int getIndirectionIndex() { - result = this.(FinalParameterNode).getIndirectionIndex() - or - this.(IndirectOperand).hasOperandAndIndirectionIndex(_, result) - } -} - -/** - * INTERNAL: do not use. - * - * A node representing the indirection of a value after it - * has been returned from a function. - */ -class IndirectArgumentOutNode extends PostUpdateNodeImpl { - override ArgumentOperand operand; - - int getArgumentIndex() { - exists(CallInstruction call | call.getArgumentOperand(result) = operand) - } - - Operand getAddressOperand() { result = operand } - - CallInstruction getCallInstruction() { result.getAnArgumentOperand() = operand } - - /** - * Gets the `Function` that the call targets, if this is statically known. - */ - Function getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() } - - override string toStringImpl() { - exists(string prefix | if indirectionIndex > 0 then prefix = "" else prefix = "pointer to " | - // This string should be unique enough to be helpful but common enough to - // avoid storing too many different strings. - result = prefix + this.getStaticCallTarget().getName() + " output argument" - or - not exists(this.getStaticCallTarget()) and - result = prefix + "output argument" - ) - } -} - -/** - * Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and - * `operand` represents a use of the fully converted value of `call`. - */ -private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) { - operandForFullyConvertedCall(operand, call) and - hasOperandAndIndex(node, operand, indirectionIndex) -} - -/** - * Holds if `node` is an indirect instruction with columns `(instr, indirectionIndex)`, and - * `instr` represents a use of the fully converted value of `call`. - * - * Note that `hasOperand(node, _, _, _)` implies `not hasInstruction(node, _, _, _)`. - */ -private predicate hasInstruction( - Node node, CallInstruction call, int indirectionIndex, Instruction instr -) { - instructionForFullyConvertedCall(instr, call) and - hasInstructionAndIndex(node, instr, indirectionIndex) -} - -/** - * INTERNAL: do not use. - * - * A node representing the indirect value of a function call (i.e., a value hidden - * behind a number of indirections). - */ -class IndirectReturnOutNode extends Node { - CallInstruction call; - int indirectionIndex; - - IndirectReturnOutNode() { - // Annoyingly, we need to pick the fully converted value as the output of the function to - // make flow through in the shared dataflow library work correctly. - hasOperand(this, call, indirectionIndex, _) - or - hasInstruction(this, call, indirectionIndex, _) - } - - CallInstruction getCallInstruction() { result = call } - - int getIndirectionIndex() { result = indirectionIndex } - - /** Gets the operand associated with this node, if any. */ - Operand getOperand() { hasOperand(this, call, indirectionIndex, result) } - - /** Gets the instruction associated with this node, if any. */ - Instruction getInstruction() { hasInstruction(this, call, indirectionIndex, result) } -} - -/** - * An `IndirectReturnOutNode` which is used as a destination of a store operation. - * When it's used for a store operation it's useful to have this be a `PostUpdateNode` for - * the shared dataflow library's flow-through mechanism to detect flow in cases such as: - * ```cpp - * struct MyInt { - * int i; - * int& getRef() { return i; } - * }; - * ... - * MyInt mi; - * mi.getRef() = source(); // this is detected as a store to `i` via flow-through. - * sink(mi.i); - * ``` - */ -private class PostIndirectReturnOutNode extends IndirectReturnOutNode, PostUpdateNode { - PostIndirectReturnOutNode() { - any(StoreInstruction store).getDestinationAddressOperand() = this.getOperand() - } - - override Node getPreUpdateNode() { result = this } -} - -/** - * INTERNAL: Do not use. - * - * Returns `t`, but stripped of the outer-most `indirectionIndex` number of indirections. - */ -private Type getTypeImpl0(Type t, int indirectionIndex) { - indirectionIndex = 0 and - result = t - or - indirectionIndex > 0 and - exists(Type stripped | - stripped = stripPointer(t.stripTopLevelSpecifiers()) and - // We need to avoid the case where `stripPointer(t) = t` (which can happen - // on iterators that specify a `value_type` that is the iterator itself). - // Such a type would create an infinite loop otherwise. For these cases we - // simply don't produce a result for `getTypeImpl`. - // To be on the safe side, we check whether the _unspecified_ type has - // changed since this also prevents an infinite loop when `stripped` and - // `t` only differ by const'ness or volatile'ness. - stripped.getUnspecifiedType() != t.getUnspecifiedType() and - result = getTypeImpl0(stripped, indirectionIndex - 1) - ) -} - -/** - * INTERNAL: Do not use. - * - * Returns `t`, but stripped of the outer-most `indirectionIndex` number of indirections. - * - * If `indirectionIndex` cannot be stripped off `t`, an `UnknownType` is returned. - */ -bindingset[t, indirectionIndex] -pragma[inline_late] -Type getTypeImpl(Type t, int indirectionIndex) { - result = getTypeImpl0(t, indirectionIndex) - or - // If we cannot produce the right type we return an error type. - // This can sometimes happen when we don't know the real - // type of a void pointer. - not exists(getTypeImpl0(t, indirectionIndex)) and - result instanceof UnknownType -} - -private module RawIndirectNodes { - /** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an operand in the IR - * after `index` number of loads. - */ - private class RawIndirectOperand0 extends Node, TRawIndirectOperand0 { - Node0Impl node; - int indirectionIndex; - - RawIndirectOperand0() { this = TRawIndirectOperand0(node, indirectionIndex) } - - /** Gets the underlying instruction. */ - Operand getOperand() { result = node.asOperand() } - - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } - - override Declaration getFunction() { result = node.getFunction() } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = node.getEnclosingCallable() - } - - override predicate isGLValue() { this.getOperand().isGLValue() } - - override Type getType() { - exists(int sub, Type type, boolean isGLValue | - type = getOperandType(this.getOperand(), isGLValue) and - if isGLValue = true then sub = 1 else sub = 0 - | - result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub) - ) - } - - final override Location getLocationImpl() { - if exists(this.getOperand().getLocation()) - then result = this.getOperand().getLocation() - else result instanceof UnknownLocation - } - - override string toStringImpl() { - result = stars(this) + operandNode(this.getOperand()).toStringImpl() - } - } - - /** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an instruction in the IR - * after `index` number of loads. - */ - private class RawIndirectInstruction0 extends Node, TRawIndirectInstruction0 { - Node0Impl node; - int indirectionIndex; - - RawIndirectInstruction0() { this = TRawIndirectInstruction0(node, indirectionIndex) } - - /** Gets the underlying instruction. */ - Instruction getInstruction() { result = node.asInstruction() } - - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } - - override Declaration getFunction() { result = node.getFunction() } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = node.getEnclosingCallable() - } - - override predicate isGLValue() { this.getInstruction().isGLValue() } - - override Type getType() { - exists(int sub, Type type, boolean isGLValue | - type = getInstructionType(this.getInstruction(), isGLValue) and - if isGLValue = true then sub = 1 else sub = 0 - | - result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub) - ) - } - - final override Location getLocationImpl() { - if exists(this.getInstruction().getLocation()) - then result = this.getInstruction().getLocation() - else result instanceof UnknownLocation - } - - override string toStringImpl() { - result = stars(this) + instructionNode(this.getInstruction()).toStringImpl() - } - } - - /** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an operand in the IR - * after a number of loads. - */ - class RawIndirectOperand extends Node { - int indirectionIndex; - Operand operand; - - RawIndirectOperand() { - exists(Node0Impl node | operand = node.asOperand() | - this = TRawIndirectOperand0(node, indirectionIndex) - or - this = TRawIndirectInstruction0(node, indirectionIndex) - ) - } - - /** Gets the operand associated with this node. */ - Operand getOperand() { result = operand } - - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } - } - - /** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an instruction in the IR - * after a number of loads. - */ - class RawIndirectInstruction extends Node { - int indirectionIndex; - Instruction instr; - - RawIndirectInstruction() { - exists(Node0Impl node | instr = node.asInstruction() | - this = TRawIndirectOperand0(node, indirectionIndex) - or - this = TRawIndirectInstruction0(node, indirectionIndex) - ) - } - - /** Gets the instruction associated with this node. */ - Instruction getInstruction() { result = instr } - - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } - } -} - -import RawIndirectNodes - -/** - * INTERNAL: do not use. - * - * A node representing the value of an output parameter - * just before reaching the end of a function. - */ -class FinalParameterNode extends Node, TFinalParameterNode { - Parameter p; - int indirectionIndex; - - FinalParameterNode() { this = TFinalParameterNode(p, indirectionIndex) } - - /** Gets the parameter associated with this final use. */ - Parameter getParameter() { result = p } - - /** Gets the underlying indirection index. */ - int getIndirectionIndex() { result = indirectionIndex } - - /** Gets the argument index associated with this final use. */ - final int getArgumentIndex() { result = p.getIndex() } - - override Declaration getFunction() { result = p.getFunction() } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Type getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) } - - final override Location getLocationImpl() { - // Parameters can have multiple locations. When there's a unique location we use - // that one, but if multiple locations exist we default to an unknown location. - result = unique( | | p.getLocation()) - or - not exists(unique( | | p.getLocation())) and - result instanceof UnknownLocation - } - - override string toStringImpl() { result = stars(this) + p.toString() } -} - -/** - * The value of an uninitialized local variable, viewed as a node in a data - * flow graph. - */ -class UninitializedNode extends Node { - LocalVariable v; - - UninitializedNode() { - exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv | - def.getIndirectionIndex() = 0 and - def.getValue().asInstruction() instanceof UninitializedInstruction and - SsaImpl::defToNode(this, def, sv) and - v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst() - ) - } - - /** Gets the uninitialized local variable corresponding to this node. */ - LocalVariable getLocalVariable() { result = v } -} - -abstract private class AbstractParameterNode extends Node { - /** - * Holds if this node is the parameter of `f` at the specified position. The - * implicit `this` parameter is considered to have position `-1`, and - * pointer-indirection parameters are at further negative positions. - */ - predicate isSourceParameterOf(Function f, ParameterPosition pos) { none() } - - /** - * Holds if this node is the parameter of `sc` at the specified position. The - * implicit `this` parameter is considered to have position `-1`, and - * pointer-indirection parameters are at further negative positions. - */ - predicate isSummaryParameterOf( - FlowSummaryImpl::Public::SummarizedCallable sc, ParameterPosition pos - ) { - none() - } - - /** - * Holds if this node is the parameter of `c` at the specified position. The - * implicit `this` parameter is considered to have position `-1`, and - * pointer-indirection parameters are at further negative positions. - */ - final predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.isSummaryParameterOf(c.asSummarizedCallable(), pos) - or - this.isSourceParameterOf(c.asSourceCallable(), pos) - } - - /** Gets the `Parameter` associated with this node, if it exists. */ - Parameter getParameter() { none() } // overridden by subclasses -} - -abstract private class AbstractIndirectParameterNode extends AbstractParameterNode { - /** Gets the indirection index of this parameter node. */ - abstract int getIndirectionIndex(); -} - -/** - * INTERNAL: do not use. - * - * A node representing an indirection of a parameter. - */ -final class IndirectParameterNode = AbstractIndirectParameterNode; - -pragma[noinline] -private predicate indirectParameterNodeHasArgumentIndexAndIndex( - IndirectInstructionParameterNode node, int argumentIndex, int indirectionIndex -) { - node.hasInstructionAndIndirectionIndex(_, indirectionIndex) and - node.getArgumentIndex() = argumentIndex -} - -pragma[noinline] -private predicate indirectPositionHasArgumentIndexAndIndex( - IndirectionPosition pos, int argumentIndex, int indirectionIndex -) { - pos.getArgumentIndex() = argumentIndex and - pos.getIndirectionIndex() = indirectionIndex -} - -private class IndirectInstructionParameterNode extends AbstractIndirectParameterNode instanceof IndirectInstruction -{ - InitializeParameterInstruction init; - - IndirectInstructionParameterNode() { - IndirectInstruction.super.hasInstructionAndIndirectionIndex(init, _) - } - - int getArgumentIndex() { init.hasIndex(result) } - - override string toStringImpl() { - exists(string prefix | prefix = stars(this) | - result = prefix + this.getParameter().toString() - or - not exists(this.getParameter()) and - result = prefix + "this" - ) - } - - /** Gets the parameter whose indirection is initialized. */ - override Parameter getParameter() { result = init.getParameter() } - - override DataFlowCallable getEnclosingCallable() { - result.asSourceCallable() = this.getFunction() - } - - override Declaration getFunction() { result = init.getEnclosingFunction() } - - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - this.getFunction() = f and - exists(int argumentIndex, int indirectionIndex | - indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and - indirectParameterNodeHasArgumentIndexAndIndex(this, argumentIndex, indirectionIndex) - ) - } - - /** Gets the underlying operand and the underlying indirection index. */ - predicate hasInstructionAndIndirectionIndex(Instruction instr, int index) { - IndirectInstruction.super.hasInstructionAndIndirectionIndex(instr, index) - } - - final override int getIndirectionIndex() { this.hasInstructionAndIndirectionIndex(init, result) } -} - -/** - * The value of a parameter at function entry, viewed as a node in a data - * flow graph. This includes both explicit parameters such as `x` in `f(x)` - * and implicit parameters such as `this` in `x.f()`. - * - * To match a specific kind of parameter, consider using one of the subclasses - * `ExplicitParameterNode`, `ThisParameterNode`, or - * `ParameterIndirectionNode`. - */ -final class ParameterNode = AbstractParameterNode; - -abstract private class AbstractDirectParameterNode extends AbstractParameterNode { } - -/** An explicit positional parameter, including `this`, but not `...`. */ -final class DirectParameterNode = AbstractDirectParameterNode; - -/** - * INTERNAL: Do not use. - * - * A non-indirect parameter node that is represented as an `Instruction`. - */ -abstract class InstructionDirectParameterNode extends InstructionNode, AbstractDirectParameterNode { - final override InitializeParameterInstruction instr; - - /** - * INTERNAL: Do not use. - * - * Gets the `IRVariable` that this parameter references. - */ - final IRVariable getIRVariable() { result = instr.getIRVariable() } -} - -abstract private class AbstractExplicitParameterNode extends AbstractDirectParameterNode { } - -final class ExplicitParameterNode = AbstractExplicitParameterNode; - -/** An explicit positional parameter, not including `this` or `...`. */ -private class ExplicitParameterInstructionNode extends AbstractExplicitParameterNode, - InstructionDirectParameterNode -{ - ExplicitParameterInstructionNode() { exists(instr.getParameter()) } - - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - f.getParameter(pos.(DirectPosition).getArgumentIndex()) = instr.getParameter() - } - - override string toStringImpl() { result = instr.getParameter().toString() } - - override Parameter getParameter() { result = instr.getParameter() } -} - -/** An implicit `this` parameter. */ -class ThisParameterInstructionNode extends AbstractExplicitParameterNode, - InstructionDirectParameterNode -{ - ThisParameterInstructionNode() { instr.getIRVariable() instanceof IRThisVariable } - - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - pos.(DirectPosition).getArgumentIndex() = -1 and - instr.getEnclosingFunction() = f - } - - override string toStringImpl() { result = "this" } -} - -/** - * A parameter node that is part of a summary. - */ -class SummaryParameterNode extends AbstractParameterNode, FlowSummaryNode { - SummaryParameterNode() { - FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _) - } - - private ParameterPosition getPosition() { - FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result) - } - - override predicate isSummaryParameterOf( - FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition p - ) { - c = this.getSummarizedCallable() and - p = this.getPosition() - } -} - -private class DirectBodyLessParameterNode extends AbstractExplicitParameterNode, - BodyLessParameterNodeImpl -{ - DirectBodyLessParameterNode() { indirectionIndex = 0 } - - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - this.getFunction() = f and - f.getParameter(pos.(DirectPosition).getArgumentIndex()) = p - } - - override Parameter getParameter() { result = p } -} - -private class IndirectBodyLessParameterNode extends AbstractIndirectParameterNode, - BodyLessParameterNodeImpl -{ - IndirectBodyLessParameterNode() { not this instanceof DirectBodyLessParameterNode } - - override predicate isSourceParameterOf(Function f, ParameterPosition pos) { - exists(int argumentPosition | - this.getFunction() = f and - f.getParameter(argumentPosition) = p and - indirectPositionHasArgumentIndexAndIndex(pos, argumentPosition, indirectionIndex) - ) - } - - override int getIndirectionIndex() { - result = BodyLessParameterNodeImpl.super.getIndirectionIndex() - } - - override Parameter getParameter() { result = p } -} - -/** - * A node associated with an object after an operation that might have - * changed its state. - * - * This can be either the argument to a callable after the callable returns - * (which might have mutated the argument), or the qualifier of a field after - * an update to the field. - * - * Nodes corresponding to AST elements, for example `ExprNode`, usually refer - * to the value before the update with the exception of `ClassInstanceExpr`, - * which represents the value after the constructor has run. - */ -abstract class PostUpdateNode extends Node { - /** - * Gets the node before the state update. - */ - abstract Node getPreUpdateNode(); - - final override Type getType() { result = this.getPreUpdateNode().getType() } -} - -/** - * The base class for nodes that perform "partial definitions". - * - * In contrast to a normal "definition", which provides a new value for - * something, a partial definition is an expression that may affect a - * value, but does not necessarily replace it entirely. For example: - * ``` - * x.y = 1; // a partial definition of the object `x`. - * x.y.z = 1; // a partial definition of the object `x.y` and `x`. - * x.setY(1); // a partial definition of the object `x`. - * setY(&x); // a partial definition of the object `x`. - * ``` - */ -abstract private class PartialDefinitionNode extends PostUpdateNode { - /** Gets the indirection index of this node. */ - abstract int getIndirectionIndex(); - - /** Gets the expression that is partially defined by this node. */ - abstract Expr getDefinedExpr(); -} - -/** - * A `PostUpdateNode` that is part of a flow summary. These are synthesized, - * for example, when a models-as-data summary models a write to a field since - * the write needs to target a `PostUpdateNode`. - */ -class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode { - SummaryPostUpdateNode() { - FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), _) - } - - override Node getPreUpdateNode() { - FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), - result.(FlowSummaryNode).getSummaryNode()) - } -} - -/** - * A node that represents the value of a variable after a function call that - * may have changed the variable because it's passed by reference. - * - * A typical example would be a call `f(&x)`. Firstly, there will be flow into - * `x` from previous definitions of `x`. Secondly, there will be a - * `DefinitionByReferenceNode` to represent the value of `x` after the call has - * returned. This node will have its `getArgument()` equal to `&x` and its - * `getVariableAccess()` equal to `x`. - */ -class DefinitionByReferenceNode extends IndirectArgumentOutNode { - DefinitionByReferenceNode() { this.getIndirectionIndex() > 0 } - - /** Gets the unconverted argument corresponding to this node. */ - Expr getArgument() { result = this.getAddressOperand().getDef().getUnconvertedResultExpression() } - - /** Gets the parameter through which this value is assigned. */ - Parameter getParameter() { - result = this.getCallInstruction().getStaticCallTarget().getParameter(this.getArgumentIndex()) - } -} - -/** - * A `Node` corresponding to a global (or `static` local) variable in the - * program, as opposed to the value of that variable at some particular point. - * This is used to model flow through global variables (and `static` local - * variables). - * - * There is no `VariableNode` for non-`static` local variables. - */ -class VariableNode extends Node, TGlobalLikeVariableNode { - Variable v; - int indirectionIndex; - - VariableNode() { this = TGlobalLikeVariableNode(v, indirectionIndex) } - - /** Gets the variable corresponding to this node. */ - Variable getVariable() { result = v } - - /** Gets the indirection index of this node. */ - int getIndirectionIndex() { result = indirectionIndex } - - override Declaration getFunction() { none() } - - override DataFlowCallable getEnclosingCallable() { - // When flow crosses from one _enclosing callable_ to another, the - // interprocedural data-flow library discards call contexts and inserts a - // node in the big-step relation used for human-readable path explanations. - // Therefore we want a distinct enclosing callable for each `VariableNode`, - // and that can be the `Variable` itself. - result.asSourceCallable() = v - } - - override Type getType() { result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1) } - - final override Location getLocationImpl() { - // Certain variables (such as parameters) can have multiple locations. - // When there's a unique location we use that one, but if multiple locations - // exist we default to an unknown location. - result = unique( | | v.getLocation()) - or - not exists(unique( | | v.getLocation())) and - result instanceof UnknownLocation - } - - override string toStringImpl() { result = stars(this) + v.toString() } -} - -/** - * Gets the node corresponding to `instr`. - */ -InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } - -/** - * Gets the node corresponding to `operand`. - */ -OperandNode operandNode(Operand operand) { result.getOperand() = operand } - -/** - * Gets the `Node` corresponding to the value of evaluating `e` or any of its - * conversions. There is no result if `e` is a `Conversion`. For data flowing - * _out of_ an expression, like when an argument is passed by reference, use - * `definitionByReferenceNodeFromArgument` instead. - */ -ExprNode exprNode(Expr e) { result.getExpr(_) = e } - -/** - * Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may - * be a `Conversion`. For data flowing _out of_ an expression, like when an - * argument is passed by reference, use - * `definitionByReferenceNodeFromArgument` instead. - */ -ExprNode convertedExprNode(Expr e) { result.getConvertedExpr(_) = e } - -/** - * Gets the `Node` corresponding to the value of `p` at function entry. - */ -ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p } - -/** - * Gets the `Node` corresponding to a definition by reference of the variable - * that is passed as unconverted `argument` of a call. - */ -DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) { - result.getArgument() = argument -} - -/** Gets the `VariableNode` corresponding to the variable `v`. */ -VariableNode variableNode(Variable v) { - result.getVariable() = v and result.getIndirectionIndex() = 1 -} - -/** - * DEPRECATED: See UninitializedNode. - * - * Gets the `Node` corresponding to the value of an uninitialized local - * variable `v`. - */ -Node uninitializedNode(LocalVariable v) { none() } - -predicate hasOperandAndIndex(IndirectOperand indirectOperand, Operand operand, int indirectionIndex) { - indirectOperand.hasOperandAndIndirectionIndex(operand, indirectionIndex) -} - -predicate hasInstructionAndIndex( - IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex -) { - indirectInstr.hasInstructionAndIndirectionIndex(instr, indirectionIndex) -} +private import DataFlowNodes +import DataFlowNodes::Public cached private module Cached { @@ -1818,6 +122,7 @@ private module Cached { cached predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) { ( + TaintTrackingUtil::forceCachingInSameStage() and // Def-use/Use-use flow SsaImpl::ssaFlow(nodeFrom, nodeTo) or @@ -1919,35 +224,7 @@ private module Cached { ) ) } -} - -import Cached - -/** - * Holds if data flows from `source` to `sink` in zero or more local - * (intra-procedural) steps. - */ -pragma[inline] -predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } - -/** - * Holds if data can flow from `i1` to `i2` in zero or more - * local (intra-procedural) steps. - */ -pragma[inline] -predicate localInstructionFlow(Instruction e1, Instruction e2) { - localFlow(instructionNode(e1), instructionNode(e2)) -} -/** - * INTERNAL: Do not use. - * - * Ideally this module would be private, but the `asExprInternal` predicate is - * needed in `DefaultTaintTrackingImpl`. Once `DefaultTaintTrackingImpl` is gone - * we can make this module private. - */ -cached -module ExprFlowCached { /** * Holds if `n` is an indirect operand of a `PointerArithmeticInstruction`, and * `e` is the result of loading from the `PointerArithmeticInstruction`. @@ -1997,8 +274,7 @@ module ExprFlowCached { * `x[i]` steps to the expression `x[i - 1]` without traversing the * entire chain. */ - cached - Expr asExprInternal(Node n) { + private Expr asExprInternal(Node n) { isIndirectBaseOfArrayAccess(n, result) or not isIndirectBaseOfArrayAccess(n, _) and @@ -2060,7 +336,23 @@ module ExprFlowCached { predicate localExprFlowStep(Expr e1, Expr e2) { localExprFlowStepImpl(_, e1, _, e2) } } -import ExprFlowCached +import Cached + +/** + * Holds if data flows from `source` to `sink` in zero or more local + * (intra-procedural) steps. + */ +pragma[inline] +predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } + +/** + * Holds if data can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +pragma[inline] +predicate localInstructionFlow(Instruction e1, Instruction e2) { + localFlow(instructionNode(e1), instructionNode(e2)) +} /** * Holds if data can flow from `e1` to `e2` in one or more @@ -2080,158 +372,6 @@ predicate localExprFlow(Expr e1, Expr e2) { localExprFlowPlus(e1, e2) } -/** - * A canonical representation of a field. - * - * For performance reasons we want a unique `Content` that represents - * a given field across any template instantiation of a class. - * - * This is possible in _almost_ all cases, but there are cases where it is - * not possible to map between a field in the uninstantiated template to a - * field in the instantiated template. This happens in the case of local class - * definitions (because the local class is not the template that constructs - * the instantiation - it is the enclosing function). So this abstract class - * has two implementations: a non-local case (where we can represent a - * canonical field as the field declaration from an uninstantiated class - * template or a non-templated class), and a local case (where we simply use - * the field from the instantiated class). - */ -abstract private class CanonicalField extends Field { - /** Gets a field represented by this canonical field. */ - abstract Field getAField(); - - /** - * Gets a class that declares a field represented by this canonical field. - */ - abstract Class getADeclaringType(); - - /** - * Gets a type that this canonical field may have. Note that this may - * not be a unique type. For example, consider this case: - * ``` - * template - * struct S { T x; }; - * - * S s1; - * S s2; - * ``` - * In this case the canonical field corresponding to `S::x` has two types: - * `int` and `char`. - */ - Type getAType() { result = this.getAField().getType() } - - Type getAnUnspecifiedType() { result = this.getAType().getUnspecifiedType() } -} - -private class NonLocalCanonicalField extends CanonicalField { - Class declaringType; - - NonLocalCanonicalField() { - declaringType = this.getDeclaringType() and - not declaringType.isFromTemplateInstantiation(_) and - not declaringType.isLocal() // handled in LocalCanonicalField - } - - override Field getAField() { - exists(Class c | result.getDeclaringType() = c | - // Either the declaring class of the field is a template instantiation - // that has been constructed from this canonical declaration - c.isConstructedFrom(declaringType) and - pragma[only_bind_out](result.getName()) = pragma[only_bind_out](this.getName()) - or - // or this canonical declaration is not a template. - not c.isConstructedFrom(_) and - result = this - ) - } - - override Class getADeclaringType() { - result = this.getDeclaringType() - or - result.isConstructedFrom(this.getDeclaringType()) - } -} - -private class LocalCanonicalField extends CanonicalField { - Class declaringType; - - LocalCanonicalField() { - declaringType = this.getDeclaringType() and - declaringType.isLocal() - } - - override Field getAField() { result = this } - - override Class getADeclaringType() { result = declaringType } -} - -/** - * A canonical representation of a `Union`. See `CanonicalField` for the explanation for - * why we need a canonical representation. - */ -abstract private class CanonicalUnion extends Union { - /** Gets a union represented by this canonical union. */ - abstract Union getAUnion(); - - /** Gets a canonical field of this canonical union. */ - CanonicalField getACanonicalField() { result.getDeclaringType() = this } -} - -private class NonLocalCanonicalUnion extends CanonicalUnion { - NonLocalCanonicalUnion() { not this.isFromTemplateInstantiation(_) and not this.isLocal() } - - override Union getAUnion() { - result = this - or - result.isConstructedFrom(this) - } -} - -private class LocalCanonicalUnion extends CanonicalUnion { - LocalCanonicalUnion() { this.isLocal() } - - override Union getAUnion() { result = this } -} - -bindingset[f] -pragma[inline_late] -private int getFieldSize(CanonicalField f) { result = max(f.getAType().getSize()) } - -/** - * Gets a field in the union `u` whose size - * is `bytes` number of bytes. - */ -private CanonicalField getAFieldWithSize(CanonicalUnion u, int bytes) { - result = u.getACanonicalField() and - bytes = getFieldSize(result) -} - -cached -private newtype TContent = - TNonUnionContent(CanonicalField f, int indirectionIndex) { - // the indirection index for field content starts at 1 (because `TNonUnionContent` is thought of as - // the address of the field, `FieldAddress` in the IR). - indirectionIndex = [1 .. max(SsaImpl::getMaxIndirectionsForType(f.getAnUnspecifiedType()))] and - // Reads and writes of union fields are tracked using `UnionContent`. - not f.getDeclaringType() instanceof Union - } or - TUnionContent(CanonicalUnion u, int bytes, int indirectionIndex) { - exists(CanonicalField f | - f = u.getACanonicalField() and - bytes = getFieldSize(f) and - // We key `UnionContent` by the union instead of its fields since a write to one - // field can be read by any read of the union's fields. Again, the indirection index - // is 1-based (because 0 is considered the address). - indirectionIndex = - [1 .. max(SsaImpl::getMaxIndirectionsForType(getAFieldWithSize(u, bytes) - .getAnUnspecifiedType()) - )] - ) - } or - TElementContent(int indirectionIndex) { - indirectionIndex = [1 .. getMaxElementContentIndirectionIndex()] - } - /** * A description of the way data may be stored inside an object. Examples * include instance fields, the contents of a collection object, or the contents diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll index 6d69dd11e80b..927d2ea90288 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ExprNodes.qll @@ -6,8 +6,8 @@ private import cpp private import semmle.code.cpp.ir.IR private import DataFlowUtil private import DataFlowPrivate -private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr -private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag +private import DataFlowNodes +private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction cached private module Cached { @@ -73,17 +73,9 @@ private module Cached { // a result for `getConvertedResultExpression`. We remap this here so that // this `ConvertInstruction` maps to the result of the expression that // represents the extent. - exists(TranslatedNonConstantAllocationSize tas | - result = tas.getExtent().getExpr() and - instr = tas.getInstruction(AllocationExtentConvertTag()) - ) + result = IRConstruction::Raw::getAllocationExtentConvertExpr(instr) or - // There's no instruction that returns `ParenthesisExpr`, but some queries - // expect this - exists(TranslatedTransparentConversion ttc | - result = ttc.getExpr().(ParenthesisExpr) and - instr = ttc.getResult() - ) + result = IRConstruction::Raw::getTransparentConversionParenthesisExpr(instr) or // Certain expressions generate `CopyValueInstruction`s only when they // are needed. Examples of this include crement operations and compound @@ -112,10 +104,10 @@ private module Cached { // needed, and in that case the only value that will propagate forward in // the program is the value that's been updated. So in those cases we just // use the result of `node.asDefinition()` as the result of `node.asExpr()`. - exists(TranslatedCoreExpr tco | - tco.getInstruction(_) = instr and - tco.producesExprResult() and - result = asDefinitionImpl0(instr) + exists(StoreInstruction store | + store = instr and + IRConstruction::Raw::instructionProducesExprResult(store) and + result = asDefinitionImpl0(store) ) or // IR construction breaks an array aggregate literal `{1, 2, 3}` into a @@ -145,18 +137,9 @@ private module Cached { // For an expression such as `i += 2` we pretend that the generated // `StoreInstruction` contains the result of the expression even though // this isn't totally aligned with the C/C++ standard. - exists(TranslatedAssignOperation tao | - store = tao.getInstruction(AssignmentStoreTag()) and - result = tao.getExpr() - ) + result = IRConstruction::Raw::getAssignOperationStoreExpr(store) or - // Similarly for `i++` and `++i` we pretend that the generated - // `StoreInstruction` contains the result of the expression even though - // this isn't totally aligned with the C/C++ standard. - exists(TranslatedCrementOperation tco | - store = tco.getInstruction(CrementStoreTag()) and - result = tco.getExpr() - ) + result = IRConstruction::Raw::getCrementOperationStoreExpr(store) } /** @@ -166,11 +149,7 @@ private module Cached { */ private predicate excludeAsDefinitionResult(StoreInstruction store) { // Exclude the store to the temporary generated by a ternary expression. - exists(TranslatedConditionalExpr tce | - store = tce.getInstruction(ConditionValueFalseStoreTag()) - or - store = tce.getInstruction(ConditionValueTrueStoreTag()) - ) + IRConstruction::Raw::isConditionalExprTempStore(store) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll index f880bee1c1c4..5fd7bb4567b9 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll @@ -6,6 +6,7 @@ private import semmle.code.cpp.ir.IR private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs private import DataFlowUtil +private import DataFlowNodes private import DataFlowPrivate private import SsaImpl as Ssa diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll index c0976f8c3e99..93d4ddfda680 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRFieldFlowSteps.qll @@ -6,6 +6,7 @@ private import cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes private import PrintIRUtilities /** A property provider for local IR dataflow store steps. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll index e310db319319..2c741e244d13 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll @@ -2,6 +2,7 @@ private import cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes private import SsaImpl as Ssa private import PrintIRUtilities diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll index 5dfe53c946bf..2e092851b3be 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll @@ -6,6 +6,7 @@ private import cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes private Instruction getInstruction(Node n, string stars) { result = [n.asInstruction(), n.(RawIndirectInstruction).getInstruction()] and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImpl.qll index 80b440fff221..f1bdd6b8c520 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImpl.qll @@ -10,8 +10,9 @@ private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO private import semmle.code.cpp.ir.internal.IRCppLanguage private import semmle.code.cpp.ir.dataflow.internal.ModelUtil -private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedInitialization +private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction private import DataFlowPrivate +private import DataFlowNodes import SsaImplCommon private module SourceVariables { @@ -438,10 +439,7 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari * initialize `v`. */ private Instruction getInitializationTargetAddress(IRVariable v) { - exists(TranslatedVariableInitialization init | - init.getIRVariable() = v and - result = init.getTargetAddress() - ) + result = IRConstruction::Raw::getInitializationTargetAddress(v) } /** An initial definition of an SSA variable address. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll index 10ebfdb5be0d..45a6755356b5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll @@ -4,47 +4,12 @@ import semmle.code.cpp.ir.internal.IRCppLanguage private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects private import DataFlowImplCommon as DataFlowImplCommon private import DataFlowUtil +private import DataFlowNodes private import semmle.code.cpp.models.interfaces.PointerWrapper private import DataFlowPrivate private import TypeFlow private import semmle.code.cpp.ir.ValueNumbering -/** - * Holds if `operand` is an operand that is not used by the dataflow library. - * Ignored operands are not recognized as uses by SSA, and they don't have a - * corresponding `(Indirect)OperandNode`. - */ -predicate ignoreOperand(Operand operand) { - operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or - operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or - operand instanceof MemoryOperand -} - -/** - * Holds if `instr` is an instruction that is not used by the dataflow library. - * Ignored instructions are not recognized as reads/writes by SSA, and they - * don't have a corresponding `(Indirect)InstructionNode`. - */ -predicate ignoreInstruction(Instruction instr) { - DataFlowImplCommon::forceCachingInSameStage() and - ( - instr instanceof CallSideEffectInstruction or - instr instanceof CallReadSideEffectInstruction or - instr instanceof ExitFunctionInstruction or - instr instanceof EnterFunctionInstruction or - instr instanceof WriteSideEffectInstruction or - instr instanceof PhiInstruction or - instr instanceof ReadSideEffectInstruction or - instr instanceof ChiInstruction or - instr instanceof InitializeIndirectionInstruction or - instr instanceof AliasedDefinitionInstruction or - instr instanceof AliasedUseInstruction or - instr instanceof InitializeNonLocalInstruction or - instr instanceof ReturnIndirectionInstruction or - instr instanceof UninitializedGroupInstruction - ) -} - /** * Gets the C++ type of `this` in the member function `f`. * The result is a glvalue if `isGLValue` is true, and @@ -55,26 +20,6 @@ private CppType getThisType(Cpp::MemberFunction f, boolean isGLValue) { result.hasType(f.getTypeOfThis(), isGLValue) } -/** - * Gets the C++ type of the instruction `i`. - * - * This is equivalent to `i.getResultLanguageType()` with the exception - * of instructions that directly references a `this` IRVariable. In this - * case, `i.getResultLanguageType()` gives an unknown type, whereas the - * predicate gives the expected type (i.e., a potentially cv-qualified - * type `A*` where `A` is the declaring type of the member function that - * contains `i`). - */ -cached -CppType getResultLanguageType(Instruction i) { - if i.(VariableAddressInstruction).getIRVariable() instanceof IRThisVariable - then - if i.isGLValue() - then result = getThisType(i.getEnclosingFunction(), true) - else result = getThisType(i.getEnclosingFunction(), false) - else result = i.getResultLanguageType() -} - /** * Gets the C++ type of the operand `operand`. * This is equivalent to the type of the operand's defining instruction. @@ -347,10 +292,6 @@ predicate isWrite(Node0Impl value, Operand address, boolean certain) { ) } -predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) { - any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo) -} - newtype TBaseSourceVariable = // Each IR variable gets its own source variable TBaseIRVariable(IRVariable var) or @@ -572,6 +513,69 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns cached private module Cached { + /** + * Holds if `operand` is an operand that is not used by the dataflow library. + * Ignored operands are not recognized as uses by SSA, and they don't have a + * corresponding `(Indirect)OperandNode`. + */ + cached + predicate ignoreOperand(Operand operand) { + operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or + operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or + operand instanceof MemoryOperand + } + + /** + * Holds if `instr` is an instruction that is not used by the dataflow library. + * Ignored instructions are not recognized as reads/writes by SSA, and they + * don't have a corresponding `(Indirect)InstructionNode`. + */ + cached + predicate ignoreInstruction(Instruction instr) { + DataFlowImplCommon::forceCachingInSameStage() and + ( + instr instanceof CallSideEffectInstruction or + instr instanceof CallReadSideEffectInstruction or + instr instanceof ExitFunctionInstruction or + instr instanceof EnterFunctionInstruction or + instr instanceof WriteSideEffectInstruction or + instr instanceof PhiInstruction or + instr instanceof ReadSideEffectInstruction or + instr instanceof ChiInstruction or + instr instanceof InitializeIndirectionInstruction or + instr instanceof AliasedDefinitionInstruction or + instr instanceof AliasedUseInstruction or + instr instanceof InitializeNonLocalInstruction or + instr instanceof ReturnIndirectionInstruction or + instr instanceof UninitializedGroupInstruction + ) + } + + cached + predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) { + any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo) + } + + /** + * Gets the C++ type of the instruction `i`. + * + * This is equivalent to `i.getResultLanguageType()` with the exception + * of instructions that directly references a `this` IRVariable. In this + * case, `i.getResultLanguageType()` gives an unknown type, whereas the + * predicate gives the expected type (i.e., a potentially cv-qualified + * type `A*` where `A` is the declaring type of the member function that + * contains `i`). + */ + cached + CppType getResultLanguageType(Instruction i) { + if i.(VariableAddressInstruction).getIRVariable() instanceof IRThisVariable + then + if i.isGLValue() + then result = getThisType(i.getEnclosingFunction(), true) + else result = getThisType(i.getEnclosingFunction(), false) + else result = i.getResultLanguageType() + } + /** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */ private predicate isConversion(Operand op) { exists(Instruction def, Operand use | diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll index f190569330f5..3e85489b126f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll @@ -5,65 +5,82 @@ private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.SideEffect private import DataFlowUtil private import DataFlowPrivate +private import DataFlowNodes private import SsaImpl as Ssa private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import semmle.code.cpp.ir.dataflow.FlowSteps -/** - * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local - * (intra-procedural) step. This relation is only used for local taint flow - * (for example `TaintTracking::localTaint(source, sink)`) so it may contain - * special cases that should only apply to local taint flow. - */ -predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - // dataflow step - DataFlow::localFlowStep(nodeFrom, nodeTo) - or - // taint flow step - localAdditionalTaintStep(nodeFrom, nodeTo, _) - or - // models-as-data summarized flow for local data flow (i.e. special case for flow - // through calls to modeled functions, without relying on global dataflow to join - // the dots). - FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _) -} - -/** - * Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding - * local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent - * different objects. - */ cached -predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) { - operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) and - model = "" - or - modeledTaintStep(nodeFrom, nodeTo, model) - or - // Flow from (the indirection of) an operand of a pointer arithmetic instruction to the - // indirection of the pointer arithmetic instruction. This provides flow from `source` - // in `x[source]` to the result of the associated load instruction. - exists(PointerArithmeticInstruction pai, int indirectionIndex | - nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and - hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1) - ) and - model = "" - or - any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) and - model = "" - or - // models-as-data summarized flow - FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), - nodeTo.(FlowSummaryNode).getSummaryNode(), false, model) - or - // object->field conflation for content that is a `TaintInheritingContent`. - exists(DataFlow::ContentSet f | - readStep(nodeFrom, f, nodeTo) and - f.getAReadContent() instanceof TaintInheritingContent - ) and - model = "" +private module Cached { + private import DataFlowImplCommon as DataFlowImplCommon + + /** + * This predicate exists to collapse the `cached` predicates in this module with the + * `cached` predicates in other C/C++ dataflow files, which is then collapsed + * with the `cached` predicates in `DataFlowImplCommon.qll`. + */ + cached + predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() } + + /** + * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local + * (intra-procedural) step. This relation is only used for local taint flow + * (for example `TaintTracking::localTaint(source, sink)`) so it may contain + * special cases that should only apply to local taint flow. + */ + cached + predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // dataflow step + DataFlow::localFlowStep(nodeFrom, nodeTo) + or + // taint flow step + localAdditionalTaintStep(nodeFrom, nodeTo, _) + or + // models-as-data summarized flow for local data flow (i.e. special case for flow + // through calls to modeled functions, without relying on global dataflow to join + // the dots). + FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _) + } + + /** + * Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding + * local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent + * different objects. + */ + cached + predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) { + operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) and + model = "" + or + modeledTaintStep(nodeFrom, nodeTo, model) + or + // Flow from (the indirection of) an operand of a pointer arithmetic instruction to the + // indirection of the pointer arithmetic instruction. This provides flow from `source` + // in `x[source]` to the result of the associated load instruction. + exists(PointerArithmeticInstruction pai, int indirectionIndex | + nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1) + ) and + model = "" + or + any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) and + model = "" + or + // models-as-data summarized flow + FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), + nodeTo.(FlowSummaryNode).getSummaryNode(), false, model) + or + // object->field conflation for content that is a `TaintInheritingContent`. + exists(DataFlow::ContentSet f | + readStep(nodeFrom, f, nodeTo) and + f.getAReadContent() instanceof TaintInheritingContent + ) and + model = "" + } } +import Cached + /** * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local * (intra-procedural) step. @@ -196,7 +213,7 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut, string // Taint flow from a pointer argument to an output, when the model specifies flow from the deref // to that output, but the deref is not modeled in the IR for the caller. exists( - CallInstruction call, DataFlow::SideEffectOperandNode indirectArgument, Function func, + CallInstruction call, SideEffectOperandNode indirectArgument, Function func, FunctionInput modelIn, FunctionOutput modelOut | indirectArgument = callInput(call, modelIn) and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 594e37b668d6..9e9a47a5b4f1 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -15,6 +15,7 @@ private import TranslatedCall private import TranslatedStmt private import TranslatedFunction private import TranslatedGlobalVar +private import TranslatedInitialization TranslatedElement getInstructionTranslatedElement(Instruction instruction) { instruction = TRawInstruction(result, _) @@ -194,6 +195,89 @@ module Raw { Expr getInstructionUnconvertedResultExpression(Instruction instruction) { result = getInstructionConvertedResultExpression(instruction).getUnconverted() } + + /** + * Gets the expression associated with the instruction `instr` that computes + * the `Convert` instruction on the extent expression of an allocation. + */ + cached + Expr getAllocationExtentConvertExpr(Instruction instr) { + exists(TranslatedNonConstantAllocationSize tas | + instr = tas.getInstruction(AllocationExtentConvertTag()) and + result = tas.getExtent().getExpr() + ) + } + + /** + * Gets the `ParenthesisExpr` associated with a transparent conversion + * instruction, if any. + */ + cached + ParenthesisExpr getTransparentConversionParenthesisExpr(Instruction instr) { + exists(TranslatedTransparentConversion ttc | + result = ttc.getExpr() and + instr = ttc.getResult() + ) + } + + /** + * Holds if `instr` belongs to a `TranslatedCoreExpr` that produces an + * expression result. This indicates that the instruction represents a + * definition whose result should be mapped back to the expression. + */ + cached + predicate instructionProducesExprResult(Instruction instr) { + exists(TranslatedCoreExpr tco | + tco.getInstruction(_) = instr and + tco.producesExprResult() + ) + } + + /** + * Gets the expression associated with a `StoreInstruction` generated + * by an `TranslatedAssignOperation`. + */ + cached + Expr getAssignOperationStoreExpr(StoreInstruction store) { + exists(TranslatedAssignOperation tao | + store = tao.getInstruction(AssignmentStoreTag()) and + result = tao.getExpr() + ) + } + + /** + * Gets the expression associated with a `StoreInstruction` generated + * by an `TranslatedCrementOperation`. + */ + cached + Expr getCrementOperationStoreExpr(StoreInstruction store) { + exists(TranslatedCrementOperation tco | + store = tco.getInstruction(CrementStoreTag()) and + result = tco.getExpr() + ) + } + + /** + * Holds if `store` is a `StoreInstruction` that defines the temporary + * `IRVariable` generated as part of the translation of a ternary expression. + */ + cached + predicate isConditionalExprTempStore(StoreInstruction store) { + exists(TranslatedConditionalExpr tce | + store = tce.getInstruction(ConditionValueFalseStoreTag()) + or + store = tce.getInstruction(ConditionValueTrueStoreTag()) + ) + } + + /** Gets the instruction that computes the address used to initialize `v`. */ + cached + Instruction getInitializationTargetAddress(IRVariable v) { + exists(TranslatedVariableInitialization init | + init.getIRVariable() = v and + result = init.getTargetAddress() + ) + } } class TStageInstruction = TRawInstruction or TRawUnreachedInstruction; diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme b/cpp/ql/lib/semmlecode.cpp.dbscheme index 7e7c2f55670f..770002bb0232 100644 --- a/cpp/ql/lib/semmlecode.cpp.dbscheme +++ b/cpp/ql/lib/semmlecode.cpp.dbscheme @@ -245,6 +245,25 @@ trap_filename( string filename: string ref ); +/** + * Gives the tag name for `tag`. + * For debugging only. + */ +tag_name( + int tag: @tag, + string name: string ref +); + +@trap_or_tag = @tag | @trap; + +/** + * Gives the name for the source file. + */ +source_file_name( + int sf: @source_file, + string name: string ref +); + /** * In `build-mode: none` overlay mode, indicates that `source_file` * (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the @@ -252,16 +271,25 @@ trap_filename( * includes, or a template instantiation it transitively uses. */ source_file_uses_trap( - string source_file: string ref, + int source_file: @source_file ref, int trap_file: @trap ref ); /** - * Holds if there is a definition of `element` in TRAP file `trap_file`. + * In `build-mode: none` overlay mode, indicates that the TRAP file + * `trap_file` uses tag `tag`. + */ +trap_uses_tag( + int trap_file: @trap ref, + int tag: @tag ref +); + +/** + * Holds if there is a definition of `element` in TRAP file or tag `t`. */ -in_trap( +in_trap_or_tag( int element: @element ref, - int trap_file: @trap ref + int t: @trap_or_tag ref ); pch_uses( diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats index 1c53061ef50a..ab81be3fa7cc 100644 --- a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats @@ -2,7 +2,7 @@ @compilation - 12592 + 12591 @externalDataElement @@ -10,11 +10,11 @@ @file - 64952 + 64946 @folder - 12340 + 12339 @diagnostic @@ -25,16 +25,24 @@ 1 - @location_default - 46837429 + @tag + 1 + + + @source_file + 1 @pch 248 + + @location_default + 46837435 + @macro_expansion - 40306124 + 40309769 @other_macro_reference @@ -42,7 +50,7 @@ @normal_function - 2734381 + 2734631 @unknown_function @@ -50,7 +58,7 @@ @constructor - 694333 + 694343 @destructor @@ -74,11 +82,11 @@ @fun_decl - 4193664 + 4193416 @var_decl - 9368481 + 9367984 @type_decl @@ -86,11 +94,11 @@ @namespace_decl - 407977 + 408755 @using_declaration - 266868 + 266845 @using_directive @@ -102,15 +110,15 @@ @static_assert - 172750 + 172739 @parameter - 7010805 + 7011801 @membervariable - 1500528 + 1502766 @globalvariable @@ -118,11 +126,11 @@ @localvariable - 724674 + 724688 @enumconstant - 347955 + 348040 @errortype @@ -370,7 +378,7 @@ @routineptr - 679846 + 679857 @reference @@ -396,6 +404,10 @@ @scalable_vector 1 + + @decltype + 101757 + @typeof 811 @@ -476,13 +488,9 @@ @remove_reference 5705 - - @decltype - 101757 - @struct - 976682 + 976600 @union @@ -490,15 +498,15 @@ @enum - 41554 + 41605 @template_parameter - 864494 + 864421 @alias - 1755899 + 1755750 @unknown_usertype @@ -510,11 +518,11 @@ @template_template_parameter - 6091 + 6090 @proxy_class - 48246 + 48241 @scoped_enum @@ -522,7 +530,7 @@ @template_struct - 211194 + 211176 @template_class @@ -534,11 +542,11 @@ @mangledname - 6349610 + 6349611 @type_mention - 5911109 + 5913261 @concept_template @@ -546,11 +554,11 @@ @routinetype - 600577 + 600586 @ptrtomember - 9678 + 9677 @specifier @@ -566,7 +574,7 @@ @declspec - 330310 + 330396 @msattribute @@ -578,11 +586,11 @@ @attribute_arg_token - 16584 + 16585 @attribute_arg_constant_expr - 71632 + 71626 @attribute_arg_expr @@ -602,19 +610,19 @@ @derivation - 473787 + 473794 @frienddecl - 767814 + 767534 @comment - 11208576 + 11208578 @namespace - 8616 + 8615 @specialnamequalifyingelement @@ -622,15 +630,15 @@ @namequalifier - 3042541 + 3042471 @value - 13541563 + 13541565 @initialiser - 2244830 + 2245206 @address_of @@ -646,7 +654,7 @@ @parexpr - 4915711 + 4915712 @arithnegexpr @@ -666,7 +674,7 @@ @postincrexpr - 84579 + 84573 @postdecrexpr @@ -698,11 +706,11 @@ @divexpr - 52392 + 52388 @remexpr - 15907 + 15908 @paddexpr @@ -710,7 +718,7 @@ @psubexpr - 68022 + 68017 @pdiffexpr @@ -726,7 +734,7 @@ @andexpr - 483234 + 483235 @orexpr @@ -734,7 +742,7 @@ @xorexpr - 73958 + 73953 @eqexpr @@ -754,7 +762,7 @@ @geexpr - 81365 + 81360 @leexpr @@ -762,7 +770,7 @@ @assignexpr - 1281279 + 1281280 @assignaddexpr @@ -822,7 +830,7 @@ @commaexpr - 167880 + 167881 @subscriptexpr @@ -830,11 +838,11 @@ @callexpr - 238856 + 238860 @vastartexpr - 4964 + 4963 @vaargexpr @@ -850,7 +858,7 @@ @varaccess - 8255502 + 8255503 @runtime_sizeof @@ -858,7 +866,7 @@ @runtime_alignof - 49551 + 49552 @expr_stmt @@ -866,11 +874,11 @@ @routineexpr - 5726119 + 5725988 @type_operand - 1405527 + 1405528 @offsetofexpr @@ -882,7 +890,7 @@ @literal - 7985002 + 7991777 @aggregateliteral @@ -890,23 +898,23 @@ @c_style_cast - 6027721 + 6027720 @temp_init - 980663 + 980525 @errorexpr - 45185 + 45186 @reference_to - 1880187 + 1880002 @ref_indirect - 2094067 + 2094099 @vacuous_destructor_call @@ -914,7 +922,7 @@ @assume - 4138 + 4137 @conjugation @@ -966,7 +974,7 @@ @thisaccess - 1553675 + 1553582 @new_expr @@ -978,11 +986,11 @@ @throw_expr - 23840 + 23817 @condition_decl - 407678 + 407669 @braced_init_list @@ -990,7 +998,7 @@ @type_id - 47588 + 47589 @sizeof_pack @@ -1082,7 +1090,7 @@ @uuidof - 26691 + 26787 @delete_array_expr @@ -1098,7 +1106,7 @@ @ctordirectinit - 112100 + 112102 @ctorvirtualinit @@ -1114,7 +1122,7 @@ @dtordirectdestruct - 39194 + 39195 @dtorvirtualdestruct @@ -1122,7 +1130,7 @@ @dtorfielddestruct - 39566 + 39567 @static_cast @@ -1130,7 +1138,7 @@ @reinterpret_cast - 39964 + 39962 @const_cast @@ -1138,15 +1146,15 @@ @dynamic_cast - 789 + 788 @lambdaexpr - 18998 + 18997 @param_ref - 162180 + 162057 @noopexpr @@ -1250,7 +1258,7 @@ @noexceptexpr - 28138 + 28017 @builtinshufflevector @@ -1422,7 +1430,7 @@ @reuseexpr - 844466 + 844446 @istriviallycopyassignable @@ -1522,7 +1530,7 @@ @requires_expr - 16453 + 16452 @nested_requirement @@ -1534,7 +1542,7 @@ @concept_id - 90159 + 90157 @isinvocable @@ -1550,11 +1558,11 @@ @lambdacapture - 31866 + 31864 @stmt_expr - 2031828 + 2031829 @stmt_if @@ -1566,15 +1574,15 @@ @stmt_goto - 157278 + 157265 @stmt_label - 77734 + 77727 @stmt_return - 1238238 + 1238112 @stmt_block @@ -1590,11 +1598,11 @@ @stmt_switch_case - 833612 + 833592 @stmt_switch - 410617 + 410607 @stmt_asm @@ -1602,11 +1610,11 @@ @stmt_decl - 770031 + 769985 @stmt_empty - 428121 + 428111 @stmt_continue @@ -1614,11 +1622,11 @@ @stmt_break - 137507 + 137498 @stmt_try_block - 26372 + 26379 @stmt_microsoft_try @@ -1642,7 +1650,7 @@ @stmt_handler - 43218 + 43224 @stmt_constexpr_if @@ -1674,11 +1682,11 @@ @ppd_ifndef - 160444 + 160487 @ppd_elif - 21829 + 21827 @ppd_else @@ -1690,7 +1698,7 @@ @ppd_plain_include - 317291 + 317265 @ppd_define @@ -1772,11 +1780,11 @@ compilations - 12592 + 12591 id - 12592 + 12591 cwd @@ -1794,7 +1802,7 @@ 1 2 - 12592 + 12591 @@ -1820,11 +1828,11 @@ compilation_args - 1008169 + 1008084 id - 12592 + 12591 num @@ -1832,7 +1840,7 @@ arg - 29151 + 29149 @@ -1891,7 +1899,7 @@ 98 99 - 1336 + 1335 100 @@ -2160,12 +2168,12 @@ 1 2 - 13350 + 13349 2 3 - 12634 + 12633 3 @@ -2191,7 +2199,7 @@ 1 2 - 19304 + 19303 2 @@ -2211,11 +2219,11 @@ compilation_expanded_args - 1008169 + 1008084 id - 12592 + 12591 num @@ -2223,7 +2231,7 @@ arg - 29151 + 29149 @@ -2282,7 +2290,7 @@ 98 99 - 1336 + 1335 100 @@ -2551,12 +2559,12 @@ 1 2 - 13350 + 13349 2 3 - 12634 + 12633 3 @@ -2582,7 +2590,7 @@ 1 2 - 19304 + 19303 2 @@ -2650,11 +2658,11 @@ compilation_compiling_files - 15739 + 15738 id - 2723 + 2722 num @@ -2662,7 +2670,7 @@ file - 13669 + 13668 @@ -2850,7 +2858,7 @@ 1 2 - 12308 + 12307 2 @@ -2876,7 +2884,7 @@ 1 2 - 12526 + 12525 2 @@ -2896,11 +2904,11 @@ compilation_time - 62957 + 62953 id - 2723 + 2722 num @@ -2912,7 +2920,7 @@ seconds - 15412 + 16990 @@ -2977,7 +2985,7 @@ 4 5 - 2723 + 2722 @@ -2993,21 +3001,21 @@ 3 4 - 1034 + 381 4 5 - 326 + 980 5 - 7 - 163 + 9 + 217 - 8 - 9 + 9 + 10 163 @@ -3017,23 +3025,23 @@ 11 - 13 + 15 217 - 14 - 17 + 17 + 20 217 - 17 - 21 + 20 + 26 217 - 24 - 94 - 217 + 44 + 132 + 163 @@ -3101,12 +3109,12 @@ 3 4 - 1143 + 871 4 5 - 1252 + 1579 5 @@ -3116,32 +3124,32 @@ 6 7 - 653 + 326 7 - 9 - 217 + 8 + 435 - 9 - 10 - 217 + 8 + 9 + 163 - 10 - 15 + 9 + 11 381 - 16 - 45 + 11 + 30 381 - 50 - 94 - 108 + 40 + 95 + 217 @@ -3189,21 +3197,16 @@ 4 5 - 54 - - - 5 - 6 - 54 + 108 - 148 - 149 + 177 + 178 54 - 160 - 161 + 183 + 184 54 @@ -3220,21 +3223,21 @@ 1 2 - 9421 + 10020 2 3 - 3104 + 3975 3 4 - 1797 + 1906 4 - 44 + 47 1089 @@ -3251,32 +3254,27 @@ 1 2 - 8604 + 9639 2 3 - 2668 + 3757 3 4 - 1851 + 1579 4 5 - 925 + 1143 5 - 15 - 1198 - - - 43 - 73 - 163 + 72 + 871 @@ -3292,12 +3290,12 @@ 1 2 - 13560 + 13941 2 3 - 1851 + 3049 @@ -3573,19 +3571,19 @@ compilation_finished - 12592 + 12591 id - 12592 + 12591 cpu_seconds - 9489 + 9593 elapsed_seconds - 231 + 210 @@ -3599,7 +3597,7 @@ 1 2 - 12592 + 12591 @@ -3615,7 +3613,7 @@ 1 2 - 12592 + 12591 @@ -3631,17 +3629,17 @@ 1 2 - 7953 + 8289 2 3 - 1052 + 967 3 - 29 - 483 + 33 + 336 @@ -3657,12 +3655,12 @@ 1 2 - 8847 + 9004 2 3 - 641 + 589 @@ -3678,16 +3676,21 @@ 1 2 - 73 + 31 2 - 5 - 21 + 3 + 31 5 - 9 + 6 + 10 + + + 7 + 8 21 @@ -3696,28 +3699,48 @@ 21 - 12 + 13 14 - 21 + 10 - 19 + 14 + 15 + 10 + + + 16 + 17 + 10 + + + 32 33 - 21 + 10 - 60 - 179 - 21 + 69 + 70 + 10 - 233 - 293 - 21 + 182 + 183 + 10 + + + 216 + 217 + 10 - 312 - 313 + 288 + 289 + 10 + + + 319 + 320 10 @@ -3734,46 +3757,76 @@ 1 2 - 73 + 31 2 - 5 - 21 + 3 + 31 5 - 9 + 6 + 10 + + + 7 + 8 21 + + 9 + 10 + 10 + 10 11 - 21 + 10 - 12 + 13 14 - 21 + 10 - 18 - 32 - 21 + 14 + 15 + 10 - 59 - 154 - 21 + 16 + 17 + 10 - 168 - 219 - 21 + 32 + 33 + 10 - 245 - 246 + 67 + 68 + 10 + + + 163 + 164 + 10 + + + 170 + 171 + 10 + + + 206 + 207 + 10 + + + 240 + 241 10 @@ -4011,11 +4064,11 @@ locations_default - 46837429 + 46837435 id - 46837429 + 46837435 file @@ -4023,7 +4076,7 @@ beginLine - 7483211 + 7483212 beginColumn @@ -4031,7 +4084,7 @@ endLine - 7484207 + 7484208 endColumn @@ -4049,7 +4102,7 @@ 1 2 - 46837429 + 46837435 @@ -4065,7 +4118,7 @@ 1 2 - 46837429 + 46837435 @@ -4081,7 +4134,7 @@ 1 2 - 46837429 + 46837435 @@ -4097,7 +4150,7 @@ 1 2 - 46837429 + 46837435 @@ -4113,7 +4166,7 @@ 1 2 - 46837429 + 46837435 @@ -4514,7 +4567,7 @@ 1 2 - 4945831 + 4945832 2 @@ -4555,7 +4608,7 @@ 1 2 - 5008055 + 5008056 2 @@ -4591,12 +4644,12 @@ 1 2 - 5629551 + 5629552 2 3 - 483108 + 483109 3 @@ -4627,12 +4680,12 @@ 1 2 - 7018147 + 7018148 2 85 - 465063 + 465064 @@ -5110,7 +5163,7 @@ 1 2 - 5005068 + 5005069 2 @@ -5146,7 +5199,7 @@ 1 2 - 7035321 + 7035322 2 @@ -5167,7 +5220,7 @@ 1 2 - 5628182 + 5628183 2 @@ -5203,7 +5256,7 @@ 1 2 - 5012784 + 5012785 2 @@ -5223,7 +5276,7 @@ 12 72 - 561635 + 561636 72 @@ -5543,15 +5596,15 @@ files - 64952 + 64946 id - 64952 + 64946 name - 64952 + 64946 @@ -5565,7 +5618,7 @@ 1 2 - 64952 + 64946 @@ -5581,7 +5634,7 @@ 1 2 - 64952 + 64946 @@ -5591,15 +5644,15 @@ folders - 12340 + 12339 id - 12340 + 12339 name - 12340 + 12339 @@ -5613,7 +5666,7 @@ 1 2 - 12340 + 12339 @@ -5629,7 +5682,7 @@ 1 2 - 12340 + 12339 @@ -5639,15 +5692,15 @@ containerparent - 77271 + 77264 parent - 12340 + 12339 child - 77271 + 77264 @@ -5661,7 +5714,7 @@ 1 2 - 6007 + 6006 2 @@ -5696,7 +5749,7 @@ 44 151 - 263 + 262 @@ -5712,7 +5765,7 @@ 1 2 - 77271 + 77264 @@ -6864,6 +6917,102 @@ + + tag_name + 1 + + + tag + 1 + + + name + 1 + + + + + tag + name + + + 12 + + + 1 + 2 + 1 + + + + + + + name + tag + + + 12 + + + 1 + 2 + 1 + + + + + + + + + source_file_name + 1 + + + sf + 1 + + + name + 1 + + + + + sf + name + + + 12 + + + 1 + 2 + 1 + + + + + + + name + sf + + + 12 + + + 1 + 2 + 1 + + + + + + + source_file_uses_trap 1 @@ -6913,7 +7062,55 @@ - in_trap + trap_uses_tag + 1 + + + trap_file + 1 + + + tag + 1 + + + + + trap_file + tag + + + 12 + + + 1 + 2 + 1 + + + + + + + tag + trap_file + + + 12 + + + 1 + 2 + 1 + + + + + + + + + in_trap_or_tag 1 @@ -6921,14 +7118,14 @@ 1 - trap_file + t 1 element - trap_file + t 12 @@ -6943,7 +7140,7 @@ - trap_file + t element @@ -7344,11 +7541,11 @@ fileannotations - 4183771 + 4183417 id - 5744 + 5743 kind @@ -7356,11 +7553,11 @@ name - 58482 + 58477 value - 39356 + 39353 @@ -7379,7 +7576,7 @@ 2 3 - 5544 + 5543 @@ -7605,7 +7802,7 @@ 1 2 - 10983 + 10982 2 @@ -7615,7 +7812,7 @@ 3 5 - 5039 + 5038 5 @@ -7625,12 +7822,12 @@ 7 9 - 4576 + 4575 9 16 - 4313 + 4312 16 @@ -7645,7 +7842,7 @@ 27 47 - 4818 + 4817 47 @@ -7676,7 +7873,7 @@ 1 2 - 58482 + 58477 @@ -7692,7 +7889,7 @@ 1 2 - 11540 + 11539 2 @@ -7707,7 +7904,7 @@ 4 6 - 4050 + 4049 6 @@ -7737,7 +7934,7 @@ 41 95 - 4450 + 4449 95 @@ -7768,7 +7965,7 @@ 4 5 - 3177 + 3176 5 @@ -7778,7 +7975,7 @@ 8 14 - 2956 + 2955 14 @@ -7793,7 +7990,7 @@ 24 51 - 3524 + 3523 51 @@ -7839,7 +8036,7 @@ 1 2 - 39345 + 39342 2 @@ -7885,7 +8082,7 @@ 14 18 - 3440 + 3439 18 @@ -7895,7 +8092,7 @@ 28 34 - 3135 + 3134 34 @@ -7905,7 +8102,7 @@ 41 66 - 2977 + 2976 66 @@ -7915,7 +8112,7 @@ 92 113 - 2977 + 2976 113 @@ -7935,11 +8132,11 @@ inmacroexpansion - 150011419 + 150011437 id - 24673500 + 24673503 inv @@ -7972,12 +8169,12 @@ 6 7 - 6583219 + 6583220 7 8 - 8719893 + 8719894 8 @@ -8013,7 +8210,7 @@ 3 4 - 481561 + 481562 4 @@ -8038,7 +8235,7 @@ 10 11 - 444695 + 444696 11 @@ -8063,11 +8260,11 @@ affectedbymacroexpansion - 48740832 + 48740838 id - 7045463 + 7045464 inv @@ -8146,7 +8343,7 @@ 9 12 - 342973 + 342974 12 @@ -8181,7 +8378,7 @@ 18 20 - 344290 + 344291 20 @@ -8201,19 +8398,19 @@ macroinvocations - 40387489 + 40391183 id - 40387489 + 40391183 macro_id - 182555 + 182706 location - 5925541 + 5926766 kind @@ -8231,7 +8428,7 @@ 1 2 - 40387489 + 40391183 @@ -8247,7 +8444,7 @@ 1 2 - 40387489 + 40391183 @@ -8263,7 +8460,7 @@ 1 2 - 40387489 + 40391183 @@ -8279,17 +8476,17 @@ 1 2 - 61106 + 61156 2 3 - 27666 + 27664 3 4 - 17972 + 18080 4 @@ -8299,27 +8496,27 @@ 5 7 - 13833 + 13832 7 13 - 14704 + 14703 13 33 - 13724 + 13723 33 182 - 13724 + 13723 - 185 - 72208 - 9803 + 186 + 72214 + 9802 @@ -8335,42 +8532,42 @@ 1 2 - 77607 + 77765 2 3 - 30661 + 30659 3 4 - 14377 + 14376 4 5 - 10293 + 10292 5 8 - 14051 + 14050 8 18 - 14214 + 14213 18 90 - 13778 + 13723 90 - 12205 - 7570 + 12207 + 7624 @@ -8386,7 +8583,7 @@ 1 2 - 178035 + 178186 2 @@ -8407,17 +8604,17 @@ 1 2 - 5261599 + 5262706 2 4 - 429484 + 429618 4 - 72208 - 234457 + 72214 + 234441 @@ -8433,12 +8630,12 @@ 1 2 - 5903376 + 5904602 2 37 - 22165 + 22164 @@ -8454,7 +8651,7 @@ 1 2 - 5925541 + 5926766 @@ -8468,13 +8665,13 @@ 12 - 1494 - 1495 + 1495 + 1496 54 - 740082 - 740083 + 740200 + 740201 54 @@ -8494,8 +8691,8 @@ 54 - 3146 - 3147 + 3149 + 3150 54 @@ -8510,13 +8707,13 @@ 12 - 1076 - 1077 + 1077 + 1078 54 - 107726 - 107727 + 107755 + 107756 54 @@ -8527,15 +8724,15 @@ macroparent - 33684452 + 33686920 id - 33684452 + 33686920 parent_id - 15941266 + 15942726 @@ -8549,7 +8746,7 @@ 1 2 - 33684452 + 33686920 @@ -8565,27 +8762,27 @@ 1 2 - 7815090 + 7816185 2 3 - 1595836 + 1595835 3 4 - 4707397 + 4707507 4 5 - 1296896 + 1297133 5 205 - 526045 + 526063 @@ -8595,15 +8792,15 @@ macrolocationbind - 6022573 + 6023015 id - 4208559 + 4209042 location - 2272360 + 2272308 @@ -8617,12 +8814,12 @@ 1 2 - 3285153 + 3285657 2 3 - 489021 + 489010 3 @@ -8632,7 +8829,7 @@ 4 5 - 412633 + 412624 5 @@ -8653,12 +8850,12 @@ 1 2 - 1332200 + 1332170 2 3 - 481406 + 481395 3 @@ -8668,7 +8865,7 @@ 4 5 - 426920 + 426910 5 @@ -8683,11 +8880,11 @@ macro_argument_unexpanded - 82174179 + 82169670 invocation - 26181675 + 26181901 argument_index @@ -8695,7 +8892,7 @@ text - 341898 + 341869 @@ -8709,22 +8906,22 @@ 1 2 - 9641676 + 9643301 2 3 - 9734381 + 9733558 3 4 - 4982956 + 4982534 4 67 - 1822661 + 1822507 @@ -8740,22 +8937,22 @@ 1 2 - 9823583 + 9825192 2 3 - 9751897 + 9751073 3 4 - 4826877 + 4826468 4 67 - 1779317 + 1779167 @@ -8780,7 +8977,7 @@ 646904 - 2488685 + 2488917 31 @@ -8823,52 +9020,52 @@ 1 2 - 39545 + 39542 2 3 - 62080 + 62074 3 4 - 20935 + 20933 4 5 - 34443 + 34440 5 6 - 39093 + 39090 6 9 - 30750 + 30748 9 15 - 28878 + 28875 15 26 - 25774 + 25772 26 57 - 27026 + 27024 57 517 - 25911 + 25909 518 @@ -8889,17 +9086,17 @@ 1 2 - 242208 + 242188 2 3 - 89517 + 89509 3 9 - 10173 + 10172 @@ -8909,11 +9106,11 @@ macro_argument_expanded - 82174179 + 82169670 invocation - 26181675 + 26181901 argument_index @@ -8921,7 +9118,7 @@ text - 207070 + 207053 @@ -8935,22 +9132,22 @@ 1 2 - 9641676 + 9643301 2 3 - 9734381 + 9733558 3 4 - 4982956 + 4982534 4 67 - 1822661 + 1822507 @@ -8966,22 +9163,22 @@ 1 2 - 12589703 + 12591079 2 3 - 8396895 + 8396184 3 4 - 4208641 + 4208285 4 9 - 986434 + 986351 @@ -9006,7 +9203,7 @@ 646904 - 2488685 + 2488917 31 @@ -9049,22 +9246,22 @@ 1 2 - 21745 + 21743 2 3 - 26753 + 26750 3 4 - 43301 + 43297 4 5 - 15843 + 15842 5 @@ -9074,32 +9271,32 @@ 6 7 - 18326 + 18324 7 10 - 18883 + 18882 10 19 - 18252 + 18251 19 51 - 15696 + 15694 51 251 - 15548 + 15547 251 - 1169416 - 9468 + 1169648 + 9467 @@ -9115,17 +9312,17 @@ 1 2 - 104634 + 104625 2 3 - 88559 + 88552 3 66 - 13876 + 13875 @@ -9135,11 +9332,11 @@ functions - 4042957 + 4043207 id - 4042957 + 4043207 name @@ -9161,7 +9358,7 @@ 1 2 - 4042957 + 4043207 @@ -9177,7 +9374,7 @@ 1 2 - 4042957 + 4043207 @@ -9193,12 +9390,12 @@ 1 2 - 1441611 + 1441362 2 4 - 140128 + 140377 4 @@ -9268,8 +9465,8 @@ 124 - 21972 - 21973 + 21974 + 21975 124 @@ -9326,26 +9523,26 @@ builtin_functions - 30803 + 30800 id - 30803 + 30800 function_entry_point - 1134646 + 1134663 id - 1130923 + 1130940 entry_point - 1134646 + 1134663 @@ -9359,7 +9556,7 @@ 1 2 - 1127741 + 1127758 2 @@ -9380,7 +9577,7 @@ 1 2 - 1134646 + 1134663 @@ -9390,11 +9587,11 @@ function_return_type - 4060256 + 4060505 id - 4042957 + 4043207 return_type @@ -9412,7 +9609,7 @@ 1 2 - 4025659 + 4025908 2 @@ -9733,44 +9930,44 @@ purefunctions - 131546 + 131903 id - 131546 + 131903 function_deleted - 87799 + 87797 id - 87799 + 87797 function_defaulted - 51525 + 51524 id - 51525 + 51524 function_prototyped - 4041464 + 4041713 id - 4041464 + 4041713 @@ -9928,15 +10125,15 @@ fun_decls - 4199638 + 4199390 id - 4193664 + 4193416 function - 4018441 + 4018690 type_id @@ -9948,7 +10145,7 @@ location - 2806437 + 2806438 @@ -9962,7 +10159,7 @@ 1 2 - 4193664 + 4193416 @@ -9978,7 +10175,7 @@ 1 2 - 4187691 + 4187442 2 @@ -9999,7 +10196,7 @@ 1 2 - 4193664 + 4193416 @@ -10015,7 +10212,7 @@ 1 2 - 4193664 + 4193416 @@ -10031,12 +10228,12 @@ 1 2 - 3857778 + 3858525 2 5 - 160662 + 160165 @@ -10052,7 +10249,7 @@ 1 2 - 4000147 + 4000396 2 @@ -10073,7 +10270,7 @@ 1 2 - 4018441 + 4018690 @@ -10089,12 +10286,12 @@ 1 2 - 3877814 + 3878437 2 4 - 140626 + 140253 @@ -10129,7 +10326,7 @@ 364 - 10296 + 10294 1244 @@ -10146,7 +10343,7 @@ 1 2 - 304400 + 304401 2 @@ -10164,7 +10361,7 @@ 45797 - 1483 + 1485 9907 248 @@ -10254,12 +10451,12 @@ 3 11 - 129426 + 129550 11 3169 - 36587 + 36463 @@ -10275,12 +10472,12 @@ 1 2 - 1441113 + 1440864 2 4 - 140626 + 140875 4 @@ -10348,12 +10545,12 @@ 1 2 - 2413180 + 2413305 2 3 - 252132 + 252008 3 @@ -10374,12 +10571,12 @@ 1 2 - 2431847 + 2431972 2 3 - 233963 + 233838 3 @@ -10421,7 +10618,7 @@ 1 2 - 2767360 + 2767361 2 @@ -10473,7 +10670,7 @@ id - 1744269 + 1744270 name @@ -10703,26 +10900,26 @@ fun_decl_empty_throws - 420764 + 421590 fun_decl - 420764 + 421590 fun_decl_noexcept - 140904 + 140906 fun_decl - 140904 + 140906 constant - 140464 + 140466 @@ -10736,7 +10933,7 @@ 1 2 - 140904 + 140906 @@ -10752,7 +10949,7 @@ 1 2 - 140024 + 140026 2 @@ -10767,11 +10964,11 @@ fun_decl_empty_noexcept - 1160979 + 1160855 fun_decl - 1160979 + 1160855 @@ -10876,11 +11073,11 @@ fun_requires - 29023 + 29022 id - 10082 + 10081 kind @@ -10888,7 +11085,7 @@ constraint - 28787 + 28786 @@ -11006,7 +11203,7 @@ 1 2 - 28551 + 28550 2 @@ -11027,7 +11224,7 @@ 1 2 - 28787 + 28786 @@ -11037,11 +11234,11 @@ param_decl_bind - 7295169 + 7294672 id - 7295169 + 7294672 index @@ -11049,7 +11246,7 @@ fun_decl - 3524256 + 3524008 @@ -11063,7 +11260,7 @@ 1 2 - 7295169 + 7294672 @@ -11079,7 +11276,7 @@ 1 2 - 7295169 + 7294672 @@ -11114,12 +11311,12 @@ 343 - 16219 + 16218 622 - 28319 - 28320 + 28317 + 28318 124 @@ -11155,12 +11352,12 @@ 343 - 16219 + 16218 622 - 28319 - 28320 + 28317 + 28318 124 @@ -11177,7 +11374,7 @@ 1 2 - 1505951 + 1505826 2 @@ -11187,7 +11384,7 @@ 3 4 - 600837 + 600712 4 @@ -11213,7 +11410,7 @@ 1 2 - 1505951 + 1505826 2 @@ -11223,7 +11420,7 @@ 3 4 - 600837 + 600712 4 @@ -11243,15 +11440,15 @@ var_decls - 9374952 + 9374456 id - 9368481 + 9367984 variable - 9026372 + 9027369 type_id @@ -11259,11 +11456,11 @@ name - 850480 + 850481 location - 6259509 + 6259510 @@ -11277,7 +11474,7 @@ 1 2 - 9368481 + 9367984 @@ -11293,7 +11490,7 @@ 1 2 - 9362010 + 9361513 2 @@ -11314,7 +11511,7 @@ 1 2 - 9368481 + 9367984 @@ -11330,7 +11527,7 @@ 1 2 - 9368481 + 9367984 @@ -11346,12 +11543,12 @@ 1 2 - 8701686 + 8704176 2 5 - 324686 + 323192 @@ -11367,7 +11564,7 @@ 1 2 - 8973357 + 8974354 2 @@ -11388,7 +11585,7 @@ 1 2 - 8921213 + 8922210 2 @@ -11409,12 +11606,12 @@ 1 2 - 8780711 + 8783076 2 4 - 245661 + 244292 @@ -11466,7 +11663,7 @@ 1 2 - 868525 + 868526 2 @@ -11485,7 +11682,7 @@ 11 - 2870 + 2872 80891 @@ -11593,7 +11790,7 @@ 25 - 27138 + 27137 31236 @@ -11610,12 +11807,12 @@ 1 2 - 476015 + 475766 2 3 - 164769 + 164894 3 @@ -11625,7 +11822,7 @@ 4 8 - 72055 + 72180 8 @@ -11718,16 +11915,16 @@ 1 2 - 5758231 + 5758605 2 20 - 471161 + 470788 20 - 2942 + 2941 30116 @@ -11744,12 +11941,12 @@ 1 2 - 5838873 + 5839247 2 2935 - 420635 + 420262 @@ -11765,7 +11962,7 @@ 1 2 - 5961704 + 5961705 2 @@ -11801,11 +11998,11 @@ var_def - 3763197 + 3763198 id - 3763197 + 3763198 @@ -11967,7 +12164,7 @@ location - 1543658 + 1543659 @@ -12034,7 +12231,7 @@ 1 2 - 1594433 + 1594434 2 @@ -12102,18 +12299,18 @@ type_decl_top - 675760 + 676476 type_decl - 675760 + 676476 type_requires - 7658 + 7657 id @@ -12171,7 +12368,7 @@ 1 2 - 7615 + 7614 2 @@ -12186,11 +12383,11 @@ namespace_decls - 407977 + 408755 id - 407977 + 408755 namespace_id @@ -12198,11 +12395,11 @@ location - 407977 + 408755 bodylocation - 407977 + 408755 @@ -12216,7 +12413,7 @@ 1 2 - 407977 + 408755 @@ -12232,7 +12429,7 @@ 1 2 - 407977 + 408755 @@ -12248,7 +12445,7 @@ 1 2 - 407977 + 408755 @@ -12308,12 +12505,12 @@ 263 - 1509 + 1517 145 - 1882 - 12507 + 1890 + 12533 40 @@ -12374,12 +12571,12 @@ 263 - 1509 + 1517 145 - 1882 - 12507 + 1890 + 12533 40 @@ -12440,12 +12637,12 @@ 263 - 1509 + 1517 145 - 1882 - 12507 + 1890 + 12533 40 @@ -12462,7 +12659,7 @@ 1 2 - 407977 + 408755 @@ -12478,7 +12675,7 @@ 1 2 - 407977 + 408755 @@ -12494,7 +12691,7 @@ 1 2 - 407977 + 408755 @@ -12510,7 +12707,7 @@ 1 2 - 407977 + 408755 @@ -12526,7 +12723,7 @@ 1 2 - 407977 + 408755 @@ -12542,7 +12739,7 @@ 1 2 - 407977 + 408755 @@ -12552,19 +12749,19 @@ usings - 271002 + 270979 id - 271002 + 270979 element_id - 58818 + 58813 location - 26742 + 26740 kind @@ -12582,7 +12779,7 @@ 1 2 - 271002 + 270979 @@ -12598,7 +12795,7 @@ 1 2 - 271002 + 270979 @@ -12614,7 +12811,7 @@ 1 2 - 271002 + 270979 @@ -12630,12 +12827,12 @@ 1 2 - 51118 + 51113 2 5 - 5365 + 5364 5 @@ -12656,12 +12853,12 @@ 1 2 - 51118 + 51113 2 5 - 5365 + 5364 5 @@ -12682,7 +12879,7 @@ 1 2 - 58818 + 58813 @@ -12698,7 +12895,7 @@ 1 2 - 21093 + 21091 2 @@ -12729,7 +12926,7 @@ 1 2 - 21093 + 21091 2 @@ -12760,7 +12957,7 @@ 1 2 - 26742 + 26740 @@ -12833,15 +13030,15 @@ using_container - 577847 + 577799 parent - 21808 + 21806 child - 271002 + 270979 @@ -12885,7 +13082,7 @@ 145 146 - 2609 + 2608 146 @@ -12906,27 +13103,27 @@ 1 2 - 96218 + 96210 2 3 - 119805 + 119794 3 4 - 20020 + 20018 4 5 - 26605 + 26603 5 65 - 8353 + 8352 @@ -12936,23 +13133,23 @@ static_asserts - 172750 + 172739 id - 172750 + 172739 condition - 172750 + 172739 message - 38652 + 38650 location - 22585 + 22584 enclosing @@ -12970,7 +13167,7 @@ 1 2 - 172750 + 172739 @@ -12986,7 +13183,7 @@ 1 2 - 172750 + 172739 @@ -13002,7 +13199,7 @@ 1 2 - 172750 + 172739 @@ -13018,7 +13215,7 @@ 1 2 - 172750 + 172739 @@ -13034,7 +13231,7 @@ 1 2 - 172750 + 172739 @@ -13050,7 +13247,7 @@ 1 2 - 172750 + 172739 @@ -13066,7 +13263,7 @@ 1 2 - 172750 + 172739 @@ -13082,7 +13279,7 @@ 1 2 - 172750 + 172739 @@ -13098,7 +13295,7 @@ 1 2 - 28416 + 28414 2 @@ -13139,7 +13336,7 @@ 1 2 - 28416 + 28414 2 @@ -13180,7 +13377,7 @@ 1 2 - 35818 + 35816 2 @@ -13201,7 +13398,7 @@ 1 2 - 30222 + 30220 2 @@ -13211,12 +13408,12 @@ 3 4 - 3385 + 3384 4 12 - 1903 + 1902 12 @@ -13242,7 +13439,7 @@ 2 3 - 3717 + 3716 3 @@ -13257,7 +13454,7 @@ 5 6 - 4721 + 4720 6 @@ -13267,7 +13464,7 @@ 14 15 - 2640 + 2639 16 @@ -13277,7 +13474,7 @@ 17 18 - 4381 + 4380 19 @@ -13303,7 +13500,7 @@ 2 3 - 3717 + 3716 3 @@ -13318,7 +13515,7 @@ 5 6 - 4721 + 4720 6 @@ -13328,7 +13525,7 @@ 14 15 - 2640 + 2639 16 @@ -13338,7 +13535,7 @@ 17 18 - 4381 + 4380 19 @@ -13359,7 +13556,7 @@ 1 2 - 6940 + 6939 2 @@ -13369,7 +13566,7 @@ 3 4 - 7758 + 7757 4 @@ -13390,7 +13587,7 @@ 1 2 - 5053 + 5052 2 @@ -13415,7 +13612,7 @@ 13 14 - 2640 + 2639 16 @@ -13436,7 +13633,7 @@ 1 2 - 5709 + 5708 2 @@ -13467,7 +13664,7 @@ 1 2 - 5709 + 5708 2 @@ -13498,7 +13695,7 @@ 1 2 - 5863 + 5862 2 @@ -13544,15 +13741,15 @@ params - 7051250 + 7052247 id - 7010805 + 7011801 function - 3400056 + 3400306 index @@ -13574,7 +13771,7 @@ 1 2 - 7010805 + 7011801 @@ -13590,7 +13787,7 @@ 1 2 - 7010805 + 7011801 @@ -13606,7 +13803,7 @@ 1 2 - 6970359 + 6971355 2 @@ -13632,7 +13829,7 @@ 2 3 - 924652 + 924776 3 @@ -13647,7 +13844,7 @@ 5 65 - 145853 + 145978 @@ -13668,7 +13865,7 @@ 2 3 - 924652 + 924776 3 @@ -13683,7 +13880,7 @@ 5 65 - 145853 + 145978 @@ -13704,7 +13901,7 @@ 2 3 - 1029188 + 1029313 3 @@ -13714,7 +13911,7 @@ 4 11 - 154813 + 154938 @@ -13748,13 +13945,13 @@ 622 - 321 - 15503 + 322 + 15505 622 - 27321 - 27322 + 27323 + 27324 124 @@ -13789,13 +13986,13 @@ 622 - 321 - 15503 + 322 + 15505 622 - 27321 - 27322 + 27323 + 27324 124 @@ -13853,7 +14050,7 @@ 1 2 - 735614 + 735615 2 @@ -13945,15 +14142,15 @@ overrides - 159153 + 159143 new - 150383 + 150374 old - 17799 + 17798 @@ -13967,12 +14164,12 @@ 1 2 - 141620 + 141612 2 4 - 8762 + 8761 @@ -13988,7 +14185,7 @@ 1 2 - 9685 + 9684 2 @@ -14023,19 +14220,19 @@ membervariables - 1502979 + 1505217 id - 1500528 + 1502766 type_id - 457641 + 457991 name - 642756 + 644237 @@ -14049,7 +14246,7 @@ 1 2 - 1498186 + 1500425 2 @@ -14070,7 +14267,7 @@ 1 2 - 1500528 + 1502766 @@ -14086,22 +14283,22 @@ 1 2 - 339459 + 339817 2 3 - 72597 + 72592 3 10 - 35454 + 35397 10 4445 - 10129 + 10183 @@ -14117,17 +14314,17 @@ 1 2 - 357050 + 357407 2 3 - 64754 + 64750 3 57 - 34365 + 34362 60 @@ -14148,22 +14345,22 @@ 1 2 - 422023 + 423356 2 3 - 122484 + 122584 3 5 - 58056 + 58106 5 664 - 40192 + 40189 @@ -14179,17 +14376,17 @@ 1 2 - 525010 + 526390 2 3 - 73196 + 73300 3 668 - 44549 + 44546 @@ -14385,19 +14582,19 @@ localvariables - 724674 + 724688 id - 724674 + 724688 type_id - 53296 + 53301 name - 101406 + 101408 @@ -14411,7 +14608,7 @@ 1 2 - 724674 + 724688 @@ -14427,7 +14624,7 @@ 1 2 - 724674 + 724688 @@ -14443,7 +14640,7 @@ 1 2 - 28788 + 28793 2 @@ -14489,12 +14686,12 @@ 1 2 - 38247 + 38252 2 3 - 6703 + 6704 3 @@ -14520,7 +14717,7 @@ 1 2 - 62400 + 62401 2 @@ -14561,12 +14758,12 @@ 1 2 - 84396 + 84398 2 3 - 8392 + 8393 3 @@ -14654,15 +14851,15 @@ orphaned_variables - 44034 + 44035 var - 44034 + 44035 function - 40785 + 40786 @@ -14676,7 +14873,7 @@ 1 2 - 44034 + 44035 @@ -14707,19 +14904,19 @@ enumconstants - 347955 + 348040 id - 347955 + 348040 parent - 41554 + 41605 index - 13942 + 13941 type_id @@ -14727,11 +14924,11 @@ name - 347574 + 347659 location - 320561 + 320648 @@ -14745,7 +14942,7 @@ 1 2 - 347955 + 348040 @@ -14761,7 +14958,7 @@ 1 2 - 347955 + 348040 @@ -14777,7 +14974,7 @@ 1 2 - 347955 + 348040 @@ -14793,7 +14990,7 @@ 1 2 - 347955 + 348040 @@ -14809,7 +15006,7 @@ 1 2 - 347955 + 348040 @@ -14830,7 +15027,7 @@ 2 3 - 5772 + 5826 3 @@ -14840,7 +15037,7 @@ 4 5 - 5555 + 5554 5 @@ -14865,7 +15062,7 @@ 10 15 - 3431 + 3430 15 @@ -14875,7 +15072,7 @@ 33 257 - 1307 + 1306 @@ -14896,7 +15093,7 @@ 2 3 - 5772 + 5826 3 @@ -14906,7 +15103,7 @@ 4 5 - 5555 + 5554 5 @@ -14931,7 +15128,7 @@ 10 15 - 3431 + 3430 15 @@ -14941,7 +15138,7 @@ 33 257 - 1307 + 1306 @@ -14957,7 +15154,7 @@ 1 2 - 41554 + 41605 @@ -14978,7 +15175,7 @@ 2 3 - 5772 + 5826 3 @@ -14988,7 +15185,7 @@ 4 5 - 5555 + 5554 5 @@ -15013,7 +15210,7 @@ 10 15 - 3431 + 3430 15 @@ -15023,7 +15220,7 @@ 33 257 - 1307 + 1306 @@ -15039,17 +15236,17 @@ 1 2 - 2124 + 2123 2 3 - 5990 + 6044 3 4 - 8768 + 8767 4 @@ -15144,7 +15341,7 @@ 64 - 764 + 765 980 @@ -15200,7 +15397,7 @@ 64 - 764 + 765 980 @@ -15217,7 +15414,7 @@ 1 2 - 13942 + 13941 @@ -15272,7 +15469,7 @@ 64 - 761 + 762 980 @@ -15328,7 +15525,7 @@ 64 - 764 + 765 980 @@ -15343,8 +15540,8 @@ 12 - 6389 - 6390 + 6391 + 6392 54 @@ -15359,8 +15556,8 @@ 12 - 763 - 764 + 764 + 765 54 @@ -15391,8 +15588,8 @@ 12 - 6382 - 6383 + 6384 + 6385 54 @@ -15407,8 +15604,8 @@ 12 - 5886 - 5887 + 5888 + 5889 54 @@ -15425,7 +15622,7 @@ 1 2 - 347193 + 347278 2 @@ -15446,7 +15643,7 @@ 1 2 - 347193 + 347278 2 @@ -15467,7 +15664,7 @@ 1 2 - 347574 + 347659 @@ -15483,7 +15680,7 @@ 1 2 - 347574 + 347659 @@ -15499,7 +15696,7 @@ 1 2 - 347193 + 347278 2 @@ -15520,7 +15717,7 @@ 1 2 - 319526 + 319613 2 @@ -15541,7 +15738,7 @@ 1 2 - 320561 + 320648 @@ -15557,7 +15754,7 @@ 1 2 - 319526 + 319613 2 @@ -15578,7 +15775,7 @@ 1 2 - 320561 + 320648 @@ -15594,7 +15791,7 @@ 1 2 - 319526 + 319613 2 @@ -16301,11 +16498,11 @@ derivedtypes - 3023724 + 3023725 id - 3023724 + 3023725 name @@ -16317,7 +16514,7 @@ type_id - 1942142 + 1942143 @@ -16331,7 +16528,7 @@ 1 2 - 3023724 + 3023725 @@ -16347,7 +16544,7 @@ 1 2 - 3023724 + 3023725 @@ -16363,7 +16560,7 @@ 1 2 - 3023724 + 3023725 @@ -16642,7 +16839,7 @@ 3 4 - 123203 + 123204 4 @@ -16657,11 +16854,11 @@ pointerishsize - 2242063 + 2242064 id - 2242063 + 2242064 size @@ -16683,7 +16880,7 @@ 1 2 - 2242063 + 2242064 @@ -16699,7 +16896,7 @@ 1 2 - 2242063 + 2242064 @@ -17222,15 +17419,15 @@ typedefbase - 1755899 + 1755750 id - 1755899 + 1755750 type_id - 834290 + 834219 @@ -17244,7 +17441,7 @@ 1 2 - 1755899 + 1755750 @@ -17260,22 +17457,22 @@ 1 2 - 659390 + 659334 2 3 - 80764 + 80757 3 6 - 63921 + 63915 6 4525 - 30214 + 30211 @@ -17749,7 +17946,7 @@ base_type - 5234 + 5233 @@ -18049,15 +18246,15 @@ usertypes - 4137871 + 4137521 id - 4137871 + 4137521 name - 915412 + 915335 kind @@ -18075,7 +18272,7 @@ 1 2 - 4137871 + 4137521 @@ -18091,7 +18288,7 @@ 1 2 - 4137871 + 4137521 @@ -18107,22 +18304,22 @@ 1 2 - 652110 + 652055 2 3 - 158098 + 158085 3 8 - 70349 + 70343 8 32667 - 34853 + 34850 @@ -18138,12 +18335,12 @@ 1 2 - 863873 + 863800 2 10 - 51538 + 51534 @@ -18295,11 +18492,11 @@ usertypesize - 1359715 + 1359600 id - 1359715 + 1359600 size @@ -18321,7 +18518,7 @@ 1 2 - 1359715 + 1359600 @@ -18337,7 +18534,7 @@ 1 2 - 1359715 + 1359600 @@ -18542,15 +18739,15 @@ usertype_uuid - 47795 + 47930 id - 47795 + 47930 uuid - 47252 + 47387 @@ -18564,7 +18761,7 @@ 1 2 - 47795 + 47930 @@ -18580,7 +18777,7 @@ 1 2 - 46710 + 46845 2 @@ -18595,11 +18792,11 @@ usertype_alias_kind - 1755899 + 1755750 id - 1755899 + 1755750 alias_kind @@ -18617,7 +18814,7 @@ 1 2 - 1755899 + 1755750 @@ -18648,18 +18845,18 @@ nontype_template_parameters - 761282 + 761293 id - 761282 + 761293 type_template_type_constraint - 27071 + 27070 id @@ -18667,7 +18864,7 @@ constraint - 25934 + 25933 @@ -18717,7 +18914,7 @@ 1 2 - 24797 + 24796 2 @@ -18732,15 +18929,15 @@ mangled_name - 7910194 + 7910444 id - 7910194 + 7910444 mangled_name - 6349610 + 6349611 is_complete @@ -18758,7 +18955,7 @@ 1 2 - 7910194 + 7910444 @@ -18774,7 +18971,7 @@ 1 2 - 7910194 + 7910444 @@ -18790,12 +18987,12 @@ 1 2 - 6016461 + 6016213 2 1120 - 333148 + 333397 @@ -18811,7 +19008,7 @@ 1 2 - 6349610 + 6349611 @@ -18830,8 +19027,8 @@ 124 - 63556 - 63557 + 63558 + 63559 124 @@ -18863,59 +19060,59 @@ is_pod_class - 590965 + 590973 id - 590965 + 590973 is_standard_layout_class - 1120631 + 1120536 id - 1120631 + 1120536 is_complete - 1341620 + 1341507 id - 1341620 + 1341507 is_class_template - 231204 + 231184 id - 231204 + 231184 class_instantiation - 1122283 + 1122188 to - 1119253 + 1119158 from - 71527 + 71521 @@ -18929,12 +19126,12 @@ 1 2 - 1117128 + 1117033 2 8 - 2125 + 2124 @@ -18950,12 +19147,12 @@ 1 2 - 20388 + 20386 2 3 - 12834 + 12833 3 @@ -18980,12 +19177,12 @@ 10 17 - 5891 + 5890 17 51 - 5365 + 5364 51 @@ -19000,11 +19197,11 @@ class_template_argument - 2887609 + 2887364 type_id - 1362314 + 1362199 index @@ -19012,7 +19209,7 @@ arg_type - 818825 + 818756 @@ -19026,27 +19223,27 @@ 1 2 - 577774 + 577725 2 3 - 408671 + 408636 3 4 - 249962 + 249940 4 7 - 102688 + 102679 7 113 - 23218 + 23216 @@ -19062,22 +19259,22 @@ 1 2 - 606210 + 606159 2 3 - 422610 + 422574 3 4 - 250793 + 250771 4 113 - 82699 + 82692 @@ -19185,22 +19382,22 @@ 1 2 - 511601 + 511558 2 3 - 166904 + 166890 3 5 - 74925 + 74919 5 46 - 61417 + 61412 46 @@ -19221,17 +19418,17 @@ 1 2 - 720934 + 720873 2 3 - 79596 + 79589 3 22 - 18294 + 18293 @@ -19241,11 +19438,11 @@ class_template_argument_value - 506788 + 506795 type_id - 204502 + 204505 index @@ -19253,7 +19450,7 @@ arg_value - 506652 + 506660 @@ -19267,12 +19464,12 @@ 1 2 - 154815 + 154817 2 3 - 43086 + 43087 3 @@ -19293,7 +19490,7 @@ 1 2 - 146996 + 146998 2 @@ -19436,7 +19633,7 @@ 1 2 - 506517 + 506524 2 @@ -19457,7 +19654,7 @@ 1 2 - 506652 + 506660 @@ -19467,15 +19664,15 @@ is_proxy_class_for - 48246 + 48241 id - 48246 + 48241 templ_param_id - 45584 + 45580 @@ -19489,7 +19686,7 @@ 1 2 - 48246 + 48241 @@ -19505,7 +19702,7 @@ 1 2 - 44869 + 44865 2 @@ -19520,19 +19717,19 @@ type_mentions - 5911109 + 5913261 id - 5911109 + 5913261 type_id - 277863 + 278007 location - 5854796 + 5856951 kind @@ -19550,7 +19747,7 @@ 1 2 - 5911109 + 5913261 @@ -19566,7 +19763,7 @@ 1 2 - 5911109 + 5913261 @@ -19582,7 +19779,7 @@ 1 2 - 5911109 + 5913261 @@ -19598,42 +19795,42 @@ 1 2 - 137297 + 137451 2 3 - 31206 + 31204 3 4 - 11654 + 11653 4 5 - 14976 + 14975 5 7 - 19932 + 19931 7 12 - 21839 + 21783 12 28 - 21022 + 21020 28 8941 - 19932 + 19986 @@ -19649,42 +19846,42 @@ 1 2 - 137297 + 137451 2 3 - 31206 + 31204 3 4 - 11654 + 11653 4 5 - 14976 + 14975 5 7 - 19932 + 19931 7 12 - 21839 + 21783 12 28 - 21022 + 21020 28 8941 - 19932 + 19986 @@ -19700,7 +19897,7 @@ 1 2 - 277863 + 278007 @@ -19716,12 +19913,12 @@ 1 2 - 5809102 + 5811261 2 4 - 45693 + 45690 @@ -19737,12 +19934,12 @@ 1 2 - 5809102 + 5811261 2 4 - 45693 + 45690 @@ -19758,7 +19955,7 @@ 1 2 - 5854796 + 5856951 @@ -19772,8 +19969,8 @@ 12 - 108537 - 108538 + 108584 + 108585 54 @@ -19788,8 +19985,8 @@ 12 - 5102 - 5103 + 5105 + 5106 54 @@ -19804,8 +20001,8 @@ 12 - 107503 - 107504 + 107550 + 107551 54 @@ -19827,15 +20024,15 @@ function_instantiation - 967578 + 967592 to - 967578 + 967592 from - 181520 + 181523 @@ -19849,7 +20046,7 @@ 1 2 - 967578 + 967592 @@ -19865,12 +20062,12 @@ 1 2 - 109832 + 109834 2 3 - 42545 + 42546 3 @@ -19895,11 +20092,11 @@ function_template_argument - 2468684 + 2468721 function_id - 1443870 + 1443892 index @@ -19907,7 +20104,7 @@ arg_type - 296057 + 296062 @@ -19921,22 +20118,22 @@ 1 2 - 777934 + 777946 2 3 - 410494 + 410500 3 4 - 170689 + 170691 4 15 - 84752 + 84753 @@ -19952,22 +20149,22 @@ 1 2 - 796956 + 796968 2 3 - 408598 + 408604 3 4 - 168523 + 168525 4 9 - 69792 + 69793 @@ -20105,7 +20302,7 @@ 1 2 - 173634 + 173636 2 @@ -20130,7 +20327,7 @@ 11 76 - 23218 + 23219 79 @@ -20151,12 +20348,12 @@ 1 2 - 255137 + 255140 2 3 - 31917 + 31918 3 @@ -20171,11 +20368,11 @@ function_template_argument_value - 449824 + 449830 function_id - 195499 + 195502 index @@ -20183,7 +20380,7 @@ arg_value - 447150 + 447156 @@ -20197,7 +20394,7 @@ 1 2 - 150415 + 150417 2 @@ -20223,7 +20420,7 @@ 1 2 - 143544 + 143546 2 @@ -20376,7 +20573,7 @@ 1 2 - 444476 + 444482 2 @@ -20397,7 +20594,7 @@ 1 2 - 447150 + 447156 @@ -20976,11 +21173,11 @@ template_template_argument - 9636 + 9635 type_id - 6091 + 6090 index @@ -20988,7 +21185,7 @@ arg_type - 9047 + 9046 @@ -21002,7 +21199,7 @@ 1 2 - 4997 + 4996 2 @@ -21033,7 +21230,7 @@ 1 2 - 5018 + 5017 2 @@ -21207,7 +21404,7 @@ 1 2 - 9026 + 9025 2 @@ -21454,11 +21651,11 @@ concept_instantiation - 90159 + 90157 to - 90159 + 90157 from @@ -21476,7 +21673,7 @@ 1 2 - 90159 + 90157 @@ -21572,22 +21769,22 @@ is_type_constraint - 36788 + 36787 concept_id - 36788 + 36787 concept_template_argument - 112704 + 112701 concept_id - 76151 + 76149 index @@ -21595,7 +21792,7 @@ arg_type - 21365 + 21364 @@ -21609,12 +21806,12 @@ 1 2 - 46334 + 46333 2 3 - 24604 + 24603 3 @@ -21635,12 +21832,12 @@ 1 2 - 49938 + 49937 2 3 - 22309 + 22308 3 @@ -21794,7 +21991,7 @@ 1 2 - 17976 + 17975 2 @@ -21945,15 +22142,15 @@ routinetypes - 600577 + 600586 id - 600577 + 600586 return_type - 282011 + 282015 @@ -21967,7 +22164,7 @@ 1 2 - 600577 + 600586 @@ -21983,12 +22180,12 @@ 1 2 - 232561 + 232564 2 3 - 34997 + 34998 3 @@ -22003,11 +22200,11 @@ routinetypeargs - 1178605 + 1178524 routine - 416032 + 416004 index @@ -22015,7 +22212,7 @@ type_id - 112082 + 112074 @@ -22029,32 +22226,32 @@ 1 2 - 82945 + 82939 2 3 - 126078 + 126070 3 4 - 107888 + 107881 4 5 - 49287 + 49284 5 7 - 33167 + 33164 7 19 - 16665 + 16664 @@ -22070,27 +22267,27 @@ 1 2 - 88935 + 88929 2 3 - 138713 + 138704 3 4 - 114641 + 114633 4 5 - 40737 + 40734 5 10 - 32894 + 32892 10 @@ -22288,32 +22485,32 @@ 1 2 - 33276 + 33273 2 3 - 15576 + 15574 3 4 - 13288 + 13287 4 5 - 9803 + 9802 5 6 - 6372 + 6371 6 8 - 9476 + 9475 8 @@ -22323,7 +22520,7 @@ 13 26 - 8659 + 8658 26 @@ -22344,22 +22541,22 @@ 1 2 - 79405 + 79399 2 3 - 17536 + 17535 3 5 - 9476 + 9475 5 17 - 5664 + 5663 @@ -22369,11 +22566,11 @@ ptrtomembers - 9678 + 9677 id - 9678 + 9677 type_id @@ -22395,7 +22592,7 @@ 1 2 - 9678 + 9677 @@ -22411,7 +22608,7 @@ 1 2 - 9678 + 9677 @@ -22427,7 +22624,7 @@ 1 2 - 7732 + 7731 2 @@ -22448,7 +22645,7 @@ 1 2 - 7732 + 7731 2 @@ -22686,11 +22883,11 @@ funspecifiers - 9693167 + 9694786 func_id - 4002387 + 4002636 spec_id @@ -22708,17 +22905,17 @@ 1 2 - 1527356 + 1526111 2 3 - 504514 + 506132 3 4 - 1034166 + 1034042 4 @@ -22822,8 +23019,8 @@ 124 - 15135 - 15136 + 15137 + 15138 124 @@ -22832,8 +23029,8 @@ 124 - 22767 - 22768 + 22778 + 22779 124 @@ -24086,11 +24283,11 @@ attribute_arg_value - 16584 + 16585 arg - 16584 + 16585 value @@ -24108,7 +24305,7 @@ 1 2 - 16584 + 16585 @@ -24242,15 +24439,15 @@ attribute_arg_constant - 71632 + 71626 arg - 71632 + 71626 constant - 71632 + 71626 @@ -24264,7 +24461,7 @@ 1 2 - 71632 + 71626 @@ -24280,7 +24477,7 @@ 1 2 - 71632 + 71626 @@ -24701,11 +24898,11 @@ unspecifiedtype - 7228465 + 7228466 type_id - 7228465 + 7228466 unspecified_type_id @@ -24723,7 +24920,7 @@ 1 2 - 7228465 + 7228466 @@ -24764,7 +24961,7 @@ member - 4182091 + 4182340 parent @@ -24776,7 +24973,7 @@ child - 4177486 + 4177735 @@ -24825,7 +25022,7 @@ 9 13 - 41067 + 41068 13 @@ -25054,7 +25251,7 @@ 1 2 - 4177486 + 4177735 @@ -25070,7 +25267,7 @@ 1 2 - 4172881 + 4173131 2 @@ -25085,15 +25282,15 @@ enclosingfunction - 114986 + 114977 child - 114986 + 114977 parent - 69097 + 69091 @@ -25107,7 +25304,7 @@ 1 2 - 114986 + 114977 @@ -25123,12 +25320,12 @@ 1 2 - 37473 + 37470 2 3 - 24480 + 24478 3 @@ -25148,15 +25345,15 @@ derivations - 473787 + 473794 derivation - 473787 + 473794 sub - 452193 + 452200 index @@ -25164,11 +25361,11 @@ super - 234016 + 234020 location - 35166 + 35167 @@ -25182,7 +25379,7 @@ 1 2 - 473787 + 473794 @@ -25198,7 +25395,7 @@ 1 2 - 473787 + 473794 @@ -25214,7 +25411,7 @@ 1 2 - 473787 + 473794 @@ -25230,7 +25427,7 @@ 1 2 - 473787 + 473794 @@ -25246,7 +25443,7 @@ 1 2 - 435777 + 435784 2 @@ -25267,7 +25464,7 @@ 1 2 - 435777 + 435784 2 @@ -25288,7 +25485,7 @@ 1 2 - 435777 + 435784 2 @@ -25309,7 +25506,7 @@ 1 2 - 435777 + 435784 2 @@ -25469,12 +25666,12 @@ 1 2 - 224268 + 224272 2 1655 - 9747 + 9748 @@ -25490,12 +25687,12 @@ 1 2 - 224268 + 224272 2 1655 - 9747 + 9748 @@ -25511,7 +25708,7 @@ 1 2 - 233576 + 233580 2 @@ -25532,12 +25729,12 @@ 1 2 - 228702 + 228706 2 81 - 5313 + 5314 @@ -25553,7 +25750,7 @@ 1 2 - 26332 + 26333 2 @@ -25589,7 +25786,7 @@ 1 2 - 26332 + 26333 2 @@ -25625,7 +25822,7 @@ 1 2 - 35166 + 35167 @@ -25641,7 +25838,7 @@ 1 2 - 28532 + 28533 2 @@ -25666,11 +25863,11 @@ derspecifiers - 475547 + 475554 der_id - 473347 + 473354 spec_id @@ -25688,7 +25885,7 @@ 1 2 - 471147 + 471154 2 @@ -25734,11 +25931,11 @@ direct_base_offsets - 447048 + 447055 der_id - 447048 + 447055 offset @@ -25756,7 +25953,7 @@ 1 2 - 447048 + 447055 @@ -25953,23 +26150,23 @@ frienddecls - 767814 + 767534 id - 767814 + 767534 type_id - 54357 + 54340 decl_id - 100728 + 100695 location - 6058 + 6056 @@ -25983,7 +26180,7 @@ 1 2 - 767814 + 767534 @@ -25999,7 +26196,7 @@ 1 2 - 767814 + 767534 @@ -26015,7 +26212,7 @@ 1 2 - 767814 + 767534 @@ -26031,37 +26228,37 @@ 1 2 - 5584 + 5582 2 3 - 24978 + 25004 3 8 - 4806 + 4770 8 17 - 4738 + 4737 17 27 - 4467 + 4466 27 45 - 4298 + 4297 45 81 - 4738 + 4737 102 @@ -26082,37 +26279,37 @@ 1 2 - 5584 + 5582 2 3 - 24978 + 25004 3 8 - 4806 + 4770 8 17 - 4738 + 4737 17 27 - 4467 + 4466 27 45 - 4298 + 4297 45 81 - 4738 + 4737 102 @@ -26133,7 +26330,7 @@ 1 2 - 53004 + 52987 2 @@ -26154,27 +26351,27 @@ 1 2 - 67490 + 67502 2 3 - 8157 + 8120 3 9 - 9206 + 9203 9 24 - 7615 + 7613 24 136 - 7649 + 7646 136 @@ -26195,27 +26392,27 @@ 1 2 - 67490 + 67502 2 3 - 8157 + 8120 3 9 - 9206 + 9203 9 24 - 7615 + 7613 24 136 - 7649 + 7646 136 @@ -26236,7 +26433,7 @@ 1 2 - 99509 + 99477 2 @@ -26257,11 +26454,11 @@ 1 2 - 5686 + 5684 2 - 22496 + 22495 372 @@ -26278,7 +26475,7 @@ 1 2 - 5923 + 5921 2 @@ -26299,7 +26496,7 @@ 1 2 - 5720 + 5718 2 @@ -26314,19 +26511,19 @@ comments - 11208576 + 11208578 id - 11208576 + 11208578 contents - 4294965 + 4294966 location - 11208576 + 11208578 @@ -26340,7 +26537,7 @@ 1 2 - 11208576 + 11208578 @@ -26356,7 +26553,7 @@ 1 2 - 11208576 + 11208578 @@ -26424,7 +26621,7 @@ 1 2 - 11208576 + 11208578 @@ -26440,7 +26637,7 @@ 1 2 - 11208576 + 11208578 @@ -26450,7 +26647,7 @@ commentbinding - 3905317 + 3905318 id @@ -26458,7 +26655,7 @@ element - 3740174 + 3740175 @@ -26472,7 +26669,7 @@ 1 2 - 3281208 + 3281209 2 @@ -26508,15 +26705,15 @@ exprconv - 9634074 + 9634075 converted - 9633969 + 9633970 conversion - 9634074 + 9634075 @@ -26530,7 +26727,7 @@ 1 2 - 9633863 + 9633864 2 @@ -26551,7 +26748,7 @@ 1 2 - 9634074 + 9634075 @@ -26561,22 +26758,22 @@ compgenerated - 9923438 + 9923218 id - 9923438 + 9923218 synthetic_destructor_call - 1666623 + 1666585 element - 1241183 + 1241154 i @@ -26584,7 +26781,7 @@ destructor_call - 1666623 + 1666585 @@ -26598,12 +26795,12 @@ 1 2 - 826168 + 826149 2 3 - 408236 + 408226 3 @@ -26624,12 +26821,12 @@ 1 2 - 826168 + 826149 2 3 - 408236 + 408226 3 @@ -26782,7 +26979,7 @@ 1 2 - 1666623 + 1666585 @@ -26798,7 +26995,7 @@ 1 2 - 1666623 + 1666585 @@ -26808,15 +27005,15 @@ namespaces - 8616 + 8615 id - 8616 + 8615 name - 4555 + 4554 @@ -26830,7 +27027,7 @@ 1 2 - 8616 + 8615 @@ -26846,12 +27043,12 @@ 1 2 - 3724 + 3723 2 3 - 526 + 525 3 @@ -26985,11 +27182,11 @@ exprparents - 19456296 + 19456298 expr_id - 19456296 + 19456298 child_index @@ -26997,7 +27194,7 @@ parent_id - 12941380 + 12941382 @@ -27011,7 +27208,7 @@ 1 2 - 19456296 + 19456298 @@ -27027,7 +27224,7 @@ 1 2 - 19456296 + 19456298 @@ -27145,7 +27342,7 @@ 1 2 - 7395565 + 7395566 2 @@ -27171,7 +27368,7 @@ 1 2 - 7395565 + 7395566 2 @@ -27191,22 +27388,22 @@ expr_isload - 6898025 + 6897613 expr_id - 6898025 + 6897613 conversionkinds - 6051177 + 6051176 expr_id - 6051177 + 6051176 kind @@ -27224,7 +27421,7 @@ 1 2 - 6051177 + 6051176 @@ -27268,8 +27465,8 @@ 1 - 5832067 - 5832068 + 5832066 + 5832067 1 @@ -27280,11 +27477,11 @@ iscall - 5790730 + 5790597 caller - 5790730 + 5790597 kind @@ -27302,7 +27499,7 @@ 1 2 - 5790730 + 5790597 @@ -27464,23 +27661,23 @@ namequalifiers - 3042541 + 3042471 id - 3042541 + 3042471 qualifiableelement - 3042541 + 3042471 qualifyingelement - 47728 + 47727 location - 554597 + 554584 @@ -27494,7 +27691,7 @@ 1 2 - 3042541 + 3042471 @@ -27510,7 +27707,7 @@ 1 2 - 3042541 + 3042471 @@ -27526,7 +27723,7 @@ 1 2 - 3042541 + 3042471 @@ -27542,7 +27739,7 @@ 1 2 - 3042541 + 3042471 @@ -27558,7 +27755,7 @@ 1 2 - 3042541 + 3042471 @@ -27574,7 +27771,7 @@ 1 2 - 3042541 + 3042471 @@ -27590,7 +27787,7 @@ 1 2 - 31447 + 31446 2 @@ -27600,7 +27797,7 @@ 3 5 - 4140 + 4139 5 @@ -27626,7 +27823,7 @@ 1 2 - 31447 + 31446 2 @@ -27636,7 +27833,7 @@ 3 5 - 4140 + 4139 5 @@ -27662,7 +27859,7 @@ 1 2 - 34665 + 34664 2 @@ -27693,22 +27890,22 @@ 1 2 - 79412 + 79410 2 6 - 41014 + 41013 6 7 - 397789 + 397780 7 192 - 36381 + 36380 @@ -27724,22 +27921,22 @@ 1 2 - 79412 + 79410 2 6 - 41014 + 41013 6 7 - 397789 + 397780 7 192 - 36381 + 36380 @@ -27755,22 +27952,22 @@ 1 2 - 114956 + 114953 2 4 - 13321 + 13320 4 5 - 414049 + 414040 5 33 - 12270 + 12269 @@ -27780,15 +27977,15 @@ varbind - 8255502 + 8255503 expr - 8255502 + 8255503 var - 1050486 + 1050487 @@ -27802,7 +27999,7 @@ 1 2 - 8255502 + 8255503 @@ -27873,15 +28070,15 @@ funbind - 5806003 + 5805870 expr - 5803536 + 5803403 fun - 275282 + 275275 @@ -27895,7 +28092,7 @@ 1 2 - 5801069 + 5800937 2 @@ -27916,12 +28113,12 @@ 1 2 - 181068 + 181064 2 3 - 38311 + 38310 3 @@ -27931,7 +28128,7 @@ 4 8 - 22931 + 22930 8 @@ -27946,11 +28143,11 @@ expr_allocator - 44948 + 44949 expr - 44948 + 44949 func @@ -27972,7 +28169,7 @@ 1 2 - 44948 + 44949 @@ -27988,7 +28185,7 @@ 1 2 - 44948 + 44949 @@ -28072,11 +28269,11 @@ expr_deallocator - 53477 + 53478 expr - 53477 + 53478 func @@ -28098,7 +28295,7 @@ 1 2 - 53477 + 53478 @@ -28114,7 +28311,7 @@ 1 2 - 53477 + 53478 @@ -28363,11 +28560,11 @@ values - 13541563 + 13541565 id - 13541563 + 13541565 str @@ -28385,7 +28582,7 @@ 1 2 - 13541563 + 13541565 @@ -28431,11 +28628,11 @@ valuetext - 6637568 + 6637657 id - 6637568 + 6637657 text @@ -28453,7 +28650,7 @@ 1 2 - 6637568 + 6637657 @@ -28483,7 +28680,7 @@ 7 - 593723 + 593719 27872 @@ -28494,15 +28691,15 @@ valuebind - 13649714 + 13649715 val - 13541563 + 13541565 expr - 13649714 + 13649715 @@ -28516,7 +28713,7 @@ 1 2 - 13451406 + 13451407 2 @@ -28537,7 +28734,7 @@ 1 2 - 13649714 + 13649715 @@ -28547,15 +28744,15 @@ fieldoffsets - 1500528 + 1502766 id - 1500528 + 1502766 byteoffset - 31369 + 31367 bitoffset @@ -28573,7 +28770,7 @@ 1 2 - 1500528 + 1502766 @@ -28589,7 +28786,7 @@ 1 2 - 1500528 + 1502766 @@ -28605,7 +28802,7 @@ 1 2 - 17700 + 17698 2 @@ -28620,22 +28817,22 @@ 5 12 - 2614 + 2613 12 35 - 2450 + 2396 35 - 211 + 200 2396 - 250 - 5971 - 1089 + 210 + 5988 + 1143 @@ -28651,7 +28848,7 @@ 1 2 - 30335 + 30333 2 @@ -28680,13 +28877,13 @@ 54 - 45 - 46 + 46 + 47 54 - 46 - 47 + 47 + 48 54 @@ -28695,18 +28892,18 @@ 54 - 65 - 66 + 67 + 68 54 - 82 - 83 + 84 + 85 54 - 27193 - 27194 + 27230 + 27231 54 @@ -28939,23 +29136,23 @@ initialisers - 2244830 + 2245206 init - 2244830 + 2245206 var - 978850 + 979091 expr - 2244830 + 2245206 location - 515724 + 515984 @@ -28969,7 +29166,7 @@ 1 2 - 2244830 + 2245206 @@ -28985,7 +29182,7 @@ 1 2 - 2244830 + 2245206 @@ -29001,7 +29198,7 @@ 1 2 - 2244830 + 2245206 @@ -29017,17 +29214,17 @@ 1 2 - 868820 + 869052 2 15 - 37292 + 37306 16 25 - 72737 + 72733 @@ -29043,17 +29240,17 @@ 1 2 - 868820 + 869052 2 15 - 37292 + 37306 16 25 - 72737 + 72733 @@ -29069,7 +29266,7 @@ 1 2 - 978842 + 979083 2 @@ -29090,7 +29287,7 @@ 1 2 - 2244830 + 2245206 @@ -29106,7 +29303,7 @@ 1 2 - 2244830 + 2245206 @@ -29122,7 +29319,7 @@ 1 2 - 2244830 + 2245206 @@ -29138,22 +29335,22 @@ 1 2 - 414197 + 414456 2 3 - 33502 + 33500 3 13 - 41940 + 41937 13 - 111925 - 26084 + 111939 + 26090 @@ -29169,17 +29366,17 @@ 1 2 - 443423 + 443688 2 3 - 34409 + 34407 3 - 12247 - 37891 + 12248 + 37889 @@ -29195,22 +29392,22 @@ 1 2 - 414197 + 414456 2 3 - 33502 + 33500 3 13 - 41940 + 41937 13 - 111925 - 26084 + 111939 + 26090 @@ -29220,26 +29417,26 @@ braced_initialisers - 67652 + 67650 init - 67652 + 67650 expr_ancestor - 1672586 + 1672548 exp - 1672586 + 1672548 ancestor - 837108 + 837089 @@ -29253,7 +29450,7 @@ 1 2 - 1672586 + 1672548 @@ -29269,17 +29466,17 @@ 1 2 - 17032 + 17031 2 3 - 810037 + 810018 3 19 - 10039 + 10038 @@ -29289,11 +29486,11 @@ exprs - 25213262 + 25213265 id - 25213262 + 25213265 kind @@ -29301,7 +29498,7 @@ location - 10586811 + 10586812 @@ -29315,7 +29512,7 @@ 1 2 - 25213262 + 25213265 @@ -29331,7 +29528,7 @@ 1 2 - 25213262 + 25213265 @@ -29509,7 +29706,7 @@ 1 2 - 8904644 + 8904645 2 @@ -29540,7 +29737,7 @@ 1 2 - 9044063 + 9044064 2 @@ -29560,15 +29757,15 @@ expr_reuse - 844466 + 844446 reuse - 844466 + 844446 original - 844466 + 844446 value_category @@ -29586,7 +29783,7 @@ 1 2 - 844466 + 844446 @@ -29602,7 +29799,7 @@ 1 2 - 844466 + 844446 @@ -29618,7 +29815,7 @@ 1 2 - 844466 + 844446 @@ -29634,7 +29831,7 @@ 1 2 - 844466 + 844446 @@ -29686,11 +29883,11 @@ expr_types - 25213262 + 25213265 id - 25213262 + 25213265 typeid @@ -29712,7 +29909,7 @@ 1 2 - 25213262 + 25213265 @@ -29728,7 +29925,7 @@ 1 2 - 25213262 + 25213265 @@ -29759,7 +29956,7 @@ 4 5 - 14530 + 14531 5 @@ -29881,7 +30078,7 @@ type_id - 27212 + 27213 @@ -29916,7 +30113,7 @@ 2 3 - 14384 + 14385 3 @@ -31341,15 +31538,15 @@ condition_decl_bind - 407678 + 407669 expr - 407678 + 407669 decl - 407678 + 407669 @@ -31363,7 +31560,7 @@ 1 2 - 407678 + 407669 @@ -31379,7 +31576,7 @@ 1 2 - 407678 + 407669 @@ -31389,11 +31586,11 @@ typeid_bind - 47588 + 47589 expr - 47588 + 47589 type_id @@ -31411,7 +31608,7 @@ 1 2 - 47588 + 47589 @@ -31447,15 +31644,15 @@ uuidof_bind - 26691 + 26787 expr - 26691 + 26787 type_id - 26440 + 26536 @@ -31469,7 +31666,7 @@ 1 2 - 26691 + 26787 @@ -31485,7 +31682,7 @@ 1 2 - 26229 + 26325 2 @@ -31631,11 +31828,11 @@ lambdas - 18998 + 18997 expr - 18998 + 18997 default_capture @@ -31661,7 +31858,7 @@ 1 2 - 18998 + 18997 @@ -31677,7 +31874,7 @@ 1 2 - 18998 + 18997 @@ -31693,7 +31890,7 @@ 1 2 - 18998 + 18997 @@ -31877,15 +32074,15 @@ lambda_capture - 31866 + 31864 id - 31866 + 31864 lambda - 15443 + 15442 index @@ -31893,7 +32090,7 @@ field - 31866 + 31864 captured_by_reference @@ -31905,7 +32102,7 @@ location - 17888 + 17887 @@ -31919,7 +32116,7 @@ 1 2 - 31866 + 31864 @@ -31935,7 +32132,7 @@ 1 2 - 31866 + 31864 @@ -31951,7 +32148,7 @@ 1 2 - 31866 + 31864 @@ -31967,7 +32164,7 @@ 1 2 - 31866 + 31864 @@ -31983,7 +32180,7 @@ 1 2 - 31866 + 31864 @@ -31999,7 +32196,7 @@ 1 2 - 31866 + 31864 @@ -32015,7 +32212,7 @@ 1 2 - 8187 + 8186 2 @@ -32025,7 +32222,7 @@ 3 4 - 1652 + 1651 4 @@ -32051,7 +32248,7 @@ 1 2 - 8187 + 8186 2 @@ -32061,7 +32258,7 @@ 3 4 - 1652 + 1651 4 @@ -32087,7 +32284,7 @@ 1 2 - 8187 + 8186 2 @@ -32097,7 +32294,7 @@ 3 4 - 1652 + 1651 4 @@ -32123,12 +32320,12 @@ 1 2 - 14204 + 14203 2 3 - 1239 + 1238 @@ -32144,7 +32341,7 @@ 1 2 - 15321 + 15320 2 @@ -32165,7 +32362,7 @@ 1 2 - 8778 + 8777 2 @@ -32627,7 +32824,7 @@ 1 2 - 31866 + 31864 @@ -32643,7 +32840,7 @@ 1 2 - 31866 + 31864 @@ -32659,7 +32856,7 @@ 1 2 - 31866 + 31864 @@ -32675,7 +32872,7 @@ 1 2 - 31866 + 31864 @@ -32691,7 +32888,7 @@ 1 2 - 31866 + 31864 @@ -32707,7 +32904,7 @@ 1 2 - 31866 + 31864 @@ -32965,7 +33162,7 @@ 1 2 - 15645 + 15644 2 @@ -32991,7 +33188,7 @@ 1 2 - 16220 + 16219 2 @@ -33017,7 +33214,7 @@ 1 2 - 17200 + 17199 2 @@ -33038,7 +33235,7 @@ 1 2 - 15645 + 15644 2 @@ -33064,7 +33261,7 @@ 1 2 - 17864 + 17863 2 @@ -33085,7 +33282,7 @@ 1 2 - 17888 + 17887 @@ -33221,11 +33418,11 @@ stmts - 6349665 + 6349367 id - 6349665 + 6349367 kind @@ -33233,7 +33430,7 @@ location - 2676171 + 2676092 @@ -33247,7 +33444,7 @@ 1 2 - 6349665 + 6349367 @@ -33263,7 +33460,7 @@ 1 2 - 6349665 + 6349367 @@ -33362,13 +33559,13 @@ 8 - 119906 - 119907 + 119911 + 119912 8 - 200140 - 200141 + 200145 + 200146 8 @@ -33473,13 +33670,13 @@ 8 - 49040 - 49041 + 49045 + 49046 8 - 86406 - 86407 + 86411 + 86412 8 @@ -33501,22 +33698,22 @@ 1 2 - 2218098 + 2218046 2 3 - 181666 + 181655 3 10 - 201547 + 201535 10 1789 - 74859 + 74855 @@ -33532,12 +33729,12 @@ 1 2 - 2593464 + 2593391 2 10 - 82706 + 82701 @@ -33750,15 +33947,15 @@ if_else - 435779 + 435769 if_stmt - 435779 + 435769 else_id - 435779 + 435769 @@ -33772,7 +33969,7 @@ 1 2 - 435779 + 435769 @@ -33788,7 +33985,7 @@ 1 2 - 435779 + 435769 @@ -34182,11 +34379,11 @@ switch_case - 833612 + 833592 switch_stmt - 410617 + 410607 index @@ -34194,7 +34391,7 @@ case_id - 833612 + 833592 @@ -34213,7 +34410,7 @@ 2 3 - 407742 + 407733 3 @@ -34239,7 +34436,7 @@ 2 3 - 407742 + 407733 3 @@ -34402,7 +34599,7 @@ 1 2 - 833612 + 833592 @@ -34418,7 +34615,7 @@ 1 2 - 833612 + 833592 @@ -34428,15 +34625,15 @@ switch_body - 410617 + 410607 switch_stmt - 410617 + 410607 body_id - 410617 + 410607 @@ -34450,7 +34647,7 @@ 1 2 - 410617 + 410607 @@ -34466,7 +34663,7 @@ 1 2 - 410617 + 410607 @@ -34668,19 +34865,19 @@ stmtparents - 5611103 + 5610809 id - 5611103 + 5610809 index - 15726 + 15725 parent - 2374344 + 2374243 @@ -34694,7 +34891,7 @@ 1 2 - 5611103 + 5610809 @@ -34710,7 +34907,7 @@ 1 2 - 5611103 + 5610809 @@ -34770,7 +34967,7 @@ 78 - 209703 + 209708 898 @@ -34831,7 +35028,7 @@ 78 - 209703 + 209708 898 @@ -34848,32 +35045,32 @@ 1 2 - 1355059 + 1355019 2 3 - 515764 + 515733 3 4 - 151047 + 151038 4 6 - 155242 + 155232 6 16 - 178313 + 178303 16 1943 - 18917 + 18916 @@ -34889,32 +35086,32 @@ 1 2 - 1355059 + 1355019 2 3 - 515764 + 515733 3 4 - 151047 + 151038 4 6 - 155242 + 155232 6 16 - 178313 + 178303 16 1943 - 18917 + 18916 @@ -34924,22 +35121,22 @@ ishandler - 43218 + 43224 block - 43218 + 43224 stmt_decl_bind - 723620 + 723577 stmt - 713084 + 713042 num @@ -34947,7 +35144,7 @@ decl - 723620 + 723577 @@ -34961,12 +35158,12 @@ 1 2 - 705642 + 705600 2 10 - 7442 + 7441 @@ -34982,12 +35179,12 @@ 1 2 - 705642 + 705600 2 10 - 7442 + 7441 @@ -35115,7 +35312,7 @@ 1 2 - 723620 + 723577 @@ -35131,7 +35328,7 @@ 1 2 - 723620 + 723577 @@ -35141,11 +35338,11 @@ stmt_decl_entry_bind - 723620 + 723577 stmt - 713084 + 713042 num @@ -35153,7 +35350,7 @@ decl_entry - 723620 + 723577 @@ -35167,12 +35364,12 @@ 1 2 - 705642 + 705600 2 10 - 7442 + 7441 @@ -35188,12 +35385,12 @@ 1 2 - 705642 + 705600 2 10 - 7442 + 7441 @@ -35321,7 +35518,7 @@ 1 2 - 723620 + 723577 @@ -35337,7 +35534,7 @@ 1 2 - 723620 + 723577 @@ -35385,7 +35582,7 @@ 1 2 - 1291401 + 1291402 2 @@ -35586,11 +35783,11 @@ preprocdirects - 5395214 + 5395215 id - 5395214 + 5395215 kind @@ -35598,7 +35795,7 @@ location - 5392103 + 5392104 @@ -35612,7 +35809,7 @@ 1 2 - 5395214 + 5395215 @@ -35628,7 +35825,7 @@ 1 2 - 5395214 + 5395215 @@ -35797,7 +35994,7 @@ 1 2 - 5392103 + 5392104 @@ -35887,11 +36084,11 @@ preproctext - 4341758 + 4341759 id - 4341758 + 4341759 head @@ -35913,7 +36110,7 @@ 1 2 - 4341758 + 4341759 @@ -35929,7 +36126,7 @@ 1 2 - 4341758 + 4341759 @@ -35950,7 +36147,7 @@ 2 798 - 198121 + 198122 @@ -35987,7 +36184,7 @@ 1 2 - 1531462 + 1531463 2 @@ -36033,15 +36230,15 @@ includes - 317365 + 317338 id - 317365 + 317338 included - 58461 + 58456 @@ -36055,7 +36252,7 @@ 1 2 - 317365 + 317338 @@ -36071,17 +36268,17 @@ 1 2 - 28930 + 28928 2 3 - 9405 + 9404 3 4 - 4934 + 4933 4 @@ -36207,11 +36404,11 @@ link_parent - 30224721 + 30225171 element - 3843710 + 3843767 link_target @@ -36229,17 +36426,17 @@ 1 2 - 527062 + 527070 2 9 - 26772 + 26773 9 10 - 3289875 + 3289924 diff --git a/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/in_trap_or_tag.ql b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/in_trap_or_tag.ql new file mode 100644 index 000000000000..331806e01fd3 --- /dev/null +++ b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/in_trap_or_tag.ql @@ -0,0 +1,11 @@ +class Element extends @element { + string toString() { none() } +} + +class Trap extends @trap { + string toString() { none() } +} + +from Element e, Trap trap +where in_trap(e, trap) +select e, trap diff --git a/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/old.dbscheme b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/old.dbscheme new file mode 100644 index 000000000000..7e7c2f55670f --- /dev/null +++ b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/old.dbscheme @@ -0,0 +1,2517 @@ + +/*- Compilations -*/ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * Optionally, record the build mode for each compilation. + */ +compilation_build_mode( + unique int id : @compilation ref, + int mode : int ref +); + +/* +case @compilation_build_mode.mode of + 0 = @build_mode_none +| 1 = @build_mode_manual +| 2 = @build_mode_auto +; +*/ + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- C++ dbscheme -*/ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +/** + * Gives the TRAP filename that `trap` is associated with. + * For debugging only. + */ +trap_filename( + int trap: @trap, + string filename: string ref +); + +/** + * In `build-mode: none` overlay mode, indicates that `source_file` + * (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the + * TRAP file corresponding to `foo.c`, something it transitively + * includes, or a template instantiation it transitively uses. + */ +source_file_uses_trap( + string source_file: string ref, + int trap_file: @trap ref +); + +/** + * Holds if there is a definition of `element` in TRAP file `trap_file`. + */ +in_trap( + int element: @element ref, + int trap_file: @trap ref +); + +pch_uses( + int pch: @pch ref, + int compilation: @compilation ref, + int id: @file ref +) + +#keyset[pch, compilation] +pch_creations( + int pch: @pch, + int compilation: @compilation ref, + int from: @file ref +) + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +case @macroinvocation.kind of + 1 = @macro_expansion +| 2 = @other_macro_reference +; + +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location_default ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +case @function.kind of + 0 = @unknown_function +| 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +// ... 6 = @builtin_function deprecated // GCC built-in functions, e.g. __builtin___memcpy_chk +| 7 = @user_defined_literal +| 8 = @deduction_guide +; + +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +builtin_functions( + int id: @function ref +) + +function_entry_point( + int id: @function ref, + unique int entry_point: @stmt ref +); + +function_return_type( + int id: @function ref, + int return_type: @type ref +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref +); + +/* +case @coroutine_placeholder_variable.kind of + 1 = @handle +| 2 = @promise +| 3 = @init_await_resume +; +*/ + +coroutine_placeholder_variable( + unique int placeholder_variable: @variable ref, + int kind: int ref, + int function: @function ref +) + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +function_prototyped(unique int id: @function ref) + +deduction_guide_for_class( + int id: @function ref, + int class_template: @usertype ref +) + +member_function_this_type( + unique int id: @function ref, + int this_type: @type ref +); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +/* +case @fun_requires.kind of + 1 = @template_attached +| 2 = @function_attached +; +*/ + +fun_requires( + int id: @fun_decl ref, + int kind: int ref, + int constraint: @expr ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_specialized(int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable ref); +var_requires( + int id: @var_decl ref, + int constraint: @expr ref +); + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); +type_requires( + int id: @type_decl ref, + int constraint: @expr ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +case @using.kind of + 1 = @using_declaration +| 2 = @using_directive +| 3 = @using_enum_declaration +; + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref, + int kind: int ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @parameterized_element ref, + int index: int ref, + int type_id: @type ref +); + +overrides( + int new: @function ref, + int old: @function ref +); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function ref +) + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/** + * Built-in types are the fundamental types, e.g., integral, floating, and void. + */ +case @builtintype.kind of + 1 = @errortype +| 2 = @unknowntype +| 3 = @void +| 4 = @boolean +| 5 = @char +| 6 = @unsigned_char +| 7 = @signed_char +| 8 = @short +| 9 = @unsigned_short +| 10 = @signed_short +| 11 = @int +| 12 = @unsigned_int +| 13 = @signed_int +| 14 = @long +| 15 = @unsigned_long +| 16 = @signed_long +| 17 = @long_long +| 18 = @unsigned_long_long +| 19 = @signed_long_long +// ... 20 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +// ... 40 _Decimal32 +// ... 41 _Decimal64 +// ... 42 _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +// ... 50 _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +| 54 = @fp16 // __fp16 +| 55 = @std_bfloat16 // __bf16 +| 56 = @std_float16 // std::float16_t +| 57 = @complex_std_float32 // _Complex _Float32 +| 58 = @complex_float32x // _Complex _Float32x +| 59 = @complex_std_float64 // _Complex _Float64 +| 60 = @complex_float64x // _Complex _Float64x +| 61 = @complex_std_float128 // _Complex _Float128 +| 62 = @mfp8 // __mfp8 +| 63 = @scalable_vector_count // __SVCount_t +| 64 = @complex_fp16 // _Complex __fp16 +| 65 = @complex_std_bfloat16 // _Complex __bf16 +| 66 = @complex_std_float16 // _Complex std::float16_t +; + +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/** + * Derived types are types that are directly derived from existing types and + * point to, refer to, transform type data to return a new type. + */ +case @derivedtype.kind of + 1 = @pointer +| 2 = @reference +| 3 = @type_with_specifiers +| 4 = @array +| 5 = @gnu_vector +| 6 = @routineptr +| 7 = @routinereference +| 8 = @rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated +| 10 = @block +| 11 = @scalable_vector // Arm SVE +; + +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +tupleelements( + unique int id: @derivedtype ref, + int num_elements: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator or C23 `typeof`/`typeof_unqual` + * operator taking an expression as its argument. For example: + * ``` + * int a; + * decltype(1+a) b; + * typeof(1+a) c; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * changes the semantics of the decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ + +/* +case @decltype.kind of +| 0 = @decltype +| 1 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +; +*/ + +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int kind: int ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +case @type_operator.kind of + 0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +| 1 = @underlying_type +| 2 = @bases +| 3 = @direct_bases +| 4 = @add_lvalue_reference +| 5 = @add_pointer +| 6 = @add_rvalue_reference +| 7 = @decay +| 8 = @make_signed +| 9 = @make_unsigned +| 10 = @remove_all_extents +| 11 = @remove_const +| 12 = @remove_cv +| 13 = @remove_cvref +| 14 = @remove_extent +| 15 = @remove_pointer +| 16 = @remove_reference_t +| 17 = @remove_restrict +| 18 = @remove_volatile +| 19 = @remove_reference +; + +type_operators( + unique int id: @type_operator, + int arg_type: @type ref, + int kind: int ref, + int base_type: @type ref +) + +case @usertype.kind of + 0 = @unknown_usertype +| 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +// ... 5 = @typedef deprecated // classic C: typedef typedef type name +// ... 6 = @template deprecated +| 7 = @template_parameter +| 8 = @template_template_parameter +| 9 = @proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated +| 13 = @scoped_enum +// ... 14 = @using_alias deprecated // a using name = type style typedef +| 15 = @template_struct +| 16 = @template_class +| 17 = @template_union +| 18 = @alias +; + +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + string uuid: string ref +); + +/* +case @usertype.alias_kind of +| 0 = @typedef +| 1 = @alias +*/ + +usertype_alias_kind( + int id: @usertype ref, + int alias_kind: int ref +) + +nontype_template_parameters( + int id: @expr ref +); + +type_template_type_constraint( + int id: @usertype ref, + int constraint: @expr ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname, + boolean is_complete: boolean ref +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@user_or_decltype = @usertype | @decltype; + +is_proxy_class_for( + unique int id: @usertype ref, + int templ_param_id: @user_or_decltype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location_default ref, + // a_symbol_reference_kind from the frontend. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +template_template_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +template_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +template_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@concept = @concept_template | @concept_id; + +concept_templates( + unique int concept_id: @concept_template, + string name: string ref, + int location: @location_default ref +); +concept_instantiation( + unique int to: @concept_id ref, + int from: @concept_template ref +); +is_type_constraint(int concept_id: @concept_id ref); +concept_template_argument( + int concept_id: @concept ref, + int index: int ref, + int arg_type: @type ref +); +concept_template_argument_value( + int concept_id: @concept ref, + int index: int ref, + int arg_value: @expr ref +); + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +explicit_specifier_exprs( + unique int func_id: @function ref, + int constant: @expr ref +) + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +| 4 = @attribute_arg_constant_expr +| 5 = @attribute_arg_expr +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_constant( + unique int arg: @attribute_arg ref, + int constant: @expr ref +) +attribute_arg_expr( + unique int arg: @attribute_arg ref, + int expr: @expr ref +) +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +namespaceattributes( + int namespace_id: @namespace ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + | @routinetype + | @ptrtomember + | @decltype + | @type_operator; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl + | @concept_template; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + | @c11_generic + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall( + unique int caller: @funbindexpr ref, + int kind: int ref +); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype + | @decltype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + ; + +@assign_pointer_expr = @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr + | @assign_bitwise_expr + | @assign_pointer_expr + ; + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + Binary encoding of the allocator form. + + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + Binary encoding of the deallocator form. + + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 4 = destroying_delete + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_default ref +); + +braced_initialisers( + int init: @initialiser ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_default ref +); + +expr_reuse( + int reuse: @expr ref, + int original: @expr ref, + int value_category: int ref +) + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // frontend internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +| 363 = @reuseexpr +| 364 = @istriviallycopyassignable +| 365 = @isassignablenopreconditioncheck +| 366 = @referencebindstotemporary +| 367 = @issameas +| 368 = @builtinhasattribute +| 369 = @ispointerinterconvertiblewithclass +| 370 = @builtinispointerinterconvertiblewithclass +| 371 = @iscorrespondingmember +| 372 = @builtiniscorrespondingmember +| 373 = @isboundedarray +| 374 = @isunboundedarray +| 375 = @isreferenceable +| 378 = @isnothrowconvertible +| 379 = @referenceconstructsfromtemporary +| 380 = @referenceconvertsfromtemporary +| 381 = @isconvertible +| 382 = @isvalidwinrttype +| 383 = @iswinclass +| 384 = @iswininterface +| 385 = @istriviallyequalitycomparable +| 386 = @isscopedenum +| 387 = @istriviallyrelocatable +| 388 = @datasizeof +| 389 = @c11_generic +| 390 = @requires_expr +| 391 = @nested_requirement +| 392 = @compound_requirement +| 393 = @concept_id +| 394 = @isinvocable +| 395 = @isnothrowinvocable +| 396 = @isbitwisecloneable +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @istrivialexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + | @istriviallycopyassignable + | @isassignablenopreconditioncheck + | @referencebindstotemporary + | @issameas + | @builtinhasattribute + | @ispointerinterconvertiblewithclass + | @builtinispointerinterconvertiblewithclass + | @iscorrespondingmember + | @builtiniscorrespondingmember + | @isboundedarray + | @isunboundedarray + | @isreferenceable + | @isnothrowconvertible + | @referenceconstructsfromtemporary + | @referenceconvertsfromtemporary + | @isconvertible + | @isvalidwinrttype + | @iswinclass + | @iswininterface + | @istriviallyequalitycomparable + | @isscopedenum + | @istriviallyrelocatable + | @isinvocable + | @isnothrowinvocable + | @isbitwisecloneable + ; + +compound_requirement_is_noexcept( + int expr: @compound_requirement ref +); + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +param_ref_to_this( + int expr: @param_ref ref +) + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref, + int position: int ref, + boolean is_designated: boolean ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref, + int position: int ref, + boolean is_designated: boolean ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof | @sizeof_pack; + +sizeof_bind( + unique int expr: @sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref, + boolean has_explicit_parameter_list: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_default ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +| 38 = @stmt_consteval_if +| 39 = @stmt_not_consteval_if +| 40 = @stmt_leave +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +type_is_vla(unique int type_id: @derivedtype ref) + +if_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +@stmt_consteval_or_not_consteval_if = @stmt_consteval_if | @stmt_not_consteval_if; + +consteval_if_then( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int then_id: @stmt ref +); + +consteval_if_else( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +@stmt_for_or_range_based_for = @stmt_for + | @stmt_range_based_for; + +for_initialization( + unique int for_stmt: @stmt_for_or_range_based_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@parameterized_element = @function | @stmt_block | @requires_expr; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @parameterized_element ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue | @stmt_leave; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 14 = @ppd_ms_import +| 15 = @ppd_elifdef +| 16 = @ppd_elifndef +| 17 = @ppd_embed +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +embeds( + unique int id: @ppd_embed ref, + int included: @file ref +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/*- Database metadata -*/ + +/** + * The CLI will automatically emit applicable tuples for this table, + * such as `databaseMetadata("isOverlay", "true")` when building an + * overlay database. + */ +databaseMetadata( + string metadataKey: string ref, + string value: string ref +); + +/*- Overlay support -*/ + +/** + * The CLI will automatically emit tuples for each new/modified/deleted file + * when building an overlay database. + */ +overlayChangedFiles( + string path: string ref +); + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; diff --git a/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/semmlecode.cpp.dbscheme b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/semmlecode.cpp.dbscheme new file mode 100644 index 000000000000..770002bb0232 --- /dev/null +++ b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/semmlecode.cpp.dbscheme @@ -0,0 +1,2545 @@ + +/*- Compilations -*/ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * Optionally, record the build mode for each compilation. + */ +compilation_build_mode( + unique int id : @compilation ref, + int mode : int ref +); + +/* +case @compilation_build_mode.mode of + 0 = @build_mode_none +| 1 = @build_mode_manual +| 2 = @build_mode_auto +; +*/ + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/*- External data -*/ + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/*- Source location prefix -*/ + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/*- Files and folders -*/ + +/** + * The location of an element. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @file | @folder + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/*- Lines of code -*/ + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +/*- Diagnostic messages -*/ + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/*- C++ dbscheme -*/ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +/** + * Gives the TRAP filename that `trap` is associated with. + * For debugging only. + */ +trap_filename( + int trap: @trap, + string filename: string ref +); + +/** + * Gives the tag name for `tag`. + * For debugging only. + */ +tag_name( + int tag: @tag, + string name: string ref +); + +@trap_or_tag = @tag | @trap; + +/** + * Gives the name for the source file. + */ +source_file_name( + int sf: @source_file, + string name: string ref +); + +/** + * In `build-mode: none` overlay mode, indicates that `source_file` + * (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the + * TRAP file corresponding to `foo.c`, something it transitively + * includes, or a template instantiation it transitively uses. + */ +source_file_uses_trap( + int source_file: @source_file ref, + int trap_file: @trap ref +); + +/** + * In `build-mode: none` overlay mode, indicates that the TRAP file + * `trap_file` uses tag `tag`. + */ +trap_uses_tag( + int trap_file: @trap ref, + int tag: @tag ref +); + +/** + * Holds if there is a definition of `element` in TRAP file or tag `t`. + */ +in_trap_or_tag( + int element: @element ref, + int t: @trap_or_tag ref +); + +pch_uses( + int pch: @pch ref, + int compilation: @compilation ref, + int id: @file ref +) + +#keyset[pch, compilation] +pch_creations( + int pch: @pch, + int compilation: @compilation ref, + int from: @file ref +) + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +case @macroinvocation.kind of + 1 = @macro_expansion +| 2 = @other_macro_reference +; + +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location_default ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +case @function.kind of + 0 = @unknown_function +| 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +// ... 6 = @builtin_function deprecated // GCC built-in functions, e.g. __builtin___memcpy_chk +| 7 = @user_defined_literal +| 8 = @deduction_guide +; + +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +builtin_functions( + int id: @function ref +) + +function_entry_point( + int id: @function ref, + unique int entry_point: @stmt ref +); + +function_return_type( + int id: @function ref, + int return_type: @type ref +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref +); + +/* +case @coroutine_placeholder_variable.kind of + 1 = @handle +| 2 = @promise +| 3 = @init_await_resume +; +*/ + +coroutine_placeholder_variable( + unique int placeholder_variable: @variable ref, + int kind: int ref, + int function: @function ref +) + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +function_prototyped(unique int id: @function ref) + +deduction_guide_for_class( + int id: @function ref, + int class_template: @usertype ref +) + +member_function_this_type( + unique int id: @function ref, + int this_type: @type ref +); + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +/* +case @fun_requires.kind of + 1 = @template_attached +| 2 = @function_attached +; +*/ + +fun_requires( + int id: @fun_decl ref, + int kind: int ref, + int constraint: @expr ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_specialized(int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable ref); +var_requires( + int id: @var_decl ref, + int constraint: @expr ref +); + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); +type_requires( + int id: @type_decl ref, + int constraint: @expr ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +case @using.kind of + 1 = @using_declaration +| 2 = @using_directive +| 3 = @using_enum_declaration +; + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref, + int kind: int ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref, + int enclosing : @element ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @parameterized_element ref, + int index: int ref, + int type_id: @type ref +); + +overrides( + int new: @function ref, + int old: @function ref +); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function ref +) + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/** + * Built-in types are the fundamental types, e.g., integral, floating, and void. + */ +case @builtintype.kind of + 1 = @errortype +| 2 = @unknowntype +| 3 = @void +| 4 = @boolean +| 5 = @char +| 6 = @unsigned_char +| 7 = @signed_char +| 8 = @short +| 9 = @unsigned_short +| 10 = @signed_short +| 11 = @int +| 12 = @unsigned_int +| 13 = @signed_int +| 14 = @long +| 15 = @unsigned_long +| 16 = @signed_long +| 17 = @long_long +| 18 = @unsigned_long_long +| 19 = @signed_long_long +// ... 20 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +// ... 40 _Decimal32 +// ... 41 _Decimal64 +// ... 42 _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +// ... 50 _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +| 54 = @fp16 // __fp16 +| 55 = @std_bfloat16 // __bf16 +| 56 = @std_float16 // std::float16_t +| 57 = @complex_std_float32 // _Complex _Float32 +| 58 = @complex_float32x // _Complex _Float32x +| 59 = @complex_std_float64 // _Complex _Float64 +| 60 = @complex_float64x // _Complex _Float64x +| 61 = @complex_std_float128 // _Complex _Float128 +| 62 = @mfp8 // __mfp8 +| 63 = @scalable_vector_count // __SVCount_t +| 64 = @complex_fp16 // _Complex __fp16 +| 65 = @complex_std_bfloat16 // _Complex __bf16 +| 66 = @complex_std_float16 // _Complex std::float16_t +; + +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/** + * Derived types are types that are directly derived from existing types and + * point to, refer to, transform type data to return a new type. + */ +case @derivedtype.kind of + 1 = @pointer +| 2 = @reference +| 3 = @type_with_specifiers +| 4 = @array +| 5 = @gnu_vector +| 6 = @routineptr +| 7 = @routinereference +| 8 = @rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated +| 10 = @block +| 11 = @scalable_vector // Arm SVE +; + +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +tupleelements( + unique int id: @derivedtype ref, + int num_elements: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator or C23 `typeof`/`typeof_unqual` + * operator taking an expression as its argument. For example: + * ``` + * int a; + * decltype(1+a) b; + * typeof(1+a) c; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * changes the semantics of the decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ + +/* +case @decltype.kind of +| 0 = @decltype +| 1 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +; +*/ + +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int kind: int ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +case @type_operator.kind of + 0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual +| 1 = @underlying_type +| 2 = @bases +| 3 = @direct_bases +| 4 = @add_lvalue_reference +| 5 = @add_pointer +| 6 = @add_rvalue_reference +| 7 = @decay +| 8 = @make_signed +| 9 = @make_unsigned +| 10 = @remove_all_extents +| 11 = @remove_const +| 12 = @remove_cv +| 13 = @remove_cvref +| 14 = @remove_extent +| 15 = @remove_pointer +| 16 = @remove_reference_t +| 17 = @remove_restrict +| 18 = @remove_volatile +| 19 = @remove_reference +; + +type_operators( + unique int id: @type_operator, + int arg_type: @type ref, + int kind: int ref, + int base_type: @type ref +) + +case @usertype.kind of + 0 = @unknown_usertype +| 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +// ... 5 = @typedef deprecated // classic C: typedef typedef type name +// ... 6 = @template deprecated +| 7 = @template_parameter +| 8 = @template_template_parameter +| 9 = @proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated +| 13 = @scoped_enum +// ... 14 = @using_alias deprecated // a using name = type style typedef +| 15 = @template_struct +| 16 = @template_class +| 17 = @template_union +| 18 = @alias +; + +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + string uuid: string ref +); + +/* +case @usertype.alias_kind of +| 0 = @typedef +| 1 = @alias +*/ + +usertype_alias_kind( + int id: @usertype ref, + int alias_kind: int ref +) + +nontype_template_parameters( + int id: @expr ref +); + +type_template_type_constraint( + int id: @usertype ref, + int constraint: @expr ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname, + boolean is_complete: boolean ref +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@user_or_decltype = @usertype | @decltype; + +is_proxy_class_for( + unique int id: @usertype ref, + int templ_param_id: @user_or_decltype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location_default ref, + // a_symbol_reference_kind from the frontend. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +template_template_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +template_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +template_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +@concept = @concept_template | @concept_id; + +concept_templates( + unique int concept_id: @concept_template, + string name: string ref, + int location: @location_default ref +); +concept_instantiation( + unique int to: @concept_id ref, + int from: @concept_template ref +); +is_type_constraint(int concept_id: @concept_id ref); +concept_template_argument( + int concept_id: @concept ref, + int index: int ref, + int arg_type: @type ref +); +concept_template_argument_value( + int concept_id: @concept ref, + int index: int ref, + int arg_value: @expr ref +); + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +explicit_specifier_exprs( + unique int func_id: @function ref, + int constant: @expr ref +) + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +| 4 = @attribute_arg_constant_expr +| 5 = @attribute_arg_expr +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_constant( + unique int arg: @attribute_arg ref, + int constant: @expr ref +) +attribute_arg_expr( + unique int arg: @attribute_arg ref, + int expr: @expr ref +) +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +namespaceattributes( + int namespace_id: @namespace ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + | @routinetype + | @ptrtomember + | @decltype + | @type_operator; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl + | @concept_template; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + | @c11_generic + ; + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall( + unique int caller: @funbindexpr ref, + int kind: int ref +); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype + | @decltype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + ; + +@assign_pointer_expr = @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr + | @assign_bitwise_expr + | @assign_pointer_expr + ; + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + Binary encoding of the allocator form. + + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + Binary encoding of the deallocator form. + + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 4 = destroying_delete + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_default ref +); + +braced_initialisers( + int init: @initialiser ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_default ref +); + +expr_reuse( + int reuse: @expr ref, + int original: @expr ref, + int value_category: int ref +) + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // frontend internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +| 363 = @reuseexpr +| 364 = @istriviallycopyassignable +| 365 = @isassignablenopreconditioncheck +| 366 = @referencebindstotemporary +| 367 = @issameas +| 368 = @builtinhasattribute +| 369 = @ispointerinterconvertiblewithclass +| 370 = @builtinispointerinterconvertiblewithclass +| 371 = @iscorrespondingmember +| 372 = @builtiniscorrespondingmember +| 373 = @isboundedarray +| 374 = @isunboundedarray +| 375 = @isreferenceable +| 378 = @isnothrowconvertible +| 379 = @referenceconstructsfromtemporary +| 380 = @referenceconvertsfromtemporary +| 381 = @isconvertible +| 382 = @isvalidwinrttype +| 383 = @iswinclass +| 384 = @iswininterface +| 385 = @istriviallyequalitycomparable +| 386 = @isscopedenum +| 387 = @istriviallyrelocatable +| 388 = @datasizeof +| 389 = @c11_generic +| 390 = @requires_expr +| 391 = @nested_requirement +| 392 = @compound_requirement +| 393 = @concept_id +| 394 = @isinvocable +| 395 = @isnothrowinvocable +| 396 = @isbitwisecloneable +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @istrivialexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + | @istriviallycopyassignable + | @isassignablenopreconditioncheck + | @referencebindstotemporary + | @issameas + | @builtinhasattribute + | @ispointerinterconvertiblewithclass + | @builtinispointerinterconvertiblewithclass + | @iscorrespondingmember + | @builtiniscorrespondingmember + | @isboundedarray + | @isunboundedarray + | @isreferenceable + | @isnothrowconvertible + | @referenceconstructsfromtemporary + | @referenceconvertsfromtemporary + | @isconvertible + | @isvalidwinrttype + | @iswinclass + | @iswininterface + | @istriviallyequalitycomparable + | @isscopedenum + | @istriviallyrelocatable + | @isinvocable + | @isnothrowinvocable + | @isbitwisecloneable + ; + +compound_requirement_is_noexcept( + int expr: @compound_requirement ref +); + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +param_ref_to_this( + int expr: @param_ref ref +) + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref, + int position: int ref, + boolean is_designated: boolean ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref, + int position: int ref, + boolean is_designated: boolean ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof | @sizeof_pack; + +sizeof_bind( + unique int expr: @sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref, + boolean has_explicit_parameter_list: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +@access = @varaccess | @routineexpr ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_default ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +| 37 = @stmt_co_return +| 38 = @stmt_consteval_if +| 39 = @stmt_not_consteval_if +| 40 = @stmt_leave +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +type_is_vla(unique int type_id: @derivedtype ref) + +if_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +@stmt_consteval_or_not_consteval_if = @stmt_consteval_if | @stmt_not_consteval_if; + +consteval_if_then( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int then_id: @stmt ref +); + +consteval_if_else( + unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +@stmt_for_or_range_based_for = @stmt_for + | @stmt_range_based_for; + +for_initialization( + unique int for_stmt: @stmt_for_or_range_based_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@parameterized_element = @function | @stmt_block | @requires_expr; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @parameterized_element ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue | @stmt_leave; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 14 = @ppd_ms_import +| 15 = @ppd_elifdef +| 16 = @ppd_elifndef +| 17 = @ppd_embed +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +embeds( + unique int id: @ppd_embed ref, + int included: @file ref +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/*- Database metadata -*/ + +/** + * The CLI will automatically emit applicable tuples for this table, + * such as `databaseMetadata("isOverlay", "true")` when building an + * overlay database. + */ +databaseMetadata( + string metadataKey: string ref, + string value: string ref +); + +/*- Overlay support -*/ + +/** + * The CLI will automatically emit tuples for each new/modified/deleted file + * when building an overlay database. + */ +overlayChangedFiles( + string path: string ref +); + +/*- XML Files -*/ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; diff --git a/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/source_files.ql b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/source_files.ql new file mode 100644 index 000000000000..19c08d64ece8 --- /dev/null +++ b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/source_files.ql @@ -0,0 +1,22 @@ +newtype TSourceFile = MkSourceFile(string name) { source_file_uses_trap(name, _) } + +module FreshSourceFile = QlBuiltins::NewEntity; + +class SourceFile extends FreshSourceFile::EntityId { + string toString() { none() } +} + +class Trap extends @trap { + string toString() { none() } +} + +query predicate mk_source_file_name(SourceFile source_file, string name) { + source_file = FreshSourceFile::map(MkSourceFile(name)) +} + +query predicate mk_source_file_uses_trap(SourceFile source_file, Trap trap) { + exists(string name | + source_file_uses_trap(name, trap) and + mk_source_file_name(source_file, name) + ) +} diff --git a/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/upgrade.properties b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/upgrade.properties new file mode 100644 index 000000000000..26400eeded84 --- /dev/null +++ b/cpp/ql/lib/upgrades/7e7c2f55670f8123d514cf542ccb1938118ac561/upgrade.properties @@ -0,0 +1,6 @@ +description: Add source_file_name +compatibility: backwards +source_file_uses_trap.rel: run source_files.ql mk_source_file_uses_trap +source_file_name.rel: run source_files.ql mk_source_file_name +in_trap.rel: delete +in_trap_or_tag.rel: run in_trap_or_tag.ql diff --git a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql index b4e517b3bab9..c85b33a9727a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql @@ -15,6 +15,7 @@ import cpp import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import semmle.code.cpp.ir.dataflow.DataFlow +private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes /** Gets a loop that contains `e`. */ Loop getAnEnclosingLoopOfExpr(Expr e) { result = getAnEnclosingLoopOfStmt(e.getEnclosingStmt()) } @@ -45,9 +46,9 @@ private Expr getExpr(DataFlow::Node node) { or result = node.asOperand().getUse().getAst() or - result = node.(DataFlow::RawIndirectInstruction).getInstruction().getAst() + result = node.(RawIndirectInstruction).getInstruction().getAst() or - result = node.(DataFlow::RawIndirectOperand).getOperand().getUse().getAst() + result = node.(RawIndirectOperand).getOperand().getUse().getAst() } /** @@ -208,7 +209,7 @@ class LoopWithAlloca extends Stmt { this.conditionRequiresInequality(va, _, _) and DataFlow::localFlow(result, DataFlow::exprNode(va)) and // Phi nodes will be preceded by nodes that represent actual definitions - not result instanceof DataFlow::SsaSynthNode and + not result instanceof SsaSynthNode and // A source is outside the loop if it's not inside the loop not exists(Expr e | e = getExpr(result) | this = getAnEnclosingLoopOfExpr(e)) ) diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index df5c3c92c42a..82056b71c4d2 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 1.5.12 +version: 1.5.13-dev groups: - cpp - queries diff --git a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll index f2c621d04cb6..90160df3c210 100644 --- a/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll +++ b/cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll @@ -8,6 +8,7 @@ private import semmle.code.cpp.dataflow.ExternalFlow as ExternalFlow private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as DataFlowPrivate +private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes as DataFlowNodes private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl private import semmle.code.cpp.ir.dataflow.internal.TaintTrackingImplSpecific private import semmle.code.cpp.dataflow.new.TaintTracking as Tt @@ -403,7 +404,7 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { } predicate apiSource(DataFlow::Node source) { - DataFlowPrivate::nodeHasOperand(source, any(DataFlow::FieldAddress fa), 1) + DataFlowPrivate::nodeHasOperand(source, any(DataFlowNodes::FieldAddress fa), 1) or source instanceof DataFlow::ParameterNode } @@ -416,7 +417,7 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig { result = "Argument[" + DataFlow::repeatStars(indirectionIndex) + argumentIndex + "]" ) or - DataFlowPrivate::nodeHasOperand(source, any(DataFlow::FieldAddress fa), 1) and + DataFlowPrivate::nodeHasOperand(source, any(DataFlowNodes::FieldAddress fa), 1) and result = qualifierString() } diff --git a/cpp/ql/test/library-tests/dataflow/fields/A.cpp b/cpp/ql/test/library-tests/dataflow/fields/A.cpp index a3a151576e54..d65fa7c543d0 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/A.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/A.cpp @@ -46,7 +46,7 @@ class A { C *c = new C(); B *b = B::make(c); - sink(b->c); // $ast,ir + sink(b->c); // $ ast,ir } void f2() diff --git a/cpp/ql/test/library-tests/dataflow/fields/C.cpp b/cpp/ql/test/library-tests/dataflow/fields/C.cpp index 96bbb25a3b67..6e5165caa9a1 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/C.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/C.cpp @@ -26,9 +26,9 @@ class C void func() { - sink(s1); // $ast,ir + sink(s1); // $ ast,ir sink(s2); // $ MISSING: ast,ir - sink(s3); // $ast,ir + sink(s3); // $ ast,ir sink(s4); // $ MISSING: ast,ir } }; diff --git a/cpp/ql/test/library-tests/dataflow/fields/D.cpp b/cpp/ql/test/library-tests/dataflow/fields/D.cpp index ee51e6e5428c..b2c882a69822 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/D.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/D.cpp @@ -19,7 +19,7 @@ class D { }; static void sinkWrap(Box2* b2) { - sink(b2->getBox1()->getElem()); // $ast,ir=28:15 ast,ir=35:15 ast,ir=42:15 ast,ir=49:15 + sink(b2->getBox1()->getElem()); // $ ast,ir=28:15 ast,ir=35:15 ast,ir=42:15 ast,ir=49:15 } Box2* boxfield; diff --git a/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp b/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp index d8c6a194151c..680b1489228a 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/by_reference.cpp @@ -48,25 +48,25 @@ struct S { void test_setDirectly() { S s; s.setDirectly(user_input()); - sink(s.getDirectly()); // $ast ir + sink(s.getDirectly()); // $ ast ir } void test_setIndirectly() { S s; s.setIndirectly(user_input()); - sink(s.getIndirectly()); // $ast ir + sink(s.getIndirectly()); // $ ast ir } void test_setThroughNonMember() { S s; s.setThroughNonMember(user_input()); - sink(s.getThroughNonMember()); // $ast ir + sink(s.getThroughNonMember()); // $ ast ir } void test_nonMemberSetA() { S s; nonMemberSetA(&s, user_input()); - sink(nonMemberGetA(&s)); // $ast,ir + sink(nonMemberGetA(&s)); // $ ast,ir } //////////////////// @@ -112,7 +112,7 @@ void test_outer_with_ptr(Outer *pouter) { sink(outer.a); // $ ast,ir sink(pouter->inner_nested.a); // $ ast,ir - sink(pouter->inner_ptr->a); // $ast,ir + sink(pouter->inner_ptr->a); // $ ast,ir sink(pouter->a); // $ ast,ir } diff --git a/cpp/ql/test/library-tests/dataflow/fields/simple.cpp b/cpp/ql/test/library-tests/dataflow/fields/simple.cpp index d220b416e1a9..fb598bd9d71e 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/simple.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/simple.cpp @@ -64,7 +64,7 @@ void single_field_test() A a; a.i = user_input(); A a2 = a; - sink(a2.i); //$ ast,ir + sink(a2.i); // $ ast,ir } struct C { @@ -81,7 +81,7 @@ struct C2 void m() { f2.f1 = user_input(); - sink(getf2f1()); //$ ast,ir + sink(getf2f1()); // $ ast,ir } }; @@ -91,7 +91,7 @@ void single_field_test_typedef(A_typedef a) { a.i = user_input(); A_typedef a2 = a; - sink(a2.i); //$ ast,ir + sink(a2.i); // $ ast,ir } namespace TestAdditionalCallTargets { @@ -168,4 +168,4 @@ void test_union_with_two_instantiations_of_different_sizes() { sink(u_int.y); // $ MISSING: ir } -} // namespace Simple \ No newline at end of file +} // namespace Simple diff --git a/cpp/ql/test/library-tests/dataflow/fields/struct_init.c b/cpp/ql/test/library-tests/dataflow/fields/struct_init.c index d2abfeefc086..2b6716a4bc3b 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/struct_init.c +++ b/cpp/ql/test/library-tests/dataflow/fields/struct_init.c @@ -12,14 +12,14 @@ struct Outer { }; void absink(struct AB *ab) { - sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20 + sink(ab->a); // $ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20 sink(ab->b); // no flow } int struct_init(void) { struct AB ab = { user_input(), 0 }; - sink(ab.a); //$ ast,ir + sink(ab.a); // $ ast,ir sink(ab.b); // no flow absink(&ab); @@ -28,9 +28,9 @@ int struct_init(void) { &ab, }; - sink(outer.nestedAB.a); //$ ast,ir + sink(outer.nestedAB.a); // $ ast,ir sink(outer.nestedAB.b); // no flow - sink(outer.pointerAB->a); //$ ast,ir + sink(outer.pointerAB->a); // $ ast,ir sink(outer.pointerAB->b); // no flow absink(&outer.nestedAB); diff --git a/cpp/ql/test/library-tests/dataflow/models-as-data/FlowSummaryNode.ql b/cpp/ql/test/library-tests/dataflow/models-as-data/FlowSummaryNode.ql index 399e2e129b3b..7b551515b460 100644 --- a/cpp/ql/test/library-tests/dataflow/models-as-data/FlowSummaryNode.ql +++ b/cpp/ql/test/library-tests/dataflow/models-as-data/FlowSummaryNode.ql @@ -1,6 +1,7 @@ import testModels private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes string describe(DataFlow::Node n) { n instanceof ParameterNode and result = "ParameterNode" diff --git a/cpp/ql/test/library-tests/dataflow/models-as-data/tests.cpp b/cpp/ql/test/library-tests/dataflow/models-as-data/tests.cpp index 92397bc91c34..cb2bf9650835 100644 --- a/cpp/ql/test/library-tests/dataflow/models-as-data/tests.cpp +++ b/cpp/ql/test/library-tests/dataflow/models-as-data/tests.cpp @@ -75,7 +75,7 @@ void test_sources() { int e = localMadSource(); sink(e); // $ ir - sink(MyNamespace::namespaceLocalMadSource()); // $: ir + sink(MyNamespace::namespaceLocalMadSource()); // $ ir sink(MyNamespace::namespaceLocalMadSourceVar); // $ ir sink(MyNamespace::MyNamespace2::namespace2LocalMadSource()); // $ ir sink(MyNamespace::localMadSource()); // $ (the MyNamespace version of this function is not a source) @@ -475,4 +475,4 @@ void test_receive_array() { int array[10] = {x}; int y = receive_array(array); sink(y); // $ ir -} \ No newline at end of file +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 70d5b8c7b001..fa32e192239b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -450,7 +450,7 @@ void test_qualifiers() b.member = source(); sink(b); // $ ir MISSING: ast sink(b.member); // $ ast,ir - sink(b.getMember()); // $ MISSING: ir ast + sink(b.getMember()); // $ MISSING: ir ast c = new MyClass2(0); @@ -865,4 +865,4 @@ void test_iconv(size_t size) { size_t size_out; iconv(0, &s, &size, &p, &size_out); sink(*p); // $ ast,ir -} \ No newline at end of file +} diff --git a/cpp/ql/test/library-tests/ir/points_to/points_to.cpp b/cpp/ql/test/library-tests/ir/points_to/points_to.cpp index fa4d062c5f87..43a3077d0510 100644 --- a/cpp/ql/test/library-tests/ir/points_to/points_to.cpp +++ b/cpp/ql/test/library-tests/ir/points_to/points_to.cpp @@ -24,64 +24,64 @@ struct DerivedVI : virtual Base1 { }; void Locals() { - Point pt = { //$ussa=pt - 1, //$ussa=pt[0..4) - 2 //$ussa=pt[4..8) + Point pt = { // $ ussa=pt + 1, // $ ussa=pt[0..4) + 2 // $ ussa=pt[4..8) }; - int i = pt.x; //$ussa=pt[0..4) - i = pt.y; //$ussa=pt[4..8) + int i = pt.x; // $ ussa=pt[0..4) + i = pt.y; // $ ussa=pt[4..8) int* p = &pt.x; - i = *p; //$ussa=pt[0..4) + i = *p; // $ ussa=pt[0..4) p = &pt.y; - i = *p; //$ussa=pt[4..8) + i = *p; // $ ussa=pt[4..8) } void PointsTo( - int a, //$raw=a - Point& b, //$raw=b ussa=*b - Point* c, //$raw=c ussa=*c - int* d, //$raw=d ussa=*d - DerivedSI* e, //$raw=e ussa=*e - DerivedMI* f, //$raw=f ussa=*f - DerivedVI* g //$raw=g ussa=*g + int a, // $ raw=a + Point& b, // $ raw=b ussa=*b + Point* c, // $ raw=c ussa=*c + int* d, // $ raw=d ussa=*d + DerivedSI* e, // $ raw=e ussa=*e + DerivedMI* f, // $ raw=f ussa=*f + DerivedVI* g // $ raw=g ussa=*g ) { - int i = a; //$raw=a - i = *&a; //$raw=a - i = *(&a + 0); //$raw=a - i = b.x; //$raw=b ussa=*b[0..4) - i = b.y; //$raw=b ussa=*b[4..8) - i = c->x; //$raw=c ussa=*c[0..4) - i = c->y; //$raw=c ussa=*c[4..8) - i = *d; //$raw=d ussa=*d[0..4) - i = *(d + 0); //$raw=d ussa=*d[0..4) - i = d[5]; //$raw=d ussa=*d[20..24) - i = 5[d]; //$raw=d ussa=*d[20..24) - i = d[a]; //$raw=d raw=a ussa=*d[?..?) - i = a[d]; //$raw=d raw=a ussa=*d[?..?) + int i = a; // $ raw=a + i = *&a; // $ raw=a + i = *(&a + 0); // $ raw=a + i = b.x; // $ raw=b ussa=*b[0..4) + i = b.y; // $ raw=b ussa=*b[4..8) + i = c->x; // $ raw=c ussa=*c[0..4) + i = c->y; // $ raw=c ussa=*c[4..8) + i = *d; // $ raw=d ussa=*d[0..4) + i = *(d + 0); // $ raw=d ussa=*d[0..4) + i = d[5]; // $ raw=d ussa=*d[20..24) + i = 5[d]; // $ raw=d ussa=*d[20..24) + i = d[a]; // $ raw=d raw=a ussa=*d[?..?) + i = a[d]; // $ raw=d raw=a ussa=*d[?..?) - int* p = &b.x; //$raw=b - i = *p; //$ussa=*b[0..4) - p = &b.y; //$raw=b - i = *p; //$ussa=*b[4..8) - p = &c->x; //$raw=c - i = *p; //$ussa=*c[0..4) - p = &c->y; //$raw=c - i = *p; //$ussa=*c[4..8) - p = &d[5]; //$raw=d - i = *p; //$ussa=*d[20..24) - p = &d[a]; //$raw=d raw=a - i = *p; //$ussa=*d[?..?) + int* p = &b.x; // $ raw=b + i = *p; // $ ussa=*b[0..4) + p = &b.y; // $ raw=b + i = *p; // $ ussa=*b[4..8) + p = &c->x; // $ raw=c + i = *p; // $ ussa=*c[0..4) + p = &c->y; // $ raw=c + i = *p; // $ ussa=*c[4..8) + p = &d[5]; // $ raw=d + i = *p; // $ ussa=*d[20..24) + p = &d[a]; // $ raw=d raw=a + i = *p; // $ ussa=*d[?..?) - Point* q = &c[a]; //$raw=c raw=a - i = q->x; //$ussa=*c[?..?) - i = q->y; //$ussa=*c[?..?) + Point* q = &c[a]; // $ raw=c raw=a + i = q->x; // $ ussa=*c[?..?) + i = q->y; // $ ussa=*c[?..?) - i = e->b1; //$raw=e ussa=*e[0..4) - i = e->dsi; //$raw=e ussa=*e[4..8) - i = f->b1; //$raw=f ussa=*f[0..4) - i = f->b2; //$raw=f ussa=*f[4..8) - i = f->dmi; //$raw=f ussa=*f[8..12) - i = g->b1; //$raw=g ussa=*g[?..?) - i = g->dvi; //$raw=g ussa=*g[8..12) -} \ No newline at end of file + i = e->b1; // $ raw=e ussa=*e[0..4) + i = e->dsi; // $ raw=e ussa=*e[4..8) + i = f->b1; // $ raw=f ussa=*f[0..4) + i = f->b2; // $ raw=f ussa=*f[4..8) + i = f->dmi; // $ raw=f ussa=*f[8..12) + i = g->b1; // $ raw=g ussa=*g[?..?) + i = g->dvi; // $ raw=g ussa=*g[8..12) +} diff --git a/cpp/ql/test/library-tests/ir/points_to/smart_pointer.cpp b/cpp/ql/test/library-tests/ir/points_to/smart_pointer.cpp index db6be36e42ad..0e5d26875d62 100644 --- a/cpp/ql/test/library-tests/ir/points_to/smart_pointer.cpp +++ b/cpp/ql/test/library-tests/ir/points_to/smart_pointer.cpp @@ -10,24 +10,24 @@ struct S { void unique_ptr_init(S s) { unique_ptr p(new S); // MISSING: $ussa=dynamic{1} - int i = (*p).x; //$ MISSING: ussa=dynamic{1}[0..4) - *p = s; //$ MISSING: ussa=dynamic{1}[0..4) + int i = (*p).x; // $ MISSING: ussa=dynamic{1}[0..4) + *p = s; // $ MISSING: ussa=dynamic{1}[0..4) unique_ptr q = std::move(p); - *(q.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4) + *(q.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4) shared_ptr t(std::move(q)); - t->x = 5; //$ MISSING: ussa=dynamic{1}[0..4) - *t = s; //$ MISSING: ussa=dynamic{1}[0..4) - *(t.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4) + t->x = 5; // $ MISSING: ussa=dynamic{1}[0..4) + *t = s; // $ MISSING: ussa=dynamic{1}[0..4) + *(t.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4) } void shared_ptr_init(S s) { - shared_ptr p(new S); //$ MISSING: ussa=dynamic{1} - int i = (*p).x; //$ MISSING: ussa=dynamic{1}[0..4) - *p = s; //$ MISSING: ussa=dynamic{1}[0..4) + shared_ptr p(new S); // $ MISSING: ussa=dynamic{1} + int i = (*p).x; // $ MISSING: ussa=dynamic{1}[0..4) + *p = s; // $ MISSING: ussa=dynamic{1}[0..4) shared_ptr q = std::move(p); - *(q.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4) + *(q.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4) shared_ptr t(q); - t->x = 5; //$ MISSING: ussa=dynamic{1}[0..4) - *t = s; //$ MISSING: ussa=dynamic{1}[0..4) - *(t.get()) = s; //$ MISSING: ussa=dynamic{1}[0..4) + t->x = 5; // $ MISSING: ussa=dynamic{1}[0..4) + *t = s; // $ MISSING: ussa=dynamic{1}[0..4) + *(t.get()) = s; // $ MISSING: ussa=dynamic{1}[0..4) } diff --git a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp index 649d99a7575c..05b11b793c35 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp +++ b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp @@ -46,7 +46,7 @@ int test4() { } range(total); // $ MISSING: range=>=0 range(i); // $ range===2 - range(total + i); // $ range="<=Phi: i+2" MISSING: range===i+2 range=>=2 range=>=i+0 + range(total + i); // $ range="<=Phi: i+2" MISSING: range===i+2 range=>=2 range=>=i+0 return total + i; } @@ -210,7 +210,7 @@ int test14(int x) { int x3 = (int)(unsigned int)x; range(x3); char c0 = x; - range(c0); + range(c0); unsigned short s0 = x; range(s0); range(x0 + x1 + x2 + x3 + c0 + s0); // $ overflow=+ overflow=+- @@ -218,7 +218,7 @@ int test14(int x) { } long long test15(long long x) { - return (x > 0 && (range(x), x == (int)x)) ? // $ range=>=1 + return (x > 0 && (range(x), x == (int)x)) ? // $ range=>=1 (range(x), x) : // $ range=>=1 (range(x), -1); } @@ -228,7 +228,7 @@ int test_unary(int a) { int total = 0; if (3 <= a && a <= 11) { - range(a); // $ range=<=11 range=>=3 + range(a); // $ range=<=11 range=>=3 int b = +a; range(b); // $ range=<=11 range=>=3 int c = -a; @@ -384,7 +384,7 @@ int test_mult02(int a, int b) { total += r; range(total); // $ range=">=Phi: 0-143" range=">=Phi: 0-286" } - range(total); // $range=">=Phi: 0-143" range=">=Phi: 0-286" + range(total); // $ range=">=Phi: 0-143" range=">=Phi: 0-286" return total; } @@ -467,7 +467,7 @@ int test_mult04(int a, int b) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=0 range=>=-13 int r = a*b; // 0 .. 221 - range(r); // $ range=<=221 range=>=0 + range(r); // $ range=<=221 range=>=0 total += r; range(total); // $ range="<=Phi: - ...+221" } @@ -1030,7 +1030,7 @@ void test_negate_signed(int s) { } } -// By setting the guard after the use in another guard we +// By setting the guard after the use in another guard we // don't get the useful information void test_guard_after_use(int pos, int size, int offset) { if (pos + offset >= size) { // $ overflow=+- @@ -1040,12 +1040,12 @@ void test_guard_after_use(int pos, int size, int offset) { return; } range(pos + 1); // $ overflow=+ range="==InitializeParameter: pos+1" MISSING: range="<=InitializeParameter: size-1" -} +} int cond(); -// This is basically what we get when we have a loop that calls +// This is basically what we get when we have a loop that calls // realloc in some iterations void alloc_in_loop(int origLen) { if (origLen <= 10) { @@ -1066,12 +1066,12 @@ void alloc_in_loop(int origLen) { } } -// This came from a case where it handled the leftovers before an unrolled loop +// This came from a case where it handled the leftovers before an unrolled loop void mask_at_start(int len) { if (len < 0) { return; } - int leftOver = len & 63; + int leftOver = len & 63; for (int i = 0; i < leftOver; i++) { range(i); // $ range=<=62 range=>=0 range="<=Store: ... & ... | Store: leftOver-1" range="<=InitializeParameter: len-1" } diff --git a/cpp/ql/test/library-tests/ir/types/complex.c b/cpp/ql/test/library-tests/ir/types/complex.c index d8b187462811..4584bdf104b6 100644 --- a/cpp/ql/test/library-tests/ir/types/complex.c +++ b/cpp/ql/test/library-tests/ir/types/complex.c @@ -1,14 +1,14 @@ void Complex(void) { - _Complex float cf; //$irtype=cfloat8 - _Complex double cd; //$irtype=cfloat16 - _Complex long double cld; //$irtype=cfloat32 + _Complex float cf; // $ irtype=cfloat8 + _Complex double cd; // $ irtype=cfloat16 + _Complex long double cld; // $ irtype=cfloat32 // _Complex __float128 cf128; } void Imaginary(void) { - _Imaginary float jf; //$irtype=ifloat4 - _Imaginary double jd; //$irtype=ifloat8 - _Imaginary long double jld; //$irtype=ifloat16 + _Imaginary float jf; // $ irtype=ifloat4 + _Imaginary double jd; // $ irtype=ifloat8 + _Imaginary long double jld; // $ irtype=ifloat16 // _Imaginary __float128 jf128; } diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.cpp b/cpp/ql/test/library-tests/ir/types/irtypes.cpp index 321382567b7a..ddc2df8e96d0 100644 --- a/cpp/ql/test/library-tests/ir/types/irtypes.cpp +++ b/cpp/ql/test/library-tests/ir/types/irtypes.cpp @@ -22,44 +22,44 @@ enum class ScopedE { }; void IRTypes() { - char c; //$irtype=int1 - signed char sc; //$irtype=int1 - unsigned char uc; //$irtype=uint1 - short s; //$irtype=int2 - signed short ss; //$irtype=int2 - unsigned short us; //$irtype=uint2 - int i; //$irtype=int4 - signed int si; //$irtype=int4 - unsigned int ui; //$irtype=uint4 - long l; //$irtype=int8 - signed long sl; //$irtype=int8 - unsigned long ul; //$irtype=uint8 - long long ll; //$irtype=int8 - signed long long sll; //$irtype=int8 - unsigned long long ull; //$irtype=uint8 - bool b; //$irtype=bool1 - float f; //$irtype=float4 - double d; //$irtype=float8 - long double ld; //$irtype=float16 - __float128 f128; //$irtype=float16 + char c; // $ irtype=int1 + signed char sc; // $ irtype=int1 + unsigned char uc; // $ irtype=uint1 + short s; // $ irtype=int2 + signed short ss; // $ irtype=int2 + unsigned short us; // $ irtype=uint2 + int i; // $ irtype=int4 + signed int si; // $ irtype=int4 + unsigned int ui; // $ irtype=uint4 + long l; // $ irtype=int8 + signed long sl; // $ irtype=int8 + unsigned long ul; // $ irtype=uint8 + long long ll; // $ irtype=int8 + signed long long sll; // $ irtype=int8 + unsigned long long ull; // $ irtype=uint8 + bool b; // $ irtype=bool1 + float f; // $ irtype=float4 + double d; // $ irtype=float8 + long double ld; // $ irtype=float16 + __float128 f128; // $ irtype=float16 - wchar_t wc; //$irtype=uint4 -// char8_t c8; //$irtype=uint1 - char16_t c16; //$irtype=uint2 - char32_t c32; //$irtype=uint4 + wchar_t wc; // $ irtype=uint4 +// char8_t c8; // $ irtype=uint1 + char16_t c16; // $ irtype=uint2 + char32_t c32; // $ irtype=uint4 - int* pi; //$irtype=addr8 - int& ri = i; //$irtype=addr8 - void (*pfn)() = nullptr; //$irtype=func8 - void (&rfn)() = IRTypes; //$irtype=func8 + int* pi; // $ irtype=addr8 + int& ri = i; // $ irtype=addr8 + void (*pfn)() = nullptr; // $ irtype=func8 + void (&rfn)() = IRTypes; // $ irtype=func8 - A s_a; //$irtype=opaque4{A} - B s_b; //$irtype=opaque16{B} + A s_a; // $ irtype=opaque4{A} + B s_b; // $ irtype=opaque16{B} - E e; //$irtype=uint4 - ScopedE se; //$irtype=uint4 + E e; // $ irtype=uint4 + ScopedE se; // $ irtype=uint4 - B a_b[10]; //$irtype=opaque160{B[10]} + B a_b[10]; // $ irtype=opaque160{B[10]} } // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/query-tests/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification/test.cpp index a2dce39cc852..6e0320e8d84d 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification/test.cpp @@ -1338,7 +1338,7 @@ void indirect_time_conversion_check(WORD year, WORD offset){ void set_time(WORD year, WORD month, WORD day){ SYSTEMTIME tmp; - tmp.wYear = year; //$ Alert[cpp/leap-year/unchecked-after-arithmetic-year-modification] + tmp.wYear = year; // $ Alert[cpp/leap-year/unchecked-after-arithmetic-year-modification] tmp.wMonth = month; tmp.wDay = day; } diff --git a/csharp/documentation/library-coverage/coverage.csv b/csharp/documentation/library-coverage/coverage.csv index 5dbefc4c8167..a70a91755624 100644 --- a/csharp/documentation/library-coverage/coverage.csv +++ b/csharp/documentation/library-coverage/coverage.csv @@ -44,5 +44,5 @@ NHibernate,3,,,,,,,,,,,,3,,,,,,,,,, Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,,,73,18 ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,,,7, SourceGenerators,,,5,,,,,,,,,,,,,,,,,,,,5 -System,59,47,12495,,6,5,12,,,4,1,,31,2,,6,15,17,4,3,,6382,6113 +System,59,48,12495,,6,5,12,,,4,1,,31,2,,6,15,17,5,3,,6382,6113 Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,,, diff --git a/csharp/documentation/library-coverage/coverage.rst b/csharp/documentation/library-coverage/coverage.rst index 4061f675b859..f487850e54b9 100644 --- a/csharp/documentation/library-coverage/coverage.rst +++ b/csharp/documentation/library-coverage/coverage.rst @@ -8,7 +8,7 @@ C# framework & library support Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting` `ServiceStack `_,"``ServiceStack.*``, ``ServiceStack``",,7,194, - System,"``System.*``, ``System``",47,12495,59,5 + System,"``System.*``, ``System``",48,12495,59,5 Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.AspNetCore.Components``, ``Microsoft.AspNetCore.Http``, ``Microsoft.AspNetCore.Mvc``, ``Microsoft.AspNetCore.WebUtilities``, ``Microsoft.CSharp``, ``Microsoft.Data.SqlClient``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.DotNet.Build.Tasks``, ``Microsoft.DotNet.PlatformAbstractions``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.JSInterop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``NHibernate``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",60,2406,162,4 - Totals,,107,14908,415,9 + Totals,,108,14908,415,9 diff --git a/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/old.dbscheme b/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/old.dbscheme new file mode 100644 index 000000000000..e73ca2c93df8 --- /dev/null +++ b/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/old.dbscheme @@ -0,0 +1,1489 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile.rsp` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Overlay support + */ + +/** + * The CLI will automatically emit the tuple `databaseMetadata("isOverlay", "true")`, + * along with an `overlayChangedFiles` tuple for each new/modified/deleted file, + * when building an overlay database, and these can be used by the discard predicates. + */ +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path : string ref +); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +@locatable = @declaration_with_accessors | @callable_accessor | @declaration_or_directive + | @diagnostic | @extractor_message | @preprocessor_directive | @attribute | @type_mention | @type_parameter_constraints + | @declaration_with_accessors | @callable_accessor | @operator | @method + | @constructor | @destructor | @field | @local_variable | @parameter | @stmt | @expr + | @xmllocatable | @commentline | @commentblock | @asp_element + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type +| 34 = @inline_array_type +| 35 = @extension_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type | @extension_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extension_receiver_type( + unique int extension: @extension_type ref, + int receiver_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event | @operator; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type | @extension_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +@has_scoped_annotation = @local_scope_variable + +scoped_annotation( + int id: @has_scoped_annotation ref, + int kind: int ref // scoped ref = 1, scoped value = 2 + ); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @utf16_string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr +| 133 = @urshift_expr +| 134 = @assign_urshift_expr +| 135 = @utf8_string_literal_expr +/* C# 12.0 */ +| 136 = @collection_expr +| 137 = @spread_element_expr +| 138 = @interpolated_string_insert_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr | @urshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/* Compiler generated */ + +compiler_generated(unique int id: @element ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); diff --git a/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/semmlecode.csharp.dbscheme b/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/semmlecode.csharp.dbscheme new file mode 100644 index 000000000000..178a7e6cf335 --- /dev/null +++ b/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/semmlecode.csharp.dbscheme @@ -0,0 +1,1489 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile.rsp` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Overlay support + */ + +/** + * The CLI will automatically emit the tuple `databaseMetadata("isOverlay", "true")`, + * along with an `overlayChangedFiles` tuple for each new/modified/deleted file, + * when building an overlay database, and these can be used by the discard predicates. + */ +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path : string ref +); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +@locatable = @declaration_with_accessors | @callable_accessor | @declaration_or_directive + | @diagnostic | @extractor_message | @preprocessor_directive | @attribute | @type_mention | @type_parameter_constraints + | @declaration_with_accessors | @callable_accessor | @operator | @method + | @constructor | @destructor | @field | @local_variable | @parameter | @stmt | @expr + | @xmllocatable | @commentline | @commentblock | @asp_element + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type +| 34 = @inline_array_type +| 35 = @extension_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type | @extension_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extension_receiver_type( + unique int extension: @extension_type ref, + int receiver_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event | @operator; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type | @extension_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +@has_scoped_annotation = @local_scope_variable + +scoped_annotation( + int id: @has_scoped_annotation ref, + int kind: int ref // scoped ref = 1, scoped value = 2 + ); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @utf16_string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr +| 133 = @urshift_expr +| 134 = @assign_urshift_expr +| 135 = @utf8_string_literal_expr +/* C# 12.0 */ +| 136 = @collection_expr +| 137 = @spread_element_expr +| 138 = @interpolated_string_insert_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr | @urshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/* Compiler generated */ + +compiler_generated(unique int id: @element ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); diff --git a/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/upgrade.properties b/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/upgrade.properties new file mode 100644 index 000000000000..8a1d7d33e598 --- /dev/null +++ b/csharp/downgrades/e73ca2c93df8aae162f1704edc4817a5cb330529/upgrade.properties @@ -0,0 +1,2 @@ +description: Remove inclusion of @assign_expr in @bin_op +compatibility: full diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 48039b4b962e..58c94cf047a1 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -12,7 +13,9 @@ namespace Semmle.Extraction.CSharp.Entities internal class Constructor : Method { private readonly List declaringReferenceSyntax; - + private readonly Lazy ordinaryConstructorSyntaxLazy; + private readonly Lazy primaryConstructorSyntaxLazy; + private readonly Lazy primaryBaseLazy; private Constructor(Context cx, IMethodSymbol init) : base(cx, init) { @@ -20,8 +23,28 @@ private Constructor(Context cx, IMethodSymbol init) Symbol.DeclaringSyntaxReferences .Select(r => r.GetSyntax()) .ToList(); + ordinaryConstructorSyntaxLazy = new Lazy(() => + declaringReferenceSyntax + .OfType() + .FirstOrDefault()); + primaryConstructorSyntaxLazy = new Lazy(() => + declaringReferenceSyntax + .OfType() + .FirstOrDefault(t => t is ClassDeclarationSyntax or StructDeclarationSyntax or RecordDeclarationSyntax)); + primaryBaseLazy = new Lazy(() => + PrimaryConstructorSyntax? + .BaseList? + .Types + .OfType() + .FirstOrDefault()); } + private ConstructorDeclarationSyntax? OrdinaryConstructorSyntax => ordinaryConstructorSyntaxLazy.Value; + + private TypeDeclarationSyntax? PrimaryConstructorSyntax => primaryConstructorSyntaxLazy.Value; + + private PrimaryConstructorBaseTypeSyntax? PrimaryBase => primaryBaseLazy.Value; + public override void Populate(TextWriter trapFile) { PopulateMethod(trapFile); @@ -176,23 +199,6 @@ private void ExtractSourceInitializer(TextWriter trapFile, ITypeSymbol? type, IM init.PopulateArguments(trapFile, arguments, 0); } - private ConstructorDeclarationSyntax? OrdinaryConstructorSyntax => - declaringReferenceSyntax - .OfType() - .FirstOrDefault(); - - private TypeDeclarationSyntax? PrimaryConstructorSyntax => - declaringReferenceSyntax - .OfType() - .FirstOrDefault(t => t is ClassDeclarationSyntax or StructDeclarationSyntax or RecordDeclarationSyntax); - - private PrimaryConstructorBaseTypeSyntax? PrimaryBase => - PrimaryConstructorSyntax? - .BaseList? - .Types - .OfType() - .FirstOrDefault(); - private bool IsPrimary => PrimaryConstructorSyntax is not null; // This is a default constructor in a class or struct declared in source. @@ -223,7 +229,7 @@ Symbol.ContainingType.TypeKind is TypeKind.Class or TypeKind.Struct && { case MethodKind.StaticConstructor: case MethodKind.Constructor: - return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor); + return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor.GetBodyDeclaringSymbol()); default: throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor"); } diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 4ab586833bd0..db6b6b5e014d 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.7.60 +version: 1.7.61-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 7cefce31de91..e0ee0aaab8fb 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.7.60 +version: 1.7.61-dev groups: - csharp - solorigate diff --git a/csharp/ql/consistency-queries/CfgConsistency.ql b/csharp/ql/consistency-queries/CfgConsistency.ql index d7f0c091538d..4b0d15f8a819 100644 --- a/csharp/ql/consistency-queries/CfgConsistency.ql +++ b/csharp/ql/consistency-queries/CfgConsistency.ql @@ -1,63 +1,5 @@ import csharp import semmle.code.csharp.controlflow.internal.Completion -import semmle.code.csharp.controlflow.internal.PreBasicBlocks import ControlFlow import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl::Consistency import semmle.code.csharp.controlflow.internal.Splitting - -private predicate splitBB(ControlFlow::BasicBlock bb) { - exists(ControlFlow::Node first | - first = bb.getFirstNode() and - first.isJoin() and - strictcount(first.getAPredecessor().getAstNode()) = 1 - ) -} - -private class RelevantBasicBlock extends ControlFlow::BasicBlock { - RelevantBasicBlock() { not splitBB(this) } -} - -predicate bbStartInconsistency(ControlFlowElement cfe) { - exists(RelevantBasicBlock bb | bb.getFirstNode() = cfe.getAControlFlowNode()) and - not cfe = any(PreBasicBlock bb).getFirstElement() -} - -predicate bbSuccInconsistency(ControlFlowElement pred, ControlFlowElement succ) { - exists(RelevantBasicBlock predBB, RelevantBasicBlock succBB | - predBB.getLastNode() = pred.getAControlFlowNode() and - succBB = predBB.getASuccessor() and - succBB.getFirstNode() = succ.getAControlFlowNode() - ) and - not exists(PreBasicBlock predBB, PreBasicBlock succBB | - predBB.getLastNode() = pred and - succBB = predBB.getASuccessor() and - succBB.getFirstElement() = succ - ) -} - -predicate bbIntraSuccInconsistency(ControlFlowElement pred, ControlFlowElement succ) { - exists(ControlFlow::BasicBlock bb, int i | - pred.getAControlFlowNode() = bb.getNode(i) and - succ.getAControlFlowNode() = bb.getNode(i + 1) - ) and - not exists(PreBasicBlock bb | - bb.getLastNode() = pred and - bb.getASuccessor().getFirstElement() = succ - ) and - not exists(PreBasicBlock bb, int i | - bb.getNode(i) = pred and - bb.getNode(i + 1) = succ - ) -} - -query predicate preBasicBlockConsistency(ControlFlowElement cfe1, ControlFlowElement cfe2, string s) { - bbStartInconsistency(cfe1) and - cfe2 = cfe1 and - s = "start inconsistency" - or - bbSuccInconsistency(cfe1, cfe2) and - s = "succ inconsistency" - or - bbIntraSuccInconsistency(cfe1, cfe2) and - s = "intra succ inconsistency" -} diff --git a/csharp/ql/lib/change-notes/2026-02-24-partial-constructors.md b/csharp/ql/lib/change-notes/2026-02-24-partial-constructors.md new file mode 100644 index 000000000000..5ce442aaa10f --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-02-24-partial-constructors.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* C# 14: Added support for partial constructors. diff --git a/csharp/ql/lib/change-notes/2026-03-02-post-update-nodes.md b/csharp/ql/lib/change-notes/2026-03-02-post-update-nodes.md new file mode 100644 index 000000000000..d021cabf1a08 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-03-02-post-update-nodes.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added post-update nodes for struct-type arguments, allowing data flow out of method calls via those arguments. diff --git a/csharp/ql/lib/change-notes/2026-03-03-implicit-conversion-reverse-flow.md b/csharp/ql/lib/change-notes/2026-03-03-implicit-conversion-reverse-flow.md new file mode 100644 index 000000000000..842c2069b3e7 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-03-03-implicit-conversion-reverse-flow.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added reverse taint flow from implicit conversion operator calls to their arguments. diff --git a/csharp/ql/lib/change-notes/2026-03-04-websocket-receiveasync.md b/csharp/ql/lib/change-notes/2026-03-04-websocket-receiveasync.md new file mode 100644 index 000000000000..7b709cad7ca7 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-03-04-websocket-receiveasync.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added `System.Net.WebSockets::ReceiveAsync` as a remote flow source. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md b/csharp/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md new file mode 100644 index 000000000000..23fdce9b6159 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol. diff --git a/csharp/ql/lib/ext/System.Net.WebSockets.model.yml b/csharp/ql/lib/ext/System.Net.WebSockets.model.yml new file mode 100644 index 000000000000..23a14504a573 --- /dev/null +++ b/csharp/ql/lib/ext/System.Net.WebSockets.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: sourceModel + data: + - ["System.Net.WebSockets", "WebSocket", True, "ReceiveAsync", "", "", "Argument[0]", "remote", "manual"] diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 86fc09ebfd27..2393305504ed 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 5.4.8 +version: 5.4.9-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/lib/semmle/code/csharp/Stmt.qll b/csharp/ql/lib/semmle/code/csharp/Stmt.qll index aea8b0378196..4d79bf9fa549 100644 --- a/csharp/ql/lib/semmle/code/csharp/Stmt.qll +++ b/csharp/ql/lib/semmle/code/csharp/Stmt.qll @@ -183,9 +183,10 @@ class SwitchStmt extends SelectionStmt, Switch, @switch_stmt { * return 3; * } * ``` - * Note that this reorders the `default` case to always be at the end. */ - override CaseStmt getCase(int i) { result = SwithStmtInternal::getCase(this, i) } + override CaseStmt getCase(int i) { + result = rank[i + 1](CaseStmt cs, int idx | cs = this.getChildStmt(idx) | cs order by idx) + } /** Gets a case of this `switch` statement. */ override CaseStmt getACase() { result = this.getCase(_) } @@ -208,87 +209,29 @@ class SwitchStmt extends SelectionStmt, Switch, @switch_stmt { * ```csharp * switch (x) { * case "abc": // i = 0 - * return 0; - * case int i when i > 0: // i = 1 - * return 1; - * case string s: // i = 2 - * Console.WriteLine(s); - * return 2; // i = 3 - * default: // i = 4 - * return 3; // i = 5 + * return 0; // i = 1 + * case int i when i > 0: // i = 2 + * return 1; // i = 3 + * case string s: // i = 4 + * Console.WriteLine(s); // i = 5 + * return 2; // i = 6 + * default: // i = 7 + * return 3; // i = 8 * } * ``` - * - * Note that each non-`default` case is a labeled statement, so the statement - * that follows is a child of the labeled statement, and not the `switch` block. */ - Stmt getStmt(int i) { result = SwithStmtInternal::getStmt(this, i) } + Stmt getStmt(int i) { result = this.getChildStmt(i) } /** Gets a statement in the body of this `switch` statement. */ Stmt getAStmt() { result = this.getStmt(_) } } -cached -private module SwithStmtInternal { - cached - CaseStmt getCase(SwitchStmt ss, int i) { - exists(int index, int rankIndex | - caseIndex(ss, result, index) and - rankIndex = i + 1 and - index = rank[rankIndex](int j, CaseStmt cs | caseIndex(ss, cs, j) | j) - ) - } - - /** Implicitly reorder case statements to put the default case last if needed. */ - private predicate caseIndex(SwitchStmt ss, CaseStmt case, int index) { - exists(int i | case = ss.getChildStmt(i) | - if case instanceof DefaultCase - then index = max(int j | exists(ss.getChildStmt(j))) + 1 - else index = i - ) - } - - cached - Stmt getStmt(SwitchStmt ss, int i) { - exists(int index, int rankIndex | - result = ss.getChildStmt(index) and - rankIndex = i + 1 and - index = - rank[rankIndex](int j, Stmt s | - // `getChild` includes both labeled statements and the targeted - // statements of labeled statement as separate children, but we - // only want the labeled statement - s = getLabeledStmt(ss, j) - | - j - ) - ) - } - - private Stmt getLabeledStmt(SwitchStmt ss, int i) { - result = ss.getChildStmt(i) and - not result = any(CaseStmt cs).getBody() - } -} - /** A `case` statement. */ class CaseStmt extends Case, @case_stmt { override Expr getExpr() { result = any(SwitchStmt ss | ss.getACase() = this).getExpr() } override PatternExpr getPattern() { result = this.getChild(0) } - override Stmt getBody() { - exists(int i, Stmt next | - this = this.getParent().getChild(i) and - next = this.getParent().getChild(i + 1) - | - result = next and - not result instanceof CaseStmt - or - result = next.(CaseStmt).getBody() - ) - } - /** * Gets the condition on this case, if any. For example, the type case on line 3 * has no condition, and the type case on line 4 has condition `s.Length > 0`, in diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll index 414cfc2d50ae..40ec3722edd2 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll @@ -142,6 +142,7 @@ private module GuardsInput implements } } + pragma[nomagic] predicate equalityTest(Expr eqtest, Expr left, Expr right, boolean polarity) { exists(ComparisonTest ct | ct.getExpr() = eqtest and @@ -410,6 +411,22 @@ private predicate typePattern(PatternMatch pm, TypePatternExpr tpe, Type t) { t = pm.getExpr().getType() } +pragma[nomagic] +private predicate dereferenceableExpr(Expr e, boolean isNullableType) { + exists(Type t | t = e.getType() | + t instanceof NullableType and + isNullableType = true + or + t instanceof RefType and + isNullableType = false + ) + or + exists(Expr parent | + dereferenceableExpr(parent, isNullableType) and + e = getNullEquivParent(parent) + ) +} + /** * An expression that evaluates to a value that can be dereferenced. That is, * an expression that may evaluate to `null`. @@ -418,21 +435,12 @@ class DereferenceableExpr extends Expr { private boolean isNullableType; DereferenceableExpr() { - exists(Expr e, Type t | - // There is currently a bug in the extractor: the type of `x?.Length` is - // incorrectly `int`, while it should have been `int?`. We apply - // `getNullEquivParent()` as a workaround - this = getNullEquivParent*(e) and - t = e.getType() and - not this instanceof SwitchCaseExpr and - not this instanceof PatternExpr - | - t instanceof NullableType and - isNullableType = true - or - t instanceof RefType and - isNullableType = false - ) + // There is currently a bug in the extractor: the type of `x?.Length` is + // incorrectly `int`, while it should have been `int?`. We apply + // `getNullEquivParent()` as a workaround + dereferenceableExpr(this, isNullableType) and + not this instanceof SwitchCaseExpr and + not this instanceof PatternExpr } /** Holds if this expression has a nullable type `T?`. */ diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll index 6be79a17be25..1696869e5911 100644 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll @@ -94,9 +94,19 @@ private Element getAChild(Element p) { result = p.(AssignOperation).getExpandedAssignment() } +pragma[nomagic] +private predicate astNode(Element e) { + e = any(@top_level_exprorstmt_parent p | not p instanceof Attribute) + or + exists(Element parent | + astNode(parent) and + e = getAChild(parent) + ) +} + /** An AST node. */ class AstNode extends Element, TAstNode { - AstNode() { this = getAChild*(any(@top_level_exprorstmt_parent p | not p instanceof Attribute)) } + AstNode() { astNode(this) } int getId() { idOf(this, result) } } @@ -298,6 +308,93 @@ private class ConstructorTree extends ControlFlowTree instanceof Constructor { } } +cached +private module SwithStmtInternal { + // Reorders default to be last if needed + cached + CaseStmt getCase(SwitchStmt ss, int i) { + exists(int index, int rankIndex | + caseIndex(ss, result, index) and + rankIndex = i + 1 and + index = rank[rankIndex](int j, CaseStmt cs | caseIndex(ss, cs, j) | j) + ) + } + + /** Implicitly reorder case statements to put the default case last if needed. */ + private predicate caseIndex(SwitchStmt ss, CaseStmt case, int index) { + exists(int i | case = ss.getChildStmt(i) | + if case instanceof DefaultCase + then index = max(int j | exists(ss.getChildStmt(j))) + 1 + else index = i + ) + } + + /** + * Gets the `i`th statement in the body of this `switch` statement. + * + * Example: + * + * ```csharp + * switch (x) { + * case "abc": // i = 0 + * return 0; + * case int i when i > 0: // i = 1 + * return 1; + * case string s: // i = 2 + * Console.WriteLine(s); + * return 2; // i = 3 + * default: // i = 4 + * return 3; // i = 5 + * } + * ``` + * + * Note that each non-`default` case is a labeled statement, so the statement + * that follows is a child of the labeled statement, and not the `switch` block. + */ + cached + Stmt getStmt(SwitchStmt ss, int i) { + exists(int index, int rankIndex | + result = ss.getChildStmt(index) and + rankIndex = i + 1 and + index = + rank[rankIndex](int j, Stmt s | + // `getChild` includes both labeled statements and the targeted + // statements of labeled statement as separate children, but we + // only want the labeled statement + s = getLabeledStmt(ss, j) + | + j + ) + ) + } + + private Stmt getLabeledStmt(SwitchStmt ss, int i) { + result = ss.getChildStmt(i) and + not result = caseStmtGetBody(_) + } +} + +private ControlFlowElement caseGetBody(Case c) { + result = c.getBody() or result = caseStmtGetBody(c) +} + +private ControlFlowElement caseStmtGetBody(CaseStmt c) { + exists(int i, Stmt next | + c = c.getParent().getChild(i) and + next = c.getParent().getChild(i + 1) + | + result = next and + not result instanceof CaseStmt + or + result = caseStmtGetBody(next) + ) +} + +// Reorders default to be last if needed +private Case switchGetCase(Switch s, int i) { + result = s.(SwitchExpr).getCase(i) or result = SwithStmtInternal::getCase(s, i) +} + abstract private class SwitchTree extends ControlFlowTree instanceof Switch { override predicate propagatesAbnormal(AstNode child) { child = super.getExpr() } @@ -305,27 +402,27 @@ abstract private class SwitchTree extends ControlFlowTree instanceof Switch { // Flow from last element of switch expression to first element of first case last(super.getExpr(), pred, c) and c instanceof NormalCompletion and - first(super.getCase(0), succ) + first(switchGetCase(this, 0), succ) or // Flow from last element of case pattern to next case - exists(Case case, int i | case = super.getCase(i) | + exists(Case case, int i | case = switchGetCase(this, i) | last(case.getPattern(), pred, c) and c.(MatchingCompletion).isNonMatch() and - first(super.getCase(i + 1), succ) + first(switchGetCase(this, i + 1), succ) ) or // Flow from last element of condition to next case - exists(Case case, int i | case = super.getCase(i) | + exists(Case case, int i | case = switchGetCase(this, i) | last(case.getCondition(), pred, c) and c instanceof FalseCompletion and - first(super.getCase(i + 1), succ) + first(switchGetCase(this, i + 1), succ) ) } } abstract private class CaseTree extends ControlFlowTree instanceof Case { final override predicate propagatesAbnormal(AstNode child) { - child in [super.getPattern().(ControlFlowElement), super.getCondition(), super.getBody()] + child in [super.getPattern().(ControlFlowElement), super.getCondition(), caseGetBody(this)] } override predicate succ(AstNode pred, AstNode succ, Completion c) { @@ -338,13 +435,13 @@ abstract private class CaseTree extends ControlFlowTree instanceof Case { first(super.getCondition(), succ) else // Flow from last element of pattern to first element of body - first(super.getBody(), succ) + first(caseGetBody(this), succ) ) or // Flow from last element of condition to first element of body last(super.getCondition(), pred, c) and c instanceof TrueCompletion and - first(super.getBody(), succ) + first(caseGetBody(this), succ) } } @@ -1216,10 +1313,11 @@ module Statements { c instanceof NormalCompletion or // A statement exits with a `break` completion - last(super.getStmt(_), last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion()) + last(SwithStmtInternal::getStmt(this, _), last, + c.(NestedBreakCompletion).getAnInnerCompatibleCompletion()) or // A statement exits abnormally - last(super.getStmt(_), last, c) and + last(SwithStmtInternal::getStmt(this, _), last, c) and not c instanceof BreakCompletion and not c instanceof NormalCompletion and not any(LabeledStmtTree t | @@ -1228,8 +1326,8 @@ module Statements { or // Last case exits with a non-match exists(CaseStmt cs, int last_ | - last_ = max(int i | exists(super.getCase(i))) and - cs = super.getCase(last_) + last_ = max(int i | exists(SwithStmtInternal::getCase(this, i))) and + cs = SwithStmtInternal::getCase(this, last_) | last(cs.getPattern(), last, c) and not c.(MatchingCompletion).isMatch() @@ -1248,22 +1346,22 @@ module Statements { c instanceof SimpleCompletion or // Flow from last element of non-`case` statement `i` to first element of statement `i+1` - exists(int i | last(super.getStmt(i), pred, c) | - not super.getStmt(i) instanceof CaseStmt and + exists(int i | last(SwithStmtInternal::getStmt(this, i), pred, c) | + not SwithStmtInternal::getStmt(this, i) instanceof CaseStmt and c instanceof NormalCompletion and - first(super.getStmt(i + 1), succ) + first(SwithStmtInternal::getStmt(this, i + 1), succ) ) or // Flow from last element of `case` statement `i` to first element of statement `i+1` exists(int i, Stmt body | - body = super.getStmt(i).(CaseStmt).getBody() and + body = caseStmtGetBody(SwithStmtInternal::getStmt(this, i)) and // in case of fall-through cases, make sure to not jump from their shared body back // to one of the fall-through cases - not body = super.getStmt(i + 1).(CaseStmt).getBody() and + not body = caseStmtGetBody(SwithStmtInternal::getStmt(this, i + 1)) and last(body, pred, c) | c instanceof NormalCompletion and - first(super.getStmt(i + 1), succ) + first(SwithStmtInternal::getStmt(this, i + 1), succ) ) } } @@ -1279,7 +1377,7 @@ module Statements { not c.(MatchingCompletion).isMatch() or // Case body exits with any completion - last(super.getBody(), last, c) + last(caseStmtGetBody(this), last, c) } final override predicate succ(AstNode pred, AstNode succ, Completion c) { diff --git a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll b/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll deleted file mode 100644 index 38eca378edf2..000000000000 --- a/csharp/ql/lib/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll +++ /dev/null @@ -1,175 +0,0 @@ -/** - * INTERNAL: Do not use. - * - * Provides a basic block implementation on control flow elements. That is, - * a "pre-CFG" where the nodes are (unsplit) control flow elements and the - * successor relation is `succ = succ(pred, _)`. - * - * The logic is duplicated from the implementation in `BasicBlocks.qll`, and - * being an internal class, all predicate documentation has been removed. - */ - -import csharp -private import Completion -private import ControlFlowGraphImpl -private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg -private import codeql.controlflow.BasicBlock as BB - -private predicate startsBB(ControlFlowElement cfe) { - not succ(_, cfe, _) and - ( - succ(cfe, _, _) - or - scopeLast(_, cfe, _) - ) - or - strictcount(ControlFlowElement pred, Completion c | succ(pred, cfe, c)) > 1 - or - succ(_, cfe, any(ConditionalCompletion c)) - or - exists(ControlFlowElement pred, int i | - succ(pred, cfe, _) and - i = count(ControlFlowElement succ, Completion c | succ(pred, succ, c)) - | - i > 1 - or - i = 1 and - scopeLast(_, pred, _) - ) -} - -private predicate intraBBSucc(ControlFlowElement pred, ControlFlowElement succ) { - succ(pred, succ, _) and - not startsBB(succ) -} - -private predicate bbIndex(ControlFlowElement bbStart, ControlFlowElement cfe, int i) = - shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfe, i) - -private predicate succBB(PreBasicBlock pred, PreBasicBlock succ) { succ = pred.getASuccessor() } - -private predicate entryBB(PreBasicBlock bb) { scopeFirst(_, bb) } - -private predicate bbIDominates(PreBasicBlock dom, PreBasicBlock bb) = - idominance(entryBB/1, succBB/2)(_, dom, bb) - -class PreBasicBlock extends ControlFlowElement { - PreBasicBlock() { startsBB(this) } - - PreBasicBlock getASuccessor(Cfg::SuccessorType t) { - succ(this.getLastNode(), result, any(Completion c | t = c.getAMatchingSuccessorType())) - } - - deprecated PreBasicBlock getASuccessorByType(Cfg::SuccessorType t) { - result = this.getASuccessor(t) - } - - PreBasicBlock getASuccessor() { result = this.getASuccessor(_) } - - PreBasicBlock getAPredecessor() { result.getASuccessor() = this } - - ControlFlowElement getNode(int pos) { bbIndex(this, result, pos) } - - deprecated ControlFlowElement getElement(int pos) { result = this.getNode(pos) } - - ControlFlowElement getAnElement() { result = this.getNode(_) } - - ControlFlowElement getFirstElement() { result = this } - - ControlFlowElement getLastNode() { result = this.getNode(this.length() - 1) } - - deprecated ControlFlowElement getLastElement() { result = this.getLastNode() } - - int length() { result = strictcount(this.getAnElement()) } - - PreBasicBlock getImmediateDominator() { bbIDominates(result, this) } - - predicate immediatelyDominates(PreBasicBlock bb) { bbIDominates(this, bb) } - - pragma[inline] - predicate strictlyDominates(PreBasicBlock bb) { this.immediatelyDominates+(bb) } - - pragma[inline] - predicate dominates(PreBasicBlock bb) { - bb = this - or - this.strictlyDominates(bb) - } - - predicate inDominanceFrontier(PreBasicBlock df) { - this = df.getAPredecessor() and not bbIDominates(this, df) - or - exists(PreBasicBlock prev | prev.inDominanceFrontier(df) | - bbIDominates(this, prev) and - not bbIDominates(this, df) - ) - } - - /** Unsupported. Do not use. */ - predicate strictlyPostDominates(PreBasicBlock bb) { none() } - - /** Unsupported. Do not use. */ - predicate postDominates(PreBasicBlock bb) { - this.strictlyPostDominates(bb) or - this = bb - } -} - -private Completion getConditionalCompletion(ConditionalCompletion cc) { - result.getInnerCompletion() = cc -} - -pragma[nomagic] -private predicate conditionBlockImmediatelyControls( - ConditionBlock cond, PreBasicBlock succ, ConditionalCompletion cc -) { - exists(ControlFlowElement last, Completion c | - last = cond.getLastNode() and - c = getConditionalCompletion(cc) and - succ(last, succ, c) and - // In the pre-CFG, we need to account for case where one predecessor node has - // two edges to the same successor node. Assertion expressions are examples of - // such nodes. - not exists(Completion other | - succ(last, succ, other) and - other != c - ) and - forall(PreBasicBlock pred | pred = succ.getAPredecessor() and pred != cond | - succ.dominates(pred) - ) - ) -} - -class ConditionBlock extends PreBasicBlock { - ConditionBlock() { - exists(Completion c | c = getConditionalCompletion(_) | - succ(this.getLastNode(), _, c) - or - scopeLast(_, this.getLastNode(), c) - ) - } - - pragma[nomagic] - predicate controls(PreBasicBlock controlled, Cfg::ConditionalSuccessor s) { - exists(PreBasicBlock succ, ConditionalCompletion c | - conditionBlockImmediatelyControls(this, succ, c) - | - succ.dominates(controlled) and - s = c.getAMatchingSuccessorType() - ) - } -} - -module PreCfg implements BB::CfgSig { - class ControlFlowNode = ControlFlowElement; - - class BasicBlock = PreBasicBlock; - - class EntryBasicBlock extends BasicBlock { - EntryBasicBlock() { entryBB(this) } - } - - predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) { - conditionBlockImmediatelyControls(bb1, bb2, _) - } -} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll index 8ab7bb0fba43..706893c64ea0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll @@ -15,16 +15,47 @@ private class ControlFlowScope extends ControlFlowElement { predicate isNonExact() { exactScope = false } } -private ControlFlowElement getANonExactScopeChild(ControlFlowScope scope) { - scope.isNonExact() and - result = scope +private newtype TControlFlowElementOrBasicBlock = + TControlFlowElement(ControlFlowElement cfe) or + TBasicBlock(ControlFlow::BasicBlock bb) + +class ControlFlowElementOrBasicBlock extends TControlFlowElementOrBasicBlock { + ControlFlowElement asControlFlowElement() { this = TControlFlowElement(result) } + + ControlFlow::BasicBlock asBasicBlock() { this = TBasicBlock(result) } + + string toString() { + result = this.asControlFlowElement().toString() + or + result = this.asBasicBlock().toString() + } + + Location getLocation() { + result = this.asControlFlowElement().getLocation() + or + result = this.asBasicBlock().getLocation() + } +} + +private predicate isBasicBlock(ControlFlowElementOrBasicBlock c) { c instanceof TBasicBlock } + +private predicate isNonExactScope(ControlFlowElementOrBasicBlock c) { + c.asControlFlowElement().(ControlFlowScope).isNonExact() +} + +private predicate step(ControlFlowElementOrBasicBlock pred, ControlFlowElementOrBasicBlock succ) { + pred.asBasicBlock().getANode().getAstNode() = succ.asControlFlowElement() or - result = getANonExactScopeChild(scope).getAChild() + pred.asControlFlowElement() = succ.asControlFlowElement().getAChild() } +private predicate basicBlockInNonExactScope( + ControlFlowElementOrBasicBlock bb, ControlFlowElementOrBasicBlock scope +) = doublyBoundedFastTC(step/2, isBasicBlock/1, isNonExactScope/1)(bb, scope) + pragma[noinline] private ControlFlow::BasicBlock getABasicBlockInScope(ControlFlowScope scope, boolean exactScope) { - result.getANode().getAstNode() = getANonExactScopeChild(scope) and + basicBlockInNonExactScope(TBasicBlock(result), TControlFlowElement(scope)) and exactScope = false or scope.isExact() and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 1b3de63495f0..70161a6fc477 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -6,7 +6,9 @@ private import ControlFlowReachability private import FlowSummaryImpl as FlowSummaryImpl private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary private import semmle.code.csharp.dataflow.internal.ExternalFlow +private import semmle.code.csharp.commons.Collections private import semmle.code.csharp.Conversion +private import semmle.code.csharp.exprs.internal.Expr private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl private import semmle.code.csharp.ExprOrStmtParent private import semmle.code.csharp.Unification @@ -16,7 +18,6 @@ private import semmle.code.csharp.frameworks.EntityFramework private import semmle.code.csharp.frameworks.system.linq.Expressions private import semmle.code.csharp.frameworks.NHibernate private import semmle.code.csharp.frameworks.Razor -private import semmle.code.csharp.frameworks.system.Collections private import semmle.code.csharp.frameworks.system.threading.Tasks private import semmle.code.csharp.internal.Location private import codeql.util.Unit @@ -1087,7 +1088,7 @@ predicate exprMayHavePostUpdateNode(Expr e) { or t = any(TypeParameter tp | not tp.isValueType()) or - t.isRefLikeType() + t instanceof Struct ) } @@ -2377,6 +2378,16 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { storeStepDelegateCall(node1, c, node2) } +pragma[nomagic] +private predicate isAssignExprLValueDescendant(Expr e) { + e = any(AssignExpr ae).getLValue() + or + exists(Expr parent | + isAssignExprLValueDescendant(parent) and + e = parent.getAChildExpr() + ) +} + private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration { ReadStepConfiguration() { this = "ReadStepConfiguration" } @@ -2432,7 +2443,7 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration scope = any(AssignExpr ae | ae = defTo.(AssignableDefinitions::TupleAssignmentDefinition).getAssignment() and - e = ae.getLValue().getAChildExpr*().(TupleExpr) and + isAssignExprLValueDescendant(e.(TupleExpr)) and exactScope = false and isSuccessor = true ) @@ -2488,7 +2499,7 @@ private predicate readContentStep(Node node1, Content c, Node node2) { ) or // item = variable in node1 = (..., variable, ...) in a case/is var (..., ...) - te = any(PatternExpr pe).getAChildExpr*() and + isPatternExprDescendant(te) and exists(AssignableDefinitions::LocalVariableDefinition lvd | node2.(AssignableDefinitionNode).getDefinition() = lvd and lvd.getDeclaration() = item and @@ -2545,6 +2556,7 @@ private predicate clearsCont(Node n, Content c) { a.getType() = s and f = s.getAField() and c.(FieldContent).getField() = f.getUnboundDeclaration() and + not f.getType() instanceof CollectionType and not f.isRef() ) or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll index edfaae018e98..024e9cf119d5 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll @@ -239,12 +239,25 @@ module ModelValidation { ) } + private string getIncorrectConstructorSummaryOutput() { + exists(string namespace, string type, string name, string output | + type = name or + type = name + "<" + any(string s) + | + summaryModel(namespace, type, _, name, _, _, _, output, _, _, _) and + output.matches("ReturnValue%") and + result = + "Constructor model for " + namespace + "." + type + + " should use `Argument[this]` in the output, not `ReturnValue`." + ) + } + /** Holds if some row in a MaD flow model appears to contain typos. */ query predicate invalidModelRow(string msg) { msg = [ getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(), - KindVal::getInvalidModelKind() + getIncorrectConstructorSummaryOutput(), KindVal::getInvalidModelKind() ] } } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index b24a104d3880..bb08c8f7e2ca 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -109,6 +109,16 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon } } +private ControlFlow::Nodes::ExprNode getALastEvalNode(ControlFlow::Nodes::ExprNode cfn) { + exists(OperatorCall oc | any(LocalTaintExprStepConfiguration x).hasExprPath(_, result, oc, cfn) | + oc.getTarget() instanceof ImplicitConversionOperator + ) +} + +private ControlFlow::Nodes::ExprNode getPostUpdateReverseStep(ControlFlow::Nodes::ExprNode e) { + result = getALastEvalNode(e) +} + private predicate localTaintStepCommon(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { hasNodePath(any(LocalTaintExprStepConfiguration x), nodeFrom, nodeTo) } @@ -177,6 +187,16 @@ private module Cached { readStep(nodeFrom, any(DataFlow::ContentSet c | c.isElement()), nodeTo) or nodeTo = nodeFrom.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false) + or + // Allow reverse update flow for implicit conversion operator calls. + // This is needed to support flow out of method call arguments, where an implicit conversion is applied + // to a call argument. + nodeTo.(PostUpdateNode).getPreUpdateNode().(DataFlow::ExprNode).getControlFlowNode() = + getPostUpdateReverseStep(nodeFrom + .(PostUpdateNode) + .getPreUpdateNode() + .(DataFlow::ExprNode) + .getControlFlowNode()) ) and model = "" or diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll index 8ab7bb0fba43..706893c64ea0 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll @@ -15,16 +15,47 @@ private class ControlFlowScope extends ControlFlowElement { predicate isNonExact() { exactScope = false } } -private ControlFlowElement getANonExactScopeChild(ControlFlowScope scope) { - scope.isNonExact() and - result = scope +private newtype TControlFlowElementOrBasicBlock = + TControlFlowElement(ControlFlowElement cfe) or + TBasicBlock(ControlFlow::BasicBlock bb) + +class ControlFlowElementOrBasicBlock extends TControlFlowElementOrBasicBlock { + ControlFlowElement asControlFlowElement() { this = TControlFlowElement(result) } + + ControlFlow::BasicBlock asBasicBlock() { this = TBasicBlock(result) } + + string toString() { + result = this.asControlFlowElement().toString() + or + result = this.asBasicBlock().toString() + } + + Location getLocation() { + result = this.asControlFlowElement().getLocation() + or + result = this.asBasicBlock().getLocation() + } +} + +private predicate isBasicBlock(ControlFlowElementOrBasicBlock c) { c instanceof TBasicBlock } + +private predicate isNonExactScope(ControlFlowElementOrBasicBlock c) { + c.asControlFlowElement().(ControlFlowScope).isNonExact() +} + +private predicate step(ControlFlowElementOrBasicBlock pred, ControlFlowElementOrBasicBlock succ) { + pred.asBasicBlock().getANode().getAstNode() = succ.asControlFlowElement() or - result = getANonExactScopeChild(scope).getAChild() + pred.asControlFlowElement() = succ.asControlFlowElement().getAChild() } +private predicate basicBlockInNonExactScope( + ControlFlowElementOrBasicBlock bb, ControlFlowElementOrBasicBlock scope +) = doublyBoundedFastTC(step/2, isBasicBlock/1, isNonExactScope/1)(bb, scope) + pragma[noinline] private ControlFlow::BasicBlock getABasicBlockInScope(ControlFlowScope scope, boolean exactScope) { - result.getANode().getAstNode() = getANonExactScopeChild(scope) and + basicBlockInNonExactScope(TBasicBlock(result), TControlFlowElement(scope)) and exactScope = false or scope.isExact() and diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll index a5576f023d7b..9fa2a93724d4 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Assignment.qll @@ -11,7 +11,7 @@ import Expr * (`LocalVariableDeclAndInitExpr`), a simple assignment (`AssignExpr`), or * an assignment operation (`AssignOperation`). */ -class Assignment extends Operation, @assign_expr { +class Assignment extends BinaryOperation, @assign_expr { Assignment() { this instanceof LocalVariableDeclExpr implies @@ -20,6 +20,10 @@ class Assignment extends Operation, @assign_expr { expr_parent(_, 0, this) } + override Expr getLeftOperand() { result = this.getChild(1) } + + override Expr getRightOperand() { result = this.getChild(0) } + /** Gets the left operand of this assignment. */ Expr getLValue() { result = this.getChild(1) } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index ada010652588..c3b9bcc363b3 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -21,6 +21,7 @@ import semmle.code.csharp.Type private import semmle.code.csharp.ExprOrStmtParent private import semmle.code.csharp.frameworks.System private import semmle.code.csharp.TypeRef +private import internal.Expr /** * An expression. Either an access (`Access`), a call (`Call`), an object or @@ -64,14 +65,24 @@ class Expr extends ControlFlowElement, @expr { /** Gets the enclosing callable of this expression, if any. */ override Callable getEnclosingCallable() { enclosingCallable(this, result) } + pragma[nomagic] + private predicate isExpandedAssignmentRValueDescendant() { + this = + any(AssignOperation op).getExpandedAssignment().getRValue().getChildExpr(0).getAChildExpr() + or + exists(Expr parent | + parent.isExpandedAssignmentRValueDescendant() and + this = parent.getAChildExpr() + ) + } + /** * Holds if this expression is generated by the compiler and does not appear * explicitly in the source code. */ final predicate isImplicit() { compiler_generated(this) or - this = - any(AssignOperation op).getExpandedAssignment().getRValue().getChildExpr(0).getAChildExpr+() + this.isExpandedAssignmentRValueDescendant() } /** @@ -233,7 +244,8 @@ class UnaryOperation extends Operation, @un_op { * A binary operation. Either a binary arithmetic operation * (`BinaryArithmeticOperation`), a binary bitwise operation * (`BinaryBitwiseOperation`), a comparison operation (`ComparisonOperation`), - * or a binary logical operation (`BinaryLogicalOperation`). + * a binary logical operation (`BinaryLogicalOperation`), or an + * assignment (`Assignment`). */ class BinaryOperation extends Operation, @bin_op { /** Gets the left operand of this binary operation. */ @@ -1133,7 +1145,7 @@ class TupleExpr extends Expr, @tuple_expr { /** Holds if this expression is a tuple construction. */ predicate isConstruction() { not this = getAnAssignOrForeachChild() and - not this = any(PatternExpr pe).getAChildExpr*() + not isPatternExprDescendant(this) } override string getAPrimaryQlClass() { result = "TupleExpr" } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/internal/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/internal/Expr.qll new file mode 100644 index 000000000000..94dfac721932 --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/exprs/internal/Expr.qll @@ -0,0 +1,11 @@ +private import csharp + +pragma[nomagic] +predicate isPatternExprDescendant(Expr e) { + e instanceof PatternExpr + or + exists(Expr parent | + isPatternExprDescendant(parent) and + e = parent.getAChildExpr() + ) +} diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme index 178a7e6cf335..e73ca2c93df8 100644 --- a/csharp/ql/lib/semmlecode.csharp.dbscheme +++ b/csharp/ql/lib/semmlecode.csharp.dbscheme @@ -1261,10 +1261,10 @@ case @expr.kind of @rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; @comp_expr = @equality_op_expr | @rel_op_expr; -@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; +@op_expr = @un_op | @bin_op | @ternary_op; @ternary_op = @ternary_log_op_expr; -@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; @un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr | @pointer_indirection_expr | @address_of_expr; diff --git a/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/old.dbscheme b/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/old.dbscheme new file mode 100644 index 000000000000..178a7e6cf335 --- /dev/null +++ b/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/old.dbscheme @@ -0,0 +1,1489 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile.rsp` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Overlay support + */ + +/** + * The CLI will automatically emit the tuple `databaseMetadata("isOverlay", "true")`, + * along with an `overlayChangedFiles` tuple for each new/modified/deleted file, + * when building an overlay database, and these can be used by the discard predicates. + */ +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path : string ref +); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +@locatable = @declaration_with_accessors | @callable_accessor | @declaration_or_directive + | @diagnostic | @extractor_message | @preprocessor_directive | @attribute | @type_mention | @type_parameter_constraints + | @declaration_with_accessors | @callable_accessor | @operator | @method + | @constructor | @destructor | @field | @local_variable | @parameter | @stmt | @expr + | @xmllocatable | @commentline | @commentblock | @asp_element + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type +| 34 = @inline_array_type +| 35 = @extension_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type | @extension_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extension_receiver_type( + unique int extension: @extension_type ref, + int receiver_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event | @operator; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type | @extension_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +@has_scoped_annotation = @local_scope_variable + +scoped_annotation( + int id: @has_scoped_annotation ref, + int kind: int ref // scoped ref = 1, scoped value = 2 + ); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @utf16_string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr +| 133 = @urshift_expr +| 134 = @assign_urshift_expr +| 135 = @utf8_string_literal_expr +/* C# 12.0 */ +| 136 = @collection_expr +| 137 = @spread_element_expr +| 138 = @interpolated_string_insert_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr | @urshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/* Compiler generated */ + +compiler_generated(unique int id: @element ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); diff --git a/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/semmlecode.csharp.dbscheme b/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/semmlecode.csharp.dbscheme new file mode 100644 index 000000000000..e73ca2c93df8 --- /dev/null +++ b/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/semmlecode.csharp.dbscheme @@ -0,0 +1,1489 @@ +/* This is a dummy line to alter the dbscheme, so we can make a database upgrade + * without actually changing any of the dbscheme predicates. It contains a date + * to allow for such updates in the future as well. + * + * 2021-07-14 + * + * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a + * previously seen state (matching a previously seen SHA), which would make the upgrade + * mechanism not work properly. + */ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | f1.cs + * 3 | f2.cs + * 4 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@someFile.rsp` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +compilation_assembly( + unique int id : @compilation ref, + int assembly: @assembly ref +) + +// Populated by the CSV extractor +externalData( + int id: @externalDataElement, + string path: string ref, + int column: int ref, + string value: string ref); + +sourceLocationPrefix( + string prefix: string ref); + +/* + * Overlay support + */ + +/** + * The CLI will automatically emit the tuple `databaseMetadata("isOverlay", "true")`, + * along with an `overlayChangedFiles` tuple for each new/modified/deleted file, + * when building an overlay database, and these can be used by the discard predicates. + */ +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path : string ref +); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @externalDataElement + | @xmllocatable | @asp_element | @namespace | @preprocessor_directive; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors + | @local_function | @lambda_expr; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +@locatable = @declaration_with_accessors | @callable_accessor | @declaration_or_directive + | @diagnostic | @extractor_message | @preprocessor_directive | @attribute | @type_mention | @type_parameter_constraints + | @declaration_with_accessors | @callable_accessor | @operator | @method + | @constructor | @destructor | @field | @local_variable | @parameter | @stmt | @expr + | @xmllocatable | @commentline | @commentblock | @asp_element + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +locations_mapped( + unique int id: @location_default ref, + int mapped_to: @location_default ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + string fullname: string ref, + string name: string ref, + string version: string ref); + +files( + unique int id: @file, + string name: string ref); + +folders( + unique int id: @folder, + string name: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + string name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_global( + unique int id: @using_directive ref +); + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning + | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if + | @directive_elif | @directive_else | @directive_endif; + +@conditional_directive = @directive_if | @directive_elif; +@branch_directive = @directive_if | @directive_elif | @directive_else; + +directive_ifs( + unique int id: @directive_if, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref); /* 0: false, 1: true */ + +directive_elifs( + unique int id: @directive_elif, + int branchTaken: int ref, /* 0: false, 1: true */ + int conditionValue: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +directive_elses( + unique int id: @directive_else, + int branchTaken: int ref, /* 0: false, 1: true */ + int parent: @directive_if ref, + int index: int ref); + +#keyset[id, start] +directive_endifs( + unique int id: @directive_endif, + unique int start: @directive_if ref); + +directive_define_symbols( + unique int id: @define_symbol_expr ref, + string name: string ref); + +directive_regions( + unique int id: @directive_region, + string name: string ref); + +#keyset[id, start] +directive_endregions( + unique int id: @directive_endregion, + unique int start: @directive_region ref); + +directive_lines( + unique int id: @directive_line, + int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */ + +directive_line_value( + unique int id: @directive_line ref, + int line: int ref); + +directive_line_file( + unique int id: @directive_line ref, + int file: @file ref); + +directive_line_offset( + unique int id: @directive_line ref, + int offset: int ref); + +directive_line_span( + unique int id: @directive_line ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +directive_nullables( + unique int id: @directive_nullable, + int setting: int ref, /* 0: disable, 1: enable, 2: restore */ + int target: int ref); /* 0: none, 1: annotations, 2: warnings */ + +directive_warnings( + unique int id: @directive_warning, + string message: string ref); + +directive_errors( + unique int id: @directive_error, + string message: string ref); + +directive_undefines( + unique int id: @directive_undefine, + string name: string ref); + +directive_defines( + unique int id: @directive_define, + string name: string ref); + +pragma_checksums( + unique int id: @pragma_checksum, + int file: @file ref, + string guid: string ref, + string bytes: string ref); + +pragma_warnings( + unique int id: @pragma_warning, + int kind: int ref /* 0 = disable, 1 = restore */); + +#keyset[id, index] +pragma_warning_error_codes( + int id: @pragma_warning ref, + string errorCode: string ref, + int index: int ref); + +preprocessor_directive_location( + unique int id: @preprocessor_directive ref, + int loc: @location ref); + +preprocessor_directive_compilation( + int id: @preprocessor_directive ref, + int compilation: @compilation ref); + +preprocessor_directive_active( + unique int id: @preprocessor_directive ref, + int active: int ref); /* 0: false, 1: true */ + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + string name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type +| 33 = @function_pointer_type +| 34 = @inline_array_type +| 35 = @extension_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type | @void_type | @inline_array_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type | @extension_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + string name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +function_pointer_return_type( + unique int function_pointer_id: @function_pointer_type ref, + int return_type_id: @type_or_ref ref); + +extension_receiver_type( + unique int extension: @extension_type ref, + int receiver_type_id: @type_or_ref ref); + +extend( + int sub: @type ref, + int super: @type_or_ref ref); + +anonymous_types( + unique int id: @type ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int kind: int ref, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +case @attribute.kind of + 0 = @attribute_default +| 1 = @attribute_return +| 2 = @attribute_assembly +| 3 = @attribute_module +; + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref); + +/** + * The nullable flow state of an expression, as determined by Roslyn. + * 0 = none (default, not populated) + * 1 = not null + * 2 = maybe null + */ +expr_flowstate(unique int id: @expr ref, int state: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** FUNCTION POINTERS */ + +function_pointer_calling_conventions( + int id: @function_pointer_type ref, + int kind: int ref); + +#keyset[id, index] +has_unmanaged_calling_conventions( + int id: @function_pointer_type ref, + int index: int ref, + int conv_id: @type_or_ref ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr; + +modifiers( + unique int id: @modifier, + string name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event | @operator; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + string name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + string name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +init_only_accessors( + unique int id: @accessor ref); + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + string name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + string name: string ref, + string symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + string name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + string name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + string name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + string name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type | @extension_type; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + string name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, params/array = 3, this = 4, in = 5, ref readonly = 6 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +@has_scoped_annotation = @local_scope_variable + +scoped_annotation( + int id: @has_scoped_annotation ref, + int kind: int ref // scoped ref = 1, scoped value = 2 + ); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +foreach_stmt_info( + unique int id: @foreach_stmt ref, + int kind: int ref /* non-async = 1, async = 2 */); + +@foreach_symbol = @method | @property | @type_or_ref; + +#keyset[id, kind] +foreach_stmt_desugar( + int id: @foreach_stmt ref, + int symbol: @foreach_symbol ref, + int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @utf16_string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +/* C# 9.0 */ +| 122 = @lt_pattern_expr +| 123 = @gt_pattern_expr +| 124 = @le_pattern_expr +| 125 = @ge_pattern_expr +| 126 = @not_pattern_expr +| 127 = @and_pattern_expr +| 128 = @or_pattern_expr +| 129 = @function_pointer_invocation_expr +| 130 = @with_expr +/* C# 11.0 */ +| 131 = @list_pattern_expr +| 132 = @slice_pattern_expr +| 133 = @urshift_expr +| 134 = @assign_urshift_expr +| 135 = @utf8_string_literal_expr +/* C# 12.0 */ +| 136 = @collection_expr +| 137 = @spread_element_expr +| 138 = @interpolated_string_insert_expr +/* Preprocessor */ +| 999 = @define_symbol_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; +@unary_pattern_expr = @not_pattern_expr; +@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr; +@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@string_literal_expr = @utf16_string_literal_expr | @utf8_string_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr | @assign_urshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr | @urshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @assign_expr | @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr | @function_pointer_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +stackalloc_array_creation( + unique int id: @array_creation_expr ref); + +implicitly_typed_object_creation( + unique int id: @implicitly_typeable_object_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_value( + unique int id: @expr ref, + string value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + string name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + string name: string ref); + +lambda_expr_return_type( + unique int id: @lambda_expr ref, + int type_id: @type_or_ref ref); + +/* Compiler generated */ + +compiler_generated(unique int id: @element ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + string text: string ref, + string rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + string name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + string name: string ref); +asp_element_body( + unique int element: @asp_element ref, + string body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + string name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + string name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); diff --git a/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/upgrade.properties b/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/upgrade.properties new file mode 100644 index 000000000000..0722ccf985d5 --- /dev/null +++ b/csharp/ql/lib/upgrades/178a7e6cf335486d33d4e49543148e3f57f04a9a/upgrade.properties @@ -0,0 +1,2 @@ +description: Expand @bin_op union to include @assign_expr +compatibility: full diff --git a/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql b/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql index d40a28450fca..b980bfba1aea 100644 --- a/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql +++ b/csharp/ql/src/Likely Bugs/DangerousNonShortCircuitLogic.ql @@ -15,23 +15,6 @@ import csharp -/** An expression containing a qualified member access, a method call, or an array access. */ -class DangerousExpression extends Expr { - DangerousExpression() { - exists(Expr e | this = e.getParent*() | - exists(Expr q | q = e.(MemberAccess).getQualifier() | - not q instanceof ThisAccess and - not q instanceof BaseAccess - ) - or - e instanceof MethodCall - or - e instanceof ArrayAccess - ) and - not exists(Expr e | this = e.getParent*() | e.(Call).getTarget().getAParameter().isOutOrRef()) - } -} - /** A use of `&` or `|` on operands of type boolean. */ class NonShortCircuit extends BinaryBitwiseOperation { NonShortCircuit() { @@ -42,10 +25,40 @@ class NonShortCircuit extends BinaryBitwiseOperation { ) and not exists(AssignBitwiseOperation abo | abo.getExpandedAssignment().getRValue() = this) and this.getLeftOperand().getType() instanceof BoolType and - this.getRightOperand().getType() instanceof BoolType and - this.getRightOperand() instanceof DangerousExpression + this.getRightOperand().getType() instanceof BoolType + } + + pragma[nomagic] + private predicate hasRightOperandDescendant(Expr e) { + e = this.getRightOperand() + or + exists(Expr parent | + this.hasRightOperandDescendant(parent) and + e.getParent() = parent + ) + } + + /** + * Holds if this non-short-circuit expression contains a qualified member access, + * a method call, or an array access inside the right operand. + */ + predicate isDangerous() { + exists(Expr e | this.hasRightOperandDescendant(e) | + exists(Expr q | q = e.(MemberAccess).getQualifier() | + not q instanceof ThisAccess and + not q instanceof BaseAccess + ) + or + e instanceof MethodCall + or + e instanceof ArrayAccess + ) and + not exists(Expr e | this.hasRightOperandDescendant(e) | + e.(Call).getTarget().getAParameter().isOutOrRef() + ) } } from NonShortCircuit e +where e.isDangerous() select e, "Potentially dangerous use of non-short circuit logic." diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index c09ee09f35b8..6290164f0bbc 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 1.6.3 +version: 1.6.4-dev groups: - csharp - queries diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index ebe04faf7258..b2094817cfb6 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -321,6 +321,7 @@ | CSharp7.cs:283:20:283:62 | call to method Select,(Int32,String)> | CSharp7.cs:283:13:283:16 | access to local variable list | | CSharp7.cs:283:32:283:35 | SSA param(item) | CSharp7.cs:283:41:283:44 | access to parameter item | | CSharp7.cs:283:32:283:35 | item | CSharp7.cs:283:32:283:35 | SSA param(item) | +| CSharp7.cs:283:41:283:44 | [post] access to parameter item | CSharp7.cs:283:51:283:54 | access to parameter item | | CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:41:283:48 | access to property Key | | CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:51:283:54 | access to parameter item | | CSharp7.cs:283:51:283:54 | access to parameter item | CSharp7.cs:283:51:283:60 | access to property Value | diff --git a/csharp/ql/test/library-tests/dataflow/constructors/ConstructorFlow.expected b/csharp/ql/test/library-tests/dataflow/constructors/ConstructorFlow.expected index 678dca279ff0..6e063d49ef62 100644 --- a/csharp/ql/test/library-tests/dataflow/constructors/ConstructorFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/constructors/ConstructorFlow.expected @@ -122,6 +122,16 @@ edges | Constructors.cs:143:29:143:30 | access to local variable o2 : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj2] : Object | provenance | | | Constructors.cs:144:14:144:15 | access to local variable r1 : R1 [property Obj1] : Object | Constructors.cs:144:14:144:20 | access to property Obj1 | provenance | | | Constructors.cs:145:14:145:15 | access to local variable r1 : R1 [property Obj2] : Object | Constructors.cs:145:14:145:20 | access to property Obj2 | provenance | | +| Constructors.cs:157:40:157:40 | o : Object | Constructors.cs:157:52:157:52 | access to parameter o : Object | provenance | | +| Constructors.cs:157:46:157:48 | [post] this access : CPartial [property Obj] : Object | Constructors.cs:157:24:157:31 | this [Return] : CPartial [property Obj] : Object | provenance | | +| Constructors.cs:157:52:157:52 | access to parameter o : Object | Constructors.cs:157:46:157:48 | [post] this access : CPartial [property Obj] : Object | provenance | | +| Constructors.cs:162:13:162:13 | access to local variable o : Object | Constructors.cs:163:37:163:37 | access to local variable o : Object | provenance | | +| Constructors.cs:162:17:162:34 | call to method Source : Object | Constructors.cs:162:13:162:13 | access to local variable o : Object | provenance | | +| Constructors.cs:163:13:163:20 | access to local variable cPartial : CPartial [property Obj] : Object | Constructors.cs:164:14:164:21 | access to local variable cPartial : CPartial [property Obj] : Object | provenance | | +| Constructors.cs:163:24:163:38 | object creation of type CPartial : CPartial [property Obj] : Object | Constructors.cs:163:13:163:20 | access to local variable cPartial : CPartial [property Obj] : Object | provenance | | +| Constructors.cs:163:37:163:37 | access to local variable o : Object | Constructors.cs:157:40:157:40 | o : Object | provenance | | +| Constructors.cs:163:37:163:37 | access to local variable o : Object | Constructors.cs:163:24:163:38 | object creation of type CPartial : CPartial [property Obj] : Object | provenance | | +| Constructors.cs:164:14:164:21 | access to local variable cPartial : CPartial [property Obj] : Object | Constructors.cs:164:14:164:25 | access to property Obj | provenance | | nodes | Constructors.cs:3:18:3:26 | [post] this access : C_no_ctor [field s1] : Object | semmle.label | [post] this access : C_no_ctor [field s1] : Object | | Constructors.cs:5:24:5:25 | [post] this access : C_no_ctor [field s1] : Object | semmle.label | [post] this access : C_no_ctor [field s1] : Object | @@ -255,6 +265,17 @@ nodes | Constructors.cs:144:14:144:20 | access to property Obj1 | semmle.label | access to property Obj1 | | Constructors.cs:145:14:145:15 | access to local variable r1 : R1 [property Obj2] : Object | semmle.label | access to local variable r1 : R1 [property Obj2] : Object | | Constructors.cs:145:14:145:20 | access to property Obj2 | semmle.label | access to property Obj2 | +| Constructors.cs:157:24:157:31 | this [Return] : CPartial [property Obj] : Object | semmle.label | this [Return] : CPartial [property Obj] : Object | +| Constructors.cs:157:40:157:40 | o : Object | semmle.label | o : Object | +| Constructors.cs:157:46:157:48 | [post] this access : CPartial [property Obj] : Object | semmle.label | [post] this access : CPartial [property Obj] : Object | +| Constructors.cs:157:52:157:52 | access to parameter o : Object | semmle.label | access to parameter o : Object | +| Constructors.cs:162:13:162:13 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| Constructors.cs:162:17:162:34 | call to method Source : Object | semmle.label | call to method Source : Object | +| Constructors.cs:163:13:163:20 | access to local variable cPartial : CPartial [property Obj] : Object | semmle.label | access to local variable cPartial : CPartial [property Obj] : Object | +| Constructors.cs:163:24:163:38 | object creation of type CPartial : CPartial [property Obj] : Object | semmle.label | object creation of type CPartial : CPartial [property Obj] : Object | +| Constructors.cs:163:37:163:37 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| Constructors.cs:164:14:164:21 | access to local variable cPartial : CPartial [property Obj] : Object | semmle.label | access to local variable cPartial : CPartial [property Obj] : Object | +| Constructors.cs:164:14:164:25 | access to property Obj | semmle.label | access to property Obj | subpaths | Constructors.cs:44:18:44:19 | this access : C2 [parameter o21param] : Object | Constructors.cs:46:23:46:27 | this access : C2 [parameter o21param] : Object | Constructors.cs:46:23:46:27 | [post] this access : C2 [field Obj21] : Object | Constructors.cs:44:18:44:19 | [post] this access : C2 [field Obj21] : Object | | Constructors.cs:64:37:64:37 | access to parameter o : Object | Constructors.cs:57:54:57:55 | o2 : Object | Constructors.cs:59:13:59:14 | access to parameter o1 : Object | Constructors.cs:64:27:64:34 | access to parameter o22param : Object | @@ -273,6 +294,7 @@ subpaths | Constructors.cs:132:29:132:30 | access to local variable o2 : Object | Constructors.cs:121:38:121:40 | oc2 : Object | Constructors.cs:121:16:121:17 | this [Return] : C4 [property Obj2] : Object | Constructors.cs:132:18:132:31 | object creation of type C4 : C4 [property Obj2] : Object | | Constructors.cs:143:25:143:26 | access to local variable o1 : Object | Constructors.cs:137:29:137:32 | Obj1 : Object | Constructors.cs:137:19:137:20 | this [Return] : R1 [property Obj1] : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj1] : Object | | Constructors.cs:143:29:143:30 | access to local variable o2 : Object | Constructors.cs:137:42:137:45 | Obj2 : Object | Constructors.cs:137:19:137:20 | this [Return] : R1 [property Obj2] : Object | Constructors.cs:143:18:143:31 | object creation of type R1 : R1 [property Obj2] : Object | +| Constructors.cs:163:37:163:37 | access to local variable o : Object | Constructors.cs:157:40:157:40 | o : Object | Constructors.cs:157:24:157:31 | this [Return] : CPartial [property Obj] : Object | Constructors.cs:163:24:163:38 | object creation of type CPartial : CPartial [property Obj] : Object | testFailures #select | Constructors.cs:15:18:15:19 | access to field s1 | Constructors.cs:5:29:5:45 | call to method Source : Object | Constructors.cs:15:18:15:19 | access to field s1 | $@ | Constructors.cs:5:29:5:45 | call to method Source : Object | call to method Source : Object | @@ -288,3 +310,4 @@ testFailures | Constructors.cs:134:14:134:20 | access to property Obj2 | Constructors.cs:131:18:131:34 | call to method Source : Object | Constructors.cs:134:14:134:20 | access to property Obj2 | $@ | Constructors.cs:131:18:131:34 | call to method Source : Object | call to method Source : Object | | Constructors.cs:144:14:144:20 | access to property Obj1 | Constructors.cs:141:18:141:34 | call to method Source : Object | Constructors.cs:144:14:144:20 | access to property Obj1 | $@ | Constructors.cs:141:18:141:34 | call to method Source : Object | call to method Source : Object | | Constructors.cs:145:14:145:20 | access to property Obj2 | Constructors.cs:142:18:142:35 | call to method Source : Object | Constructors.cs:145:14:145:20 | access to property Obj2 | $@ | Constructors.cs:142:18:142:35 | call to method Source : Object | call to method Source : Object | +| Constructors.cs:164:14:164:25 | access to property Obj | Constructors.cs:162:17:162:34 | call to method Source : Object | Constructors.cs:164:14:164:25 | access to property Obj | $@ | Constructors.cs:162:17:162:34 | call to method Source : Object | call to method Source : Object | diff --git a/csharp/ql/test/library-tests/dataflow/constructors/Constructors.cs b/csharp/ql/test/library-tests/dataflow/constructors/Constructors.cs index 9eae5079d847..94beb58544b3 100644 --- a/csharp/ql/test/library-tests/dataflow/constructors/Constructors.cs +++ b/csharp/ql/test/library-tests/dataflow/constructors/Constructors.cs @@ -145,6 +145,25 @@ public void M7() Sink(r1.Obj2); // $ hasValueFlow=10 } + public partial class CPartial + { + public object Obj { get; } + + public partial CPartial(object o); + } + + public partial class CPartial + { + public partial CPartial(object o) => Obj = o; + } + + public void M8() + { + var o = Source(11); + var cPartial = new CPartial(o); + Sink(cPartial.Obj); // $ hasValueFlow=11 + } + public static void Sink(object o) { } public static T Source(object source) => throw null; diff --git a/csharp/ql/test/library-tests/dataflow/external-models/Sources.cs b/csharp/ql/test/library-tests/dataflow/external-models/Sources.cs index 6f73f096ef9c..10b8a37cc0f8 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/Sources.cs +++ b/csharp/ql/test/library-tests/dataflow/external-models/Sources.cs @@ -21,6 +21,9 @@ void Foo() x = TaggedSrcPropertyGetter; x = this[0]; + + S s; + StructSrc(s); } [SourceAttribute] @@ -65,7 +68,10 @@ void SrcArg(object src) { } [SourceAttribute] object this[int i] => null; + + void StructSrc(S s) { } } + struct S { } class SourceAttribute : System.Attribute { } } diff --git a/csharp/ql/test/library-tests/dataflow/external-models/srcs.expected b/csharp/ql/test/library-tests/dataflow/external-models/srcs.expected index 855e51fca562..063626c07265 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/srcs.expected +++ b/csharp/ql/test/library-tests/dataflow/external-models/srcs.expected @@ -11,9 +11,10 @@ invalidModelRow | Sources.cs:20:17:20:33 | call to method SrcTwoArg | local | | Sources.cs:22:17:22:39 | access to property TaggedSrcPropertyGetter | local | | Sources.cs:23:17:23:23 | access to indexer | local | -| Sources.cs:27:14:27:20 | this | local | -| Sources.cs:27:29:27:45 | taggedMethodParam | local | -| Sources.cs:31:47:31:60 | taggedSrcParam | local | -| Sources.cs:43:45:43:45 | p | local | -| Sources.cs:50:50:50:50 | p | local | -| Sources.cs:56:16:56:30 | this | local | +| Sources.cs:26:23:26:23 | [post] access to local variable s | local | +| Sources.cs:30:14:30:20 | this | local | +| Sources.cs:30:29:30:45 | taggedMethodParam | local | +| Sources.cs:34:47:34:60 | taggedSrcParam | local | +| Sources.cs:46:45:46:45 | p | local | +| Sources.cs:53:50:53:50 | p | local | +| Sources.cs:59:16:59:30 | this | local | diff --git a/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml index ca5103b1cd5e..b4dcd75be26e 100644 --- a/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml +++ b/csharp/ql/test/library-tests/dataflow/external-models/srcs.ext.yml @@ -19,3 +19,4 @@ extensions: - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute", "", "local", "manual"] - ["My.Qltest", "SourceAttribute", false, "", "", "Attribute.Getter", "ReturnValue", "local", "manual"] - ["My.Qltest", "A", false, "SrcTwoArg", "(System.String,System.String)", "", "ReturnValue", "local", "manual"] + - ["My.Qltest", "A", false, "StructSrc", "", "", "Argument[0]", "local", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/remote/RemoteFlowSource.cs b/csharp/ql/test/library-tests/dataflow/flowsources/remote/RemoteFlowSource.cs index 1693e584435f..5889183f5257 100644 --- a/csharp/ql/test/library-tests/dataflow/flowsources/remote/RemoteFlowSource.cs +++ b/csharp/ql/test/library-tests/dataflow/flowsources/remote/RemoteFlowSource.cs @@ -44,5 +44,13 @@ public static void M2(System.Web.HttpRequestBase request) { Use(request.Unvalidated.RawUrl); } + + public static async void M3(System.Net.WebSockets.WebSocket webSocket) + { + var buffer = new byte[1024]; + var segment = new ArraySegment(buffer); + var result = await webSocket.ReceiveAsync(segment, System.Threading.CancellationToken.None); + Use(segment); + } } } diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.expected b/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.expected index a683f688cc76..f5f541d73d53 100644 --- a/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.expected +++ b/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.expected @@ -9,3 +9,4 @@ | RemoteFlowSource.cs:40:17:40:23 | access to parameter request | ASP.NET query string | | RemoteFlowSource.cs:45:17:45:23 | access to parameter request | ASP.NET query string | | RemoteFlowSource.cs:45:17:45:42 | access to property RawUrl | ASP.NET unvalidated request data | +| RemoteFlowSource.cs:52:55:52:61 | [post] access to local variable segment | external | diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected index b7ae291bf0fb..9c7965a4b6a9 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected @@ -185,6 +185,10 @@ source | System.IO;StreamWriter;StreamWriter;(System.String,System.IO.FileStreamOptions);Argument[this];file-write;manual | | System.IO;StreamWriter;StreamWriter;(System.String,System.Text.Encoding,System.IO.FileStreamOptions);Argument[this];file-write;manual | | System.Net.Sockets;TcpClient;GetStream;();ReturnValue;remote;manual | +| System.Net.WebSockets;ClientWebSocket;ReceiveAsync;(System.ArraySegment,System.Threading.CancellationToken);Argument[0];remote;manual | +| System.Net.WebSockets;ClientWebSocket;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);Argument[0];remote;manual | +| System.Net.WebSockets;WebSocket;ReceiveAsync;(System.ArraySegment,System.Threading.CancellationToken);Argument[0];remote;manual | +| System.Net.WebSockets;WebSocket;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);Argument[0];remote;manual | | System;Console;Read;();ReturnValue;stdin;manual | | System;Console;ReadKey;();ReturnValue;stdin;manual | | System;Console;ReadKey;(System.Boolean);ReturnValue;stdin;manual | diff --git a/csharp/ql/test/library-tests/dataflow/operators/ImplicitConversionOperator.cs b/csharp/ql/test/library-tests/dataflow/operators/ImplicitConversionOperator.cs new file mode 100644 index 000000000000..05be934ecb37 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/operators/ImplicitConversionOperator.cs @@ -0,0 +1,14 @@ +using System; + +public class TestImplicitConversionOperator +{ + static void Sink(object o) { } + static void TaintArgument(ArraySegment segment) { } + + public void M1() + { + byte[] bytes = new byte[1]; + TaintArgument(bytes); + Sink(bytes); + } +} diff --git a/csharp/ql/test/library-tests/dataflow/operators/implicitConversionOperatorFlow.expected b/csharp/ql/test/library-tests/dataflow/operators/implicitConversionOperatorFlow.expected new file mode 100644 index 000000000000..e9daee309cc5 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/operators/implicitConversionOperatorFlow.expected @@ -0,0 +1,8 @@ +edges +| ImplicitConversionOperator.cs:11:23:11:27 | [post] call to operator implicit conversion : ArraySegment | ImplicitConversionOperator.cs:12:14:12:18 | access to local variable bytes | provenance | | +nodes +| ImplicitConversionOperator.cs:11:23:11:27 | [post] call to operator implicit conversion : ArraySegment | semmle.label | [post] call to operator implicit conversion : ArraySegment | +| ImplicitConversionOperator.cs:12:14:12:18 | access to local variable bytes | semmle.label | access to local variable bytes | +subpaths +#select +| ImplicitConversionOperator.cs:12:14:12:18 | access to local variable bytes | ImplicitConversionOperator.cs:11:23:11:27 | [post] call to operator implicit conversion : ArraySegment | ImplicitConversionOperator.cs:12:14:12:18 | access to local variable bytes | $@ | ImplicitConversionOperator.cs:11:23:11:27 | [post] call to operator implicit conversion : ArraySegment | [post] call to operator implicit conversion : ArraySegment | diff --git a/csharp/ql/test/library-tests/dataflow/operators/implicitConversionOperatorFlow.ql b/csharp/ql/test/library-tests/dataflow/operators/implicitConversionOperatorFlow.ql new file mode 100644 index 000000000000..74f7947a7c81 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/operators/implicitConversionOperatorFlow.ql @@ -0,0 +1,29 @@ +/** + * @kind path-problem + */ + +import csharp +import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate +import Taint::PathGraph + +module TaintConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(MethodCall mc | + mc.getTarget().hasName("TaintArgument") and + mc.getAnArgument() = src.(DataFlowPrivate::PostUpdateNode).getPreUpdateNode().asExpr() + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | + mc.getTarget().hasName("Sink") and + mc.getAnArgument() = sink.asExpr() + ) + } +} + +module Taint = TaintTracking::Global; + +from Taint::PathNode source, Taint::PathNode sink +where Taint::flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/csharp/ql/test/library-tests/dataflow/structs/StructFlow.expected b/csharp/ql/test/library-tests/dataflow/structs/StructFlow.expected new file mode 100644 index 000000000000..be27c832f117 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/structs/StructFlow.expected @@ -0,0 +1,92 @@ +models +edges +| structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | provenance | | +| structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | provenance | | +| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | provenance | | +| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | provenance | | +| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | provenance | | +| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | provenance | | +| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | provenance | | +| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | provenance | | +| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | provenance | | +| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | provenance | | +| structs.cs:18:21:18:37 | call to method Source : Object | structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | provenance | | +| structs.cs:18:21:18:37 | call to method Source : Object | structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | provenance | | +| structs.cs:24:13:24:13 | access to local variable o : Object | structs.cs:25:24:25:24 | access to local variable o : Object | provenance | | +| structs.cs:24:13:24:13 | access to local variable o : Object | structs.cs:25:24:25:24 | access to local variable o : Object | provenance | | +| structs.cs:24:17:24:33 | call to method Source : Object | structs.cs:24:13:24:13 | access to local variable o : Object | provenance | | +| structs.cs:24:17:24:33 | call to method Source : Object | structs.cs:24:13:24:13 | access to local variable o : Object | provenance | | +| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | provenance | | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | provenance | | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | provenance | | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | provenance | | +| structs.cs:25:24:25:24 | access to local variable o : Object | structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | provenance | | +| structs.cs:25:24:25:24 | access to local variable o : Object | structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | provenance | | +| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | provenance | | +| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | provenance | | +| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | structs.cs:26:14:26:22 | access to array element | provenance | | +| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | structs.cs:26:14:26:22 | access to array element | provenance | | +| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | provenance | | +| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | provenance | | +| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | provenance | | +| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | structs.cs:33:14:33:22 | access to array element | provenance | | +| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | structs.cs:33:14:33:22 | access to array element | provenance | | +nodes +| structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | semmle.label | this [Return] : S [field args, element] : Object | +| structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | semmle.label | this [Return] : S [field args, element] : Object | +| structs.cs:10:27:10:30 | args : Object[] [element] : Object | semmle.label | args : Object[] [element] : Object | +| structs.cs:10:27:10:30 | args : Object[] [element] : Object | semmle.label | args : Object[] [element] : Object | +| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | semmle.label | [post] this access : S [field args, element] : Object | +| structs.cs:12:13:12:16 | [post] this access : S [field args, element] : Object | semmle.label | [post] this access : S [field args, element] : Object | +| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | semmle.label | access to parameter args : Object[] [element] : Object | +| structs.cs:12:25:12:28 | access to parameter args : Object[] [element] : Object | semmle.label | access to parameter args : Object[] [element] : Object | +| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | semmle.label | s [Return] : S [field args, element] : Object | +| structs.cs:16:30:16:30 | s [Return] : S [field args, element] : Object | semmle.label | s [Return] : S [field args, element] : Object | +| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | semmle.label | [post] access to parameter s : S [field args, element] : Object | +| structs.cs:18:9:18:9 | [post] access to parameter s : S [field args, element] : Object | semmle.label | [post] access to parameter s : S [field args, element] : Object | +| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | semmle.label | [post] access to field args : Object[] [element] : Object | +| structs.cs:18:9:18:14 | [post] access to field args : Object[] [element] : Object | semmle.label | [post] access to field args : Object[] [element] : Object | +| structs.cs:18:21:18:37 | call to method Source : Object | semmle.label | call to method Source : Object | +| structs.cs:18:21:18:37 | call to method Source : Object | semmle.label | call to method Source : Object | +| structs.cs:24:13:24:13 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| structs.cs:24:13:24:13 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| structs.cs:24:17:24:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| structs.cs:24:17:24:33 | call to method Source : Object | semmle.label | call to method Source : Object | +| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object | +| structs.cs:25:13:25:13 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object | +| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | semmle.label | object creation of type S : S [field args, element] : Object | +| structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | semmle.label | object creation of type S : S [field args, element] : Object | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | semmle.label | [...] : Object[] [element] : Object | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | semmle.label | [...] : Object[] [element] : Object | +| structs.cs:25:24:25:24 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| structs.cs:25:24:25:24 | access to local variable o : Object | semmle.label | access to local variable o : Object | +| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object | +| structs.cs:26:14:26:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object | +| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object | +| structs.cs:26:14:26:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object | +| structs.cs:26:14:26:22 | access to array element | semmle.label | access to array element | +| structs.cs:26:14:26:22 | access to array element | semmle.label | access to array element | +| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | semmle.label | [post] access to local variable s : S [field args, element] : Object | +| structs.cs:32:20:32:20 | [post] access to local variable s : S [field args, element] : Object | semmle.label | [post] access to local variable s : S [field args, element] : Object | +| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object | +| structs.cs:33:14:33:14 | access to local variable s : S [field args, element] : Object | semmle.label | access to local variable s : S [field args, element] : Object | +| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object | +| structs.cs:33:14:33:19 | access to field args : Object[] [element] : Object | semmle.label | access to field args : Object[] [element] : Object | +| structs.cs:33:14:33:22 | access to array element | semmle.label | access to array element | +| structs.cs:33:14:33:22 | access to array element | semmle.label | access to array element | +subpaths +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | +| structs.cs:25:23:25:25 | [...] : Object[] [element] : Object | structs.cs:10:27:10:30 | args : Object[] [element] : Object | structs.cs:10:16:10:16 | this [Return] : S [field args, element] : Object | structs.cs:25:17:25:26 | object creation of type S : S [field args, element] : Object | +testFailures +#select +| structs.cs:26:14:26:22 | access to array element | structs.cs:24:17:24:33 | call to method Source : Object | structs.cs:26:14:26:22 | access to array element | $@ | structs.cs:24:17:24:33 | call to method Source : Object | call to method Source : Object | +| structs.cs:26:14:26:22 | access to array element | structs.cs:24:17:24:33 | call to method Source : Object | structs.cs:26:14:26:22 | access to array element | $@ | structs.cs:24:17:24:33 | call to method Source : Object | call to method Source : Object | +| structs.cs:33:14:33:22 | access to array element | structs.cs:18:21:18:37 | call to method Source : Object | structs.cs:33:14:33:22 | access to array element | $@ | structs.cs:18:21:18:37 | call to method Source : Object | call to method Source : Object | +| structs.cs:33:14:33:22 | access to array element | structs.cs:18:21:18:37 | call to method Source : Object | structs.cs:33:14:33:22 | access to array element | $@ | structs.cs:18:21:18:37 | call to method Source : Object | call to method Source : Object | diff --git a/csharp/ql/test/library-tests/dataflow/structs/StructFlow.ql b/csharp/ql/test/library-tests/dataflow/structs/StructFlow.ql new file mode 100644 index 000000000000..9ab95f59caf3 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/structs/StructFlow.ql @@ -0,0 +1,12 @@ +/** + * @kind path-problem + */ + +import csharp +import utils.test.InlineFlowTest +import DefaultFlowTest +import PathGraph + +from PathNode source, PathNode sink +where flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/csharp/ql/test/library-tests/dataflow/structs/structs.cs b/csharp/ql/test/library-tests/dataflow/structs/structs.cs new file mode 100644 index 000000000000..275e27512e42 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/structs/structs.cs @@ -0,0 +1,40 @@ +using System; + +public class Test +{ + public struct S + { + public int field; + public object[] args; + + public S(object[] args) + { + this.args = args; + } + } + + public void SetTainted(S s) + { + s.args[0] = Source(2); + s.field = Source(3); + } + + public void M1() + { + var o = Source(1); + var s = new S([o]); + Sink(s.args[0]); // $ hasValueFlow=1 + } + + public void M2() + { + var s = new S(new object[1]); + SetTainted(s); + Sink(s.args[0]); // $ hasValueFlow=2 + Sink(s.field); // $ no flow. + } + + public static void Sink(object o) { } + + static T Source(object source) => throw null; +} diff --git a/csharp/ql/test/library-tests/dispatch/CallGraph.expected b/csharp/ql/test/library-tests/dispatch/CallGraph.expected index 2feb959dd863..31e2a99ae24c 100644 --- a/csharp/ql/test/library-tests/dispatch/CallGraph.expected +++ b/csharp/ql/test/library-tests/dispatch/CallGraph.expected @@ -270,9 +270,10 @@ | ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:637:21:637:21 | M | | ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:646:21:646:21 | M | | ViableCallable.cs:679:17:679:20 | Run3 | ViableCallable.cs:648:21:648:21 | M | -| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:703:42:703:44 | get_Property | -| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:703:63:703:65 | set_Property | -| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:705:49:705:51 | get_Item | -| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:705:70:705:72 | set_Item | -| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:706:51:706:53 | add_Event | -| ViableCallable.cs:709:17:709:20 | Run1 | ViableCallable.cs:706:59:706:64 | remove_Event | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:704:24:704:31 | Partial1 | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:705:42:705:44 | get_Property | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:705:63:705:65 | set_Property | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:707:49:707:51 | get_Item | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:707:70:707:72 | set_Item | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:708:51:708:53 | add_Event | +| ViableCallable.cs:711:17:711:20 | Run1 | ViableCallable.cs:708:59:708:64 | remove_Event | diff --git a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected index 5d6b4be4f878..84dc17b073aa 100644 --- a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected +++ b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected @@ -518,9 +518,10 @@ | ViableCallable.cs:683:9:683:16 | call to method M | C22+TestOverloadResolution2.M(Int32[]) | | ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution1.M(List) | | ViableCallable.cs:687:9:687:16 | call to method M | C22+TestOverloadResolution2.M(List) | -| ViableCallable.cs:714:9:714:18 | access to property Property | C23+Partial1.set_Property(object) | -| ViableCallable.cs:717:13:717:22 | access to property Property | C23+Partial1.get_Property() | -| ViableCallable.cs:720:9:720:12 | access to indexer | C23+Partial1.set_Item(int, object) | -| ViableCallable.cs:723:13:723:16 | access to indexer | C23+Partial1.get_Item(int) | -| ViableCallable.cs:726:9:726:15 | access to event Event | C23+Partial1.add_Event(EventHandler) | -| ViableCallable.cs:729:9:729:15 | access to event Event | C23+Partial1.remove_Event(EventHandler) | +| ViableCallable.cs:716:9:716:18 | access to property Property | C23+Partial1.set_Property(object) | +| ViableCallable.cs:719:13:719:22 | access to property Property | C23+Partial1.get_Property() | +| ViableCallable.cs:722:9:722:12 | access to indexer | C23+Partial1.set_Item(int, object) | +| ViableCallable.cs:725:13:725:16 | access to indexer | C23+Partial1.get_Item(int) | +| ViableCallable.cs:728:9:728:15 | access to event Event | C23+Partial1.add_Event(EventHandler) | +| ViableCallable.cs:731:9:731:15 | access to event Event | C23+Partial1.remove_Event(EventHandler) | +| ViableCallable.cs:734:18:734:43 | object creation of type Partial1 | C23+Partial1.Partial1(object) | diff --git a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs index e904eb01a862..dee8d9b0d1d6 100644 --- a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs +++ b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs @@ -692,6 +692,7 @@ public class C23 { public partial class Partial1 { + public partial Partial1(object obj); public partial object Property { get; set; } public partial object this[int index] { get; set; } @@ -700,6 +701,7 @@ public partial class Partial1 public partial class Partial1 { + public partial Partial1(object obj) { } public partial object Property { get { return null; } set { } } public partial object this[int index] { get { return null; } set { } } @@ -727,5 +729,8 @@ public void Run1(Partial1 p) // Viable callable: Partial1.remove_Event p.Event -= (sender, e) => { }; + + // Viable callable: Partial1.Partial1(object) + var p0 = new Partial1(new object()); } } diff --git a/csharp/ql/test/library-tests/linq/Linq2.ql b/csharp/ql/test/library-tests/linq/Linq2.ql index b3909f88b70f..5f1fc3de85b8 100644 --- a/csharp/ql/test/library-tests/linq/Linq2.ql +++ b/csharp/ql/test/library-tests/linq/Linq2.ql @@ -5,4 +5,5 @@ import csharp from BinaryOperation e +where not e instanceof Assignment select e, e.getAnOperand() diff --git a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected index 497d1e0026df..484540d72b2e 100644 --- a/csharp/ql/test/library-tests/partial/MethodIsPartial.expected +++ b/csharp/ql/test/library-tests/partial/MethodIsPartial.expected @@ -1,8 +1,8 @@ -| Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | true | -| Partial.cs:8:17:8:23 | Method2 | false | -| Partial.cs:19:18:19:39 | PartialMethodWithBody1 | true | -| Partial.cs:20:27:20:48 | PartialMethodWithBody2 | true | -| Partial.cs:24:17:24:23 | Method3 | false | -| Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 | true | -| Partial.cs:47:17:47:23 | Method4 | false | -| Partial.cs:52:17:52:23 | Method5 | false | +| Partial.cs:9:18:9:42 | PartialMethodWithoutBody1 | true | +| Partial.cs:10:17:10:23 | Method2 | false | +| Partial.cs:23:18:23:39 | PartialMethodWithBody1 | true | +| Partial.cs:24:27:24:48 | PartialMethodWithBody2 | true | +| Partial.cs:28:17:28:23 | Method3 | false | +| Partial.cs:50:18:50:42 | PartialMethodWithoutBody2 | true | +| Partial.cs:51:17:51:23 | Method4 | false | +| Partial.cs:57:17:57:23 | Method5 | false | diff --git a/csharp/ql/test/library-tests/partial/Partial.cs b/csharp/ql/test/library-tests/partial/Partial.cs index b619258170b9..6ab87c95e8bb 100644 --- a/csharp/ql/test/library-tests/partial/Partial.cs +++ b/csharp/ql/test/library-tests/partial/Partial.cs @@ -2,6 +2,8 @@ partial class TwoPartClass { + // Declaring declaration. + public partial TwoPartClass(object obj); partial void PartialMethodWithBody1(); public partial object PartialMethodWithBody2(object obj); partial void PartialMethodWithoutBody1(); @@ -16,6 +18,8 @@ public void Method2() { } partial class TwoPartClass { + // Implementation declaration. + public partial TwoPartClass(object obj) { } partial void PartialMethodWithBody1() { } public partial object PartialMethodWithBody2(object obj) { @@ -49,6 +53,7 @@ public void Method4() { } class NonPartialClass { + public NonPartialClass(object obj) { } public void Method5() { } public object Property { get; set; } public object this[int index] diff --git a/csharp/ql/test/library-tests/partial/Partial1.expected b/csharp/ql/test/library-tests/partial/Partial1.expected index 826ed13c4577..b5421182c8df 100644 --- a/csharp/ql/test/library-tests/partial/Partial1.expected +++ b/csharp/ql/test/library-tests/partial/Partial1.expected @@ -1,18 +1,19 @@ | Partial.cs:3:15:3:26 | TwoPartClass | -| Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | -| Partial.cs:17:15:17:26 | TwoPartClass | -| Partial.cs:19:18:19:39 | PartialMethodWithBody1 | -| Partial.cs:20:27:20:48 | PartialMethodWithBody2 | -| Partial.cs:27:27:27:42 | PartialProperty1 | -| Partial.cs:29:9:29:11 | get_PartialProperty1 | -| Partial.cs:30:9:30:11 | set_PartialProperty1 | -| Partial.cs:34:27:34:30 | Item | -| Partial.cs:36:9:36:11 | get_Item | -| Partial.cs:37:9:37:11 | set_Item | -| Partial.cs:41:39:41:51 | PartialEvent1 | -| Partial.cs:41:55:41:57 | add_PartialEvent1 | -| Partial.cs:41:63:41:68 | remove_PartialEvent1 | -| Partial.cs:44:15:44:33 | OnePartPartialClass | -| Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 | +| Partial.cs:9:18:9:42 | PartialMethodWithoutBody1 | +| Partial.cs:19:15:19:26 | TwoPartClass | +| Partial.cs:22:20:22:31 | TwoPartClass | +| Partial.cs:23:18:23:39 | PartialMethodWithBody1 | +| Partial.cs:24:27:24:48 | PartialMethodWithBody2 | +| Partial.cs:31:27:31:42 | PartialProperty1 | +| Partial.cs:33:9:33:11 | get_PartialProperty1 | +| Partial.cs:34:9:34:11 | set_PartialProperty1 | +| Partial.cs:38:27:38:30 | Item | +| Partial.cs:40:9:40:11 | get_Item | +| Partial.cs:41:9:41:11 | set_Item | +| Partial.cs:45:39:45:51 | PartialEvent1 | +| Partial.cs:45:55:45:57 | add_PartialEvent1 | +| Partial.cs:45:63:45:68 | remove_PartialEvent1 | +| Partial.cs:48:15:48:33 | OnePartPartialClass | +| Partial.cs:50:18:50:42 | PartialMethodWithoutBody2 | | PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | | PartialMultipleFiles2.cs:1:22:1:41 | PartialMultipleFiles | diff --git a/csharp/ql/test/library-tests/partial/Partial2.expected b/csharp/ql/test/library-tests/partial/Partial2.expected index 969b37b6ab99..4d5e0aa79a49 100644 --- a/csharp/ql/test/library-tests/partial/Partial2.expected +++ b/csharp/ql/test/library-tests/partial/Partial2.expected @@ -1,17 +1,17 @@ | Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:3:15:3:26 | | -| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | -| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:8:17:8:23 | Method2 | -| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:19:18:19:39 | PartialMethodWithBody1 | -| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:20:27:20:48 | PartialMethodWithBody2 | -| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:24:17:24:23 | Method3 | -| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:3:15:3:26 | | -| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | -| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:8:17:8:23 | Method2 | -| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:19:18:19:39 | PartialMethodWithBody1 | -| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:20:27:20:48 | PartialMethodWithBody2 | -| Partial.cs:17:15:17:26 | TwoPartClass | Partial.cs:24:17:24:23 | Method3 | -| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:44:15:44:33 | | -| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 | -| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:47:17:47:23 | Method4 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:9:18:9:42 | PartialMethodWithoutBody1 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:10:17:10:23 | Method2 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:23:18:23:39 | PartialMethodWithBody1 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:24:27:24:48 | PartialMethodWithBody2 | +| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:28:17:28:23 | Method3 | +| Partial.cs:19:15:19:26 | TwoPartClass | Partial.cs:3:15:3:26 | | +| Partial.cs:19:15:19:26 | TwoPartClass | Partial.cs:9:18:9:42 | PartialMethodWithoutBody1 | +| Partial.cs:19:15:19:26 | TwoPartClass | Partial.cs:10:17:10:23 | Method2 | +| Partial.cs:19:15:19:26 | TwoPartClass | Partial.cs:23:18:23:39 | PartialMethodWithBody1 | +| Partial.cs:19:15:19:26 | TwoPartClass | Partial.cs:24:27:24:48 | PartialMethodWithBody2 | +| Partial.cs:19:15:19:26 | TwoPartClass | Partial.cs:28:17:28:23 | Method3 | +| Partial.cs:48:15:48:33 | OnePartPartialClass | Partial.cs:48:15:48:33 | | +| Partial.cs:48:15:48:33 | OnePartPartialClass | Partial.cs:50:18:50:42 | PartialMethodWithoutBody2 | +| Partial.cs:48:15:48:33 | OnePartPartialClass | Partial.cs:51:17:51:23 | Method4 | | PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | | | PartialMultipleFiles2.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | | diff --git a/csharp/ql/test/library-tests/partial/PartialAccessors.expected b/csharp/ql/test/library-tests/partial/PartialAccessors.expected index 4e53caaff841..c09756d252e7 100644 --- a/csharp/ql/test/library-tests/partial/PartialAccessors.expected +++ b/csharp/ql/test/library-tests/partial/PartialAccessors.expected @@ -1,12 +1,12 @@ -| Partial.cs:29:9:29:11 | get_PartialProperty1 | true | -| Partial.cs:30:9:30:11 | set_PartialProperty1 | true | -| Partial.cs:36:9:36:11 | get_Item | true | -| Partial.cs:37:9:37:11 | set_Item | true | -| Partial.cs:41:55:41:57 | add_PartialEvent1 | true | -| Partial.cs:41:63:41:68 | remove_PartialEvent1 | true | -| Partial.cs:53:30:53:32 | get_Property | false | -| Partial.cs:53:35:53:37 | set_Property | false | -| Partial.cs:56:9:56:11 | get_Item | false | -| Partial.cs:57:9:57:11 | set_Item | false | -| Partial.cs:59:31:59:35 | add_Event | false | -| Partial.cs:59:31:59:35 | remove_Event | false | +| Partial.cs:33:9:33:11 | get_PartialProperty1 | true | +| Partial.cs:34:9:34:11 | set_PartialProperty1 | true | +| Partial.cs:40:9:40:11 | get_Item | true | +| Partial.cs:41:9:41:11 | set_Item | true | +| Partial.cs:45:55:45:57 | add_PartialEvent1 | true | +| Partial.cs:45:63:45:68 | remove_PartialEvent1 | true | +| Partial.cs:58:30:58:32 | get_Property | false | +| Partial.cs:58:35:58:37 | set_Property | false | +| Partial.cs:61:9:61:11 | get_Item | false | +| Partial.cs:62:9:62:11 | set_Item | false | +| Partial.cs:64:31:64:35 | add_Event | false | +| Partial.cs:64:31:64:35 | remove_Event | false | diff --git a/csharp/ql/test/library-tests/partial/PartialConstructors.expected b/csharp/ql/test/library-tests/partial/PartialConstructors.expected index 907725529019..943ac0ae4b6d 100644 --- a/csharp/ql/test/library-tests/partial/PartialConstructors.expected +++ b/csharp/ql/test/library-tests/partial/PartialConstructors.expected @@ -1,4 +1,4 @@ -| Partial.cs:3:15:3:26 | TwoPartClass | Partial.cs:3:15:3:26 | {...} | -| Partial.cs:44:15:44:33 | OnePartPartialClass | Partial.cs:44:15:44:33 | {...} | -| Partial.cs:50:7:50:21 | NonPartialClass | Partial.cs:50:7:50:21 | {...} | +| Partial.cs:22:20:22:31 | TwoPartClass | Partial.cs:22:45:22:47 | {...} | +| Partial.cs:48:15:48:33 | OnePartPartialClass | Partial.cs:48:15:48:33 | {...} | +| Partial.cs:56:12:56:26 | NonPartialClass | Partial.cs:56:40:56:42 | {...} | | PartialMultipleFiles1.cs:1:22:1:41 | PartialMultipleFiles | PartialMultipleFiles1.cs:1:22:1:41 | {...} | diff --git a/csharp/ql/test/library-tests/partial/PartialEvents.expected b/csharp/ql/test/library-tests/partial/PartialEvents.expected index 324f3e4e2b01..4c7e610c37d3 100644 --- a/csharp/ql/test/library-tests/partial/PartialEvents.expected +++ b/csharp/ql/test/library-tests/partial/PartialEvents.expected @@ -1,2 +1,2 @@ -| Partial.cs:41:39:41:51 | PartialEvent1 | true | -| Partial.cs:59:31:59:35 | Event | false | +| Partial.cs:45:39:45:51 | PartialEvent1 | true | +| Partial.cs:64:31:64:35 | Event | false | diff --git a/csharp/ql/test/library-tests/partial/PartialIndexers.expected b/csharp/ql/test/library-tests/partial/PartialIndexers.expected index 5f8c0b50b99c..425a9897a478 100644 --- a/csharp/ql/test/library-tests/partial/PartialIndexers.expected +++ b/csharp/ql/test/library-tests/partial/PartialIndexers.expected @@ -1,2 +1,2 @@ -| Partial.cs:34:27:34:30 | Item | true | -| Partial.cs:54:19:54:22 | Item | false | +| Partial.cs:38:27:38:30 | Item | true | +| Partial.cs:59:19:59:22 | Item | false | diff --git a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected index 43cbf4a162ad..c15189262cad 100644 --- a/csharp/ql/test/library-tests/partial/PartialMethodBody.expected +++ b/csharp/ql/test/library-tests/partial/PartialMethodBody.expected @@ -1,4 +1,4 @@ -| Partial.cs:7:18:7:42 | PartialMethodWithoutBody1 | false | 0 | -| Partial.cs:19:18:19:39 | PartialMethodWithBody1 | true | 1 | -| Partial.cs:20:27:20:48 | PartialMethodWithBody2 | true | 1 | -| Partial.cs:46:18:46:42 | PartialMethodWithoutBody2 | false | 0 | +| Partial.cs:9:18:9:42 | PartialMethodWithoutBody1 | false | 0 | +| Partial.cs:23:18:23:39 | PartialMethodWithBody1 | true | 1 | +| Partial.cs:24:27:24:48 | PartialMethodWithBody2 | true | 1 | +| Partial.cs:50:18:50:42 | PartialMethodWithoutBody2 | false | 0 | diff --git a/csharp/ql/test/library-tests/partial/PartialProperties.expected b/csharp/ql/test/library-tests/partial/PartialProperties.expected index 9d9c5f8a0e18..5510fd53ad64 100644 --- a/csharp/ql/test/library-tests/partial/PartialProperties.expected +++ b/csharp/ql/test/library-tests/partial/PartialProperties.expected @@ -1,2 +1,2 @@ -| Partial.cs:27:27:27:42 | PartialProperty1 | true | -| Partial.cs:53:19:53:26 | Property | false | +| Partial.cs:31:27:31:42 | PartialProperty1 | true | +| Partial.cs:58:19:58:26 | Property | false | diff --git a/csharp/ql/test/library-tests/partial/PrintAst.expected b/csharp/ql/test/library-tests/partial/PrintAst.expected index dc96317ab03b..c49afdc169f7 100644 --- a/csharp/ql/test/library-tests/partial/PrintAst.expected +++ b/csharp/ql/test/library-tests/partial/PrintAst.expected @@ -1,116 +1,126 @@ Partial.cs: # 3| [Class] TwoPartClass -# 7| 6: [Method] PartialMethodWithoutBody1 -# 7| -1: [TypeMention] Void -# 8| 7: [Method] Method2 -# 8| -1: [TypeMention] Void -# 8| 4: [BlockStmt] {...} -# 19| 8: [Method] PartialMethodWithBody1 -# 19| -1: [TypeMention] Void -# 19| 4: [BlockStmt] {...} -# 20| 9: [Method] PartialMethodWithBody2 -# 20| -1: [TypeMention] object +# 9| 5: [Method] PartialMethodWithoutBody1 +# 9| -1: [TypeMention] Void +# 10| 6: [Method] Method2 +# 10| -1: [TypeMention] Void +# 10| 4: [BlockStmt] {...} +# 22| 7: [InstanceConstructor] TwoPartClass #-----| 2: (Parameters) -# 20| 0: [Parameter] obj -# 20| -1: [TypeMention] object -# 21| 4: [BlockStmt] {...} -# 22| 0: [ReturnStmt] return ...; -# 22| 0: [ParameterAccess] access to parameter obj -# 24| 10: [Method] Method3 -# 24| -1: [TypeMention] Void -# 24| 4: [BlockStmt] {...} -# 25| 11: [Field] _backingField -# 25| -1: [TypeMention] object -# 27| 12: [Property] PartialProperty1 -# 27| -1: [TypeMention] object -# 29| 3: [Getter] get_PartialProperty1 -# 29| 4: [BlockStmt] {...} -# 29| 0: [ReturnStmt] return ...; -# 29| 0: [FieldAccess] access to field _backingField -# 30| 4: [Setter] set_PartialProperty1 +# 22| 0: [Parameter] obj +# 22| -1: [TypeMention] object +# 22| 4: [BlockStmt] {...} +# 23| 8: [Method] PartialMethodWithBody1 +# 23| -1: [TypeMention] Void +# 23| 4: [BlockStmt] {...} +# 24| 9: [Method] PartialMethodWithBody2 +# 24| -1: [TypeMention] object +#-----| 2: (Parameters) +# 24| 0: [Parameter] obj +# 24| -1: [TypeMention] object +# 25| 4: [BlockStmt] {...} +# 26| 0: [ReturnStmt] return ...; +# 26| 0: [ParameterAccess] access to parameter obj +# 28| 10: [Method] Method3 +# 28| -1: [TypeMention] Void +# 28| 4: [BlockStmt] {...} +# 29| 11: [Field] _backingField +# 29| -1: [TypeMention] object +# 31| 12: [Property] PartialProperty1 +# 31| -1: [TypeMention] object +# 33| 3: [Getter] get_PartialProperty1 +# 33| 4: [BlockStmt] {...} +# 33| 0: [ReturnStmt] return ...; +# 33| 0: [FieldAccess] access to field _backingField +# 34| 4: [Setter] set_PartialProperty1 #-----| 2: (Parameters) -# 30| 0: [Parameter] value -# 30| 4: [BlockStmt] {...} -# 30| 0: [ExprStmt] ...; -# 30| 0: [AssignExpr] ... = ... -# 30| 0: [FieldAccess] access to field _backingField -# 30| 1: [ParameterAccess] access to parameter value -# 32| 13: [Field] _backingArray -# 32| -1: [TypeMention] Object[] -# 32| 1: [TypeMention] object -# 34| 14: [Indexer] Item -# 34| -1: [TypeMention] object +# 34| 0: [Parameter] value +# 34| 4: [BlockStmt] {...} +# 34| 0: [ExprStmt] ...; +# 34| 0: [AssignExpr] ... = ... +# 34| 0: [FieldAccess] access to field _backingField +# 34| 1: [ParameterAccess] access to parameter value +# 36| 13: [Field] _backingArray +# 36| -1: [TypeMention] Object[] +# 36| 1: [TypeMention] object +# 38| 14: [Indexer] Item +# 38| -1: [TypeMention] object #-----| 1: (Parameters) -# 34| 0: [Parameter] index -# 34| -1: [TypeMention] int -# 36| 3: [Getter] get_Item -#-----| 2: (Parameters) -# 34| 0: [Parameter] index -# 36| 4: [BlockStmt] {...} -# 36| 0: [ReturnStmt] return ...; -# 36| 0: [ArrayAccess] access to array element -# 36| -1: [FieldAccess] access to field _backingArray -# 36| 0: [ParameterAccess] access to parameter index -# 37| 4: [Setter] set_Item +# 38| 0: [Parameter] index +# 38| -1: [TypeMention] int +# 40| 3: [Getter] get_Item #-----| 2: (Parameters) -# 34| 0: [Parameter] index -# 37| 1: [Parameter] value -# 37| 4: [BlockStmt] {...} -# 37| 0: [ExprStmt] ...; -# 37| 0: [AssignExpr] ... = ... -# 37| 0: [ArrayAccess] access to array element -# 37| -1: [FieldAccess] access to field _backingArray -# 37| 0: [ParameterAccess] access to parameter index -# 37| 1: [ParameterAccess] access to parameter value -# 41| 15: [Event] PartialEvent1 -# 41| 3: [AddEventAccessor] add_PartialEvent1 +# 38| 0: [Parameter] index +# 40| 4: [BlockStmt] {...} +# 40| 0: [ReturnStmt] return ...; +# 40| 0: [ArrayAccess] access to array element +# 40| -1: [FieldAccess] access to field _backingArray +# 40| 0: [ParameterAccess] access to parameter index +# 41| 4: [Setter] set_Item #-----| 2: (Parameters) -# 41| 0: [Parameter] value +# 38| 0: [Parameter] index +# 41| 1: [Parameter] value # 41| 4: [BlockStmt] {...} -# 41| 4: [RemoveEventAccessor] remove_PartialEvent1 +# 41| 0: [ExprStmt] ...; +# 41| 0: [AssignExpr] ... = ... +# 41| 0: [ArrayAccess] access to array element +# 41| -1: [FieldAccess] access to field _backingArray +# 41| 0: [ParameterAccess] access to parameter index +# 41| 1: [ParameterAccess] access to parameter value +# 45| 15: [Event] PartialEvent1 +# 45| 3: [AddEventAccessor] add_PartialEvent1 #-----| 2: (Parameters) -# 41| 0: [Parameter] value -# 41| 4: [BlockStmt] {...} -# 44| [Class] OnePartPartialClass -# 46| 6: [Method] PartialMethodWithoutBody2 -# 46| -1: [TypeMention] Void -# 47| 7: [Method] Method4 -# 47| -1: [TypeMention] Void -# 47| 4: [BlockStmt] {...} -# 50| [Class] NonPartialClass -# 52| 6: [Method] Method5 -# 52| -1: [TypeMention] Void -# 52| 4: [BlockStmt] {...} -# 53| 7: [Property] Property -# 53| -1: [TypeMention] object -# 53| 3: [Getter] get_Property -# 53| 4: [Setter] set_Property +# 45| 0: [Parameter] value +# 45| 4: [BlockStmt] {...} +# 45| 4: [RemoveEventAccessor] remove_PartialEvent1 +#-----| 2: (Parameters) +# 45| 0: [Parameter] value +# 45| 4: [BlockStmt] {...} +# 48| [Class] OnePartPartialClass +# 50| 6: [Method] PartialMethodWithoutBody2 +# 50| -1: [TypeMention] Void +# 51| 7: [Method] Method4 +# 51| -1: [TypeMention] Void +# 51| 4: [BlockStmt] {...} +# 54| [Class] NonPartialClass +# 56| 5: [InstanceConstructor] NonPartialClass +#-----| 2: (Parameters) +# 56| 0: [Parameter] obj +# 56| -1: [TypeMention] object +# 56| 4: [BlockStmt] {...} +# 57| 6: [Method] Method5 +# 57| -1: [TypeMention] Void +# 57| 4: [BlockStmt] {...} +# 58| 7: [Property] Property +# 58| -1: [TypeMention] object +# 58| 3: [Getter] get_Property +# 58| 4: [Setter] set_Property #-----| 2: (Parameters) -# 53| 0: [Parameter] value -# 54| 8: [Indexer] Item -# 54| -1: [TypeMention] object +# 58| 0: [Parameter] value +# 59| 8: [Indexer] Item +# 59| -1: [TypeMention] object #-----| 1: (Parameters) -# 54| 0: [Parameter] index -# 54| -1: [TypeMention] int -# 56| 3: [Getter] get_Item +# 59| 0: [Parameter] index +# 59| -1: [TypeMention] int +# 61| 3: [Getter] get_Item #-----| 2: (Parameters) -# 54| 0: [Parameter] index -# 56| 4: [BlockStmt] {...} -# 56| 0: [ReturnStmt] return ...; -# 56| 0: [NullLiteral] null -# 57| 4: [Setter] set_Item +# 59| 0: [Parameter] index +# 61| 4: [BlockStmt] {...} +# 61| 0: [ReturnStmt] return ...; +# 61| 0: [NullLiteral] null +# 62| 4: [Setter] set_Item #-----| 2: (Parameters) -# 54| 0: [Parameter] index -# 57| 1: [Parameter] value -# 57| 4: [BlockStmt] {...} -# 59| 9: [Event] Event -# 59| -1: [TypeMention] EventHandler -# 59| 3: [AddEventAccessor] add_Event +# 59| 0: [Parameter] index +# 62| 1: [Parameter] value +# 62| 4: [BlockStmt] {...} +# 64| 9: [Event] Event +# 64| -1: [TypeMention] EventHandler +# 64| 3: [AddEventAccessor] add_Event #-----| 2: (Parameters) -# 59| 0: [Parameter] value -# 59| 4: [RemoveEventAccessor] remove_Event +# 64| 0: [Parameter] value +# 64| 4: [RemoveEventAccessor] remove_Event #-----| 2: (Parameters) -# 59| 0: [Parameter] value +# 64| 0: [Parameter] value PartialMultipleFiles1.cs: # 1| [Class] PartialMultipleFiles PartialMultipleFiles2.cs: diff --git a/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/AspNetCore/NoPolicy/Program.cs b/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/AspNetCore/NoPolicy/Program.cs index 4df46f20c8c8..4d0d6a5d390d 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/AspNetCore/NoPolicy/Program.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/AspNetCore/NoPolicy/Program.cs @@ -2,12 +2,12 @@ public class MyController : Microsoft.AspNetCore.Mvc.Controller { public void CookieDefault() { - Response.Cookies.Append("auth", "value"); // $Alert // BAD: HttpOnly is set to false by default + Response.Cookies.Append("auth", "value"); // $ Alert // BAD: HttpOnly is set to false by default } public void CookieDefault2() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $ Alert Response.Cookies.Append("auth", "value", cookieOptions); // BAD: HttpOnly is set to false by default } @@ -39,14 +39,14 @@ void CookieDirectTrueInitializer() void CookieDirectFalse() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $ Alert cookieOptions.HttpOnly = false; Response.Cookies.Append("auth", "secret", cookieOptions); // BAD } void CookieDirectFalseInitializer() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = false }; // $Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = false }; // $ Alert Response.Cookies.Append("auth", "secret", cookieOptions); // BAD } @@ -67,7 +67,7 @@ void CookieIntermediateTrueInitializer() void CookieIntermediateFalse() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $MISSING:Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $ MISSING:Alert bool v = false; cookieOptions.HttpOnly = v; Response.Cookies.Append("auth", "secret", cookieOptions); // BAD, but not detected @@ -76,7 +76,7 @@ void CookieIntermediateFalse() void CookieIntermediateFalseInitializer() { bool v = false; - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = v }; // $MISSING:Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { HttpOnly = v }; // $ MISSING:Alert Response.Cookies.Append("auth", "secret", cookieOptions); // BAD, but not detected } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/SystemWeb/HttpOnlyCookiesFalse/Program.cs b/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/SystemWeb/HttpOnlyCookiesFalse/Program.cs index 3e63963712f0..94f50e78a3ec 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/SystemWeb/HttpOnlyCookiesFalse/Program.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-1004/HttpOnlyCookie/SystemWeb/HttpOnlyCookiesFalse/Program.cs @@ -13,7 +13,7 @@ void CookieDirectTrueInitializer() void CookieDefault() { - var cookie = new System.Web.HttpCookie("sessionID"); // $Alert // BAD: httpOnlyCookies is set to false by default + var cookie = new System.Web.HttpCookie("sessionID"); // $ Alert // BAD: httpOnlyCookies is set to false by default } void CookieDefaultForgery() @@ -29,13 +29,13 @@ void CookieForgeryDirectFalse() void CookieDirectFalse() { - var cookie = new System.Web.HttpCookie("sessionID"); // $Alert + var cookie = new System.Web.HttpCookie("sessionID"); // $ Alert cookie.HttpOnly = false; // BAD } void CookieDirectFalseInitializer() { - var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = false }; // $Alert // BAD + var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = false }; // $ Alert // BAD } void CookieIntermediateTrue() @@ -53,7 +53,7 @@ void CookieIntermediateTrueInitializer() void CookieIntermediateFalse() { - var cookie = new System.Web.HttpCookie("sessionID"); // MISSING:Alert + var cookie = new System.Web.HttpCookie("sessionID"); // MISSING:Alert bool v = false; cookie.HttpOnly = v; // BAD } @@ -61,6 +61,6 @@ void CookieIntermediateFalse() void CookieIntermediateFalseInitializer() { bool v = false; - var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = v }; // $MISSING:Alert // BAD + var cookie = new System.Web.HttpCookie("sessionID") { HttpOnly = v }; // $ MISSING:Alert // BAD } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/AspNetCore/NoPolicy/Program.cs b/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/AspNetCore/NoPolicy/Program.cs index 733e2d71fcc0..d21b19cf399a 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/AspNetCore/NoPolicy/Program.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/AspNetCore/NoPolicy/Program.cs @@ -2,12 +2,12 @@ public class MyController : Microsoft.AspNetCore.Mvc.Controller { public void CookieDefault() { - Response.Cookies.Append("name", "value"); // $Alert // BAD: Secure is set to false by default + Response.Cookies.Append("name", "value"); // $ Alert // BAD: Secure is set to false by default } public void CookieDefault2() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $ Alert Response.Cookies.Append("name", "value", cookieOptions); // BAD: Secure is set to false by default } @@ -32,14 +32,14 @@ void CookieDirectTrueInitializer() void CookieDirectFalse() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $ Alert cookieOptions.Secure = false; Response.Cookies.Append("auth", "secret", cookieOptions); // BAD } void CookieDirectFalseInitializer() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { Secure = false }; // $Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { Secure = false }; // $ Alert Response.Cookies.Append("auth", "secret", cookieOptions); // BAD } @@ -60,7 +60,7 @@ void CookieIntermediateTrueInitializer() void CookieIntermediateFalse() { - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $MISSING:Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions(); // $ MISSING:Alert bool v = false; cookieOptions.Secure = v; Response.Cookies.Append("auth", "secret", cookieOptions); // BAD, but not detected @@ -69,7 +69,7 @@ void CookieIntermediateFalse() void CookieIntermediateFalseInitializer() { bool v = false; - var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { Secure = v }; // $MISSING:Alert + var cookieOptions = new Microsoft.AspNetCore.Http.CookieOptions() { Secure = v }; // $ MISSING:Alert Response.Cookies.Append("auth", "secret", cookieOptions); // BAD, but not detected } } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/SystemWeb/RequireSSLFalse/Program.cs b/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/SystemWeb/RequireSSLFalse/Program.cs index 250b1f7780e6..b026100269f5 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/SystemWeb/RequireSSLFalse/Program.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-614/InsecureCookie/SystemWeb/RequireSSLFalse/Program.cs @@ -2,7 +2,7 @@ class Program { void CookieDefault() { - var cookie = new System.Web.HttpCookie("cookieName"); // $Alert // BAD: requireSSL is set to false by default + var cookie = new System.Web.HttpCookie("cookieName"); // $ Alert // BAD: requireSSL is set to false by default } void CookieDirectTrue() @@ -31,18 +31,18 @@ void CookieIntermediateTrueInitializer() void CookieDirectFalse() { - var cookie = new System.Web.HttpCookie("cookieName"); // $Alert + var cookie = new System.Web.HttpCookie("cookieName"); // $ Alert cookie.Secure = false; // BAD } void CookieDirectFalseInitializer() { - var cookie = new System.Web.HttpCookie("cookieName") { Secure = false }; // $Alert // BAD + var cookie = new System.Web.HttpCookie("cookieName") { Secure = false }; // $ Alert // BAD } void CookieIntermediateFalse() { - var cookie = new System.Web.HttpCookie("cookieName"); // $MISSING:Alert + var cookie = new System.Web.HttpCookie("cookieName"); // $ MISSING:Alert bool v = false; cookie.Secure = v; // BAD, but not detected } @@ -50,6 +50,6 @@ void CookieIntermediateFalse() void CookieIntermediateFalseInitializer() { bool v = false; - var cookie = new System.Web.HttpCookie("cookieName") { Secure = v }; // $MISSING:Alert // BAD, but not detected + var cookie = new System.Web.HttpCookie("cookieName") { Secure = v }; // $ MISSING:Alert // BAD, but not detected } } diff --git a/go/extractor/go.mod b/go/extractor/go.mod index 46d189d005e5..ae43e8a51bd3 100644 --- a/go/extractor/go.mod +++ b/go/extractor/go.mod @@ -9,8 +9,8 @@ toolchain go1.26.0 // when adding or removing dependencies, run // bazel mod tidy require ( - golang.org/x/mod v0.33.0 - golang.org/x/tools v0.42.0 + golang.org/x/mod v0.34.0 + golang.org/x/tools v0.43.0 ) require github.com/stretchr/testify v1.11.1 @@ -18,6 +18,6 @@ require github.com/stretchr/testify v1.11.1 require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sync v0.19.0 // indirect + golang.org/x/sync v0.20.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go/extractor/go.sum b/go/extractor/go.sum index ade080a41ad3..8bb3f3dc9fc8 100644 --- a/go/extractor/go.sum +++ b/go/extractor/go.sum @@ -6,12 +6,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/go/ql/consistency-queries/qlpack.yml b/go/ql/consistency-queries/qlpack.yml index 9a3e2990fbb1..d0473dca567c 100644 --- a/go/ql/consistency-queries/qlpack.yml +++ b/go/ql/consistency-queries/qlpack.yml @@ -1,5 +1,5 @@ name: codeql-go-consistency-queries -version: 1.0.43 +version: 1.0.44-dev groups: - go - queries diff --git a/go/ql/lib/Customizations.qll b/go/ql/lib/Customizations.qll index 127840de9dd0..56824bc03ebd 100644 --- a/go/ql/lib/Customizations.qll +++ b/go/ql/lib/Customizations.qll @@ -8,5 +8,7 @@ * `FileSystemAccess`, or the `Source` and `Sink` classes associated with the security queries * to model frameworks that are not covered by the standard library. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md b/go/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md new file mode 100644 index 000000000000..23fdce9b6159 --- /dev/null +++ b/go/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol. diff --git a/go/ql/lib/go.qll b/go/ql/lib/go.qll index 1b8bf94a0d2e..af9f676e0139 100644 --- a/go/ql/lib/go.qll +++ b/go/ql/lib/go.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Go programs. */ +overlay[local?] +module; import Customizations import semmle.go.Architectures diff --git a/go/ql/lib/ideContextual.qll b/go/ql/lib/ideContextual.qll index b28a23a6e008..2f96afdeffe0 100644 --- a/go/ql/lib/ideContextual.qll +++ b/go/ql/lib/ideContextual.qll @@ -2,6 +2,8 @@ * Provides classes and predicates related to contextual queries * in the code viewer. */ +overlay[local?] +module; import go private import codeql.util.FileSystem diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index d0e89cd798d6..dc03fcbe4f2b 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 7.0.1 +version: 7.0.2-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/lib/semmle/go/AST.qll b/go/ql/lib/semmle/go/AST.qll index 6a840f81cbbe..a0715f6ca0eb 100644 --- a/go/ql/lib/semmle/go/AST.qll +++ b/go/ql/lib/semmle/go/AST.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with AST nodes. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Architectures.qll b/go/ql/lib/semmle/go/Architectures.qll index bb4face24072..0daef5147b46 100644 --- a/go/ql/lib/semmle/go/Architectures.qll +++ b/go/ql/lib/semmle/go/Architectures.qll @@ -1,4 +1,6 @@ /** Provides classes for working with architectures. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Comments.qll b/go/ql/lib/semmle/go/Comments.qll index b55810311f88..08a0fabc1cab 100644 --- a/go/ql/lib/semmle/go/Comments.qll +++ b/go/ql/lib/semmle/go/Comments.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with code comments. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Concepts.qll b/go/ql/lib/semmle/go/Concepts.qll index 4e328ed76c45..ffa48ea9654d 100644 --- a/go/ql/lib/semmle/go/Concepts.qll +++ b/go/ql/lib/semmle/go/Concepts.qll @@ -3,6 +3,8 @@ * access or system command execution, for which individual framework libraries * provide concrete subclasses. */ +overlay[local?] +module; import go import semmle.go.dataflow.FunctionInputsAndOutputs diff --git a/go/ql/lib/semmle/go/Decls.qll b/go/ql/lib/semmle/go/Decls.qll index 9d1e4d2611a9..7588ab913bed 100644 --- a/go/ql/lib/semmle/go/Decls.qll +++ b/go/ql/lib/semmle/go/Decls.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with declarations. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/DiagnosticsReporting.qll b/go/ql/lib/semmle/go/DiagnosticsReporting.qll index 691c430aa73e..c7d0b547a867 100644 --- a/go/ql/lib/semmle/go/DiagnosticsReporting.qll +++ b/go/ql/lib/semmle/go/DiagnosticsReporting.qll @@ -1,4 +1,6 @@ /** Provides classes for working with errors and warnings recorded during extraction. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Errors.qll b/go/ql/lib/semmle/go/Errors.qll index 2e138e8de610..4ea0ed2c0150 100644 --- a/go/ql/lib/semmle/go/Errors.qll +++ b/go/ql/lib/semmle/go/Errors.qll @@ -1,4 +1,6 @@ /** Provides classes for working with Go frontend errors recorded during extraction. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Expr.qll b/go/ql/lib/semmle/go/Expr.qll index 4a4ab00f0538..0dcc707b19d8 100644 --- a/go/ql/lib/semmle/go/Expr.qll +++ b/go/ql/lib/semmle/go/Expr.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with expressions. */ +overlay[local] +module; import go @@ -829,7 +831,7 @@ class ConversionExpr extends CallOrConversionExpr { /** * A function call expression. * - * On snapshots with incomplete type information, type conversions may be misclassified + * On databases with incomplete type information, type conversions may be misclassified * as function call expressions. * * Examples: @@ -2035,6 +2037,9 @@ class ConstantName extends ValueName { override string getAPrimaryQlClass() { result = "ConstantName" } } +/** Holds if `e` is an expression that refers to the `nil` constant. */ +predicate exprRefersToNil(Expr e) { e.(ConstantName).getTarget() = Builtin::nil() } + /** * A name referring to a variable. * @@ -2093,7 +2098,7 @@ class LabelName extends Name { * Holds if `e` is a type expression, as determined by a bottom-up syntactic * analysis starting with `TypeName`s. * - * On a snapshot with full type information, this predicate covers all type + * On a database with full type information, this predicate covers all type * expressions. However, if type information is missing then not all type names * may be identified as such, so not all type expressions can be determined by * a bottom-up analysis. In such cases, `isTypeExprTopDown` below is useful. @@ -2131,11 +2136,12 @@ private predicate isTypeExprBottomUp(Expr e) { * Holds if `e` must be a type expression because it either occurs in a syntactic * position where a type is expected, or it is part of a larger type expression. * - * This predicate is only needed on snapshots for which type information is - * incomplete. It is an underapproximation; in cases where it is syntactically ambiguous - * whether an expression refers to a type or a value, we conservatively assume that - * it may be the latter and so this predicate does not consider the expression to be - * a type expression. + * This predicate is only needed on databases for which type information is + * incomplete - for example, when some dependencies could not be reached during + * extraction. It is an underapproximation; in cases where it is syntactically + * ambiguous whether an expression refers to a type or a value, we conservatively + * assume that it may be the latter and so this predicate does not consider the + * expression to be a type expression. */ pragma[nomagic] private predicate isTypeExprTopDown(Expr e) { @@ -2145,20 +2151,12 @@ private predicate isTypeExprTopDown(Expr e) { or e = any(ArrayTypeExpr ae).getElement() or - e = any(FieldDecl f).getTypeExpr() - or - e = any(ParameterDecl pd).getTypeExpr() + e = any(FieldBase fb).getTypeExpr() or e = any(TypeParamDecl tpd).getTypeConstraintExpr() or e = any(TypeParamDecl tpd).getNameExpr(_) or - e = any(ReceiverDecl rd).getTypeExpr() - or - e = any(ResultVariableDecl rvd).getTypeExpr() - or - e = any(MethodSpec md).getTypeExpr() - or e = any(MapTypeExpr mt).getKeyTypeExpr() or e = any(MapTypeExpr mt).getValueTypeExpr() @@ -2175,7 +2173,7 @@ private predicate isTypeExprTopDown(Expr e) { or e = any(TypeSwitchStmt s).getACase().getExpr(_) and // special case: `nil` is allowed in a type case but isn't a type - not e = Builtin::nil().getAReference() + not exprRefersToNil(e) or e = any(SelectorExpr sel | isTypeExprTopDown(sel)).getBase() or diff --git a/go/ql/lib/semmle/go/Files.qll b/go/ql/lib/semmle/go/Files.qll index cda168482ca9..ab4e2e084ed0 100644 --- a/go/ql/lib/semmle/go/Files.qll +++ b/go/ql/lib/semmle/go/Files.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local] +module; import go private import codeql.util.FileSystem diff --git a/go/ql/lib/semmle/go/GoMod.qll b/go/ql/lib/semmle/go/GoMod.qll index 119339c18eb6..6a899cd1d603 100644 --- a/go/ql/lib/semmle/go/GoMod.qll +++ b/go/ql/lib/semmle/go/GoMod.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with go.mod files. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/HTML.qll b/go/ql/lib/semmle/go/HTML.qll index 2f0e411a88d8..01f8a069fe9e 100644 --- a/go/ql/lib/semmle/go/HTML.qll +++ b/go/ql/lib/semmle/go/HTML.qll @@ -1,4 +1,6 @@ /** Provides classes for working with HTML documents. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Locations.qll b/go/ql/lib/semmle/go/Locations.qll index 7503421c0ff2..da55799e6df9 100644 --- a/go/ql/lib/semmle/go/Locations.qll +++ b/go/ql/lib/semmle/go/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations and program elements that have locations. */ +overlay[local] +module; import go private import semmle.go.Overlay diff --git a/go/ql/lib/semmle/go/Packages.qll b/go/ql/lib/semmle/go/Packages.qll index d11633504469..f37ddb0507ef 100644 --- a/go/ql/lib/semmle/go/Packages.qll +++ b/go/ql/lib/semmle/go/Packages.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with packages. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/PrintAst.qll b/go/ql/lib/semmle/go/PrintAst.qll index bee97008dbd8..6ea5fcc39719 100644 --- a/go/ql/lib/semmle/go/PrintAst.qll +++ b/go/ql/lib/semmle/go/PrintAst.qll @@ -1,6 +1,8 @@ /** * Provides queries to pretty-print a Go AST as a graph. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Scopes.qll b/go/ql/lib/semmle/go/Scopes.qll index 2ab08b5b5b4f..4e9a13c8ea1f 100644 --- a/go/ql/lib/semmle/go/Scopes.qll +++ b/go/ql/lib/semmle/go/Scopes.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with scopes and declared objects. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Stmt.qll b/go/ql/lib/semmle/go/Stmt.qll index 8719ad543cfa..aa6fe7c24de9 100644 --- a/go/ql/lib/semmle/go/Stmt.qll +++ b/go/ql/lib/semmle/go/Stmt.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with statements. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/StringOps.qll b/go/ql/lib/semmle/go/StringOps.qll index 3463e4fdf878..6af2946f95c5 100644 --- a/go/ql/lib/semmle/go/StringOps.qll +++ b/go/ql/lib/semmle/go/StringOps.qll @@ -1,6 +1,8 @@ /** * Provides predicates and classes for working with string operations. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index d377cb2c9d87..574d75685439 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Go types. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/Util.qll b/go/ql/lib/semmle/go/Util.qll index 02175f2d66ad..a6fe2a6b2b54 100644 --- a/go/ql/lib/semmle/go/Util.qll +++ b/go/ql/lib/semmle/go/Util.qll @@ -1,4 +1,6 @@ /** This module provides general utility classes and predicates. */ +overlay[local] +module; /** * A Boolean value. diff --git a/go/ql/lib/semmle/go/VariableWithFields.qll b/go/ql/lib/semmle/go/VariableWithFields.qll index 0fce5247dcd3..277a7dcc3263 100644 --- a/go/ql/lib/semmle/go/VariableWithFields.qll +++ b/go/ql/lib/semmle/go/VariableWithFields.qll @@ -1,4 +1,6 @@ /** Provides the `VariableWithFields` class, for working with variables with a chain of field or element accesses chained to it. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/concepts/GeneratedFile.qll b/go/ql/lib/semmle/go/concepts/GeneratedFile.qll index d1067b60ad0e..683a8be7e05c 100644 --- a/go/ql/lib/semmle/go/concepts/GeneratedFile.qll +++ b/go/ql/lib/semmle/go/concepts/GeneratedFile.qll @@ -1,4 +1,6 @@ /** Provides a class for generated files. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/concepts/HTTP.qll b/go/ql/lib/semmle/go/concepts/HTTP.qll index b3990edd0846..73f3bfb87849 100644 --- a/go/ql/lib/semmle/go/concepts/HTTP.qll +++ b/go/ql/lib/semmle/go/concepts/HTTP.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with HTTP-related concepts such as requests and responses. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/controlflow/BasicBlocks.qll b/go/ql/lib/semmle/go/controlflow/BasicBlocks.qll index 43b8c7e8dd39..dc52abb25abf 100644 --- a/go/ql/lib/semmle/go/controlflow/BasicBlocks.qll +++ b/go/ql/lib/semmle/go/controlflow/BasicBlocks.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with basic blocks. */ +overlay[local] +module; import go private import ControlFlowGraphImpl diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll index 88adb88c0264..77bb94d89f8c 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with a CFG-based program representation. */ +overlay[local] +module; import go private import ControlFlowGraphImpl @@ -62,6 +64,7 @@ module ControlFlow { BasicBlock getBasicBlock() { result.getANode() = this } /** Holds if this node dominates `dominee` in the control-flow graph. */ + overlay[caller?] pragma[inline] predicate dominatesNode(ControlFlow::Node dominee) { exists(ReachableBasicBlock thisbb, ReachableBasicBlock dbb, int i, int j | diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll index 71bd0ea561f1..a26ab3adaf5f 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll @@ -3,6 +3,8 @@ * * Provides predicates for building intra-procedural CFGs. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/controlflow/IR.qll b/go/ql/lib/semmle/go/controlflow/IR.qll index 144f0df6e7db..a4c730041082 100644 --- a/go/ql/lib/semmle/go/controlflow/IR.qll +++ b/go/ql/lib/semmle/go/controlflow/IR.qll @@ -9,6 +9,8 @@ * Each instruction is also a control-flow node, but there are control-flow nodes that are not * instructions (synthetic entry and exit nodes, as well as no-op skip nodes). */ +overlay[local] +module; import go private import semmle.go.controlflow.ControlFlowGraphImpl @@ -294,7 +296,7 @@ module IR { /** * An IR instruction that reads the value of a field. * - * On snapshots with incomplete type information, method expressions may sometimes be + * On databases with incomplete type information, method expressions may sometimes be * misclassified as field reads. */ class FieldReadInstruction extends ComponentReadInstruction { diff --git a/go/ql/lib/semmle/go/dataflow/DataFlow.qll b/go/ql/lib/semmle/go/dataflow/DataFlow.qll index c26adbfd2c2d..bc0d310566ee 100644 --- a/go/ql/lib/semmle/go/dataflow/DataFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/DataFlow.qll @@ -14,6 +14,8 @@ * (intraprocedural) data flow, invoke `DataFlow::localFlow` or * `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index 388921224ad8..e1170aeda244 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -84,6 +84,8 @@ * "taint" indicates a default additional taint step and "value" indicates a * globally applicable value-preserving step. */ +overlay[local?] +module; private import go private import internal.ExternalFlowExtensions::Extensions as Extensions diff --git a/go/ql/lib/semmle/go/dataflow/FlowSummary.qll b/go/ql/lib/semmle/go/dataflow/FlowSummary.qll index 749e1c92e06d..632697b341f1 100644 --- a/go/ql/lib/semmle/go/dataflow/FlowSummary.qll +++ b/go/ql/lib/semmle/go/dataflow/FlowSummary.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for defining flow summaries. */ +overlay[local?] +module; import go private import internal.FlowSummaryImpl as Impl diff --git a/go/ql/lib/semmle/go/dataflow/FunctionInputsAndOutputs.qll b/go/ql/lib/semmle/go/dataflow/FunctionInputsAndOutputs.qll index 89d3c297fedb..5f437f81576c 100644 --- a/go/ql/lib/semmle/go/dataflow/FunctionInputsAndOutputs.qll +++ b/go/ql/lib/semmle/go/dataflow/FunctionInputsAndOutputs.qll @@ -2,6 +2,8 @@ * Provides QL classes for indicating data flow through a function parameter, return value, * or receiver. */ +overlay[local] +module; import go private import semmle.go.dataflow.internal.DataFlowPrivate diff --git a/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll b/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll index e566ca41c2fd..88a659f6f829 100644 --- a/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll +++ b/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll @@ -29,6 +29,8 @@ * common reason for this is that the analysis cannot prove that there * are no side-effects that might cause the computed value to change. */ +overlay[local] +module; /* * Note to developers: the correctness of this module depends on the diff --git a/go/ql/lib/semmle/go/dataflow/Properties.qll b/go/ql/lib/semmle/go/dataflow/Properties.qll index f7df3391f40b..573b001a3c36 100644 --- a/go/ql/lib/semmle/go/dataflow/Properties.qll +++ b/go/ql/lib/semmle/go/dataflow/Properties.qll @@ -1,6 +1,8 @@ /** * Provides a class for representing and reasoning about properties of data-flow nodes. */ +overlay[local] +module; import go @@ -22,7 +24,7 @@ class Property extends TProperty { isTrue = eq.getPolarity().booleanXor(e.getBoolValue().booleanXor(outcome)) or this = IsNil(isTrue) and - e = Builtin::nil().getAReference() and + exprRefersToNil(e) and isTrue = eq.getPolarity().booleanXor(outcome).booleanNot() ) or diff --git a/go/ql/lib/semmle/go/dataflow/SSA.qll b/go/ql/lib/semmle/go/dataflow/SSA.qll index 69fffa393c19..46ce4da39356 100644 --- a/go/ql/lib/semmle/go/dataflow/SSA.qll +++ b/go/ql/lib/semmle/go/dataflow/SSA.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with static single assignment form (SSA). */ +overlay[local] +module; import go private import SsaImpl diff --git a/go/ql/lib/semmle/go/dataflow/SsaImpl.qll b/go/ql/lib/semmle/go/dataflow/SsaImpl.qll index 026c8114f9fb..9648335a6dde 100644 --- a/go/ql/lib/semmle/go/dataflow/SsaImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/SsaImpl.qll @@ -3,6 +3,8 @@ * * Provides predicates for constructing an SSA representation for functions. */ +overlay[local] +module; import go diff --git a/go/ql/lib/semmle/go/dataflow/TaintTracking.qll b/go/ql/lib/semmle/go/dataflow/TaintTracking.qll index c469574b3b9e..89b43de0738b 100644 --- a/go/ql/lib/semmle/go/dataflow/TaintTracking.qll +++ b/go/ql/lib/semmle/go/dataflow/TaintTracking.qll @@ -2,6 +2,8 @@ * Provides classes for performing local (intra-procedural) and * global (inter-procedural) taint-tracking analyses. */ +overlay[local?] +module; import semmle.go.dataflow.DataFlow diff --git a/go/ql/lib/semmle/go/dataflow/barrierguardutil/RedirectCheckBarrierGuard.qll b/go/ql/lib/semmle/go/dataflow/barrierguardutil/RedirectCheckBarrierGuard.qll index d185f9f78f32..cd5490e63c04 100644 --- a/go/ql/lib/semmle/go/dataflow/barrierguardutil/RedirectCheckBarrierGuard.qll +++ b/go/ql/lib/semmle/go/dataflow/barrierguardutil/RedirectCheckBarrierGuard.qll @@ -1,6 +1,8 @@ /** * Provides an implementation of a commonly used barrier guard for sanitizing untrusted URLs. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll b/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll index 8cdc3b2e1ac4..4b669a305f50 100644 --- a/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll +++ b/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll @@ -1,6 +1,8 @@ /** * Provides an implementation of a commonly used barrier guard for sanitizing untrusted URLs. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/dataflow/barrierguardutil/UrlCheck.qll b/go/ql/lib/semmle/go/dataflow/barrierguardutil/UrlCheck.qll index 8abcfb327cca..8a105cc8fa95 100644 --- a/go/ql/lib/semmle/go/dataflow/barrierguardutil/UrlCheck.qll +++ b/go/ql/lib/semmle/go/dataflow/barrierguardutil/UrlCheck.qll @@ -1,6 +1,8 @@ /** * Provides an implementation of a commonly used barrier guard for sanitizing untrusted URLs. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/dataflow/internal/ContainerFlow.qll b/go/ql/lib/semmle/go/dataflow/internal/ContainerFlow.qll index e978cb3e5874..05897354061b 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/ContainerFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/ContainerFlow.qll @@ -1,4 +1,6 @@ /** Contains predicates for dealing with container flow. */ +overlay[local?] +module; import go private import DataFlowNodes diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll index a06edad0be2c..10455f84edba 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import go private import DataFlowPrivate @@ -119,6 +122,7 @@ class ArgumentPosition extends int { } /** Holds if arguments at position `apos` match parameters at position `ppos`. */ +overlay[caller?] pragma[inline] predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos } @@ -130,6 +134,7 @@ private predicate isInterfaceMethod(Method c) { * Holds if `call` is passing `arg` to param `p` in any circumstance except passing * a receiver parameter to a concrete method. */ +overlay[caller?] pragma[inline] predicate golangSpecificParamArgFilter( DataFlowCall call, DataFlow::ParameterNode p, DataFlow::ArgumentNode arg diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index c9761d217024..ae10681799f1 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import DataFlowImplSpecific private import codeql.dataflow.internal.DataFlowImpl private import semmle.go.Locations diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index 6df86bde023d..27db6081e49d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import DataFlowImplSpecific private import codeql.dataflow.internal.DataFlowImplCommon private import semmle.go.Locations diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll index b4d927711506..cf4794a9715c 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplConsistency.qll @@ -2,6 +2,8 @@ * Provides consistency queries for checking invariants in the language-specific * data-flow classes and predicates. */ +overlay[local?] +module; private import go private import DataFlowImplSpecific as Impl diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplSpecific.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplSpecific.qll index c680778ce4d2..c2c6b0b7c43a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplSpecific.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplSpecific.qll @@ -1,6 +1,8 @@ /** * Provides Go-specific definitions for use in the data flow library. */ +overlay[local?] +module; private import codeql.dataflow.DataFlow private import semmle.go.Locations diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index 4fb767e548c6..8fca4bec8c63 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import go private import semmle.go.dataflow.FunctionInputsAndOutputs private import semmle.go.dataflow.FlowSummary diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index 76b0ef363e31..33149bf00575 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import go private import DataFlowUtil private import DataFlowImplCommon @@ -478,5 +481,6 @@ predicate allowParameterReturnInSelf(ParameterNode p) { class ContentApprox = Unit; /** Gets an approximated value for content `c`. */ +overlay[caller?] pragma[inline] ContentApprox getContentApprox(Content c) { any() } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll index 404eca4b4a25..b29ff7d5ea88 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -1,6 +1,8 @@ /** * Provides Go-specific definitions for use in the data flow library. */ +overlay[local?] +module; private import go private import semmle.go.dataflow.FunctionInputsAndOutputs @@ -147,6 +149,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) { * Holds if data flows from `source` to `sink` in zero or more local * (intra-procedural) steps. */ +overlay[caller?] pragma[inline] predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } @@ -560,7 +563,7 @@ private predicate onlyPossibleReturnOfBool(FuncDecl fd, FunctionOutput res, Node */ predicate possiblyReturnsNonNil(FuncDecl fd, FunctionOutput res, Node ret) { ret = res.getEntryNode(fd) and - not ret.asExpr() = Builtin::nil().getAReference() + not exprRefersToNil(ret.asExpr()) } /** @@ -570,7 +573,7 @@ predicate possiblyReturnsNonNil(FuncDecl fd, FunctionOutput res, Node ret) { private predicate onlyPossibleReturnOfNonNil(FuncDecl fd, FunctionOutput res, Node ret) { possiblyReturnsNonNil(fd, res, ret) and forall(Node otherRet | otherRet = res.getEntryNode(fd) and otherRet != ret | - otherRet.asExpr() = Builtin::nil().getAReference() + exprRefersToNil(otherRet.asExpr()) ) } @@ -609,7 +612,7 @@ private predicate isCertainlyNotNil(DataFlow::Node node) { */ private predicate onlyPossibleReturnOfNil(FuncDecl fd, FunctionOutput res, DataFlow::Node ret) { ret = res.getEntryNode(fd) and - ret.asExpr() = Builtin::nil().getAReference() and + exprRefersToNil(ret.asExpr()) and forall(DataFlow::Node otherRet | otherRet = res.getEntryNode(fd) and otherRet != ret | isCertainlyNotNil(otherRet) ) diff --git a/go/ql/lib/semmle/go/dataflow/internal/ExternalFlowExtensions.qll b/go/ql/lib/semmle/go/dataflow/internal/ExternalFlowExtensions.qll index 2e962299f3ed..5d43cf674c1c 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/ExternalFlowExtensions.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/ExternalFlowExtensions.qll @@ -1,6 +1,8 @@ /** * This module provides extensible predicates for defining MaD models. */ +overlay[local?] +module; private import codeql.mad.static.ModelsAsData as SharedMaD diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index f09f42872ea2..240665bd492d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for defining flow summaries. */ +overlay[local?] +module; private import go private import codeql.dataflow.internal.FlowSummaryImpl diff --git a/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingImplSpecific.qll b/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingImplSpecific.qll index b9795bb14d31..e0c416087fdd 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingImplSpecific.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingImplSpecific.qll @@ -1,6 +1,8 @@ /** * Provides Go-specific definitions for use in the taint tracking library. */ +overlay[local?] +module; private import codeql.dataflow.TaintTracking private import DataFlowImplSpecific diff --git a/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll index af28f7f40200..f9f148744939 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll @@ -1,6 +1,8 @@ /** * Provides Go-specific definitions for use in the taint-tracking library. */ +overlay[local?] +module; private import go private import FlowSummaryImpl as FlowSummaryImpl @@ -11,6 +13,7 @@ private import DataFlowPrivate as DataFlowPrivate * Holds if taint can flow from `src` to `sink` in zero or more * local (intra-procedural) steps. */ +overlay[caller?] pragma[inline] predicate localTaint(DataFlow::Node src, DataFlow::Node sink) { localTaintStep*(src, sink) } @@ -18,6 +21,7 @@ predicate localTaint(DataFlow::Node src, DataFlow::Node sink) { localTaintStep*( * Holds if taint can flow from `src` to `sink` in zero or more * local (intra-procedural) steps. */ +overlay[caller?] pragma[inline] predicate localExprTaint(Expr src, Expr sink) { localTaint(DataFlow::exprNode(src), DataFlow::exprNode(sink)) @@ -418,7 +422,7 @@ predicate functionEnsuresInputIsConstant( forex(DataFlow::Node ret, IR::ReturnInstruction ri | ret = outp.getEntryNode(fd) and ri.getReturnStmt().getAnExpr() = ret.asExpr() and - ret.asExpr() = Builtin::nil().getAReference() + exprRefersToNil(ret.asExpr()) | DataFlow::localFlow(inp.getExitNode(fd), _) and mustPassConstantCaseTestToReach(ri, inp.getExitNode(fd)) diff --git a/go/ql/lib/semmle/go/dependencies/Dependencies.qll b/go/ql/lib/semmle/go/dependencies/Dependencies.qll index d8c8ee52d298..6c9537c72c4b 100644 --- a/go/ql/lib/semmle/go/dependencies/Dependencies.qll +++ b/go/ql/lib/semmle/go/dependencies/Dependencies.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling go.mod dependencies. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/dependencies/SemVer.qll b/go/ql/lib/semmle/go/dependencies/SemVer.qll index 88d37563931f..290617781ec0 100644 --- a/go/ql/lib/semmle/go/dependencies/SemVer.qll +++ b/go/ql/lib/semmle/go/dependencies/SemVer.qll @@ -1,6 +1,8 @@ /** * Provides classes for dealing with semantic versions, for dependency versions. */ +overlay[local?] +module; import semmle.go.dependencies.Dependencies diff --git a/go/ql/lib/semmle/go/frameworks/Afero.qll b/go/ql/lib/semmle/go/frameworks/Afero.qll index c03bf6114334..22704a6af8e5 100644 --- a/go/ql/lib/semmle/go/frameworks/Afero.qll +++ b/go/ql/lib/semmle/go/frameworks/Afero.qll @@ -2,6 +2,8 @@ * Provides classes for working with sinks and taint propagators * from the `github.com/spf13/afero` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/AwsLambda.qll b/go/ql/lib/semmle/go/frameworks/AwsLambda.qll index 28f21c9101b8..f366a8770975 100644 --- a/go/ql/lib/semmle/go/frameworks/AwsLambda.qll +++ b/go/ql/lib/semmle/go/frameworks/AwsLambda.qll @@ -2,6 +2,8 @@ * Provides classes for working with remote flow sources, sinks and taint propagators * from the `github.com/aws/aws-lambda-go/lambda` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Beego.qll b/go/ql/lib/semmle/go/frameworks/Beego.qll index 383be8ec42ab..5f3f2e986c28 100644 --- a/go/ql/lib/semmle/go/frameworks/Beego.qll +++ b/go/ql/lib/semmle/go/frameworks/Beego.qll @@ -2,6 +2,8 @@ * Provides classes for working with remote flow sources, sinks and taint propagators * from the `github.com/beego/beego` package. */ +overlay[local?] +module; import go import semmle.go.security.Xss diff --git a/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll b/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll index 925b0f19fa3f..e1bc5c481bd9 100644 --- a/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll +++ b/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll @@ -2,6 +2,8 @@ * Provides classes for working with remote flow sources, sinks and taint propagators * from the `github.com/astaxie/beego/orm` subpackage. */ +overlay[local?] +module; import go private import semmle.go.security.StoredXssCustomizations diff --git a/go/ql/lib/semmle/go/frameworks/Bun.qll b/go/ql/lib/semmle/go/frameworks/Bun.qll index 5be82d2cacc5..8637c8f5704f 100644 --- a/go/ql/lib/semmle/go/frameworks/Bun.qll +++ b/go/ql/lib/semmle/go/frameworks/Bun.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `Bun` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Couchbase.qll b/go/ql/lib/semmle/go/frameworks/Couchbase.qll index b5bfbcb22a2d..d1be1a73205e 100644 --- a/go/ql/lib/semmle/go/frameworks/Couchbase.qll +++ b/go/ql/lib/semmle/go/frameworks/Couchbase.qll @@ -1,6 +1,8 @@ /** * Provides models of commonly used functions in the official Couchbase Go SDK library. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll b/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll index 154ac82e7a2a..7f0e52b449a2 100644 --- a/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll +++ b/go/ql/lib/semmle/go/frameworks/CryptoLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling cryptographic libraries. */ +overlay[local?] +module; import go import semmle.go.Concepts::Cryptography diff --git a/go/ql/lib/semmle/go/frameworks/Echo.qll b/go/ql/lib/semmle/go/frameworks/Echo.qll index a2a6e7d846af..865d8c3972b4 100644 --- a/go/ql/lib/semmle/go/frameworks/Echo.qll +++ b/go/ql/lib/semmle/go/frameworks/Echo.qll @@ -2,6 +2,8 @@ * Provides classes for working with remote flow sources, taint propagators, and HTTP sinks * from the `github.com/labstack/echo` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll index b1bf4571216a..23f3a8c2d4d9 100644 --- a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll +++ b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with concepts relating to the [github.com/elazarl/goproxy](https://pkg.go.dev/github.com/elazarl/goproxy) package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Email.qll b/go/ql/lib/semmle/go/frameworks/Email.qll index ba4cf8be4155..97894806f6ff 100644 --- a/go/ql/lib/semmle/go/frameworks/Email.qll +++ b/go/ql/lib/semmle/go/frameworks/Email.qll @@ -1,4 +1,6 @@ /** Provides classes for working with email-related APIs. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Encoding.qll b/go/ql/lib/semmle/go/frameworks/Encoding.qll index 201e2c9001d5..45f83021a0c5 100644 --- a/go/ql/lib/semmle/go/frameworks/Encoding.qll +++ b/go/ql/lib/semmle/go/frameworks/Encoding.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling taint propagation through marshalling and encoding functions. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Fasthttp.qll b/go/ql/lib/semmle/go/frameworks/Fasthttp.qll index 941e6b44945b..2dea987ade61 100644 --- a/go/ql/lib/semmle/go/frameworks/Fasthttp.qll +++ b/go/ql/lib/semmle/go/frameworks/Fasthttp.qll @@ -2,6 +2,8 @@ * Provides classes for working with remote flow sources, sinks and taint propagators * from the `github.com/valyala/fasthttp` package. */ +overlay[local?] +module; import go private import semmle.go.security.RequestForgeryCustomizations diff --git a/go/ql/lib/semmle/go/frameworks/Gin.qll b/go/ql/lib/semmle/go/frameworks/Gin.qll index 71ed5d931fa3..f6d2bf8ff55f 100644 --- a/go/ql/lib/semmle/go/frameworks/Gin.qll +++ b/go/ql/lib/semmle/go/frameworks/Gin.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling the `github.com/gin-gonic/gin` package. */ +overlay[local?] +module; import go import semmle.go.concepts.HTTP diff --git a/go/ql/lib/semmle/go/frameworks/GinCors.qll b/go/ql/lib/semmle/go/frameworks/GinCors.qll index cc993ea4dee3..cd742ac9ba26 100644 --- a/go/ql/lib/semmle/go/frameworks/GinCors.qll +++ b/go/ql/lib/semmle/go/frameworks/GinCors.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling the `github.com/gin-contrib/cors` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Glog.qll b/go/ql/lib/semmle/go/frameworks/Glog.qll index 146b8a4f814b..a9ffc4321817 100644 --- a/go/ql/lib/semmle/go/frameworks/Glog.qll +++ b/go/ql/lib/semmle/go/frameworks/Glog.qll @@ -2,6 +2,8 @@ * Provides models of commonly used functions in the `github.com/golang/glog` and `k8s.io/klog` * packages. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/GoJose.qll b/go/ql/lib/semmle/go/frameworks/GoJose.qll index 509e289f586d..6ee1feb5ab9c 100644 --- a/go/ql/lib/semmle/go/frameworks/GoJose.qll +++ b/go/ql/lib/semmle/go/frameworks/GoJose.qll @@ -2,6 +2,8 @@ * Provides classes for working with the `gopkg.in/square/go-jose` and `github.com/go-jose/go-jose` * packages. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/GoKit.qll b/go/ql/lib/semmle/go/frameworks/GoKit.qll index e4a9e48d2077..f56451b1b810 100644 --- a/go/ql/lib/semmle/go/frameworks/GoKit.qll +++ b/go/ql/lib/semmle/go/frameworks/GoKit.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with concepts relating to the [github.com/go-kit/kit](https://pkg.go.dev/github.com/go-kit/kit) package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/GoMicro.qll b/go/ql/lib/semmle/go/frameworks/GoMicro.qll index f01dcde9f1ea..723f58899ffb 100644 --- a/go/ql/lib/semmle/go/frameworks/GoMicro.qll +++ b/go/ql/lib/semmle/go/frameworks/GoMicro.qll @@ -1,6 +1,8 @@ /** * Provides models of the [Go Micro library](https://github.com/go-micro/go-micro). */ +overlay[local?] +module; import go private import semmle.go.security.RequestForgeryCustomizations diff --git a/go/ql/lib/semmle/go/frameworks/Gorqlite.qll b/go/ql/lib/semmle/go/frameworks/Gorqlite.qll index 65ac5d88baba..434c8148bd7e 100644 --- a/go/ql/lib/semmle/go/frameworks/Gorqlite.qll +++ b/go/ql/lib/semmle/go/frameworks/Gorqlite.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `gorqlite` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Gqlgen.qll b/go/ql/lib/semmle/go/frameworks/Gqlgen.qll index 4edaab46b222..bcde5ce9a361 100644 --- a/go/ql/lib/semmle/go/frameworks/Gqlgen.qll +++ b/go/ql/lib/semmle/go/frameworks/Gqlgen.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions and types in the gqlgen packages. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Jwt.qll b/go/ql/lib/semmle/go/frameworks/Jwt.qll index 681ead268341..d139f48ae2b4 100644 --- a/go/ql/lib/semmle/go/frameworks/Jwt.qll +++ b/go/ql/lib/semmle/go/frameworks/Jwt.qll @@ -2,6 +2,8 @@ * Provides classes and predicates for working with the `github.com/golang-jwt/jwt` and * `github.com/dgrijalva/jwt-go` packages. */ +overlay[local?] +module; import go private import semmle.go.security.MissingJwtSignatureCheckCustomizations::MissingJwtSignatureCheck diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll index 6fe789dccc35..ea80d0eba379 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions in the `k8s.io/api/core/v1` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll b/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll index 5c7481e58087..945904ba0aed 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions in the `k8s.io/apimachinery/pkg/runtime` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoClientGo.qll b/go/ql/lib/semmle/go/frameworks/K8sIoClientGo.qll index c087cc26ff8d..f23d069f4c0f 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoClientGo.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoClientGo.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions in the `k8s.io/client-go/kubernetes/typed/core/v1` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Logrus.qll b/go/ql/lib/semmle/go/frameworks/Logrus.qll index 83278a4cd9e2..33287462c055 100644 --- a/go/ql/lib/semmle/go/frameworks/Logrus.qll +++ b/go/ql/lib/semmle/go/frameworks/Logrus.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions in the `github.com/sirupsen/logrus` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Macaron.qll b/go/ql/lib/semmle/go/frameworks/Macaron.qll index 41e95095aa27..1c0888042632 100644 --- a/go/ql/lib/semmle/go/frameworks/Macaron.qll +++ b/go/ql/lib/semmle/go/frameworks/Macaron.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with concepts relating to the Macaron web framework */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Mux.qll b/go/ql/lib/semmle/go/frameworks/Mux.qll index e9bb5968f702..a4790e3c5cd7 100644 --- a/go/ql/lib/semmle/go/frameworks/Mux.qll +++ b/go/ql/lib/semmle/go/frameworks/Mux.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with concepts in the Mux HTTP middleware library. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/NoSQL.qll b/go/ql/lib/semmle/go/frameworks/NoSQL.qll index 2772182f4fcd..463a3923496f 100644 --- a/go/ql/lib/semmle/go/frameworks/NoSQL.qll +++ b/go/ql/lib/semmle/go/frameworks/NoSQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with NoSQL-related concepts such as queries. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Protobuf.qll b/go/ql/lib/semmle/go/frameworks/Protobuf.qll index 62443eb46af7..246608159e55 100644 --- a/go/ql/lib/semmle/go/frameworks/Protobuf.qll +++ b/go/ql/lib/semmle/go/frameworks/Protobuf.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions and types in the protobuf packages. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Revel.qll b/go/ql/lib/semmle/go/frameworks/Revel.qll index a1eff5e736e7..c6250c2f8a51 100644 --- a/go/ql/lib/semmle/go/frameworks/Revel.qll +++ b/go/ql/lib/semmle/go/frameworks/Revel.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with remote flow sources from the `github.com/revel/revel` package. */ +overlay[local?] +module; import go private import semmle.go.security.OpenUrlRedirectCustomizations diff --git a/go/ql/lib/semmle/go/frameworks/RsCors.qll b/go/ql/lib/semmle/go/frameworks/RsCors.qll index 52b4a7fe6d03..7609b27b58a5 100644 --- a/go/ql/lib/semmle/go/frameworks/RsCors.qll +++ b/go/ql/lib/semmle/go/frameworks/RsCors.qll @@ -1,4 +1,6 @@ /** Provides classes for modeling the `github.com/rs/cors` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/SQL.qll b/go/ql/lib/semmle/go/frameworks/SQL.qll index c5cf4989d1ab..fad4722ad5cb 100644 --- a/go/ql/lib/semmle/go/frameworks/SQL.qll +++ b/go/ql/lib/semmle/go/frameworks/SQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with SQL-related concepts such as queries. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Spew.qll b/go/ql/lib/semmle/go/frameworks/Spew.qll index f49a4aa4d89d..4c8720868b7e 100644 --- a/go/ql/lib/semmle/go/frameworks/Spew.qll +++ b/go/ql/lib/semmle/go/frameworks/Spew.qll @@ -1,6 +1,8 @@ /** * Provides models of commonly used functions in the `github.com/davecgh/go-spew/spew` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Squirrel.qll b/go/ql/lib/semmle/go/frameworks/Squirrel.qll index c7d75003cfe7..28168c54107e 100644 --- a/go/ql/lib/semmle/go/frameworks/Squirrel.qll +++ b/go/ql/lib/semmle/go/frameworks/Squirrel.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `squirrel` ORM package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Stdlib.qll b/go/ql/lib/semmle/go/frameworks/Stdlib.qll index 3b05627168d4..4a8a2e8d0ea4 100644 --- a/go/ql/lib/semmle/go/frameworks/Stdlib.qll +++ b/go/ql/lib/semmle/go/frameworks/Stdlib.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the standard libraries. */ +overlay[local?] +module; import go import semmle.go.frameworks.stdlib.ArchiveTar diff --git a/go/ql/lib/semmle/go/frameworks/SystemCommandExecutors.qll b/go/ql/lib/semmle/go/frameworks/SystemCommandExecutors.qll index 8abf2bbd368a..d1bbbf41d894 100644 --- a/go/ql/lib/semmle/go/frameworks/SystemCommandExecutors.qll +++ b/go/ql/lib/semmle/go/frameworks/SystemCommandExecutors.qll @@ -2,6 +2,8 @@ * Provides concrete classes for data-flow nodes that execute an * operating system command, for instance by spawning a new process. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Testing.qll b/go/ql/lib/semmle/go/frameworks/Testing.qll index c0246c7df503..c6173ac099a6 100644 --- a/go/ql/lib/semmle/go/frameworks/Testing.qll +++ b/go/ql/lib/semmle/go/frameworks/Testing.qll @@ -1,4 +1,6 @@ /** Provides classes for working with tests. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Twirp.qll b/go/ql/lib/semmle/go/frameworks/Twirp.qll index 254949ad7728..2fcd44da2ff8 100644 --- a/go/ql/lib/semmle/go/frameworks/Twirp.qll +++ b/go/ql/lib/semmle/go/frameworks/Twirp.qll @@ -1,4 +1,6 @@ /** Provides models of commonly used functions and types in the twirp packages. */ +overlay[local?] +module; import go private import semmle.go.security.RequestForgeryCustomizations diff --git a/go/ql/lib/semmle/go/frameworks/WebSocket.qll b/go/ql/lib/semmle/go/frameworks/WebSocket.qll index eb6160214cce..36c6db5c4536 100644 --- a/go/ql/lib/semmle/go/frameworks/WebSocket.qll +++ b/go/ql/lib/semmle/go/frameworks/WebSocket.qll @@ -1,4 +1,6 @@ /** Provides classes for working with WebSocket-related APIs. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/XNetHtml.qll b/go/ql/lib/semmle/go/frameworks/XNetHtml.qll index 003c0e8570e1..4eec0c9b331d 100644 --- a/go/ql/lib/semmle/go/frameworks/XNetHtml.qll +++ b/go/ql/lib/semmle/go/frameworks/XNetHtml.qll @@ -6,6 +6,8 @@ * that were already untrusted. We do not yet model adding a child `Node` to a tree then calling `Render` * yielding an untrustworthy string. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/XPath.qll b/go/ql/lib/semmle/go/frameworks/XPath.qll index 0d8dc5d8176d..d052a619c35c 100644 --- a/go/ql/lib/semmle/go/frameworks/XPath.qll +++ b/go/ql/lib/semmle/go/frameworks/XPath.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with XPath-related concepts such as XPath expressions. */ +overlay[local?] +module; import go import semmle.go.dataflow.ExternalFlow diff --git a/go/ql/lib/semmle/go/frameworks/Yaml.qll b/go/ql/lib/semmle/go/frameworks/Yaml.qll index 22fc4f8c58c1..160e5f18c6be 100644 --- a/go/ql/lib/semmle/go/frameworks/Yaml.qll +++ b/go/ql/lib/semmle/go/frameworks/Yaml.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the [gopkg.in/yaml](https://pkg.go.dev/gopkg.in/yaml.v3) package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/Zap.qll b/go/ql/lib/semmle/go/frameworks/Zap.qll index 0928d2b0595c..b634d8e97952 100644 --- a/go/ql/lib/semmle/go/frameworks/Zap.qll +++ b/go/ql/lib/semmle/go/frameworks/Zap.qll @@ -1,6 +1,8 @@ /** * Provides models of commonly used functions in the `go.uber.org/zap` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveTar.qll b/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveTar.qll index 24d16f86b665..0798f187647b 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveTar.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveTar.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `archive/tar` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveZip.qll b/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveZip.qll index ed4061700dc4..273b8ddff2c6 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveZip.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/ArchiveZip.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `archive/zip` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Bufio.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Bufio.qll index 1ddb7e0889cc..e79a5f16a900 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Bufio.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Bufio.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `bufio` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/CompressFlate.qll b/go/ql/lib/semmle/go/frameworks/stdlib/CompressFlate.qll index 5df4ac972c9a..1d63d0dda295 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/CompressFlate.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/CompressFlate.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `compress/flate` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/CompressGzip.qll b/go/ql/lib/semmle/go/frameworks/stdlib/CompressGzip.qll index 29b731ec9279..695c9ea5df5b 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/CompressGzip.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/CompressGzip.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `compress/gzip` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/CompressLzw.qll b/go/ql/lib/semmle/go/frameworks/stdlib/CompressLzw.qll index 4d8e2d1de930..319c1d4dd938 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/CompressLzw.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/CompressLzw.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `compress/lzw` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/CompressZlib.qll b/go/ql/lib/semmle/go/frameworks/stdlib/CompressZlib.qll index be8d7fa69a0b..26a2872ae1ca 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/CompressZlib.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/CompressZlib.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `compress/zlib` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/CryptoTls.qll b/go/ql/lib/semmle/go/frameworks/stdlib/CryptoTls.qll index 2bd85457cf85..a370f12c24da 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/CryptoTls.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/CryptoTls.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `crypto/tls` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll b/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll index f41326887961..1969724b4862 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `database/sql` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingAsn1.qll b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingAsn1.qll index 68d9655b11cd..7a860608a90a 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingAsn1.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingAsn1.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `encoding/asn1` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingCsv.qll b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingCsv.qll index 7606cdc16bd5..283eeebacb63 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingCsv.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingCsv.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `encoding/csv` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingGob.qll b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingGob.qll index ada9f167f8df..01db1ec539a9 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingGob.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingGob.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `encoding/gob` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingJson.qll b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingJson.qll index f38db392bd01..bf6e25ff9f12 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingJson.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingJson.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `encoding/json` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingPem.qll b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingPem.qll index cb2383d428ae..4ef997c78151 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingPem.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingPem.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `encoding/pem` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingXml.qll b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingXml.qll index b36f9007084c..b5206754529c 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/EncodingXml.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/EncodingXml.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `encoding/xml` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll index 133a69795b81..d20d0c1837ed 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Errors.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `errors` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll index 6adbd542e9b6..bc58441ada91 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `fmt` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Html.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Html.qll index 82e5f13e1305..c26d329f6253 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Html.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Html.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `html` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/HtmlTemplate.qll b/go/ql/lib/semmle/go/frameworks/stdlib/HtmlTemplate.qll index f61482c35d72..8d343bfa4fec 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/HtmlTemplate.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/HtmlTemplate.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `html/template` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Io.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Io.qll index f44ca36ff850..41597e40f02f 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Io.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Io.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `io` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/IoFs.qll b/go/ql/lib/semmle/go/frameworks/stdlib/IoFs.qll index de7fafc514f6..b071e56cbb53 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/IoFs.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/IoFs.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the 'io/fs' package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll index ca74160bf0df..a5ebca68be54 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `log` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/MimeMultipart.qll b/go/ql/lib/semmle/go/frameworks/stdlib/MimeMultipart.qll index ad60672e35e3..d8c193d7f3ea 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/MimeMultipart.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/MimeMultipart.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `mime/multipart` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/MimeQuotedprintable.qll b/go/ql/lib/semmle/go/frameworks/stdlib/MimeQuotedprintable.qll index 0cf54c107a7d..64b3d4c17557 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/MimeQuotedprintable.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/MimeQuotedprintable.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `mime/quotedprintable` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Net.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Net.qll index 5b66e523bad4..9d3f4abf6bda 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Net.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Net.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `net` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll index a2aab2517d7a..9bafe9721b76 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `net/http` package. */ +overlay[local?] +module; import go private import semmle.go.dataflow.internal.DataFlowPrivate diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttpHttputil.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttpHttputil.qll index f914626c7702..465181bb39ff 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttpHttputil.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttpHttputil.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `net/http/httputil` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetTextproto.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetTextproto.qll index 9e19e719ce51..b1d314fdfd18 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetTextproto.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetTextproto.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `net/textproto` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll index 72ea4cc6c573..0a633de08c82 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `os` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Path.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Path.qll index 98215ecd00a2..0bdf0b67ff05 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Path.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Path.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `path` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/PathFilepath.qll b/go/ql/lib/semmle/go/frameworks/stdlib/PathFilepath.qll index 379c141fb2a6..43deb8e1e7ec 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/PathFilepath.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/PathFilepath.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `path/filepath` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Reflect.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Reflect.qll index 62c09ef0c5e4..9a4a74d70d5b 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Reflect.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Reflect.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `reflect` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Regexp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Regexp.qll index 17cc0249908b..6a28cd1709f5 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Regexp.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Regexp.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `regexp` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Strconv.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Strconv.qll index 0f3d2f95cc76..7048ddcbe0dc 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Strconv.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Strconv.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `strconv` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Strings.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Strings.qll index 96b07f5de340..2f514bf28f4f 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Strings.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Strings.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `strings` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Syscall.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Syscall.qll index b93a991e8e31..cb74560809f5 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Syscall.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Syscall.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `syscall` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/TextTabwriter.qll b/go/ql/lib/semmle/go/frameworks/stdlib/TextTabwriter.qll index 964afecb4e6c..f0e78817c2d6 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/TextTabwriter.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/TextTabwriter.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `text/tabwriter` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll b/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll index c5a67f388f42..31d7f94ec57c 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `text/template` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll index d14598e6f79f..307686feac6e 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Unsafe.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling security-relevant aspects of the `unsafe` package. */ +overlay[local?] +module; import go diff --git a/go/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll b/go/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll index 1d1854407722..3bdc948842c7 100644 --- a/go/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll +++ b/go/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import go as G private import codeql.util.test.InlineExpectationsTest diff --git a/go/ql/src/RedundantCode/UnreachableStatement.ql b/go/ql/src/RedundantCode/UnreachableStatement.ql index c177705a86f4..12b035049e9e 100644 --- a/go/ql/src/RedundantCode/UnreachableStatement.ql +++ b/go/ql/src/RedundantCode/UnreachableStatement.ql @@ -26,7 +26,7 @@ ControlFlow::Node nonGuardPredecessor(ControlFlow::Node nd) { * Matches if `retval` is a constant or a struct composed wholly of constants. */ predicate isAllowedReturnValue(Expr retval) { - retval = Builtin::nil().getAReference() + exprRefersToNil(retval) or retval = Builtin::true_().getAReference() or diff --git a/go/ql/src/Security/CWE-327/examples/Crypto.go b/go/ql/src/Security/CWE-327/examples/Crypto.go index b3f71f0772bc..ec34c0c6cf55 100644 --- a/go/ql/src/Security/CWE-327/examples/Crypto.go +++ b/go/ql/src/Security/CWE-327/examples/Crypto.go @@ -13,7 +13,7 @@ func EncryptMessageWeak(key []byte, message []byte) (dst []byte) { } func EncryptMessageStrong(key []byte, message []byte) (dst []byte) { - // GOOD, AES is a weak crypto algorithm + // GOOD, AES is a strong crypto algorithm block, _ := aes.NewCipher(key) block.Encrypt(dst, message) return diff --git a/go/ql/src/experimental/CWE-203/Timing.ql b/go/ql/src/experimental/CWE-203/Timing.ql index e488adf2f97f..30ce6952e067 100644 --- a/go/ql/src/experimental/CWE-203/Timing.ql +++ b/go/ql/src/experimental/CWE-203/Timing.ql @@ -36,7 +36,7 @@ private class SensitiveStringCompareSink extends Sink { not op1 = nonSensitiveOperand and not ( // Comparisons with `nil` should be excluded. - nonSensitiveOperand = Builtin::nil().getAReference() + exprRefersToNil(nonSensitiveOperand) or // Comparisons with empty string should also be excluded. nonSensitiveOperand.getStringValue().length() = 0 @@ -60,7 +60,7 @@ private class SensitiveCompareSink extends Sink { not op1 = op2 and not ( // Comparisons with `nil` should be excluded. - op2 = Builtin::nil().getAReference() + exprRefersToNil(op2) or // Comparisons with empty string should also be excluded. op2.getStringValue().length() = 0 @@ -85,7 +85,7 @@ private class SensitiveStringSink extends Sink { not op1 = op2 and not ( // Comparisons with `nil` should be excluded. - op2 = Builtin::nil().getAReference() + exprRefersToNil(op2) or // Comparisons with empty string should also be excluded. op2.getStringValue().length() = 0 diff --git a/go/ql/src/filters/ClassifyFiles.ql b/go/ql/src/filters/ClassifyFiles.ql index f5ac12583750..8e353740c1a7 100644 --- a/go/ql/src/filters/ClassifyFiles.ql +++ b/go/ql/src/filters/ClassifyFiles.ql @@ -1,6 +1,6 @@ /** * @name Classify files - * @description This query produces a list of all files in a snapshot that are classified as + * @description This query produces a list of all files in a database that are classified as * generated code, test code or vendored-in library code. * @kind file-classifier * @id go/file-classifier diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 9a89c863bc6d..bc7a0adc3d24 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 1.5.7 +version: 1.5.8-dev groups: - go - queries diff --git a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql index 4ca15c10ac5a..bbcaa16f28bd 100644 --- a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql +++ b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstExcludeComments.ql @@ -5,6 +5,7 @@ import go import semmle.go.PrintAst +overlay[local] class Cfg extends PrintAstConfiguration { override predicate shouldPrintFunction(FuncDecl func) { any() } diff --git a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql index eaddceacaa3b..b04be6edfac4 100644 --- a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql +++ b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstNestedFunction.ql @@ -5,6 +5,7 @@ import go import semmle.go.PrintAst +overlay[local] class Cfg extends PrintAstConfiguration { override predicate shouldPrintFunction(FuncDecl func) { func.getName() = "hasNested" } diff --git a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql index 83d27b9cf26c..60cda4f5045b 100644 --- a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql +++ b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFile.ql @@ -5,6 +5,7 @@ import go import semmle.go.PrintAst +overlay[local] class Cfg extends PrintAstConfiguration { override predicate shouldPrintFunction(FuncDecl func) { any() } diff --git a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql index 382fc3977553..5b3501edc6c1 100644 --- a/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql +++ b/go/ql/test/library-tests/semmle/go/PrintAst/PrintAstRestrictFunction.ql @@ -5,6 +5,7 @@ import go import semmle.go.PrintAst +overlay[local] class Cfg extends PrintAstConfiguration { override predicate shouldPrintFunction(FuncDecl func) { func.getName() = "g" } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql index 181c55b29df9..2468a57cac0f 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_I1.ql @@ -34,6 +34,7 @@ module FlowTest implements TestSig { } } +overlay[local] class MyStep extends DataFlow::FunctionModel, Method { MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "I1", "Step") } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql index e82a6cb4da10..788c8c028d21 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_P1.ql @@ -44,6 +44,7 @@ module FlowTest implements TestSig { } } +overlay[local] class MyStep extends DataFlow::FunctionModel, Method { MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "P1", "Step") } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql index c4124dcd10e5..127fb0012a32 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalFlowInheritance/ql_S1.ql @@ -44,6 +44,7 @@ module FlowTest implements TestSig { } } +overlay[local] class MyStep extends DataFlow::FunctionModel, Method { MyStep() { this.hasQualifiedName("github.com/nonexistent/test", "S1", "Step") } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql b/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql index 78e21d534e09..bbe5618b5682 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql @@ -4,6 +4,7 @@ import ModelValidation import utils.test.InlineFlowTest import DefaultFlowTest +overlay[local] class SummaryModelTest extends DataFlow::FunctionModel { FunctionInput inp; FunctionOutput outp; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/file/test.go b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/file/test.go index 1a1457514762..27bdff33a27d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/file/test.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/file/test.go @@ -16,7 +16,7 @@ func open() { } func openFile() { - file, err := os.OpenFile("file.txt", os.O_RDWR, 0) // $source + file, err := os.OpenFile("file.txt", os.O_RDWR, 0) // $ source if err != nil { return } @@ -25,7 +25,7 @@ func openFile() { } func readFile() { - data, err := os.ReadFile("file.txt") // $source + data, err := os.ReadFile("file.txt") // $ source if err != nil { return } @@ -33,7 +33,7 @@ func readFile() { } func readFileIoUtil() { - data, err := ioutil.ReadFile("file.txt") // $source + data, err := ioutil.ReadFile("file.txt") // $ source if err != nil { return } @@ -45,14 +45,14 @@ func getFileFS() fs.ReadFileFS { } func readFileFs() { - data, err := fs.ReadFile(os.DirFS("."), "file.txt") // $source + data, err := fs.ReadFile(os.DirFS("."), "file.txt") // $ source if err != nil { return } _ = data dir := getFileFS() - data, err = dir.ReadFile("file.txt") // $source + data, err = dir.ReadFile("file.txt") // $ source if err != nil { return @@ -61,7 +61,7 @@ func readFileFs() { } func fsOpen() { - file, err := os.DirFS(".").Open("file.txt") // $source + file, err := os.DirFS(".").Open("file.txt") // $ source if err != nil { return } diff --git a/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/stdin/test.go b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/stdin/test.go index 4166dc4000b0..8a2830b73e3c 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/stdin/test.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/flowsources/local/stdin/test.go @@ -12,37 +12,37 @@ func sink(string) { func readStdinBuffer() { buf := make([]byte, 1024) - n, err := os.Stdin.Read(buf) // $source + n, err := os.Stdin.Read(buf) // $ source if err != nil { return } - sink(string(buf[:n])) // $hasTaintFlow="type conversion" + sink(string(buf[:n])) // $ hasTaintFlow="type conversion" } func readStdinBuffReader() { buf := make([]byte, 1024) - r := bufio.NewReader(os.Stdin) // $source + r := bufio.NewReader(os.Stdin) // $ source n, err := r.Read(buf) if err != nil { return } - sink(string(buf[:n])) // $hasTaintFlow="type conversion" + sink(string(buf[:n])) // $ hasTaintFlow="type conversion" } func scan() { var username, email string - fmt.Scan(&username, &email) // $source - sink(username) // $hasTaintFlow="username" + fmt.Scan(&username, &email) // $ source + sink(username) // $ hasTaintFlow="username" } func scanf() { var s string - fmt.Scanf("%s", &s) // $source - sink(s) // $hasTaintFlow="s" + fmt.Scanf("%s", &s) // $ source + sink(s) // $ hasTaintFlow="s" } func scanl() { var s string - fmt.Scanln(&s) // $source - sink(s) // $hasTaintFlow="s" + fmt.Scanln(&s) // $ source + sink(s) // $ hasTaintFlow="s" } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Macaron/sources.go b/go/ql/test/library-tests/semmle/go/frameworks/Macaron/sources.go index 9cc46d5611e6..eaf3ad51f437 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Macaron/sources.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/Macaron/sources.go @@ -7,16 +7,16 @@ import ( ) func sources(ctx *macaron.Context, body *macaron.RequestBody) { - _ = ctx.AllParams() // $RemoteFlowSource - _ = ctx.GetCookie("") // $RemoteFlowSource - _, _ = ctx.GetSecureCookie("") // $RemoteFlowSource - _, _ = ctx.GetSuperSecureCookie("", "") // $RemoteFlowSource - _, _, _ = ctx.GetFile("") // $RemoteFlowSource - _ = ctx.Params("") // $RemoteFlowSource - _ = ctx.ParamsEscape("") // $RemoteFlowSource - _ = ctx.Query("") // $RemoteFlowSource - _ = ctx.QueryEscape("") // $RemoteFlowSource - _ = ctx.QueryStrings("") // $RemoteFlowSource - _, _ = body.Bytes() // $RemoteFlowSource - _, _ = body.String() // $RemoteFlowSource + _ = ctx.AllParams() // $ RemoteFlowSource + _ = ctx.GetCookie("") // $ RemoteFlowSource + _, _ = ctx.GetSecureCookie("") // $ RemoteFlowSource + _, _ = ctx.GetSuperSecureCookie("", "") // $ RemoteFlowSource + _, _, _ = ctx.GetFile("") // $ RemoteFlowSource + _ = ctx.Params("") // $ RemoteFlowSource + _ = ctx.ParamsEscape("") // $ RemoteFlowSource + _ = ctx.Query("") // $ RemoteFlowSource + _ = ctx.QueryEscape("") // $ RemoteFlowSource + _ = ctx.QueryStrings("") // $ RemoteFlowSource + _, _ = body.Bytes() // $ RemoteFlowSource + _, _ = body.String() // $ RemoteFlowSource } diff --git a/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/old.dbscheme b/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/old.dbscheme new file mode 100644 index 000000000000..de4ded61c8ae --- /dev/null +++ b/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/old.dbscheme @@ -0,0 +1,1241 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path: string ref +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isImplicitClass( + unique int classid: @classorinterface ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +isCanonicalConstr( + int constructorid: @constructor ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +| 89 = @recordpatternexpr +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @assignment + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +isNullDefaultCase( + int id: @case ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF + // 3: ENUM_ENTRIES +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/semmlecode.dbscheme b/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/semmlecode.dbscheme new file mode 100644 index 000000000000..9f6026c40099 --- /dev/null +++ b/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/semmlecode.dbscheme @@ -0,0 +1,1240 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path: string ref +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isImplicitClass( + unique int classid: @classorinterface ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +isCanonicalConstr( + int constructorid: @constructor ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +| 89 = @recordpatternexpr +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +isNullDefaultCase( + int id: @case ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF + // 3: ENUM_ENTRIES +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/upgrade.properties b/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/upgrade.properties new file mode 100644 index 000000000000..3f8e5f96d0a0 --- /dev/null +++ b/java/downgrades/de4ded61c8ae83f829aedaf05be73307ba25ca40/upgrade.properties @@ -0,0 +1,2 @@ +description: Remove inclusion of @assignment in @binaryexpr +compatibility: full diff --git a/java/ql/consistency-queries/BinaryExpr.ql b/java/ql/consistency-queries/BinaryExpr.ql index ff4384a8d497..56763e9800f9 100644 --- a/java/ql/consistency-queries/BinaryExpr.ql +++ b/java/ql/consistency-queries/BinaryExpr.ql @@ -10,5 +10,5 @@ where e.isNthChildOf(be, i) and i != 0 and i != 1 and reason = "Unexpected operand " + i.toString() ) or - be.getOp() = " ?? " and reason = "No operator name" + be.getOp() = "??" and reason = "No operator name" select be, reason diff --git a/java/ql/consistency-queries/CfgConsistency.ql b/java/ql/consistency-queries/CfgConsistency.ql new file mode 100644 index 000000000000..38ed20134d1b --- /dev/null +++ b/java/ql/consistency-queries/CfgConsistency.ql @@ -0,0 +1,2 @@ +import java +import ControlFlow::Consistency diff --git a/java/ql/lib/change-notes/2026-02-18-cfg.md b/java/ql/lib/change-notes/2026-02-18-cfg.md new file mode 100644 index 000000000000..27bd381ec0d5 --- /dev/null +++ b/java/ql/lib/change-notes/2026-02-18-cfg.md @@ -0,0 +1,16 @@ +--- +category: breaking +--- +* The Java control flow graph (CFG) implementation has been completely + rewritten. The CFG now includes additional nodes to more accurately represent + certain constructs. This also means that any existing code that implicitly + relies on very specific details about the CFG may need to be updated. + The CFG now only includes the nodes that are reachable from the entry point. + Additionally, the following breaking changes have been made: + - `ControlFlowNode.asCall` has been removed - use `Call.getControlFlowNode` instead. + - `ControlFlowNode.getEnclosingStmt` has been removed. + - `ControlFlow::ExprNode` has been removed. + - `ControlFlow::StmtNode` has been removed. + - `ControlFlow::Node` has been removed - this was merely an alias of + `ControlFlowNode`, which is still available. + - Previously deprecated predicates on `BasicBlock` have been removed. diff --git a/java/ql/lib/change-notes/2026-03-04-binary-assignment.md b/java/ql/lib/change-notes/2026-03-04-binary-assignment.md new file mode 100644 index 000000000000..e94a7f6722bc --- /dev/null +++ b/java/ql/lib/change-notes/2026-03-04-binary-assignment.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The class `Assignment` now extends `BinaryExpr`. Uses of `BinaryExpr` may in some cases need slight adjustment. diff --git a/java/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md b/java/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md new file mode 100644 index 000000000000..23fdce9b6159 --- /dev/null +++ b/java/ql/lib/change-notes/2026-03-05-inline-expectation-space-after-$.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol. diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme index 9f6026c40099..de4ded61c8ae 100644 --- a/java/ql/lib/config/semmlecode.dbscheme +++ b/java/ql/lib/config/semmlecode.dbscheme @@ -815,6 +815,7 @@ when_branch_else(unique int id: @whenbranch ref); | @geexpr | @eqexpr | @neexpr + | @assignment | @valueeqexpr | @valueneexpr; diff --git a/java/ql/lib/ext/java.net.model.yml b/java/ql/lib/ext/java.net.model.yml index e69db468a4a4..4db8c92b5f94 100644 --- a/java/ql/lib/ext/java.net.model.yml +++ b/java/ql/lib/ext/java.net.model.yml @@ -57,7 +57,7 @@ extensions: - ["java.net", "InetSocketAddress", True, "getPort", "()", "", "Argument[this].SyntheticField[java.net.InetSocketAddress.port]", "ReturnValue", "taint", "manual"] - ["java.net", "URI", False, "resolve", "(URI)", "", "Argument[this]", "ReturnValue", "taint", "ai-manual"] - ["java.net", "URI", False, "URI", "(String,String,String,int,String,String,String)", "", "Argument[5]", "Argument[this].SyntheticField[java.net.URI.query]", "taint", "ai-manual"] - - ["java.net", "URI", False, "URI", "(String,String,String)", "", "Argument[1]", "ReturnValue", "taint", "ai-manual"] + - ["java.net", "URI", False, "URI", "(String,String,String)", "", "Argument[1]", "Argument[this]", "taint", "ai-manual"] - ["java.net", "URI", False, "URI", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.net", "URI", False, "create", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.net", "URI", False, "getPath", "()", "", "Argument[this]", "ReturnValue", "taint", "df-manual"] diff --git a/java/ql/lib/ext/java.util.zip.model.yml b/java/ql/lib/ext/java.util.zip.model.yml index dc24570995f8..852cf8afccb4 100644 --- a/java/ql/lib/ext/java.util.zip.model.yml +++ b/java/ql/lib/ext/java.util.zip.model.yml @@ -4,7 +4,7 @@ extensions: extensible: summaryModel data: - ["java.util.zip", "GZIPInputStream", False, "GZIPInputStream", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["java.util.zip", "ZipEntry", True, "ZipEntry", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-manual"] + - ["java.util.zip", "ZipEntry", True, "ZipEntry", "(String)", "", "Argument[0]", "Argument[this]", "taint", "ai-manual"] - ["java.util.zip", "ZipFile", True, "ZipFile", "(File)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.util.zip", "ZipFile", True, "ZipFile", "(File,Charset)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["java.util.zip", "ZipFile", True, "ZipFile", "(File,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml b/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml index 1cde9909d823..710e4d9bc07a 100644 --- a/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml +++ b/java/ql/lib/ext/org.apache.hc.core5.http.io.entity.model.yml @@ -3,8 +3,8 @@ extensions: pack: codeql/java-all extensible: summaryModel data: - - ["org.apache.hc.core5.http.io.entity", "BasicHttpEntity", True, "BasicHttpEntity", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["org.apache.hc.core5.http.io.entity", "BufferedHttpEntity", True, "BufferedHttpEntity", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["org.apache.hc.core5.http.io.entity", "BasicHttpEntity", True, "BasicHttpEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["org.apache.hc.core5.http.io.entity", "BufferedHttpEntity", True, "BufferedHttpEntity", "(HttpEntity)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "ByteArrayEntity", True, "ByteArrayEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "EntityUtils", True, "parse", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "EntityUtils", True, "toByteArray", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] @@ -14,6 +14,6 @@ extensions: - ["org.apache.hc.core5.http.io.entity", "HttpEntities", True, "createUrlEncoded", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "HttpEntities", True, "gzip", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "HttpEntities", True, "withTrailers", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["org.apache.hc.core5.http.io.entity", "HttpEntityWrapper", True, "HttpEntityWrapper", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["org.apache.hc.core5.http.io.entity", "InputStreamEntity", True, "InputStreamEntity", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["org.apache.hc.core5.http.io.entity", "HttpEntityWrapper", True, "HttpEntityWrapper", "(HttpEntity)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["org.apache.hc.core5.http.io.entity", "InputStreamEntity", True, "InputStreamEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["org.apache.hc.core5.http.io.entity", "StringEntity", True, "StringEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.http.entity.model.yml b/java/ql/lib/ext/org.apache.http.entity.model.yml index 4d0f0d60466d..6a8418049ca9 100644 --- a/java/ql/lib/ext/org.apache.http.entity.model.yml +++ b/java/ql/lib/ext/org.apache.http.entity.model.yml @@ -4,8 +4,8 @@ extensions: extensible: summaryModel data: - ["org.apache.http.entity", "BasicHttpEntity", True, "setContent", "(InputStream)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["org.apache.http.entity", "BufferedHttpEntity", True, "BufferedHttpEntity", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["org.apache.http.entity", "BufferedHttpEntity", True, "BufferedHttpEntity", "(HttpEntity)", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["org.apache.http.entity", "ByteArrayEntity", True, "ByteArrayEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - - ["org.apache.http.entity", "HttpEntityWrapper", True, "HttpEntityWrapper", "(HttpEntity)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["org.apache.http.entity", "InputStreamEntity", True, "InputStreamEntity", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["org.apache.http.entity", "HttpEntityWrapper", True, "HttpEntityWrapper", "(HttpEntity)", "", "Argument[0]", "Argument[this]", "taint", "manual"] + - ["org.apache.http.entity", "InputStreamEntity", True, "InputStreamEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] - ["org.apache.http.entity", "StringEntity", True, "StringEntity", "", "", "Argument[0]", "Argument[this]", "taint", "manual"] diff --git a/java/ql/lib/printCfg.ql b/java/ql/lib/printCfg.ql index 5e3cc22644ef..d90c4633de85 100644 --- a/java/ql/lib/printCfg.ql +++ b/java/ql/lib/printCfg.ql @@ -21,7 +21,7 @@ external int selectedSourceColumn(); private predicate selectedSourceColumnAlias = selectedSourceColumn/0; -module ViewCfgQueryInput implements ViewCfgQueryInputSig { +module ViewCfgQueryInput implements ControlFlow::ViewCfgQueryInputSig { predicate selectedSourceFile = selectedSourceFileAlias/0; predicate selectedSourceLine = selectedSourceLineAlias/0; @@ -42,4 +42,4 @@ module ViewCfgQueryInput implements ViewCfgQueryInputSig { } } -import ViewCfgQuery +import ControlFlow::ViewCfgQuery diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index d9ed85693a21..243a7ddd9a6b 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 8.1.1 +version: 8.1.2-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/java/Completion.qll b/java/ql/lib/semmle/code/java/Completion.qll deleted file mode 100644 index 35d3c83e2ee9..000000000000 --- a/java/ql/lib/semmle/code/java/Completion.qll +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Provides classes and predicates for representing completions. - */ -overlay[local?] -module; - -/* - * A completion represents how a statement or expression terminates. - * - * There are five kinds of completions: normal completion, - * `return` completion, `break` completion, - * `continue` completion, and `throw` completion. - * - * Normal completions are further subdivided into boolean completions and all - * other normal completions. A boolean completion adds the information that the - * cfg node terminated with the given boolean value due to a subexpression - * terminating with the other given boolean value. This is only - * relevant for conditional contexts in which the value controls the - * control-flow successor. - */ - -import java - -/** - * A label of a `LabeledStmt`. - */ -newtype Label = MkLabel(string l) { exists(LabeledStmt lbl | l = lbl.getLabel()) } - -/** - * Either a `Label` or nothing. - */ -newtype MaybeLabel = - JustLabel(Label l) or - NoLabel() - -/** - * A completion of a statement or an expression. - */ -newtype Completion = - /** - * The statement or expression completes normally and continues to the next statement. - */ - NormalCompletion() or - /** - * The statement or expression completes by returning from the function. - */ - ReturnCompletion() or - /** - * The expression completes with value `outerValue` overall and with the last control - * flow node having value `innerValue`. - */ - BooleanCompletion(boolean outerValue, boolean innerValue) { - (outerValue = true or outerValue = false) and - (innerValue = true or innerValue = false) - } or - /** - * The expression or statement completes via a `break` statement. - */ - BreakCompletion(MaybeLabel l) or - /** - * The expression or statement completes via a `yield` statement. - */ - YieldCompletion(NormalOrBooleanCompletion c) or - /** - * The expression or statement completes via a `continue` statement. - */ - ContinueCompletion(MaybeLabel l) or - /** - * The expression or statement completes by throwing a `ThrowableType`. - */ - ThrowCompletion(ThrowableType tt) - -/** A completion that is either a `NormalCompletion` or a `BooleanCompletion`. */ -class NormalOrBooleanCompletion extends Completion { - NormalOrBooleanCompletion() { - this instanceof NormalCompletion or this instanceof BooleanCompletion - } - - /** Gets a textual representation of this completion. */ - string toString() { result = "completion" } -} - -/** Gets the completion `ContinueCompletion(NoLabel())`. */ -ContinueCompletion anonymousContinueCompletion() { result = ContinueCompletion(NoLabel()) } - -/** Gets the completion `ContinueCompletion(JustLabel(l))`. */ -ContinueCompletion labelledContinueCompletion(Label l) { result = ContinueCompletion(JustLabel(l)) } - -/** Gets the completion `BreakCompletion(NoLabel())`. */ -BreakCompletion anonymousBreakCompletion() { result = BreakCompletion(NoLabel()) } - -/** Gets the completion `BreakCompletion(JustLabel(l))`. */ -BreakCompletion labelledBreakCompletion(Label l) { result = BreakCompletion(JustLabel(l)) } - -/** Gets the completion `BooleanCompletion(value, value)`. */ -Completion basicBooleanCompletion(boolean value) { result = BooleanCompletion(value, value) } diff --git a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll index 64449b6f93d7..4ec8ff8450ac 100644 --- a/java/ql/lib/semmle/code/java/ControlFlowGraph.qll +++ b/java/ql/lib/semmle/code/java/ControlFlowGraph.qll @@ -1,543 +1,327 @@ /** - * Provides classes and predicates for computing expression-level intra-procedural control flow graphs. - * - * The only API exported by this library are the toplevel classes `ControlFlow::Node` - * and its subclass `ConditionNode`, which wrap the successor relation and the - * concept of true- and false-successors of conditions. A cfg node may either be a - * statement, an expression, or an exit node for a callable, indicating that - * execution of the callable terminates. + * Provides classes representing the control flow graph within callables. */ overlay[local?] module; -/* - * The implementation is centered around the concept of a _completion_, which - * models how the execution of a statement or expression terminates. - * Completions are represented as an algebraic data type `Completion` defined in - * `Completion.qll`. - * - * The CFG is built by structural recursion over the AST. To achieve this the - * CFG edges related to a given AST node, `n`, is divided into three categories: - * 1. The in-going edge that points to the first CFG node to execute when the - * `n` is going to be executed. - * 2. The out-going edges for control-flow leaving `n` that are going to some - * other node in the surrounding context of `n`. - * 3. The edges that have both of their end-points entirely within the AST - * node and its children. - * The edges in (1) and (2) are inherently non-local and are therefore - * initially calculated as half-edges, that is, the single node, `k`, of the - * edge contained within `n`, by the predicates `k = first(n)` and - * `last(n, k, _)`, respectively. The edges in (3) can then be enumerated - * directly by the predicate `succ` by calling `first` and `last` recursively - * on the children of `n` and connecting the end-points. This yields the entire - * CFG, since all edges are in (3) for _some_ AST node. - * - * The third parameter of `last` is the completion, which is necessary to - * distinguish the out-going edges from `n`. Note that the completion changes - * as the calculation of `last` proceeds outward through the AST; for example, - * a `breakCompletion` is caught up by its surrounding loop and turned into a - * `normalCompletion`, or a `normalCompletion` proceeds outward through the end - * of a `finally` block and is turned into whatever completion was caught by - * the `finally`, or a `booleanCompletion(false, _)` occurs in a loop condition - * and is turned into a `normalCompletion` of the entire loop. When the edge is - * eventually connected we use the completion at that level of the AST as the - * label of the edge, thus creating an edge-labelled CFG. - * - * An important goal of the CFG is to get the order of side-effects correct. - * Most expressions can have side-effects and must therefore be modeled in the - * CFG in AST post-order. For example, a `MethodCall` evaluates its arguments - * before the call. Most statements don't have side-effects, but merely affect - * the control-flow and some could therefore be excluded from the CFG. However, - * as a design choice, all statements are included in the CFG and generally - * serve as their own entry-points, thus executing in some version of AST - * pre-order. A few notable exceptions are `ReturnStmt`, `ThrowStmt`, - * `SynchronizedStmt`, `ThisConstructorInvocationStmt`, and - * `SuperConstructorInvocationStmt`, which all have side-effects and therefore - * are modeled in side-effect order. Loop statement nodes are only passed on - * entry, after which control goes back and forth between body and loop - * condition. - * - * Some out-going edges from boolean expressions have a known value and in some - * contexts this affects the possible successors. For example, in `if(A || B)` - * a short-circuit edge that skips `B` must be true and can therefore only lead - * to the then-branch. If the `||` is modeled in post-order then this - * information is lost, and consequently it is better to model `||` and `&&` in - * pre-order. The conditional expression `? :` is also modeled in pre-order to - * achieve consistent CFGs for the equivalent `A && B` and `A ? B : false`. - * Finally, the logical negation is also modeled in pre-order to achieve - * consistent CFGs for the equivalent `!(A || B)` and `!A && !B`. The boolean - * value `b` is tracked with the completion `booleanCompletion(b, _)`. - * - * Note that the second parameter in a `booleanCompletion` isn't needed to - * calculate the CFG. It is, however, needed to track the value of the - * sub-expression. For example, this ensures that the false-successor of the - * `ConditionNode` `A` in `if(!(A && B))` can be correctly identified as the - * then-branch (even though this completion turns into a - * `booleanCompletion(true, _)` from the perspective of the `if`-node). - * - * As a final note, expressions that aren't actually executed in the usual - * sense are excluded from the CFG. This covers, for example, parentheses, - * l-values that aren't r-values as well, and expressions in `ConstCase`s. - * For example, the `x` in `x=3` is not in the CFG, but the `x` in `x+=3` is. - */ - import java +private import codeql.controlflow.ControlFlowGraph private import codeql.controlflow.SuccessorType -private import codeql.util.Boolean -private import Completion private import controlflow.internal.Preconditions -private import controlflow.internal.SwitchCases - -/** Provides the definition of control flow nodes. */ -module ControlFlow { - private predicate hasControlFlow(Expr e) { - not exists(ConstCase cc | e = cc.getValue(_)) and - not e.getParent*() instanceof Annotation and - not e instanceof TypeAccess and - not e instanceof ArrayTypeAccess and - not e instanceof UnionTypeAccess and - not e instanceof IntersectionTypeAccess and - not e instanceof WildcardTypeAccess and - not exists(AssignExpr ae | ae.getDest() = e) - } - private newtype TNode = - TExprNode(Expr e) { hasControlFlow(e) } or - TStmtNode(Stmt s) or - TAnnotatedExitNode(Callable c, Boolean normal) { exists(c.getBody()) } or - TExitNode(Callable c) { exists(c.getBody()) } or - TAssertThrowNode(AssertStmt s) +private module Cfg0 = Make0; - /** A node in the expression-level control-flow graph. */ - class Node extends TNode { - /** Gets an immediate successor of this node. */ - Node getASuccessor() { result = succ(this) } +private module Cfg1 = Make1; - /** Gets an immediate predecessor of this node. */ - Node getAPredecessor() { this = succ(result) } +private module Cfg2 = Make2; - /** Gets an exception successor of this node. */ - Node getAnExceptionSuccessor() { result = succ(this, ThrowCompletion(_)) } +private import Cfg0 +private import Cfg1 +private import Cfg2 +import Public - /** Gets a successor of this node that is neither an exception successor nor a jump (break, continue, return). */ - Node getANormalSuccessor() { - result = succ(this, BooleanCompletion(_, _)) or - result = succ(this, NormalCompletion()) - } +/** Provides an implementation of the AST signature for Java. */ +private module Ast implements AstSig { + private import java as J - /** Gets an immediate successor of this node of a given type, if any. */ - Node getASuccessor(SuccessorType t) { - result = branchSuccessor(this, t.(BooleanSuccessor).getValue()) - or - exists(Completion completion | - result = succ(this, completion) and - not result = branchSuccessor(this, _) - | - completion = NormalCompletion() and t instanceof DirectSuccessor - or - completion = ReturnCompletion() and t instanceof ReturnSuccessor - or - completion = BreakCompletion(_) and t instanceof BreakSuccessor - or - completion = YieldCompletion(_) and t instanceof BreakSuccessor - or - completion = ContinueCompletion(_) and t instanceof ContinueSuccessor - or - completion = ThrowCompletion(_) and t instanceof ExceptionSuccessor - ) - } + class AstNode = ExprParent; - /** Gets the basic block that contains this node. */ - BasicBlock getBasicBlock() { result.getANode() = this } + private predicate skipControlFlow(AstNode e) { + e.(Expr).getParent*() instanceof Annotation or + e instanceof TypeAccess or + e instanceof ArrayTypeAccess or + e instanceof UnionTypeAccess or + e instanceof IntersectionTypeAccess or + e instanceof WildcardTypeAccess or + // Switch cases of the form `case e1 -> e2;` skip the ExprStmt and treat + // the right-hand side as an expression. See `SwitchCase.getRuleExpression()`. + any(SwitchCase sc).getRuleExpression() = e.(J::ExprStmt).getExpr() + } - /** Gets the statement containing this node, if any. */ - Stmt getEnclosingStmt() { none() } + AstNode getChild(AstNode n, int index) { + not skipControlFlow(result) and + not skipControlFlow(n) and + result.(Expr).isNthChildOf(n, index) + or + result.(Stmt).isNthChildOf(n, index) + or + result = n.(SwitchCase).getRuleExpression() and index = -1 + } - /** Gets the immediately enclosing callable whose body contains this node. */ - Callable getEnclosingCallable() { none() } + Callable getEnclosingCallable(AstNode node) { + result = node.(Expr).getEnclosingCallable() or + result = node.(Stmt).getEnclosingCallable() + } - /** Gets the statement this `Node` corresponds to, if any. */ - Stmt asStmt() { this = TStmtNode(result) } + class Callable = J::Callable; - /** Gets the expression this `Node` corresponds to, if any. */ - Expr asExpr() { this = TExprNode(result) } + AstNode callableGetBody(Callable c) { result = c.getBody() } - /** Gets the call this `Node` corresponds to, if any. */ - Call asCall() { - result = this.asExpr() or - result = this.asStmt() - } + class Stmt = J::Stmt; - /** Gets a textual representation of this element. */ - string toString() { none() } + class Expr = J::Expr; - /** Gets the source location for this element. */ - Location getLocation() { none() } + class BlockStmt = J::BlockStmt; - /** - * Gets the most appropriate AST node for this control flow node, if any. - */ - ExprParent getAstNode() { none() } + class ExprStmt extends J::ExprStmt { + ExprStmt() { not skipControlFlow(this) } } - /** A control-flow node that represents the evaluation of an expression. */ - class ExprNode extends Node, TExprNode { - Expr e; + class IfStmt = J::IfStmt; - ExprNode() { this = TExprNode(e) } + class LoopStmt = J::LoopStmt; - override Stmt getEnclosingStmt() { result = e.getEnclosingStmt() } + class WhileStmt = J::WhileStmt; - override Callable getEnclosingCallable() { result = e.getEnclosingCallable() } + class DoStmt = J::DoStmt; - override ExprParent getAstNode() { result = e } + class ForStmt = J::ForStmt; - /** Gets a textual representation of this element. */ - override string toString() { result = e.toString() } + final private class FinalEnhancedForStmt = J::EnhancedForStmt; - /** Gets the source location for this element. */ - override Location getLocation() { result = e.getLocation() } - } + class ForeachStmt extends FinalEnhancedForStmt { + Expr getVariable() { result = super.getVariable() } - /** A control-flow node that represents a statement. */ - class StmtNode extends Node, TStmtNode { - Stmt s; - - StmtNode() { this = TStmtNode(s) } - - override Stmt getEnclosingStmt() { result = s } - - override Callable getEnclosingCallable() { result = s.getEnclosingCallable() } - - override ExprParent getAstNode() { result = s } - - override string toString() { result = s.toString() } + Expr getCollection() { result = super.getExpr() } + } - override Location getLocation() { result = s.getLocation() } + class BreakStmt extends Stmt { + BreakStmt() { this instanceof J::BreakStmt or this instanceof YieldStmt } } - /** A control flow node indicating the normal or exceptional termination of a callable. */ - class AnnotatedExitNode extends Node, TAnnotatedExitNode { - Callable c; - boolean normal; + class ContinueStmt = J::ContinueStmt; - AnnotatedExitNode() { this = TAnnotatedExitNode(c, normal) } + class ReturnStmt = J::ReturnStmt; - override Callable getEnclosingCallable() { result = c } + class ThrowStmt = J::ThrowStmt; - override ExprParent getAstNode() { result = c } + final private class FinalTryStmt = J::TryStmt; - /** Gets a textual representation of this element. */ - override string toString() { - normal = true and result = "Normal Exit" - or - normal = false and result = "Exceptional Exit" - } - - /** Gets the source location for this element. */ - override Location getLocation() { result = c.getLocation() } - } + class TryStmt extends FinalTryStmt { + Stmt getBody() { result = super.getBlock() } - /** A control flow node indicating normal termination of a callable. */ - class NormalExitNode extends AnnotatedExitNode { - NormalExitNode() { this = TAnnotatedExitNode(_, true) } - } + CatchClause getCatch(int index) { result = super.getCatchClause(index) } - /** A control flow node indicating exceptional termination of a callable. */ - class ExceptionalExitNode extends AnnotatedExitNode { - ExceptionalExitNode() { this = TAnnotatedExitNode(_, false) } + Stmt getFinally() { result = super.getFinally() } } - /** A control flow node indicating the termination of a callable. */ - class ExitNode extends Node, TExitNode { - Callable c; + AstNode getTryInit(TryStmt try, int index) { result = try.getResource(index) } - ExitNode() { this = TExitNode(c) } + final private class FinalCatchClause = J::CatchClause; - override Callable getEnclosingCallable() { result = c } + class CatchClause extends FinalCatchClause { + AstNode getVariable() { result = super.getVariable() } - override ExprParent getAstNode() { result = c } + Expr getCondition() { none() } - /** Gets a textual representation of this element. */ - override string toString() { result = "Exit" } - - /** Gets the source location for this element. */ - override Location getLocation() { result = c.getLocation() } + Stmt getBody() { result = super.getBlock() } } - /** A control flow node indicating a failing assertion. */ - class AssertThrowNode extends Node, TAssertThrowNode { - AssertStmt s; + class Switch extends AstNode { + Switch() { + this instanceof SwitchStmt or + this instanceof SwitchExpr + } - AssertThrowNode() { this = TAssertThrowNode(s) } + Expr getExpr() { + result = this.(SwitchStmt).getExpr() or + result = this.(SwitchExpr).getExpr() + } - override Stmt getEnclosingStmt() { result = s } + Case getCase(int index) { + result = this.(SwitchStmt).getCase(index) or + result = this.(SwitchExpr).getCase(index) + } - override Callable getEnclosingCallable() { result = s.getEnclosingCallable() } + Stmt getStmt(int index) { + result = this.(SwitchStmt).getStmt(index) or + result = this.(SwitchExpr).getStmt(index) + } + } - override ExprParent getAstNode() { result = s } + class Case extends AstNode instanceof J::SwitchCase { + /** Gets a pattern being matched by this case. */ + AstNode getAPattern() { + result = this.(PatternCase).getAPattern() or + result = this.(ConstCase).getValue(_) + } - /** Gets a textual representation of this element. */ - override string toString() { result = "Assert Throw" } + /** Gets the guard expression of this case, if any. */ + Expr getGuard() { result = this.(PatternCase).getGuard() } - /** Gets the source location for this element. */ - override Location getLocation() { result = s.getLocation() } + /** + * Gets the body of this case, if any. + * + * A case can either have a body as a single child AST node given by this + * predicate, or it can have an implicit body given by the sequence of + * statements between this case and the next case. + */ + AstNode getBody() { + result = this.(J::SwitchCase).getRuleExpression() + or + result = this.(J::SwitchCase).getRuleStatement() + } } -} -class ControlFlowNode = ControlFlow::Node; + class DefaultCase extends Case instanceof J::DefaultCase { } -/** Gets the intra-procedural successor of `n`. */ -private ControlFlowNode succ(ControlFlowNode n) { result = succ(n, _) } + class ConditionalExpr = J::ConditionalExpr; -cached -private module ControlFlowGraphImpl { - private import ControlFlow + class BinaryExpr = J::BinaryExpr; - private class AstNode extends ExprParent { - AstNode() { this instanceof Expr or this instanceof Stmt } + class LogicalAndExpr = AndLogicalExpr; - Stmt getEnclosingStmt() { - result = this or - result = this.(Expr).getEnclosingStmt() - } + class LogicalOrExpr = OrLogicalExpr; - Node getCfgNode() { result.asExpr() = this or result.asStmt() = this } + class NullCoalescingExpr extends BinaryExpr { + NullCoalescingExpr() { none() } } - /** - * Gets a label that applies to this statement. - */ - private Label getLabel(Stmt s) { - exists(LabeledStmt l | s = l.getStmt() | - result = MkLabel(l.getLabel()) or - result = getLabel(l) - ) - } + class UnaryExpr = J::UnaryExpr; - /** - * A throwable that's a (reflexive, transitive) supertype of an unchecked - * exception. Besides the unchecked exceptions themselves, this includes - * `java.lang.Throwable` and `java.lang.Exception`. - */ - private class UncheckedThrowableSuperType extends RefType { - UncheckedThrowableSuperType() { - this instanceof TypeThrowable or - this instanceof TypeException or - this instanceof UncheckedThrowableType - } + class LogicalNotExpr = LogNotExpr; - /** - * An unchecked throwable that is a subtype of this `UncheckedThrowableSuperType` and - * sits as high as possible in the type hierarchy. This is mostly unique except for - * `TypeThrowable` which results in both `TypeError` and `TypeRuntimeException`. - */ - UncheckedThrowableType getAnUncheckedSubtype() { - result = this - or - result instanceof TypeError and this instanceof TypeThrowable - or - result instanceof TypeRuntimeException and - (this instanceof TypeThrowable or this instanceof TypeException) - } - } + final private class FinalBooleanLiteral = J::BooleanLiteral; - /** - * Bind `t` to an exception type that may be thrown during execution of `n`, - * either because `n` is a `throw` statement, or because it is a call - * that may throw an exception, or because it is a cast and a - * `ClassCastException` is expected, or because it is a Kotlin not-null check - * and a `NullPointerException` is expected. - */ - private predicate mayThrow(AstNode n, ThrowableType t) { - t = n.(ThrowStmt).getThrownExceptionType() - or - exists(Call c | c = n | - t = c.getCallee().getAThrownExceptionType() or - uncheckedExceptionFromCatch(n, t) or - uncheckedExceptionFromFinally(n, t) or - uncheckedExceptionFromMethod(c, t) - ) - or - exists(CastExpr c | c = n | - t instanceof TypeClassCastException and - uncheckedExceptionFromCatch(n, t) - ) - or - exists(NotNullExpr nn | nn = n | - t instanceof TypeNullPointerException and - uncheckedExceptionFromCatch(n, t) - ) + class BooleanLiteral extends FinalBooleanLiteral { + boolean getValue() { result = this.getBooleanValue() } } +} - private predicate methodMayThrow(Method m, ThrowableType t) { - exists(AstNode n | - t = n.(ThrowStmt).getThrownExceptionType() and - not n.(ThrowStmt).getParent() = any(Method m0).getBody() +private module Exceptions { + private predicate methodMayThrow(Method m) { + exists(Stmt stmt | + stmt instanceof ThrowStmt and + not stmt.(ThrowStmt).getParent() = any(Method m0).getBody() or - uncheckedExceptionFromMethod(n, t) + uncheckedExceptionFromMethod(any(MethodCall call | call.getEnclosingStmt() = stmt)) | - n.getEnclosingStmt().getEnclosingCallable() = m and + stmt.getEnclosingCallable() = m and not exists(TryStmt try | - exists(try.getACatchClause()) and try.getBlock() = n.getEnclosingStmt().getEnclosingStmt*() + exists(try.getACatchClause()) and try.getBlock() = stmt.getEnclosingStmt*() ) ) } /** - * Bind `t` to an unchecked exception that may occur in a precondition check or guard wrapper. + * Holds if an unchecked exception may occur in a precondition check or guard wrapper. */ - private predicate uncheckedExceptionFromMethod(MethodCall ma, ThrowableType t) { - (methodCallChecksArgument(ma) or methodCallUnconditionallyThrows(ma)) and - (t instanceof TypeError or t instanceof TypeRuntimeException) + private predicate uncheckedExceptionFromMethod(MethodCall call) { + (methodCallChecksArgument(call) or methodCallUnconditionallyThrows(call)) or - methodMayThrow(ma.getMethod().getSourceDeclaration(), t) + methodMayThrow(call.getMethod().getSourceDeclaration()) } /** - * Bind `t` to an unchecked exception that may transfer control to a finally - * block inside which `n` is nested. + * Holds if an unchecked exception from `c` may transfer control to a finally + * block inside which `c` is nested. */ - private predicate uncheckedExceptionFromFinally(AstNode n, ThrowableType t) { + private predicate uncheckedExceptionFromFinally(Call c) { exists(TryStmt try | - n.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or - n.(Expr).getParent*() = try.getAResource() + c.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or + c.(Expr).getParent*() = try.getAResource() | - exists(try.getFinally()) and - (t instanceof TypeError or t instanceof TypeRuntimeException) + exists(try.getFinally()) ) } /** - * Bind `t` to all unchecked exceptions that may be caught by some - * `try-catch` inside which `n` is nested. + * A throwable that's a (reflexive, transitive) supertype of an unchecked + * exception. Besides the unchecked exceptions themselves, this includes + * `java.lang.Throwable` and `java.lang.Exception`. */ - private predicate uncheckedExceptionFromCatch(AstNode n, ThrowableType t) { - exists(TryStmt try, UncheckedThrowableSuperType caught | - n.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or - n.(Expr).getParent*() = try.getAResource() - | - t = caught.getAnUncheckedSubtype() and - try.getACatchClause().getACaughtType() = caught - ) - } - - private ThrowableType actualAssertionError() { - result.hasQualifiedName("java.lang", "AssertionError") - } - - private ThrowableType assertionError() { - result = actualAssertionError() - or - // In case `AssertionError` is not extracted, we use `Error` as a fallback. - not exists(actualAssertionError()) and - result.hasQualifiedName("java.lang", "Error") + private class UncheckedThrowableSuperType extends RefType { + UncheckedThrowableSuperType() { + this instanceof TypeThrowable or + this instanceof TypeException or + this instanceof UncheckedThrowableType + } } /** - * Gets an exception type that may be thrown during execution of the - * body or the resources (if any) of `try`. + * Holds if an unchecked exception from `n` may be caught by an enclosing + * catch clause. */ - private ThrowableType thrownInBody(TryStmt try) { - exists(AstNode n | - mayThrow(n, result) - or - n instanceof AssertStmt and result = assertionError() - | - n.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or + private predicate uncheckedExceptionFromCatch(Ast::AstNode n) { + exists(TryStmt try, UncheckedThrowableSuperType caught | + n.(Stmt).getEnclosingStmt+() = try.getBlock() or + n.(Expr).getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or n.(Expr).getParent*() = try.getAResource() + | + try.getACatchClause().getACaughtType() = caught and + ( + caught instanceof TypeClassCastException and n instanceof CastExpr + or + caught instanceof TypeNullPointerException and n instanceof NotNullExpr + or + n instanceof Call + ) ) } /** - * Bind `thrown` to an exception type that may be thrown during execution - * of the body or the resource declarations of the `try` block to which - * `c` belongs, such that `c` definitely catches that exception (if no - * prior catch clause handles it). + * Holds if a catch clause of `try` catches checked exceptions of type + * `caught`, and that `call` is contained within the try block. */ - private predicate mustCatch(CatchClause c, ThrowableType thrown) { - thrown = thrownInBody(c.getTry()) and - hasDescendant(c.getACaughtType(), thrown) - } - - /** - * Bind `thrown` to an exception type that may be thrown during execution - * of the body or the resource declarations of the `try` block to which - * `c` belongs, such that `c` may _not_ catch that exception. - * - * This predicate computes the complement of `mustCatch` over those - * exception types that are thrown in the body/resource declarations of - * the corresponding `try`. - */ - private predicate mayNotCatch(CatchClause c, ThrowableType thrown) { - thrown = thrownInBody(c.getTry()) and - not hasDescendant(c.getACaughtType(), thrown) + private predicate checkedExceptionFromCatchCandidate(TryStmt try, RefType caught, Call call) { + ( + call.getEnclosingStmt().getEnclosingStmt+() = try.getBlock() or + call.(Expr).getParent*() = try.getAResource() + ) and + try.getACatchClause().getACaughtType() = caught and + not caught instanceof UncheckedThrowableSuperType } /** - * Bind `thrown` to an exception type that may be thrown during execution - * of the body or the resource declarations of the `try` block to which - * `c` belongs, such that `c` possibly catches that exception. + * Holds if a catch clause of `try` catches checked exceptions of type + * `caught`, and that there is a call within the try block that declares that + * it may throw `caught` or a subtype thereof. */ - private predicate mayCatch(CatchClause c, ThrowableType thrown) { - mustCatch(c, thrown) - or - mayNotCatch(c, thrown) and exists(c.getACaughtType().commonSubtype(thrown)) + private predicate declaredCheckedExceptionFromCatchCandidate(TryStmt try, RefType caught) { + exists(Call call | + checkedExceptionFromCatchCandidate(try, caught, call) and + call.getCallee().getAThrownExceptionType().getASourceSupertype*() = caught + ) } /** - * Given an exception type `thrown`, determine which catch clauses of - * `try` may possibly catch that exception. + * Holds if `call` is contained within a try block that has a catch clause + * that catches a checked exception, but there is no call within the try + * block that declares that it may throw that exception, and no throw + * statement either. In this case, it is likely that the throws declaration + * for some reason was not extracted, so we conseratively assume that `call` + * may throw such an exception. */ - private CatchClause handlingCatchClause(TryStmt try, ThrowableType thrown) { - exists(int i | result = try.getCatchClause(i) | - mayCatch(result, thrown) and - not exists(int j | j < i | mustCatch(try.getCatchClause(j), thrown)) + private predicate checkedExceptionFromCatchCandidate(Call call) { + exists(TryStmt try, RefType caught | + checkedExceptionFromCatchCandidate(try, caught, call) and + not declaredCheckedExceptionFromCatchCandidate(try, caught) and + not exists(ThrowStmt throwstmt | + throwstmt.getEnclosingStmt+() = try.getBlock() and + throwstmt.getThrownExceptionType().getASourceSupertype*() = caught + ) ) } /** - * Boolean expressions that occur in a context in which their value affect control flow. - * That is, contexts where the control-flow edges depend on `value` given that `b` ends - * with a `booleanCompletion(value, _)`. + * Holds if `n` is expected to possibly throw an exception. This can either + * be due to a declared (likely checked) exception on a call target + * or due to an enclosing try/catch/finally. */ - private predicate inBooleanContext(AstNode b) { - exists(LogicExpr logexpr | - logexpr.(BinaryExpr).getLeftOperand() = b - or - logexpr.getAnOperand() = b and inBooleanContext(logexpr) - ) + predicate mayThrow(Ast::AstNode n) { + exists(n.(Call).getCallee().getAThrownExceptionType()) or - exists(ConditionalExpr condexpr | - condexpr.getCondition() = b - or - condexpr.getABranchExpr() = b and - inBooleanContext(condexpr) - ) + checkedExceptionFromCatchCandidate(n) or - exists(AssertStmt assertstmt | assertstmt.getExpr() = b) + uncheckedExceptionFromMethod(n) or - exists(SwitchExpr switch | - inBooleanContext(switch) and - switch.getAResult() = b - ) + uncheckedExceptionFromFinally(n) or - exists(ConditionalStmt condstmt | condstmt.getCondition() = b) - or - exists(WhenBranch whenbranch | whenbranch.getCondition() = b) - or - exists(WhenExpr whenexpr | - inBooleanContext(whenexpr) and - whenexpr.getBranch(_).getAResult() = b - ) - or - b = any(PatternCase pc).getGuard() - or - inBooleanContext(b.(ExprStmt).getExpr()) - or - inBooleanContext(b.(StmtExpr).getStmt()) + uncheckedExceptionFromCatch(n) } +} +private module NonReturningCalls { /** * A virtual method with a unique implementation. That is, the method does not * participate in overriding and there are no call targets that could dispatch @@ -608,7 +392,7 @@ private module ControlFlowGraphImpl { /** * Gets a `MethodCall` that always throws an exception or calls `exit`. */ - private MethodCall nonReturningMethodCall() { + MethodCall nonReturningMethodCall() { methodCallUnconditionallyThrows(result) or result.getMethod().getSourceDeclaration() = nonReturningMethod() or result = likelyNonReturningMethod().getAnAccess() @@ -650,1142 +434,247 @@ private module ControlFlowGraphImpl { ) ) } +} - // Join order engineering -- first determine the switch block and the case indices required, then retrieve them. - bindingset[switch, i] - pragma[inline_late] - private predicate isNthCaseOf(SwitchBlock switch, SwitchCase c, int i) { - c.isNthCaseOf(switch, i) - } +private module Input implements InputSig1, InputSig2 { + private import java as J - /** - * Gets a `SwitchCase` that may be `pred`'s direct successor, where `pred` is declared in block `switch`. - * - * This means any switch case that comes after `pred` up to the next pattern case, if any, except for `case null`. - * - * Because we know the switch block contains at least one pattern, we know by https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.11 - * that any default case comes after the last pattern case. - */ - private SwitchCase getASuccessorSwitchCase(PatternCase pred, SwitchBlock switch) { - // Note we do include `case null, default` (as well as plain old `default`) here. - not result.(ConstCase).getValue(_) instanceof NullLiteral and - exists(int maxCaseIndex | - switch = pred.getParent() and - if exists(getNextPatternCase(pred)) - then maxCaseIndex = getNextPatternCase(pred).getCaseIndex() - else maxCaseIndex = lastCaseIndex(switch) - | - isNthCaseOf(switch, result, [pred.getCaseIndex() + 1 .. maxCaseIndex]) - ) - } + predicate cfgCachedStageRef() { CfgCachedStage::ref() } - /** - * Gets a `SwitchCase` that may occur first in `switch`. - * - * If the block contains at least one PatternCase, this is any case up to and including that case, or - * the case handling the null literal if any. - * - * Otherwise it is any case in the switch block. - */ - private SwitchCase getAFirstSwitchCase(SwitchBlock switch) { - result.getParent() = switch and - ( - result.(ConstCase).getValue(_) instanceof NullLiteral - or - result instanceof NullDefaultCase - or - not exists(getFirstPatternCase(switch)) - or - result.getIndex() <= getFirstPatternCase(switch).getIndex() + /** Holds if this catch clause catches all exceptions. */ + predicate catchAll(Ast::CatchClause catch) { + catch.getACaughtType() instanceof TypeThrowable + or + exists(TryStmt try, int last | + catch.getACaughtType() instanceof TypeException and + try.getCatchClause(last) = catch and + not exists(try.getCatchClause(last + 1)) ) } - private Stmt getSwitchStatement(SwitchBlock switch, int i) { result.isNthChildOf(switch, i) } - - /** - * Holds if `last` is the last node in any of pattern case `pc`'s succeeding bind-and-test operations, - * immediately before either falling through to execute successor statements or execute a rule body - * if present. `completion` is the completion kind of the last operation. - */ - private predicate lastPatternCaseMatchingOp(PatternCase pc, Node last, Completion completion) { - last(pc.getAPattern(), last, completion) and - completion = NormalCompletion() and - not exists(pc.getGuard()) + /** Holds if this case matches all possible values. */ + predicate matchAll(Ast::Case c) { + c instanceof DefaultCase or - last(pc.getGuard(), last, completion) and - completion = BooleanCompletion(true, _) + // Switch expressions and enhanced switch blocks (those that use pattern + // cases or match null) must be exhaustive, so the last case matches all + // remaining values. + // See https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.11.2 + exists(Ast::Switch switch, int last | + switch instanceof SwitchExpr or + exists(switch.(SwitchStmt).getAPatternCase()) or + switch.(SwitchStmt).hasNullCase() + | + switch.getCase(last) = c and + not exists(switch.getCase(last + 1)) + ) + or + c.(J::PatternCase).getAPattern().getType() instanceof TypeObject } - /** - * Expressions and statements with CFG edges in post-order AST traversal. - * - * This includes most expressions, except those that initiate or propagate branching control - * flow (`LogicExpr`, `ConditionalExpr`). - * Only a few statements are included; those with specific side-effects - * occurring after the evaluation of their children, that is, `Call`, `ReturnStmt`, - * and `ThrowStmt`. CFG nodes without child nodes in the CFG that may complete - * normally are also included. - */ - private class PostOrderNode extends AstNode { - PostOrderNode() { - // For VarAccess and ArrayAccess only read accesses (r-values) are included, - // as write accesses aren't included in the CFG. - this instanceof ArrayAccess and not exists(AssignExpr a | this = a.getDest()) - or - this instanceof ArrayCreationExpr - or - this instanceof ArrayInit - or - this instanceof Assignment - or - this instanceof BinaryExpr and not this instanceof LogicExpr - or - this instanceof UnaryExpr and not this instanceof LogNotExpr - or - this instanceof CastingExpr - or - this instanceof InstanceOfExpr and not this.(InstanceOfExpr).isPattern() - or - this instanceof NotInstanceOfExpr - or - this instanceof LocalVariableDeclExpr - or - this instanceof StringTemplateExpr - or - this instanceof ClassExpr - or - this instanceof VarRead - or - this instanceof Call // includes both expressions and statements - or - this instanceof ErrorExpr - or - this instanceof ReturnStmt - or - this instanceof ThrowStmt - or - this instanceof Literal - or - this instanceof TypeLiteral - or - this instanceof ThisAccess - or - this instanceof SuperAccess - or - this.(BlockStmt).getNumStmt() = 0 - or - this instanceof SwitchCase and - not this.(SwitchCase).isRule() and - not this instanceof PatternCase - or - this instanceof RecordPatternExpr - or - this instanceof EmptyStmt - or - this instanceof LocalTypeDeclStmt - } + private newtype TLabel = + TJavaLabel(string l) { exists(LabeledStmt lbl | l = lbl.getLabel()) } or + TYield() - /** Gets child nodes in their order of execution. Indexing starts at either -1 or 0. */ - AstNode getChildNode(int index) { - exists(ArrayAccess e | e = this | - index = 0 and result = e.getArray() - or - index = 1 and result = e.getIndexExpr() - ) + class Label extends TLabel { + string toString() { + exists(string l | this = TJavaLabel(l) and result = l) or - exists(ArrayCreationExpr e | e = this | - result = e.getDimension(index) - or - index = count(e.getADimension()) and result = e.getInit() - ) - or - result = this.(ArrayInit).getInit(index) and index >= 0 - or - exists(AssignExpr e, ArrayAccess lhs | e = this and lhs = e.getDest() | - index = 0 and result = lhs.getArray() - or - index = 1 and result = lhs.getIndexExpr() - or - index = 2 and result = e.getSource() - ) - or - exists(AssignExpr e, VarAccess lhs | e = this and lhs = e.getDest() | - index = -1 and result = lhs.getQualifier() and not result instanceof TypeAccess - or - index = 0 and result = e.getSource() - ) - or - exists(AssignOp e | e = this | - index = 0 and result = e.getDest() - or - index = 1 and result = e.getRhs() - ) - or - exists(BinaryExpr e | e = this | - index = 0 and result = e.getLeftOperand() - or - index = 1 and result = e.getRightOperand() - ) - or - index = 0 and result = this.(UnaryExpr).getOperand() - or - index = 0 and result = this.(CastingExpr).getExpr() - or - index = 0 and result = this.(InstanceOfExpr).getExpr() - or - index = 0 and result = this.(NotInstanceOfExpr).getExpr() - or - index = 0 and result = this.(LocalVariableDeclExpr).getInit() - or - index = 0 and result = this.(VarRead).getQualifier() and not result instanceof TypeAccess - or - exists(Call e | e = this | - index = -1 and result = e.getQualifier() and not result instanceof TypeAccess - or - result = e.getArgument(index) - ) - or - exists(StringTemplateExpr e | e = this | result = e.getComponent(index)) - or - index = 0 and result = this.(ClassExpr).getExpr() - or - index = 0 and result = this.(ReturnStmt).getExpr() - or - index = 0 and result = this.(ThrowStmt).getExpr() - or - result = this.(RecordPatternExpr).getSubPattern(index) - } - - /** Gets the first child node, if any. */ - AstNode firstChild() { - result = this.getChildNode(-1) - or - result = this.getChildNode(0) and not exists(this.getChildNode(-1)) - } - - /** Holds if this CFG node has any child nodes. */ - predicate isLeafNode() { not exists(this.getChildNode(_)) } - - /** Holds if this node can finish with a `normalCompletion`. */ - predicate mayCompleteNormally() { - not this instanceof BooleanLiteral and - not this instanceof ReturnStmt and - not this instanceof ThrowStmt and - not this = nonReturningMethodCall() + this = TYield() and result = "yield" } } - /** - * If the body of `loop` finishes with `completion`, the loop will - * continue executing (provided the loop condition still holds). - */ - private predicate continues(Completion completion, LoopStmt loop) { - completion = NormalCompletion() - or - // only consider continue completions if there actually is a `continue` - // somewhere inside this loop; we don't particularly care whether that - // `continue` could actually target this loop, we just want to restrict - // the size of the predicate - exists(ContinueStmt cnt | cnt.getEnclosingStmt+() = loop | - completion = anonymousContinueCompletion() or - completion = labelledContinueCompletion(getLabel(loop)) + private Label getLabelOfLoop(Stmt s) { + exists(LabeledStmt l | s = l.getStmt() | + result = TJavaLabel(l.getLabel()) or + result = getLabelOfLoop(l) ) } - /** - * Determine the part of the AST node `n` that will be executed first. - */ - private Node first(AstNode n) { - result.asExpr() = n and n instanceof LogicExpr - or - result.asExpr() = n and n instanceof ConditionalExpr - or - result.asExpr() = n and n instanceof WhenExpr + predicate hasLabel(Ast::AstNode n, Label l) { + l = getLabelOfLoop(n) or - result.asStmt() = n and n instanceof WhenBranch + l = TJavaLabel(n.(BreakStmt).getLabel()) or - result.asExpr() = n and n instanceof StmtExpr + l = TJavaLabel(n.(ContinueStmt).getLabel()) or - result = n.getCfgNode() and n.(PostOrderNode).isLeafNode() + l = TYield() and n instanceof YieldStmt or - result = first(n.(PostOrderNode).firstChild()) - or - result = first(n.(InstanceOfExpr).getExpr()) - or - result = first(n.(SynchronizedStmt).getExpr()) - or - result = first(n.(AssertStmt).getExpr()) - or - result.asStmt() = n and - not n instanceof PostOrderNode and - not n instanceof SynchronizedStmt and - not n instanceof AssertStmt - or - result.asExpr() = n and n instanceof SwitchExpr - } - - /** - * Bind `last` to a node inside the body of `try` that may finish with `completion` - * such that control will be transferred to a `catch` block or the `finally` block of `try`. - * - * In other words, `last` is either a resource declaration that throws, or a - * node in the `try` block that may not complete normally, or a node in - * the `try` block that has no control flow successors inside the block. - */ - private predicate catchOrFinallyCompletion(TryStmt try, Node last, Completion completion) { - last(try.getBlock(), last, completion) - or - last(try.getAResource(), last, completion) and completion = ThrowCompletion(_) + l = TYield() and n instanceof SwitchExpr } - /** - * Bind `last` to a node inside the body of `try` that may finish with `completion` - * such that control may be transferred to the `finally` block (if it exists). - * - * In other words, if `last` throws an exception it is possibly not caught by any - * of the catch clauses. - */ - private predicate uncaught(TryStmt try, Node last, Completion completion) { - catchOrFinallyCompletion(try, last, completion) and + predicate inConditionalContext(Ast::AstNode n, ConditionKind kind) { + kind.isBoolean() and ( - exists(ThrowableType thrown | - thrown = thrownInBody(try) and - completion = ThrowCompletion(thrown) and - not mustCatch(try.getACatchClause(), thrown) - ) - or - completion = NormalCompletion() - or - completion = ReturnCompletion() - or - completion = anonymousBreakCompletion() - or - completion = labelledBreakCompletion(_) - or - completion = anonymousContinueCompletion() - or - completion = labelledContinueCompletion(_) + any(AssertStmt assertstmt).getExpr() = n or + any(WhenBranch whenbranch).getCondition() = n ) } - /** - * Bind `last` to a node inside `try` that may finish with `completion` such - * that control may be transferred to the `finally` block (if it exists). - * - * This is similar to `uncaught`, but also includes final statements of `catch` - * clauses. - */ - private predicate finallyPred(TryStmt try, Node last, Completion completion) { - uncaught(try, last, completion) or - last(try.getACatchClause(), last, completion) - } + predicate preOrderExpr(Expr e) { e instanceof WhenExpr } - private predicate lastInFinally(TryStmt try, Node last) { - last(try.getFinally(), last, NormalCompletion()) + predicate postOrInOrder(Ast::AstNode n) { + // expressions are already post-order, but we need the calls that are statements to be post-order as well + n instanceof Call + or + n instanceof SynchronizedStmt } - private predicate isNextNormalSwitchStmt(SwitchBlock switch, Stmt pred, Stmt succ) { - exists(int i, Stmt immediateSucc | - getSwitchStatement(switch, i) = pred and - getSwitchStatement(switch, i + 1) = immediateSucc and - ( - if immediateSucc instanceof PatternCase - then isNextNormalSwitchStmt(switch, immediateSucc, succ) - else succ = immediateSucc - ) - ) + private string assertThrowNodeTag() { result = "[assert-throw]" } + + private string instanceofTrueNodeTag() { result = "[instanceof-true]" } + + predicate additionalNode(Ast::AstNode n, string tag, NormalSuccessor t) { + n instanceof AssertStmt and tag = assertThrowNodeTag() and t instanceof DirectSuccessor + or + n.(InstanceOfExpr).isPattern() and + tag = instanceofTrueNodeTag() and + t.(BooleanSuccessor).getValue() = true } /** - * Bind `last` to a cfg node nested inside `n` (or, indeed, `n` itself) such - * that `last` may be the last node during an execution of `n` and finish - * with the given completion. - * - * A `booleanCompletion` implies that `n` is an `Expr`. Any abnormal - * completion besides `throwCompletion` implies that `n` is a `Stmt`. + * Holds if `ast` may result in an abrupt completion `c` originating at + * `n`. The boolean `always` indicates whether the abrupt completion + * always occurs or whether `n` may also terminate normally. */ - private predicate last(AstNode n, Node last, Completion completion) { - // Exceptions are propagated from any sub-expression. - // As are any break, yield, continue, or return completions. - exists(Expr e | e.getParent() = n | - last(e, last, completion) and not completion instanceof NormalOrBooleanCompletion - ) - or - // If an expression doesn't finish with a throw completion, then it executes normally with - // either a `normalCompletion` or a `booleanCompletion`. - // A boolean completion in a non-boolean context just indicates a normal completion - // and a normal completion in a boolean context indicates an arbitrary boolean completion. - last(n, last, NormalCompletion()) and - inBooleanContext(n) and - completion = basicBooleanCompletion(_) - or - last(n, last, BooleanCompletion(_, _)) and - not inBooleanContext(n) and - completion = NormalCompletion() and - // PatternCase has both a boolean-true completion (guard success) and a normal one - // (variable declaration completion, when no guard is present). - not n instanceof PatternCase - or - // Logic expressions and conditional expressions are executed in AST pre-order to facilitate - // proper short-circuit representation. All other expressions are executed in post-order. - // The last node of a logic expression is either in the right operand with an arbitrary - // completion, or in the left operand with the corresponding boolean completion. - exists(AndLogicalExpr andexpr | andexpr = n | - last(andexpr.getLeftOperand(), last, completion) and completion = BooleanCompletion(false, _) - or - last(andexpr.getRightOperand(), last, completion) - ) + predicate beginAbruptCompletion( + Ast::AstNode ast, PreControlFlowNode n, AbruptCompletion c, boolean always + ) { + ast instanceof AssertStmt and + n.isAdditional(ast, assertThrowNodeTag()) and + c.asSimpleAbruptCompletion() instanceof ExceptionSuccessor and + always = true or - exists(OrLogicalExpr orexpr | orexpr = n | - last(orexpr.getLeftOperand(), last, completion) and completion = BooleanCompletion(true, _) - or - last(orexpr.getRightOperand(), last, completion) - ) + Exceptions::mayThrow(ast) and + n.isIn(ast) and + c.asSimpleAbruptCompletion() instanceof ExceptionSuccessor and + always = false or - // The last node of a `LogNotExpr` is in its sub-expression with an inverted boolean completion - // (or a `normalCompletion`). - exists(Completion subcompletion | last(n.(LogNotExpr).getOperand(), last, subcompletion) | - subcompletion = NormalCompletion() and - completion = NormalCompletion() and - not inBooleanContext(n) - or - exists(boolean outervalue, boolean innervalue | - subcompletion = BooleanCompletion(outervalue, innervalue) and - completion = BooleanCompletion(outervalue.booleanNot(), innervalue) - ) - ) - or - // The last node of a `ConditionalExpr` is in either of its branches. - exists(ConditionalExpr condexpr | condexpr = n | - last(condexpr.getABranchExpr(), last, completion) - ) - or - exists(InstanceOfExpr ioe | ioe.isPattern() and ioe = n | - last.asExpr() = n and completion = basicBooleanCompletion(false) - or - last(ioe.getPattern(), last, NormalCompletion()) and completion = basicBooleanCompletion(true) - ) - or - // The last node of a node executed in post-order is the node itself. - exists(PostOrderNode p | p = n | - p.mayCompleteNormally() and last = p.getCfgNode() and completion = NormalCompletion() - ) - or - last.asExpr() = n and completion = basicBooleanCompletion(n.(BooleanLiteral).getBooleanValue()) - or - // The last statement in a block is any statement that does not complete normally, - // or the last statement. - exists(BlockStmt blk | blk = n | - last(blk.getAStmt(), last, completion) and completion != NormalCompletion() - or - last(blk.getStmt(blk.getNumStmt() - 1), last, completion) - ) - or - // The last node in an `if` statement is the last node in either of its branches or - // the last node of the condition with a false-completion in the absence of an else-branch. - exists(IfStmt ifstmt | ifstmt = n | - last(ifstmt.getCondition(), last, BooleanCompletion(false, _)) and - completion = NormalCompletion() and - not exists(ifstmt.getElse()) - or - last(ifstmt.getThen(), last, completion) - or - last(ifstmt.getElse(), last, completion) - ) - or - // A loop may terminate normally if its condition is false... - exists(LoopStmt loop | loop = n | - last(loop.getCondition(), last, BooleanCompletion(false, _)) and - completion = NormalCompletion() - or - // ...or if it's an enhanced for loop running out of items to iterate over... - // ...which may happen either immediately after the loop expression... - last(loop.(EnhancedForStmt).getExpr(), last, completion) and completion = NormalCompletion() - or - exists(Completion bodyCompletion | last(loop.getBody(), last, bodyCompletion) | - // ...or after the last node in the loop's body in an iteration that would otherwise continue. - loop instanceof EnhancedForStmt and - continues(bodyCompletion, loop) and - completion = NormalCompletion() - or - // Otherwise the last node is the last node in the loop's body... - // ...if it is an unlabelled `break` (causing the entire loop to complete normally) - ( - if bodyCompletion = anonymousBreakCompletion() - then completion = NormalCompletion() - else ( - // ...or if it is some other completion that does not continue the loop. - not continues(bodyCompletion, loop) and completion = bodyCompletion - ) - ) - ) - ) - or - // `try` statements are a bit more complicated: - exists(TryStmt try | try = n | - // the last node in a `try` is the last node in its `finally` block - // if the `finally` block completes normally, it resumes any completion that - // was current before the `finally` block was entered - lastInFinally(try, last) and - finallyPred(try, _, completion) - or - // otherwise, just take the completion of the `finally` block itself - last(try.getFinally(), last, completion) and - completion != NormalCompletion() - or - // if there is no `finally` block, take the last node of the body or - // any of the `catch` clauses - not exists(try.getFinally()) and finallyPred(try, last, completion) - ) - or - // handle `switch` statements - exists(SwitchStmt switch | switch = n | - // unlabelled `break` causes the whole `switch` to complete normally - last(switch.getAStmt(), last, anonymousBreakCompletion()) and - completion = NormalCompletion() - or - // any other abnormal completion is propagated - last(switch.getAStmt(), last, completion) and - completion != anonymousBreakCompletion() and - not completion instanceof NormalOrBooleanCompletion - or - // if a statement without a non-pattern-case successor completes normally (or for a pattern case - // the guard succeeds) then the switch completes normally. - exists(Stmt lastNormalStmt, Completion stmtCompletion | - lastNormalStmt = getSwitchStatement(switch, _) and - not isNextNormalSwitchStmt(switch, lastNormalStmt, _) and - last(lastNormalStmt, last, stmtCompletion) and - (stmtCompletion = NormalCompletion() or stmtCompletion = BooleanCompletion(true, _)) and - completion = NormalCompletion() - ) - or - // if no default case exists, then normal completion of the expression may terminate the switch - // Note this can't happen if there are pattern cases or a null literal, as - // https://docs.oracle.com/javase/specs/jls/se21/html/jls-14.html#jls-14.11.2 requires that such - // an enhanced switch block is exhaustive. - not exists(switch.getDefaultCase()) and - not exists(switch.getAPatternCase()) and - not switch.hasNullCase() and - last(switch.getExpr(), last, completion) and - completion = NormalCompletion() - ) - or - // handle `switch` expression - exists(SwitchExpr switch | switch = n | - // `yield` terminates the `switch` - last(switch.getAStmt(), last, YieldCompletion(completion)) - or - // any other abnormal completion is propagated - last(switch.getAStmt(), last, completion) and - not completion instanceof YieldCompletion and - not completion instanceof NormalOrBooleanCompletion - ) - or - // If a case rule right-hand-side completes then the switch breaks or yields, depending - // on whether this is a switch expression or statement. If it completes abruptly then the - // switch completes the same way. - exists(Completion caseCompletion, SwitchCase case | - case = n and - ( - last(case.getRuleStatement(), last, caseCompletion) - or - last(case.getRuleExpression(), last, caseCompletion) - ) - | - if caseCompletion instanceof NormalOrBooleanCompletion - then - case.getParent() instanceof SwitchStmt and completion = anonymousBreakCompletion() - or - case.getParent() instanceof SwitchExpr and completion = YieldCompletion(caseCompletion) - else completion = caseCompletion - ) - or - // A pattern case statement can complete: - // * On failure of its final type test (boolean false) - // * On failure of its guard test if any (boolean false) - // * On completion of one of its pattern variable declarations, if it is not a rule and has no guard (normal completion) - // * On success of its guard test, if it is not a rule (boolean true) - // (the latter two cases are accounted for by lastPatternCaseMatchingOp) - exists(PatternCase pc | n = pc | - last.asStmt() = pc and completion = basicBooleanCompletion(false) - or - last(pc.getGuard(), last, completion) and - completion = BooleanCompletion(false, _) - or - not pc.isRule() and - lastPatternCaseMatchingOp(pc, last, completion) - ) - or - // the last statement of a synchronized statement is the last statement of its body - last(n.(SynchronizedStmt).getBlock(), last, completion) - or - // `return` statements give rise to a `Return` completion - last.asStmt() = n.(ReturnStmt) and completion = ReturnCompletion() - or - exists(AssertStmt assertstmt | assertstmt = n | - // `assert` statements may complete normally - we use the `AssertStmt` itself - // to represent this outcome - last.asStmt() = assertstmt and completion = NormalCompletion() - or - // `assert` statements may throw - completion = ThrowCompletion(assertionError()) and - last.(AssertThrowNode).getAstNode() = assertstmt - ) - or - // `throw` statements or throwing calls give rise to `Throw` completion - exists(ThrowableType tt | mayThrow(n, tt) | - last = n.getCfgNode() and completion = ThrowCompletion(tt) - ) - or - // `break` statements give rise to a `Break` completion - exists(BreakStmt break | break = n and last.asStmt() = n | - completion = labelledBreakCompletion(MkLabel(break.getLabel())) - or - not exists(break.getLabel()) and completion = anonymousBreakCompletion() - ) - or - // yield statements get their completion wrapped as a yield - exists(Completion caseCompletion | - last(n.(YieldStmt).getValue(), last, caseCompletion) and - if caseCompletion instanceof NormalOrBooleanCompletion - then completion = YieldCompletion(caseCompletion) - else completion = caseCompletion - ) - or - // `continue` statements give rise to a `Continue` completion - exists(ContinueStmt cont | cont = n and last.asStmt() = n | - completion = labelledContinueCompletion(MkLabel(cont.getLabel())) - or - not exists(cont.getLabel()) and completion = anonymousContinueCompletion() - ) - or - // the last node in an `ExprStmt` is the last node in the expression - last(n.(ExprStmt).getExpr(), last, completion) and - completion instanceof NormalOrBooleanCompletion - or - // the last node in a `StmtExpr` is the last node in the statement - last(n.(StmtExpr).getStmt(), last, completion) - or - // the last statement of a labeled statement is the last statement of its body... - exists(LabeledStmt lbl, Completion bodyCompletion | - lbl = n and last(lbl.getStmt(), last, bodyCompletion) - | - // ...except if it's a `break` that refers to this labelled statement - if bodyCompletion = labelledBreakCompletion(MkLabel(lbl.getLabel())) - then completion = NormalCompletion() - else completion = bodyCompletion - ) - or - // the last statement of a `catch` clause is the last statement of its block - last(n.(CatchClause).getBlock(), last, completion) - or - // the last node in a variable declaration statement is in the last of its individual declarations - exists(LocalVariableDeclStmt s | s = n | - last(s.getVariable(count(s.getAVariable())), last, completion) and - completion = NormalCompletion() - ) - or - // The last node in a `when` expression is the last node in any of its branches or - // the last node of the condition of the last branch in the absence of an else-branch. - exists(WhenExpr whenexpr | whenexpr = n | - // If we have no branches then we are the last node - last.asExpr() = n and - completion = NormalCompletion() and - not exists(whenexpr.getBranch(_)) - or - // If our last branch condition is false then we are done - exists(int i | - last(whenexpr.getBranch(i), last, BooleanCompletion(false, _)) and - completion = NormalCompletion() and - not exists(whenexpr.getBranch(i + 1)) - ) - or - // Any branch getting an abnormal completion is propagated - last(whenexpr.getBranch(_), last, completion) and - not completion instanceof YieldCompletion and - not completion instanceof NormalOrBooleanCompletion - or - // The last node in any branch. This will be wrapped up as a - // YieldCompletion, so we need to unwrap it here. - last(whenexpr.getBranch(_), last, YieldCompletion(completion)) - ) - or - exists(WhenBranch whenbranch | whenbranch = n | - // If the condition completes with anything other than true - // (or "normal", which we will also see if we don't know how - // to make specific true/false edges for the condition) - // (e.g. false or an exception), then the branch is done. - last(whenbranch.getCondition(), last, completion) and - not completion = BooleanCompletion(true, _) and - not completion = NormalCompletion() - or - // Similarly any non-normal completion of the RHS - // should propagate outwards: - last(whenbranch.getRhs(), last, completion) and - not completion instanceof NormalOrBooleanCompletion - or - // Otherwise we wrap the completion up in a YieldCompletion - // so that the `when` expression can tell that we have finished, - // and it shouldn't go on to the next branch. - exists(Completion branchCompletion | - last(whenbranch.getRhs(), last, branchCompletion) and - completion = YieldCompletion(branchCompletion) - ) - ) + ast = NonReturningCalls::nonReturningMethodCall() and + n.isIn(ast) and + c.asSimpleAbruptCompletion() instanceof ExceptionSuccessor and + always = true } /** - * Compute the intra-procedural successors of cfg node `n`, assuming its - * execution finishes with the given completion. + * Holds if an abrupt completion `c` from within `ast` is caught with + * flow continuing at `n`. */ - cached - Node succ(Node n, Completion completion) { - // After executing the callable body, the final nodes are first the - // annotated exit node and then the final exit node. - exists(Callable c | last(c.getBody(), n, completion) | - if completion instanceof ThrowCompletion - then result.(ExceptionalExitNode).getEnclosingCallable() = c - else result.(NormalExitNode).getEnclosingCallable() = c - ) - or - completion = NormalCompletion() and - n.(AnnotatedExitNode).getEnclosingCallable() = result.(ExitNode).getEnclosingCallable() - or - // Logic expressions and conditional expressions execute in AST pre-order. - completion = NormalCompletion() and - ( - result = first(n.asExpr().(AndLogicalExpr).getLeftOperand()) or - result = first(n.asExpr().(OrLogicalExpr).getLeftOperand()) or - result = first(n.asExpr().(LogNotExpr).getOperand()) or - result = first(n.asExpr().(ConditionalExpr).getCondition()) - ) - or - // If a logic expression doesn't short-circuit then control flows from its left operand to its right. - exists(AndLogicalExpr e | - last(e.getLeftOperand(), n, completion) and - completion = BooleanCompletion(true, _) and - result = first(e.getRightOperand()) - ) - or - exists(OrLogicalExpr e | - last(e.getLeftOperand(), n, completion) and - completion = BooleanCompletion(false, _) and - result = first(e.getRightOperand()) - ) - or - // Control flows to the corresponding branch depending on the boolean completion of the condition. - exists(ConditionalExpr e, boolean branch | - last(e.getCondition(), n, completion) and - completion = BooleanCompletion(branch, _) and - result = first(e.getBranchExpr(branch)) + predicate endAbruptCompletion(Ast::AstNode ast, PreControlFlowNode n, AbruptCompletion c) { + exists(LabeledStmt lbl | + ast = lbl.getStmt() and + n.isAfter(lbl) and + c.getSuccessorType() instanceof BreakSuccessor and + c.hasLabel(TJavaLabel(lbl.getLabel())) ) - or - exists(InstanceOfExpr ioe | ioe.isPattern() | - last(ioe.getExpr(), n, completion) and - completion = NormalCompletion() and - result.asExpr() = ioe - or - n.asExpr() = ioe and - result = first(ioe.getPattern()) and - completion = basicBooleanCompletion(true) - ) - or - // In other expressions control flows from left to right and ends in the node itself. - exists(PostOrderNode p, int i | - last(p.getChildNode(i), n, completion) and completion = NormalCompletion() - | - result = first(p.getChildNode(i + 1)) - or - not exists(p.getChildNode(i + 1)) and result = p.getCfgNode() - ) - or - // Statements within a block execute sequentially. - result = first(n.asStmt().(BlockStmt).getStmt(0)) and completion = NormalCompletion() - or - exists(BlockStmt blk, int i | - last(blk.getStmt(i), n, completion) and - completion = NormalCompletion() and - result = first(blk.getStmt(i + 1)) - ) - or - // Control flows to the corresponding branch depending on the boolean completion of the condition. - exists(IfStmt s | - n.asStmt() = s and result = first(s.getCondition()) and completion = NormalCompletion() - or - last(s.getCondition(), n, completion) and - completion = BooleanCompletion(true, _) and - result = first(s.getThen()) - or - last(s.getCondition(), n, completion) and - completion = BooleanCompletion(false, _) and - result = first(s.getElse()) - ) - or - // For statements: - exists(ForStmt for, Node condentry | - // Any part of the control flow that aims for the condition needs to hit either the condition... - condentry = first(for.getCondition()) - or - // ...or the body if the for doesn't include a condition. - not exists(for.getCondition()) and condentry = first(for.getBody()) - | - // From the entry point, which is the for statement itself, control goes to either the first init expression... - n.asStmt() = for and result = first(for.getInit(0)) and completion = NormalCompletion() - or - // ...or the condition if the for doesn't include init expressions. - n.asStmt() = for and - not exists(for.getAnInit()) and - result = condentry and - completion = NormalCompletion() + } + + /** Holds if there is a local non-abrupt step from `n1` to `n2`. */ + predicate step(PreControlFlowNode n1, PreControlFlowNode n2) { + exists(InstanceOfExpr ioe | + // common + n1.isBefore(ioe) and + n2.isBefore(ioe.getExpr()) or - // Init expressions execute sequentially, after which control is transferred to the condition. - exists(int i | last(for.getInit(i), n, completion) and completion = NormalCompletion() | - result = first(for.getInit(i + 1)) - or - not exists(for.getInit(i + 1)) and result = condentry - ) + n1.isAfter(ioe.getExpr()) and + n2.isIn(ioe) or - // The true-successor of the condition is the body of the for loop. - last(for.getCondition(), n, completion) and - completion = BooleanCompletion(true, _) and - result = first(for.getBody()) + // std postorder: + not ioe.isPattern() and + n1.isIn(ioe) and + n2.isAfter(ioe) or - // The updates execute sequentially, after which control is transferred to the condition. - exists(int i | last(for.getUpdate(i), n, completion) and completion = NormalCompletion() | - result = first(for.getUpdate(i + 1)) - or - not exists(for.getUpdate(i + 1)) and result = condentry - ) - or - // The back edge of the loop: control goes to either the first update or the condition if no updates exist. - last(for.getBody(), n, completion) and - continues(completion, for) and - ( - result = first(for.getUpdate(0)) - or - result = condentry and not exists(for.getAnUpdate()) - ) - ) - or - // Enhanced for statements: - exists(EnhancedForStmt for | - // First the expression gets evaluated... - n.asStmt() = for and result = first(for.getExpr()) and completion = NormalCompletion() + // pattern case: + ioe.isPattern() and + n1.isIn(ioe) and + n2.isAfterValue(ioe, any(BooleanSuccessor s | s.getValue() = false)) or - // ...then the variable gets assigned... - last(for.getExpr(), n, completion) and - completion = NormalCompletion() and - result.asExpr() = for.getVariable() + n1.isIn(ioe) and + n2.isAdditional(ioe, instanceofTrueNodeTag()) or - // ...and then control goes to the body of the loop. - n.asExpr() = for.getVariable() and - result = first(for.getBody()) and - completion = NormalCompletion() + n1.isAdditional(ioe, instanceofTrueNodeTag()) and + n2.isBefore(ioe.getPattern()) or - // Finally, the back edge of the loop goes to reassign the variable. - last(for.getBody(), n, completion) and - continues(completion, for) and - result.asExpr() = for.getVariable() + n1.isAfter(ioe.getPattern()) and + n2.isAfterValue(ioe, any(BooleanSuccessor s | s.getValue() = true)) ) or - // While loops start at the condition... - result = first(n.asStmt().(WhileStmt).getCondition()) and completion = NormalCompletion() - or - // ...and do-while loops start at the body. - result = first(n.asStmt().(DoStmt).getBody()) and completion = NormalCompletion() - or - exists(LoopStmt loop | loop instanceof WhileStmt or loop instanceof DoStmt | - // Control goes from the condition via a true-completion to the body... - last(loop.getCondition(), n, completion) and - completion = BooleanCompletion(true, _) and - result = first(loop.getBody()) + exists(AssertStmt assertstmt | + n1.isBefore(assertstmt) and + n2.isBefore(assertstmt.getExpr()) or - // ...and through the back edge from the body back to the condition. - last(loop.getBody(), n, completion) and - continues(completion, loop) and - result = first(loop.getCondition()) - ) - or - // Resource declarations in a try-with-resources execute sequentially. - exists(TryStmt try, int i | - last(try.getResource(i), n, completion) and completion = NormalCompletion() - | - result = first(try.getResource(i + 1)) + n1.isAfterValue(assertstmt.getExpr(), any(BooleanSuccessor s | s.getValue() = true)) and + n2.isAfter(assertstmt) or - not exists(try.getResource(i + 1)) and result = first(try.getBlock()) - ) - or - // After the last resource declaration, control transfers to the body. - exists(TryStmt try | n.asStmt() = try and completion = NormalCompletion() | - result = first(try.getResource(0)) - or - not exists(try.getAResource()) and result = first(try.getBlock()) - ) - or - // exceptional control flow - exists(TryStmt try | catchOrFinallyCompletion(try, n, completion) | - // if the body of the `try` throws... - exists(ThrowableType tt | completion = ThrowCompletion(tt) | - // ...control transfers to a catch clause... - result = first(handlingCatchClause(try, tt)) + n1.isAfterValue(assertstmt.getExpr(), any(BooleanSuccessor s | s.getValue() = false)) and + ( + n2.isBefore(assertstmt.getMessage()) or - // ...or to the finally block - not mustCatch(try.getACatchClause(), tt) and result = first(try.getFinally()) + not exists(assertstmt.getMessage()) and + n2.isAdditional(assertstmt, assertThrowNodeTag()) ) or - // if the body completes normally, control transfers to the finally block - not completion = ThrowCompletion(_) and result = first(try.getFinally()) - ) - or - // after each catch clause, control transfers to the finally block - exists(TryStmt try | last(try.getACatchClause(), n, completion) | - result = first(try.getFinally()) + n1.isAfter(assertstmt.getMessage()) and + n2.isAdditional(assertstmt, assertThrowNodeTag()) ) or - // Catch clauses first assign their variable and then execute their block - exists(CatchClause cc | completion = NormalCompletion() | - n.asStmt() = cc and result = first(cc.getVariable()) + // Synchronized statements execute their expression _before_ synchronization, so the CFG reflects that. + exists(SynchronizedStmt synch | + n1.isBefore(synch) and + n2.isBefore(synch.getExpr()) or - last(cc.getVariable(), n, completion) and result = first(cc.getBlock()) - ) - or - // Switch statements and expressions - exists(SwitchBlock switch | - exists(Expr switchExpr | - switchExpr = switch.(SwitchStmt).getExpr() or switchExpr = switch.(SwitchExpr).getExpr() - | - // From the entry point control is transferred first to the expression... - n.getAstNode() = switch and - result = first(switchExpr) and - completion = NormalCompletion() - or - // ...and then to any case up to and including the first pattern case, if any. - last(switchExpr, n, completion) and - result = first(getAFirstSwitchCase(switch)) and - completion = NormalCompletion() - ) + n1.isAfter(synch.getExpr()) and + n2.isIn(synch) or - // Statements within a switch body execute sequentially. - // Note this includes non-rule case statements and the successful pattern match successor - // of a non-rule pattern case statement. Rule case statements do not complete normally - // (they always break or yield). - // Exception: falling through into a pattern case statement (which necessarily does not - // declare any named variables) must skip one or more such statements, otherwise we would - // incorrectly apply their type test and/or guard. - exists(Stmt pred, Stmt succ | - isNextNormalSwitchStmt(switch, pred, succ) and - last(pred, n, completion) and - result = first(succ) and - (completion = NormalCompletion() or completion = BooleanCompletion(true, _)) - ) + n1.isIn(synch) and + n2.isBefore(synch.getBlock()) or - // A pattern case that completes boolean false (type test or guard failure) continues to consider other cases: - exists(PatternCase case | completion = BooleanCompletion(false, _) | - last(case, n, completion) and result.asStmt() = getASuccessorSwitchCase(case, switch) - ) + n1.isAfter(synch.getBlock()) and + n2.isAfter(synch) ) or - // Pattern cases have internal edges: - // * Type test success -true-> one of the possible sets of variable declarations - // n.b. for unnamed patterns (e.g. case A _, B _) this means that *one* of the - // type tests has succeeded. There aren't enough nodes in the AST to describe - // a sequential test in detail, so CFG consumers have to watch out for this case. - // * Variable declarations -normal-> guard evaluation - // * Variable declarations -normal-> rule execution (when there is no guard) - // * Guard success -true-> rule execution - exists(PatternCase pc | - n.asStmt() = pc and - completion = basicBooleanCompletion(true) and - result = first(pc.getAPattern()) - or - last(pc.getAPattern(), n, completion) and - completion = NormalCompletion() and - result = first(pc.getGuard()) + exists(WhenExpr whenexpr | + n1.isBefore(whenexpr) and + n2.isBefore(whenexpr.getBranch(0)) or - lastPatternCaseMatchingOp(pc, n, completion) and - ( - result = first(pc.getRuleExpression()) + exists(int i, WhenBranch branch | branch = whenexpr.getBranch(i) | + // The `.isAfter(branch)` nodes are not needed, so they're simply skipped. + n1.isBefore(branch) and + n2.isBefore(branch.getCondition()) or - result = first(pc.getRuleStatement()) - ) - ) - or - // Non-pattern cases have an internal edge leading to their rule body if any when the case matches. - exists(SwitchCase case | n.asStmt() = case | - not case instanceof PatternCase and - completion = NormalCompletion() and - ( - result = first(case.getRuleExpression()) + n1.isAfterTrue(branch.getCondition()) and + n2.isBefore(branch.getRhs()) or - result = first(case.getRuleStatement()) - ) - ) - or - // Yield - exists(YieldStmt yield | completion = NormalCompletion() | - n.asStmt() = yield and result = first(yield.getValue()) - ) - or - // Synchronized statements execute their expression _before_ synchronization, so the CFG reflects that. - exists(SynchronizedStmt synch | completion = NormalCompletion() | - last(synch.getExpr(), n, completion) and result.asStmt() = synch - or - n.asStmt() = synch and result = first(synch.getBlock()) - ) - or - result = first(n.asStmt().(ExprStmt).getExpr()) and completion = NormalCompletion() - or - result = first(n.asExpr().(StmtExpr).getStmt()) and completion = NormalCompletion() - or - result = first(n.asStmt().(LabeledStmt).getStmt()) and completion = NormalCompletion() - or - // Variable declarations in a variable declaration statement are executed sequentially. - exists(LocalVariableDeclStmt s | completion = NormalCompletion() | - n.asStmt() = s and result = first(s.getVariable(1)) - or - exists(int i | last(s.getVariable(i), n, completion) and result = first(s.getVariable(i + 1))) - ) - or - // Assert statements: - exists(AssertStmt assertstmt | - last(assertstmt.getExpr(), n, completion) and - completion = BooleanCompletion(true, _) and - result.asStmt() = assertstmt - or - last(assertstmt.getExpr(), n, completion) and - completion = BooleanCompletion(false, _) and - ( - result = first(assertstmt.getMessage()) + n1.isAfterFalse(branch.getCondition()) and + ( + n2.isBefore(whenexpr.getBranch(i + 1)) + or + not exists(whenexpr.getBranch(i + 1)) and + n2.isAfter(whenexpr) + ) or - not exists(assertstmt.getMessage()) and - result.(AssertThrowNode).getAstNode() = assertstmt - ) - or - last(assertstmt.getMessage(), n, completion) and - completion = NormalCompletion() and - result.(AssertThrowNode).getAstNode() = assertstmt - ) - or - // When expressions: - exists(WhenExpr whenexpr | - n.asExpr() = whenexpr and - result = first(whenexpr.getBranch(0)) and - completion = NormalCompletion() - or - exists(int i | - last(whenexpr.getBranch(i), n, completion) and - completion = BooleanCompletion(false, _) and - result = first(whenexpr.getBranch(i + 1)) + n1.isAfter(branch.getRhs()) and + n2.isAfter(whenexpr) ) ) - or - // When branches: - exists(WhenBranch whenbranch | - n.asStmt() = whenbranch and - completion = NormalCompletion() and - result = first(whenbranch.getCondition()) - or - last(whenbranch.getCondition(), n, completion) and - completion = BooleanCompletion(true, _) and - result = first(whenbranch.getRhs()) - ) - } - - /* - * Conditions give rise to nodes with two normal successors, a true successor - * and a false successor. At least one of them is completely contained in the - * AST node of the branching construct and is therefore tagged with the - * corresponding `booleanCompletion` in the `succ` relation (for example, the - * then-branch of an if-statement, or the right operand of a binary logic - * expression). The other successor may be tagged with either the corresponding - * `booleanCompletion` (for example in an if-statement with an else-branch or - * in a `ConditionalExpr`) or a `normalCompletion` (for example in an - * if-statement without an else-part). - * - * If the other successor ends a finally block it may also be tagged with an - * abnormal completion instead of a `normalCompletion`. This completion is - * calculated by the `resumption` predicate. In this case the successor might - * no longer be unique, as there can be multiple completions to be resumed - * after the finally block. - */ - - /** - * Gets the _resumption_ for cfg node `n`, that is, the completion according - * to which control flow is determined if `n` completes normally. - * - * In most cases, the resumption is simply the normal completion, except if - * `n` is the last node of a `finally` block, in which case it is the - * completion of any predecessors of the `finally` block as determined by - * predicate `finallyPred`, since their completion is resumed after normal - * completion of the `finally`. - */ - private Completion resumption(Node n) { - exists(TryStmt try | lastInFinally(try, n) and finallyPred(try, _, result)) - or - not lastInFinally(_, n) and result = NormalCompletion() - } - - /** - * A true- or false-successor that is tagged with the corresponding `booleanCompletion`. - * - * That is, the `booleanCompletion` is the label of the edge in the CFG. - */ - private Node mainBranchSucc(Node n, boolean b) { result = succ(n, BooleanCompletion(_, b)) } - - /** - * A true- or false-successor that is not tagged with a `booleanCompletion`. - * - * That is, the label of the edge in the CFG is a `normalCompletion` or - * some other completion if `n` occurs as the last node in a finally block. - * - * In the latter case, when `n` occurs as the last node in a finally block, there might be - * multiple different such successors. - */ - private Node otherBranchSucc(Node n, boolean b) { - exists(Node main | main = mainBranchSucc(n, b.booleanNot()) | - result = succ(n, resumption(n)) and - not result = main and - (b = true or b = false) - ) - } - - /** Gets a true- or false-successor of `n`. */ - cached - Node branchSuccessor(Node n, boolean branch) { - result = mainBranchSucc(n, branch) or - result = otherBranchSucc(n, branch) } } -private import ControlFlowGraphImpl - -/** A control-flow node that branches based on a condition. */ -class ConditionNode extends ControlFlow::Node { - ConditionNode() { exists(branchSuccessor(this, _)) } +/** A control-flow node that branches based on a boolean condition. */ +class ConditionNode extends ControlFlowNode { + ConditionNode() { exists(this.getASuccessor(any(BooleanSuccessor t))) } /** Gets a true- or false-successor of the `ConditionNode`. */ - ControlFlow::Node getABranchSuccessor(boolean branch) { result = branchSuccessor(this, branch) } + ControlFlowNode getABranchSuccessor(boolean branch) { + result = this.getASuccessor(any(BooleanSuccessor t | t.getValue() = branch)) + } /** Gets a true-successor of the `ConditionNode`. */ - ControlFlow::Node getATrueSuccessor() { result = this.getABranchSuccessor(true) } + ControlFlowNode getATrueSuccessor() { result = this.getABranchSuccessor(true) } /** Gets a false-successor of the `ConditionNode`. */ - ControlFlow::Node getAFalseSuccessor() { result = this.getABranchSuccessor(false) } + ControlFlowNode getAFalseSuccessor() { result = this.getABranchSuccessor(false) } /** Gets the condition of this `ConditionNode`. */ ExprParent getCondition() { result = this.asExpr() or result = this.asStmt() } } - -private import codeql.controlflow.PrintGraph as PrintGraph - -private module PrintGraphInput implements PrintGraph::InputSig { - private import java as J - - class Callable = J::Callable; - - class ControlFlowNode = J::ControlFlowNode; - - ControlFlowNode getASuccessor(ControlFlowNode n, SuccessorType t) { result = n.getASuccessor(t) } -} - -import PrintGraph::PrintGraph diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index c609c35cd71e..31135429e2d8 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -392,7 +392,7 @@ class ArrayInit extends Expr, @arrayinit { * element assignments since there the assignment destination is not directly * the array variable but instead an `ArrayAccess`. */ -class Assignment extends Expr, @assignment { +class Assignment extends BinaryExpr, @assignment { /** Gets the destination (left-hand side) of the assignment. */ Expr getDest() { result.isNthChildOf(this, 0) } @@ -417,6 +417,8 @@ class Assignment extends Expr, @assignment { * For example, `x = 23`. */ class AssignExpr extends Assignment, @assignexpr { + override string getOp() { result = "=" } + override string getAPrimaryQlClass() { result = "AssignExpr" } } @@ -445,7 +447,7 @@ class AssignOp extends Assignment, @assignop { override Expr getSource() { result.getParent() = this } /** Gets a string representation of the assignment operator of this compound assignment. */ - /*abstract*/ string getOp() { result = "??=" } + /*abstract*/ override string getOp() { result = "??=" } /** Gets a printable representation of this expression. */ override string toString() { result = "..." + this.getOp() + "..." } @@ -739,155 +741,155 @@ class BinaryExpr extends Expr, @binaryexpr { } /** Gets a printable representation of this expression. */ - override string toString() { result = "..." + this.getOp() + "..." } + override string toString() { result = "... " + this.getOp() + " ..." } /** Gets a string representation of the operator of this binary expression. */ - /*abstract*/ string getOp() { result = " ?? " } + /*abstract*/ string getOp() { result = "??" } } /** A binary expression using the `*` operator. */ class MulExpr extends BinaryExpr, @mulexpr { - override string getOp() { result = " * " } + override string getOp() { result = "*" } override string getAPrimaryQlClass() { result = "MulExpr" } } /** A binary expression using the `/` operator. */ class DivExpr extends BinaryExpr, @divexpr { - override string getOp() { result = " / " } + override string getOp() { result = "/" } override string getAPrimaryQlClass() { result = "DivExpr" } } /** A binary expression using the `%` operator. */ class RemExpr extends BinaryExpr, @remexpr { - override string getOp() { result = " % " } + override string getOp() { result = "%" } override string getAPrimaryQlClass() { result = "RemExpr" } } /** A binary expression using the `+` operator. */ class AddExpr extends BinaryExpr, @addexpr { - override string getOp() { result = " + " } + override string getOp() { result = "+" } override string getAPrimaryQlClass() { result = "AddExpr" } } /** A binary expression using the `-` operator. */ class SubExpr extends BinaryExpr, @subexpr { - override string getOp() { result = " - " } + override string getOp() { result = "-" } override string getAPrimaryQlClass() { result = "SubExpr" } } /** A binary expression using the `<<` operator. */ class LeftShiftExpr extends BinaryExpr, @lshiftexpr { - override string getOp() { result = " << " } + override string getOp() { result = "<<" } override string getAPrimaryQlClass() { result = "LeftShiftExpr" } } /** A binary expression using the `>>` operator. */ class RightShiftExpr extends BinaryExpr, @rshiftexpr { - override string getOp() { result = " >> " } + override string getOp() { result = ">>" } override string getAPrimaryQlClass() { result = "RightShiftExpr" } } /** A binary expression using the `>>>` operator. */ class UnsignedRightShiftExpr extends BinaryExpr, @urshiftexpr { - override string getOp() { result = " >>> " } + override string getOp() { result = ">>>" } override string getAPrimaryQlClass() { result = "UnsignedRightShiftExpr" } } /** A binary expression using the `&` operator. */ class AndBitwiseExpr extends BinaryExpr, @andbitexpr { - override string getOp() { result = " & " } + override string getOp() { result = "&" } override string getAPrimaryQlClass() { result = "AndBitwiseExpr" } } /** A binary expression using the `|` operator. */ class OrBitwiseExpr extends BinaryExpr, @orbitexpr { - override string getOp() { result = " | " } + override string getOp() { result = "|" } override string getAPrimaryQlClass() { result = "OrBitwiseExpr" } } /** A binary expression using the `^` operator. */ class XorBitwiseExpr extends BinaryExpr, @xorbitexpr { - override string getOp() { result = " ^ " } + override string getOp() { result = "^" } override string getAPrimaryQlClass() { result = "XorBitwiseExpr" } } /** A binary expression using the `&&` operator. */ class AndLogicalExpr extends BinaryExpr, @andlogicalexpr { - override string getOp() { result = " && " } + override string getOp() { result = "&&" } override string getAPrimaryQlClass() { result = "AndLogicalExpr" } } /** A binary expression using the `||` operator. */ class OrLogicalExpr extends BinaryExpr, @orlogicalexpr { - override string getOp() { result = " || " } + override string getOp() { result = "||" } override string getAPrimaryQlClass() { result = "OrLogicalExpr" } } /** A binary expression using the `<` operator. */ class LTExpr extends BinaryExpr, @ltexpr { - override string getOp() { result = " < " } + override string getOp() { result = "<" } override string getAPrimaryQlClass() { result = "LTExpr" } } /** A binary expression using the `>` operator. */ class GTExpr extends BinaryExpr, @gtexpr { - override string getOp() { result = " > " } + override string getOp() { result = ">" } override string getAPrimaryQlClass() { result = "GTExpr" } } /** A binary expression using the `<=` operator. */ class LEExpr extends BinaryExpr, @leexpr { - override string getOp() { result = " <= " } + override string getOp() { result = "<=" } override string getAPrimaryQlClass() { result = "LEExpr" } } /** A binary expression using the `>=` operator. */ class GEExpr extends BinaryExpr, @geexpr { - override string getOp() { result = " >= " } + override string getOp() { result = ">=" } override string getAPrimaryQlClass() { result = "GEExpr" } } /** A binary expression using Java's `==` or Kotlin's `===` operator. */ class EQExpr extends BinaryExpr, @eqexpr { - override string getOp() { result = " == " } + override string getOp() { result = "==" } override string getAPrimaryQlClass() { result = "EQExpr" } } /** A binary expression using the Kotlin `==` operator, semantically equivalent to `Objects.equals`. */ class ValueEQExpr extends BinaryExpr, @valueeqexpr { - override string getOp() { result = " (value equals) " } + override string getOp() { result = "(value equals)" } override string getAPrimaryQlClass() { result = "ValueEQExpr" } } /** A binary expression using Java's `!=` or Kotlin's `!==` operator. */ class NEExpr extends BinaryExpr, @neexpr { - override string getOp() { result = " != " } + override string getOp() { result = "!=" } override string getAPrimaryQlClass() { result = "NEExpr" } } /** A binary expression using the Kotlin `!=` operator, semantically equivalent to `Objects.equals`. */ class ValueNEExpr extends BinaryExpr, @valueneexpr { - override string getOp() { result = " (value not-equals) " } + override string getOp() { result = "(value not-equals)" } override string getAPrimaryQlClass() { result = "ValueNEExpr" } } @@ -1245,6 +1247,9 @@ class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr { /** Gets the immediately enclosing statement of this class instance creation expression. */ override Stmt getEnclosingStmt() { result = Expr.super.getEnclosingStmt() } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Expr.super.getControlFlowNode() } + /** Gets a printable representation of this expression. */ override string toString() { result = "new " + this.getConstructor().getName() + "(...)" @@ -2113,6 +2118,9 @@ class MethodCall extends Expr, Call, @methodaccess { /** Gets the immediately enclosing statement that contains this method access. */ override Stmt getEnclosingStmt() { result = Expr.super.getEnclosingStmt() } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Expr.super.getControlFlowNode() } + /** Gets a printable representation of this expression. */ override string toString() { if exists(this.getMethod()) @@ -2305,6 +2313,9 @@ class Call extends ExprParent, @caller { /** Gets the enclosing statement of this call. */ /*abstract*/ Stmt getEnclosingStmt() { none() } + /** Gets the `ControlFlowNode` corresponding to this call. */ + /*abstract*/ ControlFlowNode getControlFlowNode() { none() } + /** Gets the number of arguments provided in this call. */ int getNumArgument() { count(this.getAnArgument()) = result } diff --git a/java/ql/lib/semmle/code/java/PrettyPrintAst.qll b/java/ql/lib/semmle/code/java/PrettyPrintAst.qll index 59a59cd9cdd0..52374e6e3840 100644 --- a/java/ql/lib/semmle/code/java/PrettyPrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrettyPrintAst.qll @@ -207,29 +207,12 @@ private class PpArrayInit extends PpAst, ArrayInit { override PpAst getChild(int i) { exists(int j | result = this.getInit(j) and i = 1 + 2 * j) } } -private class PpAssignment extends PpAst, Assignment { - override string getPart(int i) { - i = 1 and - this instanceof AssignExpr and - result = " = " - or - i = 1 and - result = " " + this.(AssignOp).getOp() + " " - } - - override PpAst getChild(int i) { - i = 0 and result = this.getDest() - or - i = 2 and result = this.getRhs() - } -} - private class PpLiteral extends PpAst, Literal { override string getPart(int i) { i = 0 and result = this.getLiteral() } } private class PpBinaryExpr extends PpAst, BinaryExpr { - override string getPart(int i) { i = 1 and result = this.getOp() } + override string getPart(int i) { i = 1 and result = " " + this.getOp() + " " } override PpAst getChild(int i) { i = 0 and result = this.getLeftOperand() diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll index 4366334dfbdc..e2c7779b43cb 100644 --- a/java/ql/lib/semmle/code/java/Statement.qll +++ b/java/ql/lib/semmle/code/java/Statement.qll @@ -61,7 +61,7 @@ class Stmt extends StmtParent, ExprParent, @stmt { } /** A statement parent is any element that can have a statement as its child. */ -class StmtParent extends @stmtparent, Top { } +class StmtParent extends @stmtparent, ExprParent { } /** * An error statement. @@ -960,6 +960,9 @@ class ThisConstructorInvocationStmt extends Stmt, ConstructorCall, @constructori /** Gets the immediately enclosing statement of this constructor invocation. */ override Stmt getEnclosingStmt() { result = this } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Stmt.super.getControlFlowNode() } + override string pp() { result = "this(...)" } override string toString() { result = "this(...)" } @@ -1001,6 +1004,9 @@ class SuperConstructorInvocationStmt extends Stmt, ConstructorCall, @superconstr /** Gets the immediately enclosing statement of this constructor invocation. */ override Stmt getEnclosingStmt() { result = this } + /** Gets the `ControlFlowNode` corresponding to this call. */ + override ControlFlowNode getControlFlowNode() { result = Stmt.super.getControlFlowNode() } + override string pp() { result = "super(...)" } override string toString() { result = "super(...)" } diff --git a/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll b/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll index e82192b0fbaf..2cc3f8f0ad2d 100644 --- a/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll +++ b/java/ql/lib/semmle/code/java/arithmetic/Overflow.qll @@ -93,8 +93,7 @@ class ArithExpr extends Expr { ) and forall(Expr e | e = this.(BinaryExpr).getAnOperand() or - e = this.(UnaryAssignExpr).getOperand() or - e = this.(AssignOp).getSource() + e = this.(UnaryAssignExpr).getOperand() | e.getType() instanceof NumType ) @@ -114,21 +113,17 @@ class ArithExpr extends Expr { */ Expr getLeftOperand() { result = this.(BinaryExpr).getLeftOperand() or - result = this.(UnaryAssignExpr).getOperand() or - result = this.(AssignOp).getDest() + result = this.(UnaryAssignExpr).getOperand() } /** * Gets the right-hand operand if this is a binary expression. */ - Expr getRightOperand() { - result = this.(BinaryExpr).getRightOperand() or result = this.(AssignOp).getRhs() - } + Expr getRightOperand() { result = this.(BinaryExpr).getRightOperand() } /** Gets an operand of this arithmetic expression. */ Expr getAnOperand() { result = this.(BinaryExpr).getAnOperand() or - result = this.(UnaryAssignExpr).getOperand() or - result = this.(AssignOp).getSource() + result = this.(UnaryAssignExpr).getOperand() } } diff --git a/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll b/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll index f214cbbd0b1a..a5229bea590b 100644 --- a/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll +++ b/java/ql/lib/semmle/code/java/controlflow/BasicBlocks.qll @@ -6,151 +6,8 @@ module; import java import Dominance -private import codeql.controlflow.BasicBlock as BB -private import codeql.controlflow.SuccessorType - -private module Input implements BB::InputSig { - /** Hold if `t` represents a conditional successor type. */ - predicate successorTypeIsCondition(SuccessorType t) { none() } - - /** A delineated part of the AST with its own CFG. */ - class CfgScope = Callable; - - /** The class of control flow nodes. */ - class Node = ControlFlowNode; - - /** Gets the CFG scope in which this node occurs. */ - CfgScope nodeGetCfgScope(Node node) { node.getEnclosingCallable() = result } - - /** Gets an immediate successor of this node. */ - Node nodeGetASuccessor(Node node, SuccessorType t) { result = node.getASuccessor(t) } - - /** - * Holds if `node` represents an entry node to be used when calculating - * dominance. - */ - predicate nodeIsDominanceEntry(Node node) { - exists(Stmt entrystmt | entrystmt = node.asStmt() | - exists(Callable c | entrystmt = c.getBody()) - or - // This disjunct is technically superfluous, but safeguards against extractor problems. - entrystmt instanceof BlockStmt and - not exists(entrystmt.getEnclosingCallable()) and - not entrystmt.getParent() instanceof Stmt - ) - } - - /** - * Holds if `node` represents an exit node to be used when calculating - * post dominance. - */ - predicate nodeIsPostDominanceExit(Node node) { node instanceof ControlFlow::NormalExitNode } -} - -private module BbImpl = BB::Make; - -import BbImpl - -/** Holds if the dominance relation is calculated for `bb`. */ -predicate hasDominanceInformation(BasicBlock bb) { - exists(BasicBlock entry | - Input::nodeIsDominanceEntry(entry.getFirstNode()) and entry.getASuccessor*() = bb - ) -} - -/** - * A basic block, that is, a maximal straight-line sequence of control flow nodes - * without branches or joins. - */ -class BasicBlock extends BbImpl::BasicBlock { - /** Gets the immediately enclosing callable whose body contains this node. */ - Callable getEnclosingCallable() { result = this.getScope() } - - /** - * Holds if this basic block dominates basic block `bb`. - * - * That is, all paths reaching `bb` from the entry point basic block must - * go through this basic block. - */ - predicate dominates(BasicBlock bb) { super.dominates(bb) } - - /** - * Holds if this basic block strictly dominates basic block `bb`. - * - * That is, all paths reaching `bb` from the entry point basic block must - * go through this basic block and this basic block is different from `bb`. - */ - predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) } - - /** Gets an immediate successor of this basic block of a given type, if any. */ - BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor(t) } - - BasicBlock getASuccessor() { result = super.getASuccessor() } - - BasicBlock getImmediateDominator() { result = super.getImmediateDominator() } - - predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) } - - predicate strictlyPostDominates(BasicBlock bb) { super.strictlyPostDominates(bb) } - - predicate postDominates(BasicBlock bb) { super.postDominates(bb) } - - /** - * DEPRECATED: Use `getASuccessor` instead. - * - * Gets an immediate successor of this basic block. - */ - deprecated BasicBlock getABBSuccessor() { result = this.getASuccessor() } - - /** - * DEPRECATED: Use `getAPredecessor` instead. - * - * Gets an immediate predecessor of this basic block. - */ - deprecated BasicBlock getABBPredecessor() { result.getASuccessor() = this } - - /** - * DEPRECATED: Use `strictlyDominates` instead. - * - * Holds if this basic block strictly dominates `node`. - */ - deprecated predicate bbStrictlyDominates(BasicBlock node) { this.strictlyDominates(node) } - - /** - * DEPRECATED: Use `dominates` instead. - * - * Holds if this basic block dominates `node`. (This is reflexive.) - */ - deprecated predicate bbDominates(BasicBlock node) { this.dominates(node) } - - /** - * DEPRECATED: Use `strictlyPostDominates` instead. - * - * Holds if this basic block strictly post-dominates `node`. - */ - deprecated predicate bbStrictlyPostDominates(BasicBlock node) { this.strictlyPostDominates(node) } - - /** - * DEPRECATED: Use `postDominates` instead. - * - * Holds if this basic block post-dominates `node`. (This is reflexive.) - */ - deprecated predicate bbPostDominates(BasicBlock node) { this.postDominates(node) } -} /** A basic block that ends in an exit node. */ class ExitBlock extends BasicBlock { ExitBlock() { this.getLastNode() instanceof ControlFlow::ExitNode } } - -private class BasicBlockAlias = BasicBlock; - -module Cfg implements BB::CfgSig { - class ControlFlowNode = BbImpl::ControlFlowNode; - - class BasicBlock = BasicBlockAlias; - - class EntryBasicBlock extends BasicBlock instanceof BbImpl::EntryBasicBlock { } - - predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) { BbImpl::dominatingEdge(bb1, bb2) } -} diff --git a/java/ql/lib/semmle/code/java/controlflow/Guards.qll b/java/ql/lib/semmle/code/java/controlflow/Guards.qll index 49cd0d189414..23088bd2f809 100644 --- a/java/ql/lib/semmle/code/java/controlflow/Guards.qll +++ b/java/ql/lib/semmle/code/java/controlflow/Guards.qll @@ -10,6 +10,7 @@ private import semmle.code.java.controlflow.Dominance private import semmle.code.java.controlflow.internal.Preconditions private import semmle.code.java.controlflow.internal.SwitchCases private import codeql.controlflow.Guards as SharedGuards +private import codeql.controlflow.SuccessorType /** * A basic block that terminates in a condition, splitting the subsequent control flow. @@ -75,70 +76,6 @@ class ConditionBlock extends BasicBlock { } } -// Join order engineering -- first determine the switch block and the case indices required, then retrieve them. -bindingset[switch, i] -pragma[inline_late] -private predicate isNthCaseOf(SwitchBlock switch, SwitchCase c, int i) { c.isNthCaseOf(switch, i) } - -/** - * Gets a switch case >= pred, up to but not including `pred`'s successor pattern case, - * where `pred` is declared on `switch`. - */ -private SwitchCase getACaseUpToNextPattern(PatternCase pred, SwitchBlock switch) { - // Note we do include `case null, default` (as well as plain old `default`) here. - not result.(ConstCase).getValue(_) instanceof NullLiteral and - exists(int maxCaseIndex | - switch = pred.getParent() and - if exists(getNextPatternCase(pred)) - then maxCaseIndex = getNextPatternCase(pred).getCaseIndex() - 1 - else maxCaseIndex = lastCaseIndex(switch) - | - isNthCaseOf(switch, result, [pred.getCaseIndex() .. maxCaseIndex]) - ) -} - -/** - * Gets the closest pattern case preceding `case`, including `case` itself, if any. - */ -private PatternCase getClosestPrecedingPatternCase(SwitchCase case) { - case = getACaseUpToNextPattern(result, _) -} - -/** - * Holds if `pred` is a control-flow predecessor of switch case `sc` that is not a - * fall-through from a previous case. - * - * For classic switches that means flow from the selector expression; for switches - * involving pattern cases it can also mean flow from a previous pattern case's type - * test or guard failing and proceeding to then consider subsequent cases. - */ -private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pred) { - pred = sc.getControlFlowNode().getAPredecessor() and - ( - pred.asExpr().getParent*() = sc.getSelectorExpr() - or - // Ambiguous: in the case of `case String _ when x: case "SomeConstant":`, the guard `x` - // passing edge will fall through into the constant case, and the guard failing edge - // will test if the selector equals `"SomeConstant"` and if so branch to the same - // case statement. Therefore don't label this a non-fall-through predecessor. - exists(PatternCase previousPatternCase | - previousPatternCase = getClosestPrecedingPatternCase(sc) - | - pred.asExpr().getParent*() = previousPatternCase.getGuard() and - // Check there is any statement in between the previous pattern case and this one, - // or the case is a rule, so there is no chance of a fall-through. - ( - previousPatternCase.isRule() or - not previousPatternCase.getIndex() = sc.getIndex() - 1 - ) - ) - or - // Unambigious: on the test-passing edge there must be at least one intervening - // declaration node, including anonymous `_` declarations. - pred.asStmt() = getClosestPrecedingPatternCase(sc) - ) -} - private module GuardsInput implements SharedGuards::InputSig { private import java as J private import semmle.code.java.dataflow.internal.BaseSSA as Base @@ -231,39 +168,18 @@ private module GuardsInput implements SharedGuards::InputSig { class ConstantIntegerExpr = RU::ConstantIntegerExpr; - abstract class BinaryExpr extends Expr { - Expr getLeftOperand() { - result = this.(J::BinaryExpr).getLeftOperand() or result = this.(J::AssignOp).getDest() - } - - Expr getRightOperand() { - result = this.(J::BinaryExpr).getRightOperand() or result = this.(J::AssignOp).getRhs() - } - - final Expr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() } - - final predicate hasOperands(Expr e1, Expr e2) { - this.getLeftOperand() = e1 and this.getRightOperand() = e2 - or - this.getLeftOperand() = e2 and this.getRightOperand() = e1 - } - } + class BinaryExpr = J::BinaryExpr; class AddExpr extends BinaryExpr { AddExpr() { this instanceof J::AddExpr or this instanceof J::AssignAddExpr } @@ -220,6 +204,8 @@ module Sem implements Semantic { int getBlockId1(BasicBlock bb) { idOf(bb, result) } + string getBlockId2(BasicBlock bb) { bb.getFirstNode().getIdTag() = result } + class Guard extends G::Guards_v2::Guard { Expr asExpr() { result = this } } diff --git a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll index 9aca7fad2f2a..2c04a6413eb7 100644 --- a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll @@ -326,20 +326,45 @@ private module Input implements TypeFlowInput { ) } - /** - * Holds if `ioe` checks `v`, its true-successor is `bb`, and `bb` has multiple - * predecessors. - */ - private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, Base::SsaDefinition v) { + /** Holds if `ioe` checks `v` and its true-successor is `bb`. */ + private predicate instanceofTrueSuccessor(InstanceOfExpr ioe, BasicBlock bb, Base::SsaDefinition v) { ioe.getExpr() = v.getARead() and - strictcount(bb.getAPredecessor()) > 1 and exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb) } - /** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */ - private predicate instanceofDisjunction(BasicBlock bb, Base::SsaDefinition v) { - strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) = - strictcount(bb.getAPredecessor()) + /** + * Holds if `bb` is disjunctively guarded by one (`trivial = true`) or more + * (`trivial = false`) `instanceof` tests on `v`. + */ + private predicate instanceofDisjunction(BasicBlock bb, Base::SsaDefinition v, boolean trivial) { + exists(int preds | + strictcount(bb.getAPredecessor()) = preds and + strictcount(InstanceOfExpr ioe | instanceofTrueSuccessor(ioe, bb, v)) = preds and + if preds > 1 then trivial = false else trivial = true + ) + or + strictcount(bb.getAPredecessor()) = 2 and + exists(BasicBlock pred1, BasicBlock pred2 | + pred1 != pred2 and + pred1 = bb.getAPredecessor() and + pred2 = bb.getAPredecessor() and + instanceofDisjunction(pred1, v, _) and + instanceofDisjunction(pred2, v, _) and + trivial = false + ) + } + + /** + * Holds if `bb` is disjunctively guarded by one or more `instanceof` tests + * on `v`, and `ioe` is one of those tests. + */ + private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, Base::SsaDefinition v) { + instanceofDisjunction(bb, v, _) and + ( + instanceofTrueSuccessor(ioe, bb, v) + or + exists(BasicBlock pred | pred = bb.getAPredecessor() and instanceofDisjunct(ioe, pred, v)) + ) } /** @@ -348,7 +373,7 @@ private module Input implements TypeFlowInput { */ predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) { exists(BasicBlock bb, InstanceOfExpr ioe, Base::SsaDefinition v, VarAccess va | - instanceofDisjunction(bb, v) and + instanceofDisjunction(bb, v, false) and bb.dominates(va.getBasicBlock()) and va = v.getARead() and instanceofDisjunct(ioe, bb, v) and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll index 5e3a8550e3cc..07d871ab9bc8 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -93,8 +93,7 @@ private module BaseSsaImpl { /** Holds if `n` updates the local variable `v`. */ predicate variableUpdate(BaseSsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { exists(VariableUpdate a | a.getControlFlowNode() = n | getDestVar(a) = v) and - b.getNode(i) = n and - hasDominanceInformation(b) + b.getNode(i) = n } /** Gets the definition point of a nested class in the parent scope. */ @@ -132,7 +131,7 @@ private module BaseSsaImpl { inner != outer and inner.getDeclaringType() = innerclass and result = parentDef(desugaredGetEnclosingType*(innerclass)) and - result.getEnclosingStmt().getEnclosingCallable() = outer and + result.getEnclosingCallable() = outer and capturedvar = TLocalVar(outer, v) and closurevar = TLocalVar(inner, v) ) @@ -178,15 +177,12 @@ private module SsaImplInput implements SsaImplCommon::InputSig; private predicate predictableCalcStep(Expr e1, Expr e2) { - e2.(BinaryExpr).hasOperands(e1, any(PredictableSeedExpr p)) - or - exists(AssignOp a | a = e2 | e1 = a.getDest() and a.getRhs() instanceof PredictableSeedExpr) + e2.(BinaryExpr).hasOperands(e1, any(PredictableSeedExpr p)) and + not e2 instanceof AssignExpr or exists(ConstructorCall cc, TypeNumber t | cc = e2 | cc.getArgument(0) = e1 and diff --git a/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/old.dbscheme b/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/old.dbscheme new file mode 100644 index 000000000000..9f6026c40099 --- /dev/null +++ b/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/old.dbscheme @@ -0,0 +1,1240 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path: string ref +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isImplicitClass( + unique int classid: @classorinterface ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +isCanonicalConstr( + int constructorid: @constructor ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +| 89 = @recordpatternexpr +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +isNullDefaultCase( + int id: @case ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF + // 3: ENUM_ENTRIES +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/semmlecode.dbscheme b/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/semmlecode.dbscheme new file mode 100644 index 000000000000..de4ded61c8ae --- /dev/null +++ b/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/semmlecode.dbscheme @@ -0,0 +1,1241 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +databaseMetadata( + string metadataKey : string ref, + string value : string ref +); + +overlayChangedFiles( + string path: string ref +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isImplicitClass( + unique int classid: @classorinterface ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +isCanonicalConstr( + int constructorid: @constructor ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +| 89 = @recordpatternexpr +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @assignment + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +isNullDefaultCase( + int id: @case ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF + // 3: ENUM_ENTRIES +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/upgrade.properties b/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/upgrade.properties new file mode 100644 index 000000000000..6b5f3f72a629 --- /dev/null +++ b/java/ql/lib/upgrades/9f6026c400996c13842974b24f076a486ad1f69c/upgrade.properties @@ -0,0 +1,2 @@ +description: Expand @binaryexpr union to include @assignment +compatibility: full diff --git a/java/ql/lib/utils/test/AstCfg.qll b/java/ql/lib/utils/test/AstCfg.qll new file mode 100644 index 000000000000..c44b14bee726 --- /dev/null +++ b/java/ql/lib/utils/test/AstCfg.qll @@ -0,0 +1,28 @@ +/** + * Provides utilities for getting an AST-based control flow graph in tests. + */ +overlay[local?] +module; + +import java + +private predicate isAstNode(ControlFlowNode n) { + n.injects(_) or + n instanceof ControlFlow::EntryNode or + n instanceof ControlFlow::AnnotatedExitNode or + n instanceof ControlFlow::ExitNode +} + +private predicate succToAst(ControlFlowNode n1, ControlFlowNode n2) { + n2 = n1.getASuccessor() and + isAstNode(n2) + or + exists(ControlFlowNode mid | + mid = n1.getASuccessor() and + not isAstNode(mid) and + succToAst(mid, n2) + ) +} + +/** Gets a control flow successor of `n` that skips over non-AST nodes. */ +ControlFlowNode getAnAstSuccessor(ControlFlowNode n) { isAstNode(n) and succToAst(n, result) } diff --git a/java/ql/lib/utils/test/BasicBlock.qll b/java/ql/lib/utils/test/BasicBlock.qll new file mode 100644 index 000000000000..c1f31f791825 --- /dev/null +++ b/java/ql/lib/utils/test/BasicBlock.qll @@ -0,0 +1,40 @@ +/** + * Provides utilities for working with basic blocks in tests. + */ +overlay[local?] +module; + +import java +import codeql.util.Boolean + +private predicate entryOrExit(ControlFlowNode n) { + n instanceof ControlFlow::EntryNode or + n instanceof ControlFlow::AnnotatedExitNode or + n instanceof ControlFlow::ExitNode +} + +/** Gets the first AST node in the basic block `bb`, if any. */ +ControlFlowNode getFirstAstNode(BasicBlock bb) { result = getFirstAstNode(bb, false) } + +/** + * Gets the first AST node in the basic block `bb`, if any. Otherwise, gets + * the first synthetic node. + */ +ControlFlowNode getFirstAstNodeOrSynth(BasicBlock bb) { result = getFirstAstNode(bb, true) } + +private ControlFlowNode getFirstAstNode(BasicBlock bb, Boolean allowSynthetic) { + result = + min(ControlFlowNode n, int i, int astOrder | + bb.getNode(i) = n and + if n.injects(_) + then astOrder = 0 + else + if entryOrExit(n) + then astOrder = 1 + else ( + allowSynthetic = true and astOrder = 2 + ) + | + n order by astOrder, i + ) +} diff --git a/java/ql/src/Likely Bugs/Arithmetic/OctalLiteral.ql b/java/ql/src/Likely Bugs/Arithmetic/OctalLiteral.ql index 1a8021253df0..a77458600898 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/OctalLiteral.ql +++ b/java/ql/src/Likely Bugs/Arithmetic/OctalLiteral.ql @@ -19,6 +19,7 @@ where lit.getLiteral() = val and val.regexpMatch("0[0-7][0-7]+") and lit.getParent() instanceof BinaryExpr and + not lit.getParent() instanceof Assignment and not lit.getParent() instanceof BitwiseExpr and not lit.getParent() instanceof ComparisonExpr select lit, "Integer literal starts with 0." diff --git a/java/ql/src/Likely Bugs/Arithmetic/WhitespaceContradictsPrecedence.ql b/java/ql/src/Likely Bugs/Arithmetic/WhitespaceContradictsPrecedence.ql index 52a5850e7d1d..45eb62c0defd 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/WhitespaceContradictsPrecedence.ql +++ b/java/ql/src/Likely Bugs/Arithmetic/WhitespaceContradictsPrecedence.ql @@ -138,13 +138,14 @@ int operatorWS(BinaryExpr expr) { endOfBinaryLhs(expr, line, lcol) and startOfBinaryRhs(expr, line, rcol) and parens = getParensNextToOp(expr) and - result = rcol - lcol + 1 - expr.getOp().length() - parens + result = rcol - lcol - 1 - expr.getOp().length() - parens ) } /** Find nested binary expressions where the programmer may have made a precedence mistake. */ predicate interestingNesting(BinaryExpr inner, BinaryExpr outer) { inner = outer.getAChildExpr() and + not outer instanceof Assignment and not inner instanceof AssocNestedExpr and not inner instanceof HarmlessNestedExpr and not inner.isParenthesized() diff --git a/java/ql/src/Likely Bugs/Comparison/CompareIdenticalValues.ql b/java/ql/src/Likely Bugs/Comparison/CompareIdenticalValues.ql index e46dd7c5f79f..a5163bd9dfc6 100644 --- a/java/ql/src/Likely Bugs/Comparison/CompareIdenticalValues.ql +++ b/java/ql/src/Likely Bugs/Comparison/CompareIdenticalValues.ql @@ -58,6 +58,7 @@ predicate equal(Expr left, Expr right) { sameVariable(left, right, _) or exists(BinaryExpr bLeft, BinaryExpr bRight | bLeft = left and bRight = right | + not bLeft instanceof Assignment and bLeft.getKind() = bRight.getKind() and equal(bLeft.getLeftOperand(), bRight.getLeftOperand()) and equal(bLeft.getRightOperand(), bRight.getRightOperand()) diff --git a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql index d9a1f8a3f65b..88a956bb24c3 100644 --- a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql +++ b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql @@ -101,17 +101,10 @@ Expr overFlowCand() { | bin instanceof AddExpr or bin instanceof MulExpr or - bin instanceof LeftShiftExpr - ) - or - exists(AssignOp op | - result = op and - positive(op.getDest()) and - positive(op.getRhs()) - | - op instanceof AssignAddExpr or - op instanceof AssignMulExpr or - op instanceof AssignLeftShiftExpr + bin instanceof LeftShiftExpr or + bin instanceof AssignAddExpr or + bin instanceof AssignMulExpr or + bin instanceof AssignLeftShiftExpr ) or exists(AddExpr add, CompileTimeConstantExpr c | diff --git a/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql b/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql index bf03191bdac6..edc800405f72 100644 --- a/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql +++ b/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql @@ -57,13 +57,15 @@ predicate loopExitGuard(LoopStmt loop, Expr cond) { */ predicate mainLoopCondition(LoopStmt loop, Expr cond) { loop.getCondition() = cond and - exists(Expr loopReentry, ControlFlowNode last | - if exists(loop.(ForStmt).getAnUpdate()) - then loopReentry = loop.(ForStmt).getUpdate(0) - else loopReentry = cond - | - last.getEnclosingStmt().getEnclosingStmt*() = loop.getBody() and - last.getASuccessor().asExpr().getParent*() = loopReentry + exists(BasicBlock condBlock | condBlock.getANode().isBefore(cond) | + 1 < strictcount(condBlock.getAPredecessor()) or loop instanceof DoStmt + ) +} + +predicate ssaDefinitionInLoop(LoopStmt loop, SsaDefinition ssa) { + exists(ControlFlowNode node | node = ssa.getControlFlowNode() | + node.getAstNode().(Stmt).getEnclosingStmt*() = loop or + node.getAstNode().(Expr).getEnclosingStmt().getEnclosingStmt*() = loop ) } @@ -76,7 +78,7 @@ where ) and // None of the ssa variables in `cond` are updated inside the loop. forex(SsaDefinition ssa, VarRead use | ssa.getARead() = use and use.getParent*() = cond | - not ssa.getControlFlowNode().getEnclosingStmt().getEnclosingStmt*() = loop or + not ssaDefinitionInLoop(loop, ssa) or ssa.getControlFlowNode().asExpr().getParent*() = loop.(ForStmt).getAnInit() ) and // And `cond` does not use method calls, field reads, or array reads. diff --git a/java/ql/src/Security/CWE/CWE-295/ImproperWebViewCertificateValidation.java b/java/ql/src/Security/CWE/CWE-295/ImproperWebViewCertificateValidation.java index 358800c57463..59dd74ddba3f 100644 --- a/java/ql/src/Security/CWE/CWE-295/ImproperWebViewCertificateValidation.java +++ b/java/ql/src/Security/CWE/CWE-295/ImproperWebViewCertificateValidation.java @@ -1,7 +1,7 @@ class Bad extends WebViewClient { // BAD: All certificates are trusted. - public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult - handler.proceed(); + public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $ hasResult + handler.proceed(); } } @@ -9,7 +9,7 @@ class Good extends WebViewClient { PublicKey myPubKey = ...; // GOOD: Only certificates signed by a certain public key are trusted. - public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $hasResult + public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) { // $ hasResult try { X509Certificate cert = error.getCertificate().getX509Certificate(); cert.verify(this.myPubKey); @@ -18,5 +18,5 @@ public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError catch (CertificateException|NoSuchAlgorithmException|InvalidKeyException|NoSuchProviderException|SignatureException e) { handler.cancel(); } - } -} \ No newline at end of file + } +} diff --git a/java/ql/src/Violations of Best Practice/Declarations/Common.qll b/java/ql/src/Violations of Best Practice/Declarations/Common.qll index 9b3225db81a1..45b978bd011b 100644 --- a/java/ql/src/Violations of Best Practice/Declarations/Common.qll +++ b/java/ql/src/Violations of Best Practice/Declarations/Common.qll @@ -1,41 +1,15 @@ import java -private Stmt getASwitchChild(SwitchStmt s) { - result = s.getAChild() - or - exists(Stmt mid | - mid = getASwitchChild(s) and not mid instanceof SwitchStmt and result = mid.getAChild() - ) -} - -private predicate blockInSwitch(SwitchStmt s, BasicBlock b) { - b.getFirstNode().getEnclosingStmt() = getASwitchChild(s) -} - -private predicate switchCaseControlFlow(SwitchStmt switch, BasicBlock b1, BasicBlock b2) { - blockInSwitch(switch, b1) and - b1.getASuccessor() = b2 and - blockInSwitch(switch, b2) -} - -predicate switchCaseControlFlowPlus(SwitchStmt switch, BasicBlock b1, BasicBlock b2) { - switchCaseControlFlow(switch, b1, b2) - or - exists(BasicBlock mid | - switchCaseControlFlowPlus(switch, mid, b2) and - switchCaseControlFlow(switch, b1, mid) and - not mid.getFirstNode().asStmt() = switch.getACase() - ) -} - predicate mayDropThroughWithoutComment(SwitchStmt switch, Stmt switchCase) { - switchCase = switch.getACase() and - exists(Stmt other, BasicBlock b1, BasicBlock b2 | - b1.getFirstNode().asStmt() = switchCase and - b2.getFirstNode().asStmt() = other and - switchCaseControlFlowPlus(switch, b1, b2) and - other = switch.getACase() and - not fallThroughCommented(other) + exists(int caseIx, SwitchCase next, int nextCaseStmtIx, Stmt lastInCase, ControlFlowNode node | + switch.getCase(caseIx) = switchCase and + switch.getCase(caseIx + 1) = next and + switch.getStmt(nextCaseStmtIx) = next and + switch.getStmt(nextCaseStmtIx - 1) = lastInCase and + lastInCase != switchCase and + node.isAfter(lastInCase) and + node.getANormalSuccessor().asStmt() = switch.getAStmt() and + not fallThroughCommented(next) ) } diff --git a/java/ql/src/Violations of Best Practice/legacy/AutoBoxing.ql b/java/ql/src/Violations of Best Practice/legacy/AutoBoxing.ql index 0fc6527d258c..88a653e3b516 100644 --- a/java/ql/src/Violations of Best Practice/legacy/AutoBoxing.ql +++ b/java/ql/src/Violations of Best Practice/legacy/AutoBoxing.ql @@ -36,6 +36,7 @@ Variable flowTarget(Expr arg) { */ predicate unboxed(BoxedExpr e) { exists(BinaryExpr bin | e = bin.getAnOperand() | + not bin instanceof Assignment and if bin instanceof EqualityTest or bin instanceof ComparisonExpr then bin.getAnOperand() instanceof PrimitiveExpr else bin instanceof PrimitiveExpr diff --git a/java/ql/src/experimental/quantum/Examples/ArtifactReuse.qll b/java/ql/src/experimental/quantum/Examples/ArtifactReuse.qll index 776510b52ad1..1a20a7fa2b51 100644 --- a/java/ql/src/experimental/quantum/Examples/ArtifactReuse.qll +++ b/java/ql/src/experimental/quantum/Examples/ArtifactReuse.qll @@ -42,7 +42,7 @@ private DataFlow::Node getGeneratingWrapperSet(Crypto::NonceArtifactNode a) { } private predicate ancestorOfArtifact( - Crypto::ArtifactNode a, Callable enclosingCallable, ControlFlow::Node midOrTarget + Crypto::ArtifactNode a, Callable enclosingCallable, ControlFlowNode midOrTarget ) { a.asElement().(Expr).getEnclosingCallable() = enclosingCallable and ( @@ -87,7 +87,7 @@ predicate isArtifactReuse(Crypto::ArtifactNode a, Crypto::ArtifactNode b) { ancestorOfArtifact(b, commonParent, _) ) implies - exists(Callable commonParent, ControlFlow::Node aMid, ControlFlow::Node bMid | + exists(Callable commonParent, ControlFlowNode aMid, ControlFlowNode bMid | ancestorOfArtifact(a, commonParent, aMid) and ancestorOfArtifact(b, commonParent, bMid) and a instanceof Crypto::NonceArtifactNode and diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 2e0c05eeb079..ea148f21e79a 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 1.10.8 +version: 1.10.9-dev groups: - java - queries diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected index 116bde45f980..484fb5ea042e 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStmts.expected @@ -1,205 +1,386 @@ -| Test.kt:3:8:80:1 | Exceptional Exit | 0 | Test.kt:3:8:80:1 | Exceptional Exit | -| Test.kt:3:8:80:1 | Exit | 0 | Test.kt:3:8:80:1 | Exit | -| Test.kt:3:8:80:1 | { ... } | 0 | Test.kt:3:8:80:1 | { ... } | -| Test.kt:3:8:80:1 | { ... } | 1 | Test.kt:3:1:80:1 | super(...) | -| Test.kt:3:8:80:1 | { ... } | 2 | Test.kt:3:8:80:1 | { ... } | -| Test.kt:3:8:80:1 | { ... } | 3 | Test.kt:3:8:80:1 | Normal Exit | -| Test.kt:4:2:79:2 | Exceptional Exit | 0 | Test.kt:4:2:79:2 | Exceptional Exit | -| Test.kt:4:2:79:2 | Exit | 0 | Test.kt:4:2:79:2 | Exit | +| Test.kt:3:8:80:1 | Entry | 0 | Test.kt:3:8:80:1 | Entry | +| Test.kt:3:8:80:1 | Entry | 1 | Test.kt:3:8:80:1 | { ... } | +| Test.kt:3:8:80:1 | Entry | 2 | Test.kt:3:1:80:1 | Before super(...) | +| Test.kt:3:8:80:1 | Entry | 3 | Test.kt:3:1:80:1 | super(...) | +| Test.kt:3:8:80:1 | Entry | 4 | Test.kt:3:1:80:1 | After super(...) | +| Test.kt:3:8:80:1 | Entry | 5 | Test.kt:3:8:80:1 | { ... } | +| Test.kt:3:8:80:1 | Entry | 6 | Test.kt:3:8:80:1 | After { ... } | +| Test.kt:3:8:80:1 | Entry | 7 | Test.kt:3:8:80:1 | Normal Exit | +| Test.kt:3:8:80:1 | Entry | 8 | Test.kt:3:8:80:1 | Exit | +| Test.kt:4:2:79:2 | Entry | 0 | Test.kt:4:2:79:2 | Entry | +| Test.kt:4:2:79:2 | Entry | 1 | Test.kt:4:13:79:2 | { ... } | +| Test.kt:4:2:79:2 | Entry | 2 | Test.kt:5:7:5:7 | var ...; | +| Test.kt:4:2:79:2 | Entry | 3 | Test.kt:5:7:5:7 | Before x | +| Test.kt:4:2:79:2 | Entry | 4 | Test.kt:5:16:5:16 | 0 | +| Test.kt:4:2:79:2 | Entry | 5 | Test.kt:5:7:5:7 | x | +| Test.kt:4:2:79:2 | Entry | 6 | Test.kt:5:7:5:7 | After x | +| Test.kt:4:2:79:2 | Entry | 7 | Test.kt:5:7:5:7 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 8 | Test.kt:6:7:6:7 | var ...; | +| Test.kt:4:2:79:2 | Entry | 9 | Test.kt:6:7:6:7 | Before y | +| Test.kt:4:2:79:2 | Entry | 10 | Test.kt:6:17:6:18 | 50 | +| Test.kt:4:2:79:2 | Entry | 11 | Test.kt:6:7:6:7 | y | +| Test.kt:4:2:79:2 | Entry | 12 | Test.kt:6:7:6:7 | After y | +| Test.kt:4:2:79:2 | Entry | 13 | Test.kt:6:7:6:7 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 14 | Test.kt:7:7:7:7 | var ...; | +| Test.kt:4:2:79:2 | Entry | 15 | Test.kt:7:7:7:7 | Before z | +| Test.kt:4:2:79:2 | Entry | 16 | Test.kt:7:16:7:16 | 0 | +| Test.kt:4:2:79:2 | Entry | 17 | Test.kt:7:7:7:7 | z | +| Test.kt:4:2:79:2 | Entry | 18 | Test.kt:7:7:7:7 | After z | +| Test.kt:4:2:79:2 | Entry | 19 | Test.kt:7:7:7:7 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 20 | Test.kt:8:7:8:7 | var ...; | +| Test.kt:4:2:79:2 | Entry | 21 | Test.kt:8:7:8:7 | Before w | +| Test.kt:4:2:79:2 | Entry | 22 | Test.kt:8:16:8:16 | 0 | +| Test.kt:4:2:79:2 | Entry | 23 | Test.kt:8:7:8:7 | w | +| Test.kt:4:2:79:2 | Entry | 24 | Test.kt:8:7:8:7 | After w | +| Test.kt:4:2:79:2 | Entry | 25 | Test.kt:8:7:8:7 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 26 | Test.kt:11:3:16:3 | ; | +| Test.kt:4:2:79:2 | Entry | 27 | Test.kt:11:3:16:3 | when ... | +| Test.kt:4:2:79:2 | Entry | 28 | Test.kt:11:3:16:3 | ... -> ... | +| Test.kt:4:2:79:2 | Entry | 29 | Test.kt:11:7:11:11 | Before ... > ... | +| Test.kt:4:2:79:2 | Entry | 30 | Test.kt:11:7:11:7 | x | +| Test.kt:4:2:79:2 | Entry | 31 | Test.kt:11:11:11:11 | 0 | +| Test.kt:4:2:79:2 | Entry | 32 | Test.kt:11:7:11:11 | ... > ... | | Test.kt:4:2:79:2 | Normal Exit | 0 | Test.kt:4:2:79:2 | Normal Exit | -| Test.kt:4:13:79:2 | { ... } | 0 | Test.kt:4:13:79:2 | { ... } | -| Test.kt:4:13:79:2 | { ... } | 1 | Test.kt:5:7:5:7 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 2 | Test.kt:5:16:5:16 | 0 | -| Test.kt:4:13:79:2 | { ... } | 3 | Test.kt:5:7:5:7 | x | -| Test.kt:4:13:79:2 | { ... } | 4 | Test.kt:6:7:6:7 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 5 | Test.kt:6:17:6:18 | 50 | -| Test.kt:4:13:79:2 | { ... } | 6 | Test.kt:6:7:6:7 | y | -| Test.kt:4:13:79:2 | { ... } | 7 | Test.kt:7:7:7:7 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 8 | Test.kt:7:16:7:16 | 0 | -| Test.kt:4:13:79:2 | { ... } | 9 | Test.kt:7:7:7:7 | z | -| Test.kt:4:13:79:2 | { ... } | 10 | Test.kt:8:7:8:7 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 11 | Test.kt:8:16:8:16 | 0 | -| Test.kt:4:13:79:2 | { ... } | 12 | Test.kt:8:7:8:7 | w | -| Test.kt:4:13:79:2 | { ... } | 13 | Test.kt:11:3:16:3 | ; | -| Test.kt:4:13:79:2 | { ... } | 14 | Test.kt:11:3:16:3 | when ... | -| Test.kt:4:13:79:2 | { ... } | 15 | Test.kt:11:3:16:3 | ... -> ... | -| Test.kt:4:13:79:2 | { ... } | 16 | Test.kt:11:7:11:7 | x | -| Test.kt:4:13:79:2 | { ... } | 17 | Test.kt:11:11:11:11 | 0 | -| Test.kt:4:13:79:2 | { ... } | 18 | Test.kt:11:7:11:11 | ... > ... | -| Test.kt:11:3:16:3 | ... -> ... | 0 | Test.kt:11:3:16:3 | ... -> ... | -| Test.kt:11:3:16:3 | ... -> ... | 1 | Test.kt:11:3:16:3 | true | -| Test.kt:11:3:16:3 | ... -> ... | 2 | Test.kt:14:10:16:3 | { ... } | -| Test.kt:11:3:16:3 | ... -> ... | 3 | Test.kt:15:4:15:4 | ; | -| Test.kt:11:3:16:3 | ... -> ... | 4 | Test.kt:15:8:15:9 | 30 | -| Test.kt:11:3:16:3 | ... -> ... | 5 | Test.kt:15:4:15:9 | ...=... | -| Test.kt:11:14:14:3 | { ... } | 0 | Test.kt:11:14:14:3 | { ... } | -| Test.kt:11:14:14:3 | { ... } | 1 | Test.kt:12:4:12:4 | ; | -| Test.kt:11:14:14:3 | { ... } | 2 | Test.kt:12:8:12:9 | 20 | -| Test.kt:11:14:14:3 | { ... } | 3 | Test.kt:12:4:12:9 | ...=... | -| Test.kt:11:14:14:3 | { ... } | 4 | Test.kt:13:4:13:4 | ; | -| Test.kt:11:14:14:3 | { ... } | 5 | Test.kt:13:8:13:9 | 10 | -| Test.kt:11:14:14:3 | { ... } | 6 | Test.kt:13:4:13:9 | ...=... | -| Test.kt:18:3:18:3 | ; | 0 | Test.kt:18:3:18:3 | ; | -| Test.kt:18:3:18:3 | ; | 1 | Test.kt:18:7:18:7 | 0 | -| Test.kt:18:3:18:3 | ; | 2 | Test.kt:18:3:18:7 | ...=... | -| Test.kt:18:3:18:3 | ; | 3 | Test.kt:21:3:24:9 | ; | -| Test.kt:18:3:18:3 | ; | 4 | Test.kt:21:3:24:9 | when ... | -| Test.kt:18:3:18:3 | ; | 5 | Test.kt:21:3:24:9 | ... -> ... | -| Test.kt:18:3:18:3 | ; | 6 | Test.kt:21:6:21:6 | x | -| Test.kt:18:3:18:3 | ; | 7 | Test.kt:21:10:21:10 | 0 | -| Test.kt:18:3:18:3 | ; | 8 | Test.kt:21:6:21:10 | ... < ... | -| Test.kt:21:3:24:9 | ... -> ... | 0 | Test.kt:21:3:24:9 | ... -> ... | -| Test.kt:21:3:24:9 | ... -> ... | 1 | Test.kt:21:3:24:9 | true | -| Test.kt:21:3:24:9 | ... -> ... | 2 | Test.kt:24:4:24:9 | INSTANCE | -| Test.kt:21:3:24:9 | ... -> ... | 3 | Test.kt:24:4:24:9 | return ... | -| Test.kt:22:4:22:4 | ; | 0 | Test.kt:22:4:22:4 | ; | -| Test.kt:22:4:22:4 | ; | 1 | Test.kt:22:8:22:9 | 40 | -| Test.kt:22:4:22:4 | ; | 2 | Test.kt:22:4:22:9 | ...=... | -| Test.kt:22:4:22:4 | ; | 3 | Test.kt:27:3:27:3 | ; | -| Test.kt:22:4:22:4 | ; | 4 | Test.kt:27:7:27:8 | 10 | -| Test.kt:22:4:22:4 | ; | 5 | Test.kt:27:3:27:8 | ...=... | -| Test.kt:22:4:22:4 | ; | 6 | Test.kt:30:3:33:3 | ; | -| Test.kt:22:4:22:4 | ; | 7 | Test.kt:30:3:33:3 | when ... | -| Test.kt:22:4:22:4 | ; | 8 | Test.kt:30:3:33:3 | ... -> ... | -| Test.kt:22:4:22:4 | ; | 9 | Test.kt:30:7:30:7 | x | -| Test.kt:22:4:22:4 | ; | 10 | Test.kt:30:12:30:12 | 0 | -| Test.kt:22:4:22:4 | ; | 11 | Test.kt:30:7:30:12 | ... (value equals) ... | -| Test.kt:30:15:33:3 | { ... } | 0 | Test.kt:30:15:33:3 | { ... } | -| Test.kt:30:15:33:3 | { ... } | 1 | Test.kt:31:4:31:4 | ; | -| Test.kt:30:15:33:3 | { ... } | 2 | Test.kt:31:8:31:9 | 60 | -| Test.kt:30:15:33:3 | { ... } | 3 | Test.kt:31:4:31:9 | ...=... | -| Test.kt:30:15:33:3 | { ... } | 4 | Test.kt:32:4:32:4 | ; | -| Test.kt:30:15:33:3 | { ... } | 5 | Test.kt:32:8:32:9 | 10 | -| Test.kt:30:15:33:3 | { ... } | 6 | Test.kt:32:4:32:9 | ...=... | -| Test.kt:35:3:35:3 | ; | 0 | Test.kt:35:3:35:3 | ; | -| Test.kt:35:3:35:3 | ; | 1 | Test.kt:35:7:35:8 | 20 | -| Test.kt:35:3:35:3 | ; | 2 | Test.kt:35:3:35:8 | ...=... | -| Test.kt:35:3:35:3 | ; | 3 | Test.kt:38:3:41:3 | while (...) | -| Test.kt:38:9:38:9 | x | 0 | Test.kt:38:9:38:9 | x | -| Test.kt:38:9:38:9 | x | 1 | Test.kt:38:13:38:13 | 0 | -| Test.kt:38:9:38:9 | x | 2 | Test.kt:38:9:38:13 | ... > ... | -| Test.kt:38:16:41:3 | { ... } | 0 | Test.kt:38:16:41:3 | { ... } | -| Test.kt:38:16:41:3 | { ... } | 1 | Test.kt:39:4:39:4 | ; | -| Test.kt:38:16:41:3 | { ... } | 2 | Test.kt:39:8:39:9 | 10 | -| Test.kt:38:16:41:3 | { ... } | 3 | Test.kt:39:4:39:9 | ...=... | -| Test.kt:38:16:41:3 | { ... } | 4 | Test.kt:40:4:40:6 | ; | -| Test.kt:38:16:41:3 | { ... } | 5 | Test.kt:40:4:40:6 | | -| Test.kt:38:16:41:3 | { ... } | 6 | Test.kt:40:4:40:6 | { ... } | -| Test.kt:38:16:41:3 | { ... } | 7 | Test.kt:40:4:40:6 | var ...; | -| Test.kt:38:16:41:3 | { ... } | 8 | Test.kt:40:4:40:4 | x | -| Test.kt:38:16:41:3 | { ... } | 9 | Test.kt:40:4:40:6 | tmp0 | -| Test.kt:38:16:41:3 | { ... } | 10 | Test.kt:40:4:40:4 | ; | -| Test.kt:38:16:41:3 | { ... } | 11 | Test.kt:40:4:40:6 | tmp0 | -| Test.kt:38:16:41:3 | { ... } | 12 | Test.kt:40:4:40:6 | dec(...) | -| Test.kt:38:16:41:3 | { ... } | 13 | Test.kt:40:4:40:6 | ...=... | -| Test.kt:38:16:41:3 | { ... } | 14 | Test.kt:40:4:40:6 | ; | -| Test.kt:38:16:41:3 | { ... } | 15 | Test.kt:40:4:40:6 | tmp0 | -| Test.kt:38:16:41:3 | { ... } | 16 | Test.kt:40:4:40:6 | | -| Test.kt:43:3:43:3 | ; | 0 | Test.kt:43:3:43:3 | ; | -| Test.kt:43:3:43:3 | ; | 1 | Test.kt:43:7:43:8 | 30 | -| Test.kt:43:3:43:3 | ; | 2 | Test.kt:43:3:43:8 | ...=... | -| Test.kt:43:3:43:3 | ; | 3 | Test.kt:73:3:73:3 | ; | -| Test.kt:43:3:43:3 | ; | 4 | Test.kt:73:7:73:8 | 50 | -| Test.kt:43:3:43:3 | ; | 5 | Test.kt:73:3:73:8 | ...=... | -| Test.kt:43:3:43:3 | ; | 6 | Test.kt:77:3:77:3 | ; | -| Test.kt:43:3:43:3 | ; | 7 | Test.kt:77:7:77:8 | 40 | -| Test.kt:43:3:43:3 | ; | 8 | Test.kt:77:3:77:8 | ...=... | -| Test.kt:43:3:43:3 | ; | 9 | Test.kt:78:3:78:8 | INSTANCE | -| Test.kt:43:3:43:3 | ; | 10 | Test.kt:78:3:78:8 | return ... | -| Test.kt:82:1:89:1 | Exceptional Exit | 0 | Test.kt:82:1:89:1 | Exceptional Exit | +| Test.kt:4:2:79:2 | Normal Exit | 1 | Test.kt:4:2:79:2 | Exit | +| Test.kt:11:3:16:3 | After when ... | 0 | Test.kt:11:3:16:3 | After when ... | +| Test.kt:11:3:16:3 | After when ... | 1 | Test.kt:11:3:16:3 | After ; | +| Test.kt:11:3:16:3 | After when ... | 2 | Test.kt:18:3:18:3 | ; | +| Test.kt:11:3:16:3 | After when ... | 3 | Test.kt:18:3:18:7 | Before ...=... | +| Test.kt:11:3:16:3 | After when ... | 4 | Test.kt:18:3:18:3 | z | +| Test.kt:11:3:16:3 | After when ... | 5 | Test.kt:18:7:18:7 | 0 | +| Test.kt:11:3:16:3 | After when ... | 6 | Test.kt:18:3:18:7 | ...=... | +| Test.kt:11:3:16:3 | After when ... | 7 | Test.kt:18:3:18:7 | After ...=... | +| Test.kt:11:3:16:3 | After when ... | 8 | Test.kt:18:3:18:3 | After ; | +| Test.kt:11:3:16:3 | After when ... | 9 | Test.kt:21:3:24:9 | ; | +| Test.kt:11:3:16:3 | After when ... | 10 | Test.kt:21:3:24:9 | when ... | +| Test.kt:11:3:16:3 | After when ... | 11 | Test.kt:21:3:24:9 | ... -> ... | +| Test.kt:11:3:16:3 | After when ... | 12 | Test.kt:21:6:21:10 | Before ... < ... | +| Test.kt:11:3:16:3 | After when ... | 13 | Test.kt:21:6:21:6 | x | +| Test.kt:11:3:16:3 | After when ... | 14 | Test.kt:21:10:21:10 | 0 | +| Test.kt:11:3:16:3 | After when ... | 15 | Test.kt:21:6:21:10 | ... < ... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 0 | Test.kt:11:7:11:11 | After ... > ... [false] | +| Test.kt:11:7:11:11 | After ... > ... [false] | 1 | Test.kt:11:3:16:3 | ... -> ... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 2 | Test.kt:11:3:16:3 | true | +| Test.kt:11:7:11:11 | After ... > ... [false] | 3 | Test.kt:11:3:16:3 | After true [true] | +| Test.kt:11:7:11:11 | After ... > ... [false] | 4 | Test.kt:14:10:16:3 | { ... } | +| Test.kt:11:7:11:11 | After ... > ... [false] | 5 | Test.kt:15:4:15:4 | ; | +| Test.kt:11:7:11:11 | After ... > ... [false] | 6 | Test.kt:15:4:15:9 | Before ...=... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 7 | Test.kt:15:4:15:4 | y | +| Test.kt:11:7:11:11 | After ... > ... [false] | 8 | Test.kt:15:8:15:9 | 30 | +| Test.kt:11:7:11:11 | After ... > ... [false] | 9 | Test.kt:15:4:15:9 | ...=... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 10 | Test.kt:15:4:15:9 | After ...=... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 11 | Test.kt:15:4:15:4 | After ; | +| Test.kt:11:7:11:11 | After ... > ... [false] | 12 | Test.kt:14:10:16:3 | After { ... } | +| Test.kt:11:7:11:11 | After ... > ... [true] | 0 | Test.kt:11:7:11:11 | After ... > ... [true] | +| Test.kt:11:7:11:11 | After ... > ... [true] | 1 | Test.kt:11:14:14:3 | { ... } | +| Test.kt:11:7:11:11 | After ... > ... [true] | 2 | Test.kt:12:4:12:4 | ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 3 | Test.kt:12:4:12:9 | Before ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 4 | Test.kt:12:4:12:4 | y | +| Test.kt:11:7:11:11 | After ... > ... [true] | 5 | Test.kt:12:8:12:9 | 20 | +| Test.kt:11:7:11:11 | After ... > ... [true] | 6 | Test.kt:12:4:12:9 | ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 7 | Test.kt:12:4:12:9 | After ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 8 | Test.kt:12:4:12:4 | After ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 9 | Test.kt:13:4:13:4 | ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 10 | Test.kt:13:4:13:9 | Before ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 11 | Test.kt:13:4:13:4 | z | +| Test.kt:11:7:11:11 | After ... > ... [true] | 12 | Test.kt:13:8:13:9 | 10 | +| Test.kt:11:7:11:11 | After ... > ... [true] | 13 | Test.kt:13:4:13:9 | ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 14 | Test.kt:13:4:13:9 | After ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 15 | Test.kt:13:4:13:4 | After ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 16 | Test.kt:11:14:14:3 | After { ... } | +| Test.kt:21:6:21:10 | After ... < ... [false] | 0 | Test.kt:21:6:21:10 | After ... < ... [false] | +| Test.kt:21:6:21:10 | After ... < ... [false] | 1 | Test.kt:21:3:24:9 | ... -> ... | +| Test.kt:21:6:21:10 | After ... < ... [false] | 2 | Test.kt:21:3:24:9 | true | +| Test.kt:21:6:21:10 | After ... < ... [false] | 3 | Test.kt:21:3:24:9 | After true [true] | +| Test.kt:21:6:21:10 | After ... < ... [false] | 4 | Test.kt:24:4:24:9 | Before return ... | +| Test.kt:21:6:21:10 | After ... < ... [false] | 5 | Test.kt:24:4:24:9 | INSTANCE | +| Test.kt:21:6:21:10 | After ... < ... [false] | 6 | Test.kt:24:4:24:9 | return ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 0 | Test.kt:21:6:21:10 | After ... < ... [true] | +| Test.kt:21:6:21:10 | After ... < ... [true] | 1 | Test.kt:22:4:22:4 | ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 2 | Test.kt:22:4:22:9 | Before ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 3 | Test.kt:22:4:22:4 | y | +| Test.kt:21:6:21:10 | After ... < ... [true] | 4 | Test.kt:22:8:22:9 | 40 | +| Test.kt:21:6:21:10 | After ... < ... [true] | 5 | Test.kt:22:4:22:9 | ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 6 | Test.kt:22:4:22:9 | After ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 7 | Test.kt:22:4:22:4 | After ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 8 | Test.kt:21:3:24:9 | After when ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 9 | Test.kt:21:3:24:9 | After ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 10 | Test.kt:27:3:27:3 | ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 11 | Test.kt:27:3:27:8 | Before ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 12 | Test.kt:27:3:27:3 | z | +| Test.kt:21:6:21:10 | After ... < ... [true] | 13 | Test.kt:27:7:27:8 | 10 | +| Test.kt:21:6:21:10 | After ... < ... [true] | 14 | Test.kt:27:3:27:8 | ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 15 | Test.kt:27:3:27:8 | After ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 16 | Test.kt:27:3:27:3 | After ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 17 | Test.kt:30:3:33:3 | ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 18 | Test.kt:30:3:33:3 | when ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 19 | Test.kt:30:3:33:3 | ... -> ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 20 | Test.kt:30:7:30:12 | Before ... (value equals) ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 21 | Test.kt:30:7:30:7 | x | +| Test.kt:21:6:21:10 | After ... < ... [true] | 22 | Test.kt:30:12:30:12 | 0 | +| Test.kt:21:6:21:10 | After ... < ... [true] | 23 | Test.kt:30:7:30:12 | ... (value equals) ... | +| Test.kt:30:3:33:3 | After when ... | 0 | Test.kt:30:3:33:3 | After when ... | +| Test.kt:30:3:33:3 | After when ... | 1 | Test.kt:30:3:33:3 | After ; | +| Test.kt:30:3:33:3 | After when ... | 2 | Test.kt:35:3:35:3 | ; | +| Test.kt:30:3:33:3 | After when ... | 3 | Test.kt:35:3:35:8 | Before ...=... | +| Test.kt:30:3:33:3 | After when ... | 4 | Test.kt:35:3:35:3 | z | +| Test.kt:30:3:33:3 | After when ... | 5 | Test.kt:35:7:35:8 | 20 | +| Test.kt:30:3:33:3 | After when ... | 6 | Test.kt:35:3:35:8 | ...=... | +| Test.kt:30:3:33:3 | After when ... | 7 | Test.kt:35:3:35:8 | After ...=... | +| Test.kt:30:3:33:3 | After when ... | 8 | Test.kt:35:3:35:3 | After ; | +| Test.kt:30:3:33:3 | After when ... | 9 | Test.kt:38:3:41:3 | while (...) | +| Test.kt:30:7:30:12 | After ... (value equals) ... [false] | 0 | Test.kt:30:7:30:12 | After ... (value equals) ... [false] | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 0 | Test.kt:30:7:30:12 | After ... (value equals) ... [true] | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 1 | Test.kt:30:15:33:3 | { ... } | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 2 | Test.kt:31:4:31:4 | ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 3 | Test.kt:31:4:31:9 | Before ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 4 | Test.kt:31:4:31:4 | y | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 5 | Test.kt:31:8:31:9 | 60 | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 6 | Test.kt:31:4:31:9 | ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 7 | Test.kt:31:4:31:9 | After ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 8 | Test.kt:31:4:31:4 | After ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 9 | Test.kt:32:4:32:4 | ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 10 | Test.kt:32:4:32:9 | Before ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 11 | Test.kt:32:4:32:4 | z | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 12 | Test.kt:32:8:32:9 | 10 | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 13 | Test.kt:32:4:32:9 | ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 14 | Test.kt:32:4:32:9 | After ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 15 | Test.kt:32:4:32:4 | After ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 16 | Test.kt:30:15:33:3 | After { ... } | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 0 | Test.kt:38:3:41:3 | [LoopHeader] while (...) | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 1 | Test.kt:38:9:38:13 | Before ... > ... | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 2 | Test.kt:38:9:38:9 | x | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 3 | Test.kt:38:13:38:13 | 0 | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 4 | Test.kt:38:9:38:13 | ... > ... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 0 | Test.kt:38:9:38:13 | After ... > ... [false] | +| Test.kt:38:9:38:13 | After ... > ... [false] | 1 | Test.kt:38:3:41:3 | After while (...) | +| Test.kt:38:9:38:13 | After ... > ... [false] | 2 | Test.kt:43:3:43:3 | ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 3 | Test.kt:43:3:43:8 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 4 | Test.kt:43:3:43:3 | z | +| Test.kt:38:9:38:13 | After ... > ... [false] | 5 | Test.kt:43:7:43:8 | 30 | +| Test.kt:38:9:38:13 | After ... > ... [false] | 6 | Test.kt:43:3:43:8 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 7 | Test.kt:43:3:43:8 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 8 | Test.kt:43:3:43:3 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 9 | Test.kt:73:3:73:3 | ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 10 | Test.kt:73:3:73:8 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 11 | Test.kt:73:3:73:3 | z | +| Test.kt:38:9:38:13 | After ... > ... [false] | 12 | Test.kt:73:7:73:8 | 50 | +| Test.kt:38:9:38:13 | After ... > ... [false] | 13 | Test.kt:73:3:73:8 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 14 | Test.kt:73:3:73:8 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 15 | Test.kt:73:3:73:3 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 16 | Test.kt:77:3:77:3 | ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 17 | Test.kt:77:3:77:8 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 18 | Test.kt:77:3:77:3 | w | +| Test.kt:38:9:38:13 | After ... > ... [false] | 19 | Test.kt:77:7:77:8 | 40 | +| Test.kt:38:9:38:13 | After ... > ... [false] | 20 | Test.kt:77:3:77:8 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 21 | Test.kt:77:3:77:8 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 22 | Test.kt:77:3:77:3 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 23 | Test.kt:78:3:78:8 | Before return ... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 24 | Test.kt:78:3:78:8 | INSTANCE | +| Test.kt:38:9:38:13 | After ... > ... [false] | 25 | Test.kt:78:3:78:8 | return ... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 0 | Test.kt:38:9:38:13 | After ... > ... [true] | +| Test.kt:38:9:38:13 | After ... > ... [true] | 1 | Test.kt:38:16:41:3 | { ... } | +| Test.kt:38:9:38:13 | After ... > ... [true] | 2 | Test.kt:39:4:39:4 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 3 | Test.kt:39:4:39:9 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 4 | Test.kt:39:4:39:4 | y | +| Test.kt:38:9:38:13 | After ... > ... [true] | 5 | Test.kt:39:8:39:9 | 10 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 6 | Test.kt:39:4:39:9 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 7 | Test.kt:39:4:39:9 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 8 | Test.kt:39:4:39:4 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 9 | Test.kt:40:4:40:6 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 10 | Test.kt:40:4:40:6 | Before | +| Test.kt:38:9:38:13 | After ... > ... [true] | 11 | Test.kt:40:4:40:6 | Before | +| Test.kt:38:9:38:13 | After ... > ... [true] | 12 | Test.kt:40:4:40:6 | { ... } | +| Test.kt:38:9:38:13 | After ... > ... [true] | 13 | Test.kt:40:4:40:6 | var ...; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 14 | Test.kt:40:4:40:6 | Before tmp0 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 15 | Test.kt:40:4:40:4 | x | +| Test.kt:38:9:38:13 | After ... > ... [true] | 16 | Test.kt:40:4:40:6 | tmp0 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 17 | Test.kt:40:4:40:6 | After tmp0 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 18 | Test.kt:40:4:40:6 | After var ...; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 19 | Test.kt:40:4:40:4 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 20 | Test.kt:40:4:40:6 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 21 | Test.kt:40:4:40:4 | x | +| Test.kt:38:9:38:13 | After ... > ... [true] | 22 | Test.kt:40:4:40:6 | Before dec(...) | +| Test.kt:38:9:38:13 | After ... > ... [true] | 23 | Test.kt:40:4:40:6 | tmp0 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 24 | Test.kt:40:4:40:6 | dec(...) | +| Test.kt:38:9:38:13 | After ... > ... [true] | 25 | Test.kt:40:4:40:6 | After dec(...) | +| Test.kt:38:9:38:13 | After ... > ... [true] | 26 | Test.kt:40:4:40:6 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 27 | Test.kt:40:4:40:6 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 28 | Test.kt:40:4:40:4 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 29 | Test.kt:40:4:40:6 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 30 | Test.kt:40:4:40:6 | tmp0 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 31 | Test.kt:40:4:40:6 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 32 | Test.kt:40:4:40:6 | After { ... } | +| Test.kt:38:9:38:13 | After ... > ... [true] | 33 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 34 | Test.kt:40:4:40:6 | After | +| Test.kt:38:9:38:13 | After ... > ... [true] | 35 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 36 | Test.kt:40:4:40:6 | After | +| Test.kt:38:9:38:13 | After ... > ... [true] | 37 | Test.kt:40:4:40:6 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 38 | Test.kt:38:16:41:3 | After { ... } | +| Test.kt:82:1:89:1 | Entry | 0 | Test.kt:82:1:89:1 | Entry | +| Test.kt:82:1:89:1 | Entry | 1 | Test.kt:82:21:89:1 | { ... } | +| Test.kt:82:1:89:1 | Entry | 2 | Test.kt:83:2:88:2 | try ... | +| Test.kt:82:1:89:1 | Entry | 3 | Test.kt:83:6:86:2 | { ... } | +| Test.kt:82:1:89:1 | Entry | 4 | Test.kt:84:7:84:7 | var ...; | +| Test.kt:82:1:89:1 | Entry | 5 | Test.kt:84:7:84:7 | Before x | +| Test.kt:82:1:89:1 | Entry | 6 | Test.kt:84:11:84:18 | Before (...)... | +| Test.kt:82:1:89:1 | Entry | 7 | Test.kt:84:11:84:11 | o | +| Test.kt:82:1:89:1 | Entry | 8 | Test.kt:84:11:84:18 | (...)... | | Test.kt:82:1:89:1 | Exit | 0 | Test.kt:82:1:89:1 | Exit | | Test.kt:82:1:89:1 | Normal Exit | 0 | Test.kt:82:1:89:1 | Normal Exit | -| Test.kt:82:21:89:1 | { ... } | 0 | Test.kt:82:21:89:1 | { ... } | -| Test.kt:82:21:89:1 | { ... } | 1 | Test.kt:83:2:88:2 | try ... | -| Test.kt:82:21:89:1 | { ... } | 2 | Test.kt:83:6:86:2 | { ... } | -| Test.kt:82:21:89:1 | { ... } | 3 | Test.kt:84:7:84:7 | var ...; | -| Test.kt:82:21:89:1 | { ... } | 4 | Test.kt:84:11:84:11 | o | -| Test.kt:82:21:89:1 | { ... } | 5 | Test.kt:84:11:84:18 | (...)... | -| Test.kt:84:7:84:7 | x | 0 | Test.kt:84:7:84:7 | x | -| Test.kt:84:7:84:7 | x | 1 | Test.kt:85:10:85:10 | 1 | -| Test.kt:84:7:84:7 | x | 2 | Test.kt:85:3:85:10 | return ... | +| Test.kt:84:11:84:18 | After (...)... | 0 | Test.kt:84:11:84:18 | After (...)... | +| Test.kt:84:11:84:18 | After (...)... | 1 | Test.kt:84:7:84:7 | x | +| Test.kt:84:11:84:18 | After (...)... | 2 | Test.kt:84:7:84:7 | After x | +| Test.kt:84:11:84:18 | After (...)... | 3 | Test.kt:84:7:84:7 | After var ...; | +| Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... | +| Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 | +| Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... | +| Test.kt:86:4:88:2 | After catch (...) [match] | 0 | Test.kt:86:4:88:2 | After catch (...) [match] | +| Test.kt:86:4:88:2 | After catch (...) [match] | 1 | Test.kt:86:11:86:31 | e | +| Test.kt:86:4:88:2 | After catch (...) [match] | 2 | Test.kt:86:34:88:2 | { ... } | +| Test.kt:86:4:88:2 | After catch (...) [match] | 3 | Test.kt:87:3:87:10 | Before return ... | +| Test.kt:86:4:88:2 | After catch (...) [match] | 4 | Test.kt:87:10:87:10 | 2 | +| Test.kt:86:4:88:2 | After catch (...) [match] | 5 | Test.kt:87:3:87:10 | return ... | +| Test.kt:86:4:88:2 | After catch (...) [no-match] | 0 | Test.kt:86:4:88:2 | After catch (...) [no-match] | +| Test.kt:86:4:88:2 | After catch (...) [no-match] | 1 | Test.kt:82:1:89:1 | Exceptional Exit | | Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) | -| Test.kt:86:4:88:2 | catch (...) | 1 | Test.kt:86:11:86:31 | e | -| Test.kt:86:4:88:2 | catch (...) | 2 | Test.kt:86:34:88:2 | { ... } | -| Test.kt:86:4:88:2 | catch (...) | 3 | Test.kt:87:10:87:10 | 2 | -| Test.kt:86:4:88:2 | catch (...) | 4 | Test.kt:87:3:87:10 | return ... | -| Test.kt:91:1:98:1 | Exceptional Exit | 0 | Test.kt:91:1:98:1 | Exceptional Exit | +| Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry | +| Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } | +| Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... | +| Test.kt:91:1:98:1 | Entry | 3 | Test.kt:92:6:95:2 | { ... } | +| Test.kt:91:1:98:1 | Entry | 4 | Test.kt:93:7:93:7 | var ...; | +| Test.kt:91:1:98:1 | Entry | 5 | Test.kt:93:7:93:7 | Before x | +| Test.kt:91:1:98:1 | Entry | 6 | Test.kt:93:12:93:13 | Before ...!! | +| Test.kt:91:1:98:1 | Entry | 7 | Test.kt:93:11:93:11 | o | +| Test.kt:91:1:98:1 | Entry | 8 | Test.kt:93:12:93:13 | ...!! | | Test.kt:91:1:98:1 | Exit | 0 | Test.kt:91:1:98:1 | Exit | | Test.kt:91:1:98:1 | Normal Exit | 0 | Test.kt:91:1:98:1 | Normal Exit | -| Test.kt:91:22:98:1 | { ... } | 0 | Test.kt:91:22:98:1 | { ... } | -| Test.kt:91:22:98:1 | { ... } | 1 | Test.kt:92:2:97:2 | try ... | -| Test.kt:91:22:98:1 | { ... } | 2 | Test.kt:92:6:95:2 | { ... } | -| Test.kt:91:22:98:1 | { ... } | 3 | Test.kt:93:7:93:7 | var ...; | -| Test.kt:91:22:98:1 | { ... } | 4 | Test.kt:93:11:93:11 | o | -| Test.kt:91:22:98:1 | { ... } | 5 | Test.kt:93:12:93:13 | ...!! | -| Test.kt:93:7:93:7 | x | 0 | Test.kt:93:7:93:7 | x | -| Test.kt:93:7:93:7 | x | 1 | Test.kt:94:10:94:10 | 1 | -| Test.kt:93:7:93:7 | x | 2 | Test.kt:94:3:94:10 | return ... | +| Test.kt:93:12:93:13 | After ...!! | 0 | Test.kt:93:12:93:13 | After ...!! | +| Test.kt:93:12:93:13 | After ...!! | 1 | Test.kt:93:7:93:7 | x | +| Test.kt:93:12:93:13 | After ...!! | 2 | Test.kt:93:7:93:7 | After x | +| Test.kt:93:12:93:13 | After ...!! | 3 | Test.kt:93:7:93:7 | After var ...; | +| Test.kt:93:12:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... | +| Test.kt:93:12:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 | +| Test.kt:93:12:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... | +| Test.kt:95:4:97:2 | After catch (...) [match] | 0 | Test.kt:95:4:97:2 | After catch (...) [match] | +| Test.kt:95:4:97:2 | After catch (...) [match] | 1 | Test.kt:95:11:95:33 | e | +| Test.kt:95:4:97:2 | After catch (...) [match] | 2 | Test.kt:95:36:97:2 | { ... } | +| Test.kt:95:4:97:2 | After catch (...) [match] | 3 | Test.kt:96:3:96:10 | Before return ... | +| Test.kt:95:4:97:2 | After catch (...) [match] | 4 | Test.kt:96:10:96:10 | 2 | +| Test.kt:95:4:97:2 | After catch (...) [match] | 5 | Test.kt:96:3:96:10 | return ... | +| Test.kt:95:4:97:2 | After catch (...) [no-match] | 0 | Test.kt:95:4:97:2 | After catch (...) [no-match] | +| Test.kt:95:4:97:2 | After catch (...) [no-match] | 1 | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) | -| Test.kt:95:4:97:2 | catch (...) | 1 | Test.kt:95:11:95:33 | e | -| Test.kt:95:4:97:2 | catch (...) | 2 | Test.kt:95:36:97:2 | { ... } | -| Test.kt:95:4:97:2 | catch (...) | 3 | Test.kt:96:10:96:10 | 2 | -| Test.kt:95:4:97:2 | catch (...) | 4 | Test.kt:96:3:96:10 | return ... | +| Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry | +| Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } | +| Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | ; | +| Test.kt:100:1:110:1 | Entry | 3 | Test.kt:101:5:103:5 | when ... | +| Test.kt:100:1:110:1 | Entry | 4 | Test.kt:101:5:103:5 | ... -> ... | +| Test.kt:100:1:110:1 | Entry | 5 | Test.kt:101:9:101:30 | ... && ... | +| Test.kt:100:1:110:1 | Entry | 6 | Test.kt:101:9:101:17 | Before ... (value equals) ... | +| Test.kt:100:1:110:1 | Entry | 7 | Test.kt:101:9:101:9 | x | +| Test.kt:100:1:110:1 | Entry | 8 | Test.kt:101:14:101:17 | null | +| Test.kt:100:1:110:1 | Entry | 9 | Test.kt:101:9:101:17 | ... (value equals) ... | | Test.kt:100:1:110:1 | Exit | 0 | Test.kt:100:1:110:1 | Exit | -| Test.kt:100:1:110:1 | Normal Exit | 0 | Test.kt:100:1:110:1 | Normal Exit | -| Test.kt:100:25:110:1 | { ... } | 0 | Test.kt:100:25:110:1 | { ... } | -| Test.kt:100:25:110:1 | { ... } | 1 | Test.kt:101:5:103:5 | ; | -| Test.kt:100:25:110:1 | { ... } | 2 | Test.kt:101:5:103:5 | when ... | -| Test.kt:100:25:110:1 | { ... } | 3 | Test.kt:101:5:103:5 | ... -> ... | -| Test.kt:100:25:110:1 | { ... } | 4 | Test.kt:101:9:101:30 | ... && ... | -| Test.kt:100:25:110:1 | { ... } | 5 | Test.kt:101:9:101:9 | x | -| Test.kt:100:25:110:1 | { ... } | 6 | Test.kt:101:14:101:17 | null | -| Test.kt:100:25:110:1 | { ... } | 7 | Test.kt:101:9:101:17 | ... (value equals) ... | -| Test.kt:101:22:101:22 | y | 0 | Test.kt:101:22:101:22 | y | -| Test.kt:101:22:101:22 | y | 1 | Test.kt:101:27:101:30 | null | -| Test.kt:101:22:101:22 | y | 2 | Test.kt:101:22:101:30 | ... (value equals) ... | -| Test.kt:101:33:103:5 | { ... } | 0 | Test.kt:101:33:103:5 | { ... } | -| Test.kt:101:33:103:5 | { ... } | 1 | Test.kt:102:15:102:25 | new Exception(...) | -| Test.kt:101:33:103:5 | { ... } | 2 | Test.kt:102:9:102:25 | throw ... | -| Test.kt:101:33:103:5 | { ... } | 3 | Test.kt:100:1:110:1 | Exceptional Exit | -| Test.kt:105:5:109:5 | ; | 0 | Test.kt:105:5:109:5 | ; | -| Test.kt:105:5:109:5 | ; | 1 | Test.kt:105:5:109:5 | when ... | -| Test.kt:105:5:109:5 | ; | 2 | Test.kt:105:9:107:5 | ... -> ... | -| Test.kt:105:5:109:5 | ; | 3 | Test.kt:105:9:105:9 | x | -| Test.kt:105:5:109:5 | ; | 4 | Test.kt:105:14:105:17 | null | -| Test.kt:105:5:109:5 | ; | 5 | Test.kt:105:9:105:17 | ... (value not-equals) ... | -| Test.kt:105:20:107:5 | { ... } | 0 | Test.kt:105:20:107:5 | { ... } | -| Test.kt:105:20:107:5 | { ... } | 1 | Test.kt:106:9:106:29 | ; | -| Test.kt:105:20:107:5 | { ... } | 2 | Test.kt:106:17:106:28 | "x not null" | -| Test.kt:105:20:107:5 | { ... } | 3 | Test.kt:106:9:106:29 | println(...) | -| Test.kt:107:16:109:5 | ... -> ... | 0 | Test.kt:107:16:109:5 | ... -> ... | -| Test.kt:107:16:109:5 | ... -> ... | 1 | Test.kt:107:16:107:16 | y | -| Test.kt:107:16:109:5 | ... -> ... | 2 | Test.kt:107:21:107:24 | null | -| Test.kt:107:16:109:5 | ... -> ... | 3 | Test.kt:107:16:107:24 | ... (value not-equals) ... | -| Test.kt:107:27:109:5 | { ... } | 0 | Test.kt:107:27:109:5 | { ... } | -| Test.kt:107:27:109:5 | { ... } | 1 | Test.kt:108:9:108:29 | ; | -| Test.kt:107:27:109:5 | { ... } | 2 | Test.kt:108:17:108:28 | "y not null" | -| Test.kt:107:27:109:5 | { ... } | 3 | Test.kt:108:9:108:29 | println(...) | -| Test.kt:112:1:116:1 | Exceptional Exit | 0 | Test.kt:112:1:116:1 | Exceptional Exit | -| Test.kt:112:1:116:1 | Exit | 0 | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:1:116:1 | Normal Exit | 0 | Test.kt:112:1:116:1 | Normal Exit | -| Test.kt:112:32:116:1 | { ... } | 0 | Test.kt:112:32:116:1 | { ... } | -| Test.kt:112:32:116:1 | { ... } | 1 | Test.kt:113:5:115:5 | ; | -| Test.kt:112:32:116:1 | { ... } | 2 | Test.kt:113:5:115:5 | when ... | -| Test.kt:112:32:116:1 | { ... } | 3 | Test.kt:113:5:115:5 | ... -> ... | -| Test.kt:112:32:116:1 | { ... } | 4 | Test.kt:113:9:113:14 | ... && ... | -| Test.kt:112:32:116:1 | { ... } | 5 | Test.kt:113:9:113:9 | x | -| Test.kt:113:14:113:14 | y | 0 | Test.kt:113:14:113:14 | y | -| Test.kt:113:17:115:5 | { ... } | 0 | Test.kt:113:17:115:5 | { ... } | -| Test.kt:118:1:124:1 | Exceptional Exit | 0 | Test.kt:118:1:124:1 | Exceptional Exit | -| Test.kt:118:1:124:1 | Exit | 0 | Test.kt:118:1:124:1 | Exit | -| Test.kt:118:1:124:1 | Normal Exit | 0 | Test.kt:118:1:124:1 | Normal Exit | -| Test.kt:118:37:124:1 | { ... } | 0 | Test.kt:118:37:124:1 | { ... } | -| Test.kt:118:37:124:1 | { ... } | 1 | Test.kt:119:2:123:12 | ; | -| Test.kt:118:37:124:1 | { ... } | 2 | Test.kt:119:2:123:12 | when ... | -| Test.kt:118:37:124:1 | { ... } | 3 | Test.kt:120:3:123:10 | ... -> ... | -| Test.kt:118:37:124:1 | { ... } | 4 | Test.kt:120:3:123:3 | when ... | -| Test.kt:118:37:124:1 | { ... } | 5 | Test.kt:121:4:121:9 | ... -> ... | -| Test.kt:118:37:124:1 | { ... } | 6 | Test.kt:121:4:121:4 | x | -| Test.kt:121:9:121:9 | ; | 0 | Test.kt:121:9:121:9 | ; | -| Test.kt:121:9:121:9 | ; | 1 | Test.kt:121:9:121:9 | y | -| Test.kt:122:12:122:16 | ... -> ... | 0 | Test.kt:122:12:122:16 | ... -> ... | -| Test.kt:122:12:122:16 | ... -> ... | 1 | Test.kt:122:12:122:16 | true | -| Test.kt:122:12:122:16 | ... -> ... | 2 | Test.kt:122:12:122:16 | ; | -| Test.kt:122:12:122:16 | ... -> ... | 3 | Test.kt:122:12:122:16 | false | -| Test.kt:123:8:123:10 | { ... } | 0 | Test.kt:123:8:123:10 | { ... } | +| Test.kt:101:9:101:17 | After ... (value equals) ... [false] | 0 | Test.kt:101:9:101:17 | After ... (value equals) ... [false] | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 0 | Test.kt:101:9:101:17 | After ... (value equals) ... [true] | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 1 | Test.kt:101:22:101:30 | Before ... (value equals) ... | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 2 | Test.kt:101:22:101:22 | y | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 3 | Test.kt:101:27:101:30 | null | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 4 | Test.kt:101:22:101:30 | ... (value equals) ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 0 | Test.kt:101:9:101:30 | After ... && ... [false] | +| Test.kt:101:9:101:30 | After ... && ... [false] | 1 | Test.kt:101:5:103:5 | After when ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 2 | Test.kt:101:5:103:5 | After ; | +| Test.kt:101:9:101:30 | After ... && ... [false] | 3 | Test.kt:105:5:109:5 | ; | +| Test.kt:101:9:101:30 | After ... && ... [false] | 4 | Test.kt:105:5:109:5 | when ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 5 | Test.kt:105:9:107:5 | ... -> ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 6 | Test.kt:105:9:105:17 | Before ... (value not-equals) ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 7 | Test.kt:105:9:105:9 | x | +| Test.kt:101:9:101:30 | After ... && ... [false] | 8 | Test.kt:105:14:105:17 | null | +| Test.kt:101:9:101:30 | After ... && ... [false] | 9 | Test.kt:105:9:105:17 | ... (value not-equals) ... | +| Test.kt:101:22:101:30 | After ... (value equals) ... [false] | 0 | Test.kt:101:22:101:30 | After ... (value equals) ... [false] | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 0 | Test.kt:101:22:101:30 | After ... (value equals) ... [true] | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 1 | Test.kt:101:9:101:30 | After ... && ... [true] | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 2 | Test.kt:101:33:103:5 | { ... } | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 3 | Test.kt:102:9:102:25 | Before throw ... | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 4 | Test.kt:102:15:102:25 | Before new Exception(...) | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 5 | Test.kt:102:15:102:25 | new Exception(...) | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 6 | Test.kt:102:15:102:25 | After new Exception(...) | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 7 | Test.kt:102:9:102:25 | throw ... | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 8 | Test.kt:100:1:110:1 | Exceptional Exit | +| Test.kt:105:5:109:5 | After when ... | 0 | Test.kt:105:5:109:5 | After when ... | +| Test.kt:105:5:109:5 | After when ... | 1 | Test.kt:105:5:109:5 | After ; | +| Test.kt:105:5:109:5 | After when ... | 2 | Test.kt:100:25:110:1 | After { ... } | +| Test.kt:105:5:109:5 | After when ... | 3 | Test.kt:100:1:110:1 | Normal Exit | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 0 | Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 1 | Test.kt:107:16:109:5 | ... -> ... | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 2 | Test.kt:107:16:107:24 | Before ... (value not-equals) ... | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 3 | Test.kt:107:16:107:16 | y | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 4 | Test.kt:107:21:107:24 | null | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 5 | Test.kt:107:16:107:24 | ... (value not-equals) ... | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 0 | Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 1 | Test.kt:105:20:107:5 | { ... } | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 2 | Test.kt:106:9:106:29 | ; | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 3 | Test.kt:106:9:106:29 | Before println(...) | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 4 | Test.kt:106:17:106:28 | "x not null" | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 5 | Test.kt:106:9:106:29 | println(...) | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 6 | Test.kt:106:9:106:29 | After println(...) | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 7 | Test.kt:106:9:106:29 | After ; | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 8 | Test.kt:105:20:107:5 | After { ... } | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | 0 | Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 0 | Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 1 | Test.kt:107:27:109:5 | { ... } | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 2 | Test.kt:108:9:108:29 | ; | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 3 | Test.kt:108:9:108:29 | Before println(...) | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 4 | Test.kt:108:17:108:28 | "y not null" | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 5 | Test.kt:108:9:108:29 | println(...) | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 6 | Test.kt:108:9:108:29 | After println(...) | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 7 | Test.kt:108:9:108:29 | After ; | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 8 | Test.kt:107:27:109:5 | After { ... } | +| Test.kt:112:1:116:1 | Entry | 0 | Test.kt:112:1:116:1 | Entry | +| Test.kt:112:1:116:1 | Entry | 1 | Test.kt:112:32:116:1 | { ... } | +| Test.kt:112:1:116:1 | Entry | 2 | Test.kt:113:5:115:5 | ; | +| Test.kt:112:1:116:1 | Entry | 3 | Test.kt:113:5:115:5 | when ... | +| Test.kt:112:1:116:1 | Entry | 4 | Test.kt:113:5:115:5 | ... -> ... | +| Test.kt:112:1:116:1 | Entry | 5 | Test.kt:113:9:113:14 | ... && ... | +| Test.kt:112:1:116:1 | Entry | 6 | Test.kt:113:9:113:9 | x | +| Test.kt:113:5:115:5 | After when ... | 0 | Test.kt:113:5:115:5 | After when ... | +| Test.kt:113:5:115:5 | After when ... | 1 | Test.kt:113:5:115:5 | After ; | +| Test.kt:113:5:115:5 | After when ... | 2 | Test.kt:112:32:116:1 | After { ... } | +| Test.kt:113:5:115:5 | After when ... | 3 | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:113:5:115:5 | After when ... | 4 | Test.kt:112:1:116:1 | Exit | +| Test.kt:113:9:113:9 | After x [false] | 0 | Test.kt:113:9:113:9 | After x [false] | +| Test.kt:113:9:113:9 | After x [true] | 0 | Test.kt:113:9:113:9 | After x [true] | +| Test.kt:113:9:113:9 | After x [true] | 1 | Test.kt:113:14:113:14 | y | +| Test.kt:113:9:113:14 | After ... && ... [false] | 0 | Test.kt:113:9:113:14 | After ... && ... [false] | +| Test.kt:113:14:113:14 | After y [false] | 0 | Test.kt:113:14:113:14 | After y [false] | +| Test.kt:113:14:113:14 | After y [true] | 0 | Test.kt:113:14:113:14 | After y [true] | +| Test.kt:113:14:113:14 | After y [true] | 1 | Test.kt:113:9:113:14 | After ... && ... [true] | +| Test.kt:113:14:113:14 | After y [true] | 2 | Test.kt:113:17:115:5 | { ... } | +| Test.kt:118:1:124:1 | Entry | 0 | Test.kt:118:1:124:1 | Entry | +| Test.kt:118:1:124:1 | Entry | 1 | Test.kt:118:37:124:1 | { ... } | +| Test.kt:118:1:124:1 | Entry | 2 | Test.kt:119:2:123:12 | ; | +| Test.kt:118:1:124:1 | Entry | 3 | Test.kt:119:2:123:12 | when ... | +| Test.kt:118:1:124:1 | Entry | 4 | Test.kt:120:3:123:10 | ... -> ... | +| Test.kt:118:1:124:1 | Entry | 5 | Test.kt:120:3:123:3 | when ... | +| Test.kt:118:1:124:1 | Entry | 6 | Test.kt:121:4:121:9 | ... -> ... | +| Test.kt:118:1:124:1 | Entry | 7 | Test.kt:121:4:121:4 | x | +| Test.kt:119:2:123:12 | After when ... | 0 | Test.kt:119:2:123:12 | After when ... | +| Test.kt:119:2:123:12 | After when ... | 1 | Test.kt:119:2:123:12 | After ; | +| Test.kt:119:2:123:12 | After when ... | 2 | Test.kt:118:37:124:1 | After { ... } | +| Test.kt:119:2:123:12 | After when ... | 3 | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:119:2:123:12 | After when ... | 4 | Test.kt:118:1:124:1 | Exit | +| Test.kt:120:3:123:3 | After when ... [false] | 0 | Test.kt:120:3:123:3 | After when ... [false] | +| Test.kt:120:3:123:3 | After when ... [true] | 0 | Test.kt:120:3:123:3 | After when ... [true] | +| Test.kt:120:3:123:3 | After when ... [true] | 1 | Test.kt:123:8:123:10 | { ... } | +| Test.kt:121:4:121:4 | After x [false] | 0 | Test.kt:121:4:121:4 | After x [false] | +| Test.kt:121:4:121:4 | After x [false] | 1 | Test.kt:122:12:122:16 | ... -> ... | +| Test.kt:121:4:121:4 | After x [false] | 2 | Test.kt:122:12:122:16 | true | +| Test.kt:121:4:121:4 | After x [false] | 3 | Test.kt:122:12:122:16 | After true [true] | +| Test.kt:121:4:121:4 | After x [false] | 4 | Test.kt:122:12:122:16 | ; | +| Test.kt:121:4:121:4 | After x [false] | 5 | Test.kt:122:12:122:16 | false | +| Test.kt:121:4:121:4 | After x [false] | 6 | Test.kt:122:12:122:16 | After ; | +| Test.kt:121:4:121:4 | After x [true] | 0 | Test.kt:121:4:121:4 | After x [true] | +| Test.kt:121:4:121:4 | After x [true] | 1 | Test.kt:121:9:121:9 | ; | +| Test.kt:121:4:121:4 | After x [true] | 2 | Test.kt:121:9:121:9 | y | +| Test.kt:121:4:121:4 | After x [true] | 3 | Test.kt:121:9:121:9 | After ; | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected index 6d0cb2bab712..bac6b7224475 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.expected @@ -1,6 +1,3 @@ -| Test.kt:3:8:80:1 | { ... } | Test.kt:3:8:80:1 | Exit | -| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit | -| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Exit | | Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Normal Exit | | Test.kt:4:13:79:2 | { ... } | Test.kt:11:3:16:3 | ... -> ... | | Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } | @@ -12,7 +9,6 @@ | Test.kt:4:13:79:2 | { ... } | Test.kt:38:9:38:9 | x | | Test.kt:4:13:79:2 | { ... } | Test.kt:38:16:41:3 | { ... } | | Test.kt:4:13:79:2 | { ... } | Test.kt:43:3:43:3 | ; | -| Test.kt:18:3:18:3 | ; | Test.kt:4:2:79:2 | Exit | | Test.kt:18:3:18:3 | ; | Test.kt:4:2:79:2 | Normal Exit | | Test.kt:18:3:18:3 | ; | Test.kt:21:3:24:9 | ... -> ... | | Test.kt:18:3:18:3 | ; | Test.kt:22:4:22:4 | ; | @@ -31,16 +27,22 @@ | Test.kt:35:3:35:3 | ; | Test.kt:43:3:43:3 | ; | | Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } | | Test.kt:38:9:38:9 | x | Test.kt:43:3:43:3 | ; | -| Test.kt:82:1:89:1 | Normal Exit | Test.kt:82:1:89:1 | Exit | +| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exceptional Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x | | Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) | -| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit | +| Test.kt:82:21:89:1 | { ... } | Test.kt:86:11:86:31 | e | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e | +| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x | | Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) | +| Test.kt:91:22:98:1 | { ... } | Test.kt:95:11:95:33 | e | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e | | Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y | @@ -55,16 +57,11 @@ | Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... | | Test.kt:105:5:109:5 | ; | Test.kt:107:27:109:5 | { ... } | | Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } | -| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit | | Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit | | Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y | | Test.kt:112:32:116:1 | { ... } | Test.kt:113:17:115:5 | { ... } | | Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } | -| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit | -| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Exit | | Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Normal Exit | | Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; | | Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... | | Test.kt:118:37:124:1 | { ... } | Test.kt:123:8:123:10 | { ... } | -| Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.ql b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.ql index de1e23b649cc..72de0cc435d3 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.ql +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbStrictDominance.ql @@ -1,6 +1,7 @@ import java import semmle.code.java.controlflow.Dominance +import utils.test.BasicBlock from BasicBlock b, BasicBlock b2 where b.strictlyDominates(b2) -select b, b2 +select getFirstAstNode(b), getFirstAstNode(b2) diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected index cf5da7c83b77..0596f159e223 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.expected @@ -1,7 +1,3 @@ -| Test.kt:3:8:80:1 | Exceptional Exit | Test.kt:3:8:80:1 | Exit | -| Test.kt:3:8:80:1 | { ... } | Test.kt:3:8:80:1 | Exit | -| Test.kt:4:2:79:2 | Exceptional Exit | Test.kt:4:2:79:2 | Exit | -| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit | | Test.kt:4:13:79:2 | { ... } | Test.kt:11:3:16:3 | ... -> ... | | Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } | | Test.kt:11:3:16:3 | ... -> ... | Test.kt:18:3:18:3 | ; | @@ -9,8 +5,9 @@ | Test.kt:18:3:18:3 | ; | Test.kt:21:3:24:9 | ... -> ... | | Test.kt:18:3:18:3 | ; | Test.kt:22:4:22:4 | ; | | Test.kt:21:3:24:9 | ... -> ... | Test.kt:4:2:79:2 | Normal Exit | +| Test.kt:22:4:22:4 | ; | Test.kt:30:7:30:12 | After ... (value equals) ... [false] | | Test.kt:22:4:22:4 | ; | Test.kt:30:15:33:3 | { ... } | -| Test.kt:22:4:22:4 | ; | Test.kt:35:3:35:3 | ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [false] | Test.kt:35:3:35:3 | ; | | Test.kt:30:15:33:3 | { ... } | Test.kt:35:3:35:3 | ; | | Test.kt:35:3:35:3 | ; | Test.kt:38:9:38:9 | x | | Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } | @@ -22,37 +19,45 @@ | Test.kt:82:21:89:1 | { ... } | Test.kt:84:7:84:7 | x | | Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) | | Test.kt:84:7:84:7 | x | Test.kt:82:1:89:1 | Normal Exit | -| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Normal Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e | +| Test.kt:86:11:86:31 | e | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit | | Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:93:7:93:7 | x | | Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) | | Test.kt:93:7:93:7 | x | Test.kt:91:1:98:1 | Normal Exit | -| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Normal Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e | +| Test.kt:95:11:95:33 | e | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit | +| Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y | -| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | ; | +| Test.kt:101:9:101:17 | After ... (value equals) ... [false] | Test.kt:105:5:109:5 | ; | +| Test.kt:101:22:101:22 | y | Test.kt:101:22:101:30 | After ... (value equals) ... [false] | | Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } | -| Test.kt:101:22:101:22 | y | Test.kt:105:5:109:5 | ; | +| Test.kt:101:22:101:30 | After ... (value equals) ... [false] | Test.kt:105:5:109:5 | ; | | Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | Exit | | Test.kt:105:5:109:5 | ; | Test.kt:105:20:107:5 | { ... } | | Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... | | Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit | -| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Normal Exit | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | Test.kt:100:1:110:1 | Normal Exit | +| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | | Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } | | Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit | -| Test.kt:112:1:116:1 | Exceptional Exit | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:112:32:116:1 | { ... } | Test.kt:113:9:113:9 | After x [false] | | Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y | -| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:113:9:113:9 | After x [false] | Test.kt:113:9:113:14 | After ... && ... [false] | +| Test.kt:113:9:113:14 | After ... && ... [false] | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:113:14:113:14 | After y [false] | Test.kt:113:9:113:14 | After ... && ... [false] | +| Test.kt:113:14:113:14 | y | Test.kt:113:14:113:14 | After y [false] | | Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } | | Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Normal Exit | -| Test.kt:118:1:124:1 | Exceptional Exit | Test.kt:118:1:124:1 | Exit | -| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit | | Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; | | Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... | -| Test.kt:121:9:121:9 | ; | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:120:3:123:3 | After when ... [false] | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:121:9:121:9 | ; | Test.kt:120:3:123:3 | After when ... [false] | | Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } | -| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:122:12:122:16 | ... -> ... | Test.kt:120:3:123:3 | After when ... [false] | +| Test.kt:122:12:122:16 | ... -> ... | Test.kt:123:8:123:10 | { ... } | | Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Normal Exit | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.ql b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.ql index ae2d8a393b47..ae8dc5d188d6 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.ql +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/bbSuccessor.ql @@ -1,5 +1,6 @@ import java +import utils.test.BasicBlock from BasicBlock b, BasicBlock b2 where b.getASuccessor() = b2 -select b, b2 +select getFirstAstNodeOrSynth(b), getFirstAstNodeOrSynth(b2) diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected index 1d07b13c9d75..8f9cce281606 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.expected @@ -1,12 +1,10 @@ #select | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | Test.kt:3:8:80:1 | { ... } | BlockStmt | -| Test.kt:3:8:80:1 | Exceptional Exit | Constructor | Test.kt:3:8:80:1 | Exit | Constructor | -| Test.kt:3:8:80:1 | Exit | Constructor | file://:0:0:0:0 | | | +| Test.kt:3:8:80:1 | Entry | Constructor | Test.kt:3:8:80:1 | { ... } | BlockStmt | | Test.kt:3:8:80:1 | Normal Exit | Constructor | Test.kt:3:8:80:1 | Exit | Constructor | | Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | | Test.kt:3:8:80:1 | { ... } | BlockStmt | Test.kt:3:8:80:1 | Normal Exit | Constructor | -| Test.kt:4:2:79:2 | Exceptional Exit | Method | Test.kt:4:2:79:2 | Exit | Method | -| Test.kt:4:2:79:2 | Exit | Method | file://:0:0:0:0 | | | +| Test.kt:4:2:79:2 | Entry | Method | Test.kt:4:13:79:2 | { ... } | BlockStmt | | Test.kt:4:2:79:2 | Normal Exit | Method | Test.kt:4:2:79:2 | Exit | Method | | Test.kt:4:13:79:2 | { ... } | BlockStmt | Test.kt:5:7:5:7 | var ...; | LocalVariableDeclStmt | | Test.kt:5:7:5:7 | var ...; | LocalVariableDeclStmt | Test.kt:5:16:5:16 | 0 | IntegerLiteral | @@ -31,17 +29,21 @@ | Test.kt:11:7:11:11 | ... > ... | GTExpr | Test.kt:11:14:14:3 | { ... } | BlockStmt | | Test.kt:11:11:11:11 | 0 | IntegerLiteral | Test.kt:11:7:11:11 | ... > ... | GTExpr | | Test.kt:11:14:14:3 | { ... } | BlockStmt | Test.kt:12:4:12:4 | ; | ExprStmt | -| Test.kt:12:4:12:4 | ; | ExprStmt | Test.kt:12:8:12:9 | 20 | LongLiteral | +| Test.kt:12:4:12:4 | ; | ExprStmt | Test.kt:12:4:12:4 | y | VarAccess | +| Test.kt:12:4:12:4 | y | VarAccess | Test.kt:12:8:12:9 | 20 | LongLiteral | | Test.kt:12:4:12:9 | ...=... | AssignExpr | Test.kt:13:4:13:4 | ; | ExprStmt | | Test.kt:12:8:12:9 | 20 | LongLiteral | Test.kt:12:4:12:9 | ...=... | AssignExpr | -| Test.kt:13:4:13:4 | ; | ExprStmt | Test.kt:13:8:13:9 | 10 | IntegerLiteral | +| Test.kt:13:4:13:4 | ; | ExprStmt | Test.kt:13:4:13:4 | z | VarAccess | +| Test.kt:13:4:13:4 | z | VarAccess | Test.kt:13:8:13:9 | 10 | IntegerLiteral | | Test.kt:13:4:13:9 | ...=... | AssignExpr | Test.kt:18:3:18:3 | ; | ExprStmt | | Test.kt:13:8:13:9 | 10 | IntegerLiteral | Test.kt:13:4:13:9 | ...=... | AssignExpr | | Test.kt:14:10:16:3 | { ... } | BlockStmt | Test.kt:15:4:15:4 | ; | ExprStmt | -| Test.kt:15:4:15:4 | ; | ExprStmt | Test.kt:15:8:15:9 | 30 | LongLiteral | +| Test.kt:15:4:15:4 | ; | ExprStmt | Test.kt:15:4:15:4 | y | VarAccess | +| Test.kt:15:4:15:4 | y | VarAccess | Test.kt:15:8:15:9 | 30 | LongLiteral | | Test.kt:15:4:15:9 | ...=... | AssignExpr | Test.kt:18:3:18:3 | ; | ExprStmt | | Test.kt:15:8:15:9 | 30 | LongLiteral | Test.kt:15:4:15:9 | ...=... | AssignExpr | -| Test.kt:18:3:18:3 | ; | ExprStmt | Test.kt:18:7:18:7 | 0 | IntegerLiteral | +| Test.kt:18:3:18:3 | ; | ExprStmt | Test.kt:18:3:18:3 | z | VarAccess | +| Test.kt:18:3:18:3 | z | VarAccess | Test.kt:18:7:18:7 | 0 | IntegerLiteral | | Test.kt:18:3:18:7 | ...=... | AssignExpr | Test.kt:21:3:24:9 | ; | ExprStmt | | Test.kt:18:7:18:7 | 0 | IntegerLiteral | Test.kt:18:3:18:7 | ...=... | AssignExpr | | Test.kt:21:3:24:9 | ... -> ... | WhenBranch | Test.kt:21:3:24:9 | true | BooleanLiteral | @@ -53,12 +55,14 @@ | Test.kt:21:6:21:10 | ... < ... | LTExpr | Test.kt:21:3:24:9 | ... -> ... | WhenBranch | | Test.kt:21:6:21:10 | ... < ... | LTExpr | Test.kt:22:4:22:4 | ; | ExprStmt | | Test.kt:21:10:21:10 | 0 | IntegerLiteral | Test.kt:21:6:21:10 | ... < ... | LTExpr | -| Test.kt:22:4:22:4 | ; | ExprStmt | Test.kt:22:8:22:9 | 40 | LongLiteral | +| Test.kt:22:4:22:4 | ; | ExprStmt | Test.kt:22:4:22:4 | y | VarAccess | +| Test.kt:22:4:22:4 | y | VarAccess | Test.kt:22:8:22:9 | 40 | LongLiteral | | Test.kt:22:4:22:9 | ...=... | AssignExpr | Test.kt:27:3:27:3 | ; | ExprStmt | | Test.kt:22:8:22:9 | 40 | LongLiteral | Test.kt:22:4:22:9 | ...=... | AssignExpr | | Test.kt:24:4:24:9 | INSTANCE | VarAccess | Test.kt:24:4:24:9 | return ... | ReturnStmt | | Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method | -| Test.kt:27:3:27:3 | ; | ExprStmt | Test.kt:27:7:27:8 | 10 | IntegerLiteral | +| Test.kt:27:3:27:3 | ; | ExprStmt | Test.kt:27:3:27:3 | z | VarAccess | +| Test.kt:27:3:27:3 | z | VarAccess | Test.kt:27:7:27:8 | 10 | IntegerLiteral | | Test.kt:27:3:27:8 | ...=... | AssignExpr | Test.kt:30:3:33:3 | ; | ExprStmt | | Test.kt:27:7:27:8 | 10 | IntegerLiteral | Test.kt:27:3:27:8 | ...=... | AssignExpr | | Test.kt:30:3:33:3 | ... -> ... | WhenBranch | Test.kt:30:7:30:7 | x | VarAccess | @@ -69,13 +73,16 @@ | Test.kt:30:7:30:12 | ... (value equals) ... | ValueEQExpr | Test.kt:35:3:35:3 | ; | ExprStmt | | Test.kt:30:12:30:12 | 0 | IntegerLiteral | Test.kt:30:7:30:12 | ... (value equals) ... | ValueEQExpr | | Test.kt:30:15:33:3 | { ... } | BlockStmt | Test.kt:31:4:31:4 | ; | ExprStmt | -| Test.kt:31:4:31:4 | ; | ExprStmt | Test.kt:31:8:31:9 | 60 | LongLiteral | +| Test.kt:31:4:31:4 | ; | ExprStmt | Test.kt:31:4:31:4 | y | VarAccess | +| Test.kt:31:4:31:4 | y | VarAccess | Test.kt:31:8:31:9 | 60 | LongLiteral | | Test.kt:31:4:31:9 | ...=... | AssignExpr | Test.kt:32:4:32:4 | ; | ExprStmt | | Test.kt:31:8:31:9 | 60 | LongLiteral | Test.kt:31:4:31:9 | ...=... | AssignExpr | -| Test.kt:32:4:32:4 | ; | ExprStmt | Test.kt:32:8:32:9 | 10 | IntegerLiteral | +| Test.kt:32:4:32:4 | ; | ExprStmt | Test.kt:32:4:32:4 | z | VarAccess | +| Test.kt:32:4:32:4 | z | VarAccess | Test.kt:32:8:32:9 | 10 | IntegerLiteral | | Test.kt:32:4:32:9 | ...=... | AssignExpr | Test.kt:35:3:35:3 | ; | ExprStmt | | Test.kt:32:8:32:9 | 10 | IntegerLiteral | Test.kt:32:4:32:9 | ...=... | AssignExpr | -| Test.kt:35:3:35:3 | ; | ExprStmt | Test.kt:35:7:35:8 | 20 | IntegerLiteral | +| Test.kt:35:3:35:3 | ; | ExprStmt | Test.kt:35:3:35:3 | z | VarAccess | +| Test.kt:35:3:35:3 | z | VarAccess | Test.kt:35:7:35:8 | 20 | IntegerLiteral | | Test.kt:35:3:35:8 | ...=... | AssignExpr | Test.kt:38:3:41:3 | while (...) | WhileStmt | | Test.kt:35:7:35:8 | 20 | IntegerLiteral | Test.kt:35:3:35:8 | ...=... | AssignExpr | | Test.kt:38:3:41:3 | while (...) | WhileStmt | Test.kt:38:9:38:9 | x | VarAccess | @@ -84,35 +91,40 @@ | Test.kt:38:9:38:13 | ... > ... | GTExpr | Test.kt:43:3:43:3 | ; | ExprStmt | | Test.kt:38:13:38:13 | 0 | IntegerLiteral | Test.kt:38:9:38:13 | ... > ... | GTExpr | | Test.kt:38:16:41:3 | { ... } | BlockStmt | Test.kt:39:4:39:4 | ; | ExprStmt | -| Test.kt:39:4:39:4 | ; | ExprStmt | Test.kt:39:8:39:9 | 10 | LongLiteral | +| Test.kt:39:4:39:4 | ; | ExprStmt | Test.kt:39:4:39:4 | y | VarAccess | +| Test.kt:39:4:39:4 | y | VarAccess | Test.kt:39:8:39:9 | 10 | LongLiteral | | Test.kt:39:4:39:9 | ...=... | AssignExpr | Test.kt:40:4:40:6 | ; | ExprStmt | | Test.kt:39:8:39:9 | 10 | LongLiteral | Test.kt:39:4:39:9 | ...=... | AssignExpr | -| Test.kt:40:4:40:4 | ; | ExprStmt | Test.kt:40:4:40:6 | tmp0 | VarAccess | +| Test.kt:40:4:40:4 | ; | ExprStmt | Test.kt:40:4:40:4 | x | VarAccess | | Test.kt:40:4:40:4 | x | VarAccess | Test.kt:40:4:40:6 | tmp0 | LocalVariableDeclExpr | +| Test.kt:40:4:40:4 | x | VarAccess | Test.kt:40:4:40:6 | tmp0 | VarAccess | | Test.kt:40:4:40:6 | ...=... | AssignExpr | Test.kt:40:4:40:6 | ; | ExprStmt | -| Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | | StmtExpr | | Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | tmp0 | VarAccess | -| Test.kt:40:4:40:6 | | StmtExpr | Test.kt:40:4:40:6 | { ... } | BlockStmt | +| Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | { ... } | BlockStmt | +| Test.kt:40:4:40:6 | | StmtExpr | Test.kt:40:4:40:6 | | ImplicitCoercionToUnitExpr | | Test.kt:40:4:40:6 | | ImplicitCoercionToUnitExpr | Test.kt:38:9:38:9 | x | VarAccess | | Test.kt:40:4:40:6 | dec(...) | MethodCall | Test.kt:40:4:40:6 | ...=... | AssignExpr | | Test.kt:40:4:40:6 | tmp0 | LocalVariableDeclExpr | Test.kt:40:4:40:4 | ; | ExprStmt | -| Test.kt:40:4:40:6 | tmp0 | VarAccess | Test.kt:40:4:40:6 | | ImplicitCoercionToUnitExpr | +| Test.kt:40:4:40:6 | tmp0 | VarAccess | Test.kt:40:4:40:6 | | StmtExpr | | Test.kt:40:4:40:6 | tmp0 | VarAccess | Test.kt:40:4:40:6 | dec(...) | MethodCall | | Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt | Test.kt:40:4:40:4 | x | VarAccess | | Test.kt:40:4:40:6 | { ... } | BlockStmt | Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt | -| Test.kt:43:3:43:3 | ; | ExprStmt | Test.kt:43:7:43:8 | 30 | IntegerLiteral | +| Test.kt:43:3:43:3 | ; | ExprStmt | Test.kt:43:3:43:3 | z | VarAccess | +| Test.kt:43:3:43:3 | z | VarAccess | Test.kt:43:7:43:8 | 30 | IntegerLiteral | | Test.kt:43:3:43:8 | ...=... | AssignExpr | Test.kt:73:3:73:3 | ; | ExprStmt | | Test.kt:43:7:43:8 | 30 | IntegerLiteral | Test.kt:43:3:43:8 | ...=... | AssignExpr | -| Test.kt:73:3:73:3 | ; | ExprStmt | Test.kt:73:7:73:8 | 50 | IntegerLiteral | +| Test.kt:73:3:73:3 | ; | ExprStmt | Test.kt:73:3:73:3 | z | VarAccess | +| Test.kt:73:3:73:3 | z | VarAccess | Test.kt:73:7:73:8 | 50 | IntegerLiteral | | Test.kt:73:3:73:8 | ...=... | AssignExpr | Test.kt:77:3:77:3 | ; | ExprStmt | | Test.kt:73:7:73:8 | 50 | IntegerLiteral | Test.kt:73:3:73:8 | ...=... | AssignExpr | -| Test.kt:77:3:77:3 | ; | ExprStmt | Test.kt:77:7:77:8 | 40 | IntegerLiteral | +| Test.kt:77:3:77:3 | ; | ExprStmt | Test.kt:77:3:77:3 | w | VarAccess | +| Test.kt:77:3:77:3 | w | VarAccess | Test.kt:77:7:77:8 | 40 | IntegerLiteral | | Test.kt:77:3:77:8 | ...=... | AssignExpr | Test.kt:78:3:78:8 | INSTANCE | VarAccess | | Test.kt:77:7:77:8 | 40 | IntegerLiteral | Test.kt:77:3:77:8 | ...=... | AssignExpr | | Test.kt:78:3:78:8 | INSTANCE | VarAccess | Test.kt:78:3:78:8 | return ... | ReturnStmt | | Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method | +| Test.kt:82:1:89:1 | Entry | Method | Test.kt:82:21:89:1 | { ... } | BlockStmt | | Test.kt:82:1:89:1 | Exceptional Exit | Method | Test.kt:82:1:89:1 | Exit | Method | -| Test.kt:82:1:89:1 | Exit | Method | file://:0:0:0:0 | | | | Test.kt:82:1:89:1 | Normal Exit | Method | Test.kt:82:1:89:1 | Exit | Method | | Test.kt:82:21:89:1 | { ... } | BlockStmt | Test.kt:83:2:88:2 | try ... | TryStmt | | Test.kt:83:2:88:2 | try ... | TryStmt | Test.kt:83:6:86:2 | { ... } | BlockStmt | @@ -124,13 +136,14 @@ | Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause | | Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method | | Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt | +| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:82:1:89:1 | Exceptional Exit | Method | | Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt | | Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral | | Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method | | Test.kt:87:10:87:10 | 2 | IntegerLiteral | Test.kt:87:3:87:10 | return ... | ReturnStmt | +| Test.kt:91:1:98:1 | Entry | Method | Test.kt:91:22:98:1 | { ... } | BlockStmt | | Test.kt:91:1:98:1 | Exceptional Exit | Method | Test.kt:91:1:98:1 | Exit | Method | -| Test.kt:91:1:98:1 | Exit | Method | file://:0:0:0:0 | | | | Test.kt:91:1:98:1 | Normal Exit | Method | Test.kt:91:1:98:1 | Exit | Method | | Test.kt:91:22:98:1 | { ... } | BlockStmt | Test.kt:92:2:97:2 | try ... | TryStmt | | Test.kt:92:2:97:2 | try ... | TryStmt | Test.kt:92:6:95:2 | { ... } | BlockStmt | @@ -142,13 +155,14 @@ | Test.kt:93:12:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause | | Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method | | Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt | +| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:91:1:98:1 | Exceptional Exit | Method | | Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt | | Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral | | Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method | | Test.kt:96:10:96:10 | 2 | IntegerLiteral | Test.kt:96:3:96:10 | return ... | ReturnStmt | +| Test.kt:100:1:110:1 | Entry | Method | Test.kt:100:25:110:1 | { ... } | BlockStmt | | Test.kt:100:1:110:1 | Exceptional Exit | Method | Test.kt:100:1:110:1 | Exit | Method | -| Test.kt:100:1:110:1 | Exit | Method | file://:0:0:0:0 | | | | Test.kt:100:1:110:1 | Normal Exit | Method | Test.kt:100:1:110:1 | Exit | Method | | Test.kt:100:25:110:1 | { ... } | BlockStmt | Test.kt:101:5:103:5 | ; | ExprStmt | | Test.kt:101:5:103:5 | ... -> ... | WhenBranch | Test.kt:101:9:101:30 | ... && ... | AndLogicalExpr | @@ -186,8 +200,7 @@ | Test.kt:108:9:108:29 | ; | ExprStmt | Test.kt:108:17:108:28 | "y not null" | StringLiteral | | Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Normal Exit | Method | | Test.kt:108:17:108:28 | "y not null" | StringLiteral | Test.kt:108:9:108:29 | println(...) | MethodCall | -| Test.kt:112:1:116:1 | Exceptional Exit | Method | Test.kt:112:1:116:1 | Exit | Method | -| Test.kt:112:1:116:1 | Exit | Method | file://:0:0:0:0 | | | +| Test.kt:112:1:116:1 | Entry | Method | Test.kt:112:32:116:1 | { ... } | BlockStmt | | Test.kt:112:1:116:1 | Normal Exit | Method | Test.kt:112:1:116:1 | Exit | Method | | Test.kt:112:32:116:1 | { ... } | BlockStmt | Test.kt:113:5:115:5 | ; | ExprStmt | | Test.kt:113:5:115:5 | ... -> ... | WhenBranch | Test.kt:113:9:113:14 | ... && ... | AndLogicalExpr | @@ -199,8 +212,7 @@ | Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Normal Exit | Method | | Test.kt:113:14:113:14 | y | VarAccess | Test.kt:113:17:115:5 | { ... } | BlockStmt | | Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Normal Exit | Method | -| Test.kt:118:1:124:1 | Exceptional Exit | Method | Test.kt:118:1:124:1 | Exit | Method | -| Test.kt:118:1:124:1 | Exit | Method | file://:0:0:0:0 | | | +| Test.kt:118:1:124:1 | Entry | Method | Test.kt:118:37:124:1 | { ... } | BlockStmt | | Test.kt:118:1:124:1 | Normal Exit | Method | Test.kt:118:1:124:1 | Exit | Method | | Test.kt:118:37:124:1 | { ... } | BlockStmt | Test.kt:119:2:123:12 | ; | ExprStmt | | Test.kt:119:2:123:12 | ; | ExprStmt | Test.kt:119:2:123:12 | when ... | WhenExpr | @@ -216,6 +228,7 @@ | Test.kt:122:12:122:16 | ... -> ... | WhenBranch | Test.kt:122:12:122:16 | true | BooleanLiteral | | Test.kt:122:12:122:16 | ; | ExprStmt | Test.kt:122:12:122:16 | false | BooleanLiteral | | Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Normal Exit | Method | +| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:123:8:123:10 | { ... } | BlockStmt | | Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | ; | ExprStmt | | Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Normal Exit | Method | missingSuccessor diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.ql b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.ql index c097d7d5e936..9a334d18aae7 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.ql +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/getASuccessor.ql @@ -1,53 +1,14 @@ import java +import utils.test.AstCfg -newtype TMaybeControlFlowNode = - TControlFlowNode(ControlFlowNode c) or - TNoControlFlowNode() - -class MaybeControlFlowNode extends TMaybeControlFlowNode { - abstract string toString(); - - abstract Location getLocation(); - - abstract string getPrimaryQlClasses(); -} - -class YesMaybeControlFlowNode extends MaybeControlFlowNode { - ControlFlowNode c; - - YesMaybeControlFlowNode() { this = TControlFlowNode(c) } - - override string toString() { result = c.toString() } - - override Location getLocation() { result = c.getLocation() } - - override string getPrimaryQlClasses() { result = c.getAstNode().getPrimaryQlClasses() } -} - -class NoMaybeControlFlowNode extends MaybeControlFlowNode { - NoMaybeControlFlowNode() { this = TNoControlFlowNode() } - - override string toString() { result = "" } - - override Location getLocation() { result.toString() = "file://:0:0:0:0" } - - override string getPrimaryQlClasses() { result = "" } -} - -MaybeControlFlowNode maybeSuccessor(ControlFlowNode n) { - if exists(n.getASuccessor()) - then result = TControlFlowNode(n.getASuccessor()) - else result = TNoControlFlowNode() -} - -from ControlFlowNode n, MaybeControlFlowNode m +from ControlFlowNode n, ControlFlowNode m where - m = maybeSuccessor(n) and + m = getAnAstSuccessor(n) and n.getLocation().getFile().(CompilationUnit).fromSource() -select n, n.getAstNode().getPrimaryQlClasses(), m, m.getPrimaryQlClasses() +select n, n.getAstNode().getPrimaryQlClasses(), m, m.getAstNode().getPrimaryQlClasses() query predicate missingSuccessor(Expr e) { - maybeSuccessor(e.getControlFlowNode()) instanceof NoMaybeControlFlowNode and + exists(ControlFlowNode n | n = e.getControlFlowNode() and not exists(n.getASuccessor())) and e.getFile().(CompilationUnit).fromSource() and not e instanceof TypeAccess and not e instanceof VarWrite diff --git a/java/ql/test-kotlin1/library-tests/controlflow/basic/strictDominance.expected b/java/ql/test-kotlin1/library-tests/controlflow/basic/strictDominance.expected index a85a0c120b3c..13d018efabd2 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/basic/strictDominance.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/basic/strictDominance.expected @@ -562,5 +562,4 @@ | Test.kt:121:4:121:9 | ... -> ... | Test.kt:122:12:122:16 | ... -> ... | | Test.kt:121:4:121:9 | ... -> ... | Test.kt:122:12:122:16 | ; | | Test.kt:121:4:121:9 | ... -> ... | Test.kt:123:8:123:10 | { ... } | -| Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } | | Test.kt:122:12:122:16 | ... -> ... | Test.kt:122:12:122:16 | ; | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominanceWrong.ql b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominanceWrong.ql index 4eadcddc61a6..6deead2df73b 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominanceWrong.ql +++ b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominanceWrong.ql @@ -17,5 +17,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co from Callable c, ControlFlowNode dom, ControlFlowNode node where strictlyDominates(dom, node) and - dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node) + dominanceCounterExample(any(ControlFlow::EntryNode entry | entry.getEnclosingCallable() = c), dom, + node) select c, dom, node diff --git a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected index 31da586d6307..3288b521887f 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected +++ b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.expected @@ -1,157 +1,21 @@ -| Test.kt:2:43:79:2 | { ... } | Test.kt:3:13:3:13 | var ...; | -| Test.kt:3:13:3:13 | var ...; | Test.kt:3:17:3:18 | px | -| Test.kt:3:13:3:13 | x | Test.kt:4:13:4:13 | var ...; | -| Test.kt:3:17:3:18 | px | Test.kt:3:13:3:13 | x | -| Test.kt:4:13:4:13 | var ...; | Test.kt:4:17:4:18 | pw | -| Test.kt:4:13:4:13 | w | Test.kt:5:13:5:13 | var ...; | -| Test.kt:4:17:4:18 | pw | Test.kt:4:13:4:13 | w | -| Test.kt:5:13:5:13 | var ...; | Test.kt:5:17:5:18 | pz | -| Test.kt:5:13:5:13 | z | Test.kt:7:7:7:7 | var ...; | -| Test.kt:5:17:5:18 | pz | Test.kt:5:13:5:13 | z | -| Test.kt:7:7:7:7 | j | Test.kt:8:7:8:7 | var ...; | -| Test.kt:7:7:7:7 | var ...; | Test.kt:7:7:7:7 | j | -| Test.kt:8:7:8:7 | var ...; | Test.kt:8:17:8:18 | 50 | -| Test.kt:8:7:8:7 | y | Test.kt:11:3:16:3 | ; | -| Test.kt:8:17:8:18 | 50 | Test.kt:8:7:8:7 | y | -| Test.kt:11:3:16:3 | ... -> ... | Test.kt:11:3:16:3 | true | -| Test.kt:11:3:16:3 | ... -> ... | Test.kt:11:7:11:7 | x | -| Test.kt:11:3:16:3 | ; | Test.kt:11:3:16:3 | when ... | -| Test.kt:11:3:16:3 | true | Test.kt:14:10:16:3 | { ... } | -| Test.kt:11:3:16:3 | when ... | Test.kt:11:3:16:3 | ... -> ... | -| Test.kt:11:7:11:7 | x | Test.kt:11:11:11:11 | 0 | -| Test.kt:11:7:11:11 | ... > ... | Test.kt:11:3:16:3 | ... -> ... | -| Test.kt:11:7:11:11 | ... > ... | Test.kt:11:14:14:3 | { ... } | -| Test.kt:11:7:11:11 | ... > ... | Test.kt:18:3:18:3 | ; | -| Test.kt:11:11:11:11 | 0 | Test.kt:11:7:11:11 | ... > ... | -| Test.kt:11:14:14:3 | { ... } | Test.kt:12:4:12:4 | ; | -| Test.kt:12:4:12:4 | ; | Test.kt:12:8:12:9 | 20 | -| Test.kt:12:4:12:9 | ...=... | Test.kt:13:4:13:4 | ; | -| Test.kt:12:8:12:9 | 20 | Test.kt:12:4:12:9 | ...=... | -| Test.kt:13:4:13:4 | ; | Test.kt:13:8:13:9 | 10 | -| Test.kt:13:8:13:9 | 10 | Test.kt:13:4:13:9 | ...=... | -| Test.kt:14:10:16:3 | { ... } | Test.kt:15:4:15:4 | ; | -| Test.kt:15:4:15:4 | ; | Test.kt:15:8:15:9 | 30 | -| Test.kt:15:8:15:9 | 30 | Test.kt:15:4:15:9 | ...=... | -| Test.kt:18:3:18:3 | ; | Test.kt:18:8:18:8 | x | -| Test.kt:18:3:18:20 | ...=... | Test.kt:21:3:24:11 | ; | -| Test.kt:18:7:18:20 | (...)... | Test.kt:18:3:18:20 | ...=... | -| Test.kt:18:8:18:8 | x | Test.kt:18:12:18:12 | y | -| Test.kt:18:8:18:12 | ... + ... | Test.kt:18:7:18:20 | (...)... | -| Test.kt:18:12:18:12 | y | Test.kt:18:8:18:12 | ... + ... | -| Test.kt:21:3:24:11 | ... -> ... | Test.kt:21:3:24:11 | true | -| Test.kt:21:3:24:11 | ... -> ... | Test.kt:21:7:21:7 | x | -| Test.kt:21:3:24:11 | ; | Test.kt:21:3:24:11 | when ... | -| Test.kt:21:3:24:11 | true | Test.kt:24:11:24:11 | z | -| Test.kt:21:3:24:11 | when ... | Test.kt:21:3:24:11 | ... -> ... | -| Test.kt:21:7:21:7 | x | Test.kt:21:11:21:11 | 0 | -| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Normal Exit | -| Test.kt:21:7:21:11 | ... < ... | Test.kt:21:3:24:11 | ... -> ... | -| Test.kt:21:7:21:11 | ... < ... | Test.kt:22:4:22:4 | ; | -| Test.kt:21:11:21:11 | 0 | Test.kt:21:7:21:11 | ... < ... | -| Test.kt:22:4:22:4 | ; | Test.kt:22:8:22:9 | 40 | -| Test.kt:22:4:22:9 | ...=... | Test.kt:27:3:27:3 | ; | -| Test.kt:22:8:22:9 | 40 | Test.kt:22:4:22:9 | ...=... | -| Test.kt:24:11:24:11 | z | Test.kt:24:4:24:11 | return ... | -| Test.kt:27:3:27:3 | ; | Test.kt:27:7:27:8 | 10 | -| Test.kt:27:3:27:8 | ...=... | Test.kt:30:3:33:3 | ; | -| Test.kt:27:7:27:8 | 10 | Test.kt:27:3:27:8 | ...=... | -| Test.kt:30:3:33:3 | ... -> ... | Test.kt:30:7:30:7 | x | -| Test.kt:30:3:33:3 | ; | Test.kt:30:3:33:3 | when ... | -| Test.kt:30:3:33:3 | when ... | Test.kt:30:3:33:3 | ... -> ... | -| Test.kt:30:7:30:7 | x | Test.kt:30:12:30:12 | 0 | -| Test.kt:30:7:30:12 | ... (value equals) ... | Test.kt:30:15:33:3 | { ... } | -| Test.kt:30:7:30:12 | ... (value equals) ... | Test.kt:35:3:35:3 | ; | -| Test.kt:30:12:30:12 | 0 | Test.kt:30:7:30:12 | ... (value equals) ... | -| Test.kt:30:15:33:3 | { ... } | Test.kt:31:4:31:4 | ; | -| Test.kt:31:4:31:4 | ; | Test.kt:31:8:31:9 | 60 | -| Test.kt:31:4:31:9 | ...=... | Test.kt:32:4:32:4 | ; | -| Test.kt:31:8:31:9 | 60 | Test.kt:31:4:31:9 | ...=... | -| Test.kt:32:4:32:4 | ; | Test.kt:32:8:32:9 | 10 | -| Test.kt:32:8:32:9 | 10 | Test.kt:32:4:32:9 | ...=... | -| Test.kt:35:3:35:3 | ; | Test.kt:35:3:35:3 | z | -| Test.kt:35:3:35:3 | z | Test.kt:35:8:35:8 | x | -| Test.kt:35:3:35:8 | ...+=... | Test.kt:38:3:41:3 | while (...) | -| Test.kt:35:8:35:8 | x | Test.kt:35:3:35:8 | ...+=... | -| Test.kt:38:3:41:3 | while (...) | Test.kt:38:10:38:10 | x | -| Test.kt:38:10:38:10 | x | Test.kt:38:14:38:14 | 0 | -| Test.kt:38:10:38:14 | ... > ... | Test.kt:38:17:41:3 | { ... } | -| Test.kt:38:10:38:14 | ... > ... | Test.kt:43:3:43:3 | ; | -| Test.kt:38:14:38:14 | 0 | Test.kt:38:10:38:14 | ... > ... | -| Test.kt:38:17:41:3 | { ... } | Test.kt:39:4:39:4 | ; | -| Test.kt:39:4:39:4 | ; | Test.kt:39:8:39:9 | 10 | -| Test.kt:39:4:39:9 | ...=... | Test.kt:40:4:40:6 | ; | -| Test.kt:39:8:39:9 | 10 | Test.kt:39:4:39:9 | ...=... | -| Test.kt:40:4:40:4 | ; | Test.kt:40:4:40:6 | tmp0 | -| Test.kt:40:4:40:4 | x | Test.kt:40:4:40:6 | tmp0 | -| Test.kt:40:4:40:6 | ...=... | Test.kt:40:4:40:6 | ; | -| Test.kt:40:4:40:6 | ; | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | ; | Test.kt:40:4:40:6 | tmp0 | -| Test.kt:40:4:40:6 | | Test.kt:40:4:40:6 | { ... } | -| Test.kt:40:4:40:6 | dec(...) | Test.kt:40:4:40:6 | ...=... | -| Test.kt:40:4:40:6 | tmp0 | Test.kt:40:4:40:4 | ; | -| Test.kt:40:4:40:6 | tmp0 | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | tmp0 | Test.kt:40:4:40:6 | dec(...) | -| Test.kt:40:4:40:6 | var ...; | Test.kt:40:4:40:4 | x | -| Test.kt:40:4:40:6 | { ... } | Test.kt:40:4:40:6 | var ...; | -| Test.kt:43:3:43:3 | ; | Test.kt:43:3:43:3 | z | -| Test.kt:43:3:43:3 | z | Test.kt:43:8:43:8 | y | -| Test.kt:43:3:43:15 | ...+=... | Test.kt:73:3:73:3 | ; | -| Test.kt:43:8:43:8 | y | Test.kt:43:8:43:15 | (...)... | -| Test.kt:43:8:43:15 | (...)... | Test.kt:43:3:43:15 | ...+=... | -| Test.kt:73:3:73:3 | ; | Test.kt:73:3:73:3 | z | -| Test.kt:73:3:73:3 | z | Test.kt:73:8:73:8 | x | -| Test.kt:73:3:73:16 | ...+=... | Test.kt:77:3:77:3 | ; | -| Test.kt:73:8:73:8 | x | Test.kt:73:12:73:12 | y | -| Test.kt:73:8:73:12 | ... + ... | Test.kt:73:16:73:16 | w | -| Test.kt:73:8:73:16 | ... + ... | Test.kt:73:3:73:16 | ...+=... | -| Test.kt:73:12:73:12 | | Test.kt:73:8:73:12 | ... + ... | -| Test.kt:73:12:73:12 | y | Test.kt:73:12:73:12 | | -| Test.kt:73:16:73:16 | w | Test.kt:73:8:73:16 | ... + ... | -| Test.kt:77:3:77:3 | ; | Test.kt:77:7:77:8 | 40 | -| Test.kt:77:3:77:8 | ...=... | Test.kt:78:10:78:10 | w | -| Test.kt:77:7:77:8 | 40 | Test.kt:77:3:77:8 | ...=... | -| Test.kt:78:10:78:10 | w | Test.kt:78:3:78:10 | return ... | -| Test.kt:81:25:98:2 | { ... } | Test.kt:83:7:83:7 | var ...; | -| Test.kt:83:7:83:7 | b | Test.kt:84:7:84:7 | var ...; | -| Test.kt:83:7:83:7 | var ...; | Test.kt:83:7:83:7 | b | -| Test.kt:84:7:84:7 | c | Test.kt:85:3:85:3 | ; | -| Test.kt:84:7:84:7 | var ...; | Test.kt:84:7:84:7 | c | -| Test.kt:85:3:85:3 | ; | Test.kt:85:7:85:7 | 0 | -| Test.kt:85:3:85:7 | ...=... | Test.kt:86:3:96:3 | while (...) | -| Test.kt:85:7:85:7 | 0 | Test.kt:85:3:85:7 | ...=... | -| Test.kt:86:3:96:3 | while (...) | Test.kt:86:9:86:12 | true | -| Test.kt:86:9:86:12 | true | Test.kt:86:15:96:3 | { ... } | -| Test.kt:86:15:96:3 | { ... } | Test.kt:87:4:87:4 | ; | -| Test.kt:87:4:87:4 | ; | Test.kt:87:8:87:9 | 10 | -| Test.kt:87:4:87:9 | ...=... | Test.kt:88:4:91:4 | ; | -| Test.kt:87:8:87:9 | 10 | Test.kt:87:4:87:9 | ...=... | -| Test.kt:88:4:91:4 | ... -> ... | Test.kt:88:8:88:8 | a | -| Test.kt:88:4:91:4 | ; | Test.kt:88:4:91:4 | when ... | -| Test.kt:88:4:91:4 | when ... | Test.kt:88:4:91:4 | ... -> ... | -| Test.kt:88:8:88:8 | a | Test.kt:88:12:88:14 | 100 | -| Test.kt:88:8:88:14 | ... > ... | Test.kt:88:17:91:4 | { ... } | -| Test.kt:88:8:88:14 | ... > ... | Test.kt:92:4:93:9 | ; | -| Test.kt:88:12:88:14 | 100 | Test.kt:88:8:88:14 | ... > ... | -| Test.kt:88:17:91:4 | { ... } | Test.kt:89:5:89:5 | ; | -| Test.kt:89:5:89:5 | ; | Test.kt:89:9:89:10 | 10 | -| Test.kt:89:5:89:10 | ...=... | Test.kt:90:5:90:5 | ; | -| Test.kt:89:9:89:10 | 10 | Test.kt:89:5:89:10 | ...=... | -| Test.kt:90:5:90:5 | ; | Test.kt:90:9:90:9 | c | -| Test.kt:90:9:90:9 | c | Test.kt:90:5:90:9 | ...=... | -| Test.kt:92:4:93:9 | ... -> ... | Test.kt:92:8:92:8 | a | -| Test.kt:92:4:93:9 | ; | Test.kt:92:4:93:9 | when ... | -| Test.kt:92:4:93:9 | when ... | Test.kt:92:4:93:9 | ... -> ... | -| Test.kt:92:8:92:8 | a | Test.kt:92:13:92:14 | 10 | -| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Normal Exit | -| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:93:5:93:9 | break | -| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:94:4:95:12 | ; | -| Test.kt:92:13:92:14 | 10 | Test.kt:92:8:92:14 | ... (value equals) ... | -| Test.kt:93:5:93:9 | break | Test.kt:97:10:97:10 | b | -| Test.kt:94:4:95:12 | ... -> ... | Test.kt:94:8:94:8 | a | -| Test.kt:94:4:95:12 | ; | Test.kt:94:4:95:12 | when ... | -| Test.kt:94:4:95:12 | when ... | Test.kt:94:4:95:12 | ... -> ... | -| Test.kt:94:8:94:8 | a | Test.kt:94:13:94:14 | 20 | -| Test.kt:94:8:94:14 | ... (value equals) ... | Test.kt:95:12:95:12 | c | -| Test.kt:94:13:94:14 | 20 | Test.kt:94:8:94:14 | ... (value equals) ... | -| Test.kt:95:12:95:12 | c | Test.kt:95:5:95:12 | return ... | -| Test.kt:97:10:97:10 | b | Test.kt:97:3:97:10 | return ... | +| Test.kt:2:43:79:2 | { ... } | Test.kt:11:3:16:3 | ... -> ... | +| Test.kt:2:43:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } | +| Test.kt:2:43:79:2 | { ... } | Test.kt:18:3:18:3 | ; | +| Test.kt:18:3:18:3 | ; | Test.kt:2:2:79:2 | Normal Exit | +| Test.kt:18:3:18:3 | ; | Test.kt:21:3:24:11 | ... -> ... | +| Test.kt:18:3:18:3 | ; | Test.kt:22:4:22:4 | ; | +| Test.kt:22:4:22:4 | ; | Test.kt:30:7:30:12 | After ... (value equals) ... [false] | +| Test.kt:22:4:22:4 | ; | Test.kt:30:15:33:3 | { ... } | +| Test.kt:22:4:22:4 | ; | Test.kt:35:3:35:3 | ; | +| Test.kt:35:3:35:3 | ; | Test.kt:38:10:38:10 | x | +| Test.kt:38:10:38:10 | x | Test.kt:38:17:41:3 | { ... } | +| Test.kt:38:10:38:10 | x | Test.kt:43:3:43:3 | ; | +| Test.kt:81:25:98:2 | { ... } | Test.kt:86:9:86:12 | true | +| Test.kt:86:9:86:12 | true | Test.kt:88:8:88:14 | After ... > ... [false] | +| Test.kt:86:9:86:12 | true | Test.kt:88:17:91:4 | { ... } | +| Test.kt:86:9:86:12 | true | Test.kt:92:4:93:9 | ; | +| Test.kt:92:4:93:9 | ; | Test.kt:81:2:98:2 | Normal Exit | +| Test.kt:92:4:93:9 | ; | Test.kt:93:5:93:9 | break | +| Test.kt:92:4:93:9 | ; | Test.kt:94:4:95:12 | ; | +| Test.kt:94:4:95:12 | ; | Test.kt:94:8:94:14 | After ... (value equals) ... [false] | +| Test.kt:94:4:95:12 | ; | Test.kt:95:12:95:12 | c | diff --git a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.ql b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.ql index 701640bf7209..7fc18484febf 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.ql +++ b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominator.ql @@ -1,9 +1,9 @@ -import default -import semmle.code.java.controlflow.Dominance +import java +import utils.test.BasicBlock -from Method func, ControlFlowNode dominator, ControlFlowNode node +from Method func, BasicBlock dominator, BasicBlock bb where - iDominates(dominator, node) and - dominator.getEnclosingStmt().getEnclosingCallable() = func and + dominator.immediatelyDominates(bb) and + dominator.getEnclosingCallable() = func and func.getDeclaringType().hasName("Test") -select dominator, node +select getFirstAstNodeOrSynth(dominator), getFirstAstNodeOrSynth(bb) diff --git a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominatorUnique.ql b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominatorUnique.ql index eaf75ab7bfaa..54b0d1863624 100644 --- a/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominatorUnique.ql +++ b/java/ql/test-kotlin1/library-tests/controlflow/dominance/dominatorUnique.ql @@ -7,5 +7,5 @@ where iDominates(dom1, node) and iDominates(dom2, node) and dom1 != dom2 and - func = node.getEnclosingStmt().getEnclosingCallable() + func = node.getEnclosingCallable() select func, node, dom1, dom2 diff --git a/java/ql/test-kotlin1/library-tests/exprs/binop.ql b/java/ql/test-kotlin1/library-tests/exprs/binop.ql index d865d83fcf90..303eccba5896 100644 --- a/java/ql/test-kotlin1/library-tests/exprs/binop.ql +++ b/java/ql/test-kotlin1/library-tests/exprs/binop.ql @@ -41,4 +41,5 @@ MaybeElement rhs(BinaryExpr e) { } from Expr e +where not e instanceof Assignment select e, lhs(e), rhs(e) diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected index c66d50a722d1..6a1994921f47 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStmts.expected @@ -1,205 +1,386 @@ -| Test.kt:3:1:80:1 | Exceptional Exit | 0 | Test.kt:3:1:80:1 | Exceptional Exit | -| Test.kt:3:1:80:1 | Exit | 0 | Test.kt:3:1:80:1 | Exit | -| Test.kt:3:1:80:1 | { ... } | 0 | Test.kt:3:1:80:1 | { ... } | -| Test.kt:3:1:80:1 | { ... } | 1 | Test.kt:3:1:80:1 | super(...) | -| Test.kt:3:1:80:1 | { ... } | 2 | Test.kt:3:1:80:1 | { ... } | -| Test.kt:3:1:80:1 | { ... } | 3 | Test.kt:3:1:80:1 | Normal Exit | -| Test.kt:4:2:79:2 | Exceptional Exit | 0 | Test.kt:4:2:79:2 | Exceptional Exit | -| Test.kt:4:2:79:2 | Exit | 0 | Test.kt:4:2:79:2 | Exit | +| Test.kt:3:1:80:1 | Entry | 0 | Test.kt:3:1:80:1 | Entry | +| Test.kt:3:1:80:1 | Entry | 1 | Test.kt:3:1:80:1 | { ... } | +| Test.kt:3:1:80:1 | Entry | 2 | Test.kt:3:1:80:1 | Before super(...) | +| Test.kt:3:1:80:1 | Entry | 3 | Test.kt:3:1:80:1 | super(...) | +| Test.kt:3:1:80:1 | Entry | 4 | Test.kt:3:1:80:1 | After super(...) | +| Test.kt:3:1:80:1 | Entry | 5 | Test.kt:3:1:80:1 | { ... } | +| Test.kt:3:1:80:1 | Entry | 6 | Test.kt:3:1:80:1 | After { ... } | +| Test.kt:3:1:80:1 | Entry | 7 | Test.kt:3:1:80:1 | Normal Exit | +| Test.kt:3:1:80:1 | Entry | 8 | Test.kt:3:1:80:1 | Exit | +| Test.kt:4:2:79:2 | Entry | 0 | Test.kt:4:2:79:2 | Entry | +| Test.kt:4:2:79:2 | Entry | 1 | Test.kt:4:13:79:2 | { ... } | +| Test.kt:4:2:79:2 | Entry | 2 | Test.kt:5:3:5:16 | var ...; | +| Test.kt:4:2:79:2 | Entry | 3 | Test.kt:5:3:5:16 | Before x | +| Test.kt:4:2:79:2 | Entry | 4 | Test.kt:5:16:5:16 | 0 | +| Test.kt:4:2:79:2 | Entry | 5 | Test.kt:5:3:5:16 | x | +| Test.kt:4:2:79:2 | Entry | 6 | Test.kt:5:3:5:16 | After x | +| Test.kt:4:2:79:2 | Entry | 7 | Test.kt:5:3:5:16 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 8 | Test.kt:6:3:6:18 | var ...; | +| Test.kt:4:2:79:2 | Entry | 9 | Test.kt:6:3:6:18 | Before y | +| Test.kt:4:2:79:2 | Entry | 10 | Test.kt:6:17:6:18 | 50 | +| Test.kt:4:2:79:2 | Entry | 11 | Test.kt:6:3:6:18 | y | +| Test.kt:4:2:79:2 | Entry | 12 | Test.kt:6:3:6:18 | After y | +| Test.kt:4:2:79:2 | Entry | 13 | Test.kt:6:3:6:18 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 14 | Test.kt:7:3:7:16 | var ...; | +| Test.kt:4:2:79:2 | Entry | 15 | Test.kt:7:3:7:16 | Before z | +| Test.kt:4:2:79:2 | Entry | 16 | Test.kt:7:16:7:16 | 0 | +| Test.kt:4:2:79:2 | Entry | 17 | Test.kt:7:3:7:16 | z | +| Test.kt:4:2:79:2 | Entry | 18 | Test.kt:7:3:7:16 | After z | +| Test.kt:4:2:79:2 | Entry | 19 | Test.kt:7:3:7:16 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 20 | Test.kt:8:3:8:16 | var ...; | +| Test.kt:4:2:79:2 | Entry | 21 | Test.kt:8:3:8:16 | Before w | +| Test.kt:4:2:79:2 | Entry | 22 | Test.kt:8:16:8:16 | 0 | +| Test.kt:4:2:79:2 | Entry | 23 | Test.kt:8:3:8:16 | w | +| Test.kt:4:2:79:2 | Entry | 24 | Test.kt:8:3:8:16 | After w | +| Test.kt:4:2:79:2 | Entry | 25 | Test.kt:8:3:8:16 | After var ...; | +| Test.kt:4:2:79:2 | Entry | 26 | Test.kt:11:3:16:3 | ; | +| Test.kt:4:2:79:2 | Entry | 27 | Test.kt:11:3:16:3 | when ... | +| Test.kt:4:2:79:2 | Entry | 28 | Test.kt:11:7:14:3 | ... -> ... | +| Test.kt:4:2:79:2 | Entry | 29 | Test.kt:11:7:11:11 | Before ... > ... | +| Test.kt:4:2:79:2 | Entry | 30 | Test.kt:11:7:11:7 | x | +| Test.kt:4:2:79:2 | Entry | 31 | Test.kt:11:11:11:11 | 0 | +| Test.kt:4:2:79:2 | Entry | 32 | Test.kt:11:7:11:11 | ... > ... | | Test.kt:4:2:79:2 | Normal Exit | 0 | Test.kt:4:2:79:2 | Normal Exit | -| Test.kt:4:13:79:2 | { ... } | 0 | Test.kt:4:13:79:2 | { ... } | -| Test.kt:4:13:79:2 | { ... } | 1 | Test.kt:5:3:5:16 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 2 | Test.kt:5:16:5:16 | 0 | -| Test.kt:4:13:79:2 | { ... } | 3 | Test.kt:5:3:5:16 | x | -| Test.kt:4:13:79:2 | { ... } | 4 | Test.kt:6:3:6:18 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 5 | Test.kt:6:17:6:18 | 50 | -| Test.kt:4:13:79:2 | { ... } | 6 | Test.kt:6:3:6:18 | y | -| Test.kt:4:13:79:2 | { ... } | 7 | Test.kt:7:3:7:16 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 8 | Test.kt:7:16:7:16 | 0 | -| Test.kt:4:13:79:2 | { ... } | 9 | Test.kt:7:3:7:16 | z | -| Test.kt:4:13:79:2 | { ... } | 10 | Test.kt:8:3:8:16 | var ...; | -| Test.kt:4:13:79:2 | { ... } | 11 | Test.kt:8:16:8:16 | 0 | -| Test.kt:4:13:79:2 | { ... } | 12 | Test.kt:8:3:8:16 | w | -| Test.kt:4:13:79:2 | { ... } | 13 | Test.kt:11:3:16:3 | ; | -| Test.kt:4:13:79:2 | { ... } | 14 | Test.kt:11:3:16:3 | when ... | -| Test.kt:4:13:79:2 | { ... } | 15 | Test.kt:11:7:14:3 | ... -> ... | -| Test.kt:4:13:79:2 | { ... } | 16 | Test.kt:11:7:11:7 | x | -| Test.kt:4:13:79:2 | { ... } | 17 | Test.kt:11:11:11:11 | 0 | -| Test.kt:4:13:79:2 | { ... } | 18 | Test.kt:11:7:11:11 | ... > ... | -| Test.kt:11:14:14:3 | { ... } | 0 | Test.kt:11:14:14:3 | { ... } | -| Test.kt:11:14:14:3 | { ... } | 1 | Test.kt:12:4:12:9 | ; | -| Test.kt:11:14:14:3 | { ... } | 2 | Test.kt:12:8:12:9 | 20 | -| Test.kt:11:14:14:3 | { ... } | 3 | Test.kt:12:4:12:9 | ...=... | -| Test.kt:11:14:14:3 | { ... } | 4 | Test.kt:13:4:13:9 | ; | -| Test.kt:11:14:14:3 | { ... } | 5 | Test.kt:13:8:13:9 | 10 | -| Test.kt:11:14:14:3 | { ... } | 6 | Test.kt:13:4:13:9 | ...=... | -| Test.kt:14:10:16:3 | ... -> ... | 0 | Test.kt:14:10:16:3 | ... -> ... | -| Test.kt:14:10:16:3 | ... -> ... | 1 | Test.kt:14:10:16:3 | true | -| Test.kt:14:10:16:3 | ... -> ... | 2 | Test.kt:14:10:16:3 | { ... } | -| Test.kt:14:10:16:3 | ... -> ... | 3 | Test.kt:15:4:15:9 | ; | -| Test.kt:14:10:16:3 | ... -> ... | 4 | Test.kt:15:8:15:9 | 30 | -| Test.kt:14:10:16:3 | ... -> ... | 5 | Test.kt:15:4:15:9 | ...=... | -| Test.kt:18:3:18:7 | ; | 0 | Test.kt:18:3:18:7 | ; | -| Test.kt:18:3:18:7 | ; | 1 | Test.kt:18:7:18:7 | 0 | -| Test.kt:18:3:18:7 | ; | 2 | Test.kt:18:3:18:7 | ...=... | -| Test.kt:18:3:18:7 | ; | 3 | Test.kt:21:3:24:9 | ; | -| Test.kt:18:3:18:7 | ; | 4 | Test.kt:21:3:24:9 | when ... | -| Test.kt:18:3:18:7 | ; | 5 | Test.kt:21:6:22:9 | ... -> ... | -| Test.kt:18:3:18:7 | ; | 6 | Test.kt:21:6:21:6 | x | -| Test.kt:18:3:18:7 | ; | 7 | Test.kt:21:10:21:10 | 0 | -| Test.kt:18:3:18:7 | ; | 8 | Test.kt:21:6:21:10 | ... < ... | -| Test.kt:22:4:22:9 | ; | 0 | Test.kt:22:4:22:9 | ; | -| Test.kt:22:4:22:9 | ; | 1 | Test.kt:22:8:22:9 | 40 | -| Test.kt:22:4:22:9 | ; | 2 | Test.kt:22:4:22:9 | ...=... | -| Test.kt:22:4:22:9 | ; | 3 | Test.kt:27:3:27:8 | ; | -| Test.kt:22:4:22:9 | ; | 4 | Test.kt:27:7:27:8 | 10 | -| Test.kt:22:4:22:9 | ; | 5 | Test.kt:27:3:27:8 | ...=... | -| Test.kt:22:4:22:9 | ; | 6 | Test.kt:30:3:33:3 | ; | -| Test.kt:22:4:22:9 | ; | 7 | Test.kt:30:3:33:3 | when ... | -| Test.kt:22:4:22:9 | ; | 8 | Test.kt:30:7:33:3 | ... -> ... | -| Test.kt:22:4:22:9 | ; | 9 | Test.kt:30:7:30:7 | x | -| Test.kt:22:4:22:9 | ; | 10 | Test.kt:30:12:30:12 | 0 | -| Test.kt:22:4:22:9 | ; | 11 | Test.kt:30:7:30:12 | ... (value equals) ... | -| Test.kt:24:4:24:9 | ... -> ... | 0 | Test.kt:24:4:24:9 | ... -> ... | -| Test.kt:24:4:24:9 | ... -> ... | 1 | Test.kt:24:4:24:9 | true | -| Test.kt:24:4:24:9 | ... -> ... | 2 | Test.kt:24:10:24:10 | INSTANCE | -| Test.kt:24:4:24:9 | ... -> ... | 3 | Test.kt:24:4:24:9 | return ... | -| Test.kt:30:15:33:3 | { ... } | 0 | Test.kt:30:15:33:3 | { ... } | -| Test.kt:30:15:33:3 | { ... } | 1 | Test.kt:31:4:31:9 | ; | -| Test.kt:30:15:33:3 | { ... } | 2 | Test.kt:31:8:31:9 | 60 | -| Test.kt:30:15:33:3 | { ... } | 3 | Test.kt:31:4:31:9 | ...=... | -| Test.kt:30:15:33:3 | { ... } | 4 | Test.kt:32:4:32:9 | ; | -| Test.kt:30:15:33:3 | { ... } | 5 | Test.kt:32:8:32:9 | 10 | -| Test.kt:30:15:33:3 | { ... } | 6 | Test.kt:32:4:32:9 | ...=... | -| Test.kt:35:3:35:8 | ; | 0 | Test.kt:35:3:35:8 | ; | -| Test.kt:35:3:35:8 | ; | 1 | Test.kt:35:7:35:8 | 20 | -| Test.kt:35:3:35:8 | ; | 2 | Test.kt:35:3:35:8 | ...=... | -| Test.kt:35:3:35:8 | ; | 3 | Test.kt:38:3:41:3 | while (...) | -| Test.kt:38:9:38:9 | x | 0 | Test.kt:38:9:38:9 | x | -| Test.kt:38:9:38:9 | x | 1 | Test.kt:38:13:38:13 | 0 | -| Test.kt:38:9:38:9 | x | 2 | Test.kt:38:9:38:13 | ... > ... | -| Test.kt:38:16:41:3 | { ... } | 0 | Test.kt:38:16:41:3 | { ... } | -| Test.kt:38:16:41:3 | { ... } | 1 | Test.kt:39:4:39:9 | ; | -| Test.kt:38:16:41:3 | { ... } | 2 | Test.kt:39:8:39:9 | 10 | -| Test.kt:38:16:41:3 | { ... } | 3 | Test.kt:39:4:39:9 | ...=... | -| Test.kt:38:16:41:3 | { ... } | 4 | Test.kt:40:4:40:6 | ; | -| Test.kt:38:16:41:3 | { ... } | 5 | Test.kt:40:4:40:6 | | -| Test.kt:38:16:41:3 | { ... } | 6 | Test.kt:40:4:40:6 | { ... } | -| Test.kt:38:16:41:3 | { ... } | 7 | Test.kt:40:4:40:6 | var ...; | -| Test.kt:38:16:41:3 | { ... } | 8 | Test.kt:40:4:40:4 | x | -| Test.kt:38:16:41:3 | { ... } | 9 | Test.kt:40:4:40:6 | | -| Test.kt:38:16:41:3 | { ... } | 10 | Test.kt:40:4:40:6 | ; | -| Test.kt:38:16:41:3 | { ... } | 11 | Test.kt:40:4:40:6 | | -| Test.kt:38:16:41:3 | { ... } | 12 | Test.kt:40:4:40:6 | dec(...) | -| Test.kt:38:16:41:3 | { ... } | 13 | Test.kt:40:4:40:6 | ...=... | -| Test.kt:38:16:41:3 | { ... } | 14 | Test.kt:40:4:40:6 | ; | -| Test.kt:38:16:41:3 | { ... } | 15 | Test.kt:40:4:40:6 | | -| Test.kt:38:16:41:3 | { ... } | 16 | Test.kt:40:4:40:6 | | -| Test.kt:43:3:43:8 | ; | 0 | Test.kt:43:3:43:8 | ; | -| Test.kt:43:3:43:8 | ; | 1 | Test.kt:43:7:43:8 | 30 | -| Test.kt:43:3:43:8 | ; | 2 | Test.kt:43:3:43:8 | ...=... | -| Test.kt:43:3:43:8 | ; | 3 | Test.kt:73:3:73:8 | ; | -| Test.kt:43:3:43:8 | ; | 4 | Test.kt:73:7:73:8 | 50 | -| Test.kt:43:3:43:8 | ; | 5 | Test.kt:73:3:73:8 | ...=... | -| Test.kt:43:3:43:8 | ; | 6 | Test.kt:77:3:77:8 | ; | -| Test.kt:43:3:43:8 | ; | 7 | Test.kt:77:7:77:8 | 40 | -| Test.kt:43:3:43:8 | ; | 8 | Test.kt:77:3:77:8 | ...=... | -| Test.kt:43:3:43:8 | ; | 9 | Test.kt:78:9:78:9 | INSTANCE | -| Test.kt:43:3:43:8 | ; | 10 | Test.kt:78:3:78:8 | return ... | -| Test.kt:82:1:89:1 | Exceptional Exit | 0 | Test.kt:82:1:89:1 | Exceptional Exit | +| Test.kt:4:2:79:2 | Normal Exit | 1 | Test.kt:4:2:79:2 | Exit | +| Test.kt:11:3:16:3 | After when ... | 0 | Test.kt:11:3:16:3 | After when ... | +| Test.kt:11:3:16:3 | After when ... | 1 | Test.kt:11:3:16:3 | After ; | +| Test.kt:11:3:16:3 | After when ... | 2 | Test.kt:18:3:18:7 | ; | +| Test.kt:11:3:16:3 | After when ... | 3 | Test.kt:18:3:18:7 | Before ...=... | +| Test.kt:11:3:16:3 | After when ... | 4 | Test.kt:18:3:18:7 | z | +| Test.kt:11:3:16:3 | After when ... | 5 | Test.kt:18:7:18:7 | 0 | +| Test.kt:11:3:16:3 | After when ... | 6 | Test.kt:18:3:18:7 | ...=... | +| Test.kt:11:3:16:3 | After when ... | 7 | Test.kt:18:3:18:7 | After ...=... | +| Test.kt:11:3:16:3 | After when ... | 8 | Test.kt:18:3:18:7 | After ; | +| Test.kt:11:3:16:3 | After when ... | 9 | Test.kt:21:3:24:9 | ; | +| Test.kt:11:3:16:3 | After when ... | 10 | Test.kt:21:3:24:9 | when ... | +| Test.kt:11:3:16:3 | After when ... | 11 | Test.kt:21:6:22:9 | ... -> ... | +| Test.kt:11:3:16:3 | After when ... | 12 | Test.kt:21:6:21:10 | Before ... < ... | +| Test.kt:11:3:16:3 | After when ... | 13 | Test.kt:21:6:21:6 | x | +| Test.kt:11:3:16:3 | After when ... | 14 | Test.kt:21:10:21:10 | 0 | +| Test.kt:11:3:16:3 | After when ... | 15 | Test.kt:21:6:21:10 | ... < ... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 0 | Test.kt:11:7:11:11 | After ... > ... [false] | +| Test.kt:11:7:11:11 | After ... > ... [false] | 1 | Test.kt:14:10:16:3 | ... -> ... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 2 | Test.kt:14:10:16:3 | true | +| Test.kt:11:7:11:11 | After ... > ... [false] | 3 | Test.kt:14:10:16:3 | After true [true] | +| Test.kt:11:7:11:11 | After ... > ... [false] | 4 | Test.kt:14:10:16:3 | { ... } | +| Test.kt:11:7:11:11 | After ... > ... [false] | 5 | Test.kt:15:4:15:9 | ; | +| Test.kt:11:7:11:11 | After ... > ... [false] | 6 | Test.kt:15:4:15:9 | Before ...=... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 7 | Test.kt:15:4:15:9 | y | +| Test.kt:11:7:11:11 | After ... > ... [false] | 8 | Test.kt:15:8:15:9 | 30 | +| Test.kt:11:7:11:11 | After ... > ... [false] | 9 | Test.kt:15:4:15:9 | ...=... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 10 | Test.kt:15:4:15:9 | After ...=... | +| Test.kt:11:7:11:11 | After ... > ... [false] | 11 | Test.kt:15:4:15:9 | After ; | +| Test.kt:11:7:11:11 | After ... > ... [false] | 12 | Test.kt:14:10:16:3 | After { ... } | +| Test.kt:11:7:11:11 | After ... > ... [true] | 0 | Test.kt:11:7:11:11 | After ... > ... [true] | +| Test.kt:11:7:11:11 | After ... > ... [true] | 1 | Test.kt:11:14:14:3 | { ... } | +| Test.kt:11:7:11:11 | After ... > ... [true] | 2 | Test.kt:12:4:12:9 | ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 3 | Test.kt:12:4:12:9 | Before ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 4 | Test.kt:12:4:12:9 | y | +| Test.kt:11:7:11:11 | After ... > ... [true] | 5 | Test.kt:12:8:12:9 | 20 | +| Test.kt:11:7:11:11 | After ... > ... [true] | 6 | Test.kt:12:4:12:9 | ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 7 | Test.kt:12:4:12:9 | After ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 8 | Test.kt:12:4:12:9 | After ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 9 | Test.kt:13:4:13:9 | ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 10 | Test.kt:13:4:13:9 | Before ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 11 | Test.kt:13:4:13:9 | z | +| Test.kt:11:7:11:11 | After ... > ... [true] | 12 | Test.kt:13:8:13:9 | 10 | +| Test.kt:11:7:11:11 | After ... > ... [true] | 13 | Test.kt:13:4:13:9 | ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 14 | Test.kt:13:4:13:9 | After ...=... | +| Test.kt:11:7:11:11 | After ... > ... [true] | 15 | Test.kt:13:4:13:9 | After ; | +| Test.kt:11:7:11:11 | After ... > ... [true] | 16 | Test.kt:11:14:14:3 | After { ... } | +| Test.kt:21:6:21:10 | After ... < ... [false] | 0 | Test.kt:21:6:21:10 | After ... < ... [false] | +| Test.kt:21:6:21:10 | After ... < ... [false] | 1 | Test.kt:24:4:24:9 | ... -> ... | +| Test.kt:21:6:21:10 | After ... < ... [false] | 2 | Test.kt:24:4:24:9 | true | +| Test.kt:21:6:21:10 | After ... < ... [false] | 3 | Test.kt:24:4:24:9 | After true [true] | +| Test.kt:21:6:21:10 | After ... < ... [false] | 4 | Test.kt:24:4:24:9 | Before return ... | +| Test.kt:21:6:21:10 | After ... < ... [false] | 5 | Test.kt:24:10:24:10 | INSTANCE | +| Test.kt:21:6:21:10 | After ... < ... [false] | 6 | Test.kt:24:4:24:9 | return ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 0 | Test.kt:21:6:21:10 | After ... < ... [true] | +| Test.kt:21:6:21:10 | After ... < ... [true] | 1 | Test.kt:22:4:22:9 | ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 2 | Test.kt:22:4:22:9 | Before ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 3 | Test.kt:22:4:22:9 | y | +| Test.kt:21:6:21:10 | After ... < ... [true] | 4 | Test.kt:22:8:22:9 | 40 | +| Test.kt:21:6:21:10 | After ... < ... [true] | 5 | Test.kt:22:4:22:9 | ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 6 | Test.kt:22:4:22:9 | After ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 7 | Test.kt:22:4:22:9 | After ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 8 | Test.kt:21:3:24:9 | After when ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 9 | Test.kt:21:3:24:9 | After ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 10 | Test.kt:27:3:27:8 | ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 11 | Test.kt:27:3:27:8 | Before ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 12 | Test.kt:27:3:27:8 | z | +| Test.kt:21:6:21:10 | After ... < ... [true] | 13 | Test.kt:27:7:27:8 | 10 | +| Test.kt:21:6:21:10 | After ... < ... [true] | 14 | Test.kt:27:3:27:8 | ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 15 | Test.kt:27:3:27:8 | After ...=... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 16 | Test.kt:27:3:27:8 | After ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 17 | Test.kt:30:3:33:3 | ; | +| Test.kt:21:6:21:10 | After ... < ... [true] | 18 | Test.kt:30:3:33:3 | when ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 19 | Test.kt:30:7:33:3 | ... -> ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 20 | Test.kt:30:7:30:12 | Before ... (value equals) ... | +| Test.kt:21:6:21:10 | After ... < ... [true] | 21 | Test.kt:30:7:30:7 | x | +| Test.kt:21:6:21:10 | After ... < ... [true] | 22 | Test.kt:30:12:30:12 | 0 | +| Test.kt:21:6:21:10 | After ... < ... [true] | 23 | Test.kt:30:7:30:12 | ... (value equals) ... | +| Test.kt:30:3:33:3 | After when ... | 0 | Test.kt:30:3:33:3 | After when ... | +| Test.kt:30:3:33:3 | After when ... | 1 | Test.kt:30:3:33:3 | After ; | +| Test.kt:30:3:33:3 | After when ... | 2 | Test.kt:35:3:35:8 | ; | +| Test.kt:30:3:33:3 | After when ... | 3 | Test.kt:35:3:35:8 | Before ...=... | +| Test.kt:30:3:33:3 | After when ... | 4 | Test.kt:35:3:35:8 | z | +| Test.kt:30:3:33:3 | After when ... | 5 | Test.kt:35:7:35:8 | 20 | +| Test.kt:30:3:33:3 | After when ... | 6 | Test.kt:35:3:35:8 | ...=... | +| Test.kt:30:3:33:3 | After when ... | 7 | Test.kt:35:3:35:8 | After ...=... | +| Test.kt:30:3:33:3 | After when ... | 8 | Test.kt:35:3:35:8 | After ; | +| Test.kt:30:3:33:3 | After when ... | 9 | Test.kt:38:3:41:3 | while (...) | +| Test.kt:30:7:30:12 | After ... (value equals) ... [false] | 0 | Test.kt:30:7:30:12 | After ... (value equals) ... [false] | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 0 | Test.kt:30:7:30:12 | After ... (value equals) ... [true] | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 1 | Test.kt:30:15:33:3 | { ... } | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 2 | Test.kt:31:4:31:9 | ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 3 | Test.kt:31:4:31:9 | Before ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 4 | Test.kt:31:4:31:9 | y | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 5 | Test.kt:31:8:31:9 | 60 | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 6 | Test.kt:31:4:31:9 | ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 7 | Test.kt:31:4:31:9 | After ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 8 | Test.kt:31:4:31:9 | After ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 9 | Test.kt:32:4:32:9 | ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 10 | Test.kt:32:4:32:9 | Before ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 11 | Test.kt:32:4:32:9 | z | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 12 | Test.kt:32:8:32:9 | 10 | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 13 | Test.kt:32:4:32:9 | ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 14 | Test.kt:32:4:32:9 | After ...=... | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 15 | Test.kt:32:4:32:9 | After ; | +| Test.kt:30:7:30:12 | After ... (value equals) ... [true] | 16 | Test.kt:30:15:33:3 | After { ... } | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 0 | Test.kt:38:3:41:3 | [LoopHeader] while (...) | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 1 | Test.kt:38:9:38:13 | Before ... > ... | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 2 | Test.kt:38:9:38:9 | x | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 3 | Test.kt:38:13:38:13 | 0 | +| Test.kt:38:3:41:3 | [LoopHeader] while (...) | 4 | Test.kt:38:9:38:13 | ... > ... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 0 | Test.kt:38:9:38:13 | After ... > ... [false] | +| Test.kt:38:9:38:13 | After ... > ... [false] | 1 | Test.kt:38:3:41:3 | After while (...) | +| Test.kt:38:9:38:13 | After ... > ... [false] | 2 | Test.kt:43:3:43:8 | ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 3 | Test.kt:43:3:43:8 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 4 | Test.kt:43:3:43:8 | z | +| Test.kt:38:9:38:13 | After ... > ... [false] | 5 | Test.kt:43:7:43:8 | 30 | +| Test.kt:38:9:38:13 | After ... > ... [false] | 6 | Test.kt:43:3:43:8 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 7 | Test.kt:43:3:43:8 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 8 | Test.kt:43:3:43:8 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 9 | Test.kt:73:3:73:8 | ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 10 | Test.kt:73:3:73:8 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 11 | Test.kt:73:3:73:8 | z | +| Test.kt:38:9:38:13 | After ... > ... [false] | 12 | Test.kt:73:7:73:8 | 50 | +| Test.kt:38:9:38:13 | After ... > ... [false] | 13 | Test.kt:73:3:73:8 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 14 | Test.kt:73:3:73:8 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 15 | Test.kt:73:3:73:8 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 16 | Test.kt:77:3:77:8 | ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 17 | Test.kt:77:3:77:8 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 18 | Test.kt:77:3:77:8 | w | +| Test.kt:38:9:38:13 | After ... > ... [false] | 19 | Test.kt:77:7:77:8 | 40 | +| Test.kt:38:9:38:13 | After ... > ... [false] | 20 | Test.kt:77:3:77:8 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 21 | Test.kt:77:3:77:8 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 22 | Test.kt:77:3:77:8 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [false] | 23 | Test.kt:78:3:78:8 | Before return ... | +| Test.kt:38:9:38:13 | After ... > ... [false] | 24 | Test.kt:78:9:78:9 | INSTANCE | +| Test.kt:38:9:38:13 | After ... > ... [false] | 25 | Test.kt:78:3:78:8 | return ... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 0 | Test.kt:38:9:38:13 | After ... > ... [true] | +| Test.kt:38:9:38:13 | After ... > ... [true] | 1 | Test.kt:38:16:41:3 | { ... } | +| Test.kt:38:9:38:13 | After ... > ... [true] | 2 | Test.kt:39:4:39:9 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 3 | Test.kt:39:4:39:9 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 4 | Test.kt:39:4:39:9 | y | +| Test.kt:38:9:38:13 | After ... > ... [true] | 5 | Test.kt:39:8:39:9 | 10 | +| Test.kt:38:9:38:13 | After ... > ... [true] | 6 | Test.kt:39:4:39:9 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 7 | Test.kt:39:4:39:9 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 8 | Test.kt:39:4:39:9 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 9 | Test.kt:40:4:40:6 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 10 | Test.kt:40:4:40:6 | Before | +| Test.kt:38:9:38:13 | After ... > ... [true] | 11 | Test.kt:40:4:40:6 | Before | +| Test.kt:38:9:38:13 | After ... > ... [true] | 12 | Test.kt:40:4:40:6 | { ... } | +| Test.kt:38:9:38:13 | After ... > ... [true] | 13 | Test.kt:40:4:40:6 | var ...; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 14 | Test.kt:40:4:40:6 | Before | +| Test.kt:38:9:38:13 | After ... > ... [true] | 15 | Test.kt:40:4:40:4 | x | +| Test.kt:38:9:38:13 | After ... > ... [true] | 16 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 17 | Test.kt:40:4:40:6 | After | +| Test.kt:38:9:38:13 | After ... > ... [true] | 18 | Test.kt:40:4:40:6 | After var ...; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 19 | Test.kt:40:4:40:6 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 20 | Test.kt:40:4:40:6 | Before ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 21 | Test.kt:40:4:40:6 | x | +| Test.kt:38:9:38:13 | After ... > ... [true] | 22 | Test.kt:40:4:40:6 | Before dec(...) | +| Test.kt:38:9:38:13 | After ... > ... [true] | 23 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 24 | Test.kt:40:4:40:6 | dec(...) | +| Test.kt:38:9:38:13 | After ... > ... [true] | 25 | Test.kt:40:4:40:6 | After dec(...) | +| Test.kt:38:9:38:13 | After ... > ... [true] | 26 | Test.kt:40:4:40:6 | ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 27 | Test.kt:40:4:40:6 | After ...=... | +| Test.kt:38:9:38:13 | After ... > ... [true] | 28 | Test.kt:40:4:40:6 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 29 | Test.kt:40:4:40:6 | ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 30 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 31 | Test.kt:40:4:40:6 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 32 | Test.kt:40:4:40:6 | After { ... } | +| Test.kt:38:9:38:13 | After ... > ... [true] | 33 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 34 | Test.kt:40:4:40:6 | After | +| Test.kt:38:9:38:13 | After ... > ... [true] | 35 | Test.kt:40:4:40:6 | | +| Test.kt:38:9:38:13 | After ... > ... [true] | 36 | Test.kt:40:4:40:6 | After | +| Test.kt:38:9:38:13 | After ... > ... [true] | 37 | Test.kt:40:4:40:6 | After ; | +| Test.kt:38:9:38:13 | After ... > ... [true] | 38 | Test.kt:38:16:41:3 | After { ... } | +| Test.kt:82:1:89:1 | Entry | 0 | Test.kt:82:1:89:1 | Entry | +| Test.kt:82:1:89:1 | Entry | 1 | Test.kt:82:21:89:1 | { ... } | +| Test.kt:82:1:89:1 | Entry | 2 | Test.kt:83:2:88:2 | try ... | +| Test.kt:82:1:89:1 | Entry | 3 | Test.kt:83:6:86:2 | { ... } | +| Test.kt:82:1:89:1 | Entry | 4 | Test.kt:84:3:84:18 | var ...; | +| Test.kt:82:1:89:1 | Entry | 5 | Test.kt:84:3:84:18 | Before x | +| Test.kt:82:1:89:1 | Entry | 6 | Test.kt:84:11:84:18 | Before (...)... | +| Test.kt:82:1:89:1 | Entry | 7 | Test.kt:84:11:84:11 | o | +| Test.kt:82:1:89:1 | Entry | 8 | Test.kt:84:11:84:18 | (...)... | | Test.kt:82:1:89:1 | Exit | 0 | Test.kt:82:1:89:1 | Exit | | Test.kt:82:1:89:1 | Normal Exit | 0 | Test.kt:82:1:89:1 | Normal Exit | -| Test.kt:82:21:89:1 | { ... } | 0 | Test.kt:82:21:89:1 | { ... } | -| Test.kt:82:21:89:1 | { ... } | 1 | Test.kt:83:2:88:2 | try ... | -| Test.kt:82:21:89:1 | { ... } | 2 | Test.kt:83:6:86:2 | { ... } | -| Test.kt:82:21:89:1 | { ... } | 3 | Test.kt:84:3:84:18 | var ...; | -| Test.kt:82:21:89:1 | { ... } | 4 | Test.kt:84:11:84:11 | o | -| Test.kt:82:21:89:1 | { ... } | 5 | Test.kt:84:11:84:18 | (...)... | -| Test.kt:84:3:84:18 | x | 0 | Test.kt:84:3:84:18 | x | -| Test.kt:84:3:84:18 | x | 1 | Test.kt:85:10:85:10 | 1 | -| Test.kt:84:3:84:18 | x | 2 | Test.kt:85:3:85:10 | return ... | +| Test.kt:84:11:84:18 | After (...)... | 0 | Test.kt:84:11:84:18 | After (...)... | +| Test.kt:84:11:84:18 | After (...)... | 1 | Test.kt:84:3:84:18 | x | +| Test.kt:84:11:84:18 | After (...)... | 2 | Test.kt:84:3:84:18 | After x | +| Test.kt:84:11:84:18 | After (...)... | 3 | Test.kt:84:3:84:18 | After var ...; | +| Test.kt:84:11:84:18 | After (...)... | 4 | Test.kt:85:3:85:10 | Before return ... | +| Test.kt:84:11:84:18 | After (...)... | 5 | Test.kt:85:10:85:10 | 1 | +| Test.kt:84:11:84:18 | After (...)... | 6 | Test.kt:85:3:85:10 | return ... | +| Test.kt:86:4:88:2 | After catch (...) [match] | 0 | Test.kt:86:4:88:2 | After catch (...) [match] | +| Test.kt:86:4:88:2 | After catch (...) [match] | 1 | Test.kt:86:11:86:31 | e | +| Test.kt:86:4:88:2 | After catch (...) [match] | 2 | Test.kt:86:34:88:2 | { ... } | +| Test.kt:86:4:88:2 | After catch (...) [match] | 3 | Test.kt:87:3:87:10 | Before return ... | +| Test.kt:86:4:88:2 | After catch (...) [match] | 4 | Test.kt:87:10:87:10 | 2 | +| Test.kt:86:4:88:2 | After catch (...) [match] | 5 | Test.kt:87:3:87:10 | return ... | +| Test.kt:86:4:88:2 | After catch (...) [no-match] | 0 | Test.kt:86:4:88:2 | After catch (...) [no-match] | +| Test.kt:86:4:88:2 | After catch (...) [no-match] | 1 | Test.kt:82:1:89:1 | Exceptional Exit | | Test.kt:86:4:88:2 | catch (...) | 0 | Test.kt:86:4:88:2 | catch (...) | -| Test.kt:86:4:88:2 | catch (...) | 1 | Test.kt:86:11:86:31 | e | -| Test.kt:86:4:88:2 | catch (...) | 2 | Test.kt:86:34:88:2 | { ... } | -| Test.kt:86:4:88:2 | catch (...) | 3 | Test.kt:87:10:87:10 | 2 | -| Test.kt:86:4:88:2 | catch (...) | 4 | Test.kt:87:3:87:10 | return ... | -| Test.kt:91:1:98:1 | Exceptional Exit | 0 | Test.kt:91:1:98:1 | Exceptional Exit | +| Test.kt:91:1:98:1 | Entry | 0 | Test.kt:91:1:98:1 | Entry | +| Test.kt:91:1:98:1 | Entry | 1 | Test.kt:91:22:98:1 | { ... } | +| Test.kt:91:1:98:1 | Entry | 2 | Test.kt:92:2:97:2 | try ... | +| Test.kt:91:1:98:1 | Entry | 3 | Test.kt:92:6:95:2 | { ... } | +| Test.kt:91:1:98:1 | Entry | 4 | Test.kt:93:3:93:13 | var ...; | +| Test.kt:91:1:98:1 | Entry | 5 | Test.kt:93:3:93:13 | Before x | +| Test.kt:91:1:98:1 | Entry | 6 | Test.kt:93:11:93:13 | Before ...!! | +| Test.kt:91:1:98:1 | Entry | 7 | Test.kt:93:11:93:11 | o | +| Test.kt:91:1:98:1 | Entry | 8 | Test.kt:93:11:93:13 | ...!! | | Test.kt:91:1:98:1 | Exit | 0 | Test.kt:91:1:98:1 | Exit | | Test.kt:91:1:98:1 | Normal Exit | 0 | Test.kt:91:1:98:1 | Normal Exit | -| Test.kt:91:22:98:1 | { ... } | 0 | Test.kt:91:22:98:1 | { ... } | -| Test.kt:91:22:98:1 | { ... } | 1 | Test.kt:92:2:97:2 | try ... | -| Test.kt:91:22:98:1 | { ... } | 2 | Test.kt:92:6:95:2 | { ... } | -| Test.kt:91:22:98:1 | { ... } | 3 | Test.kt:93:3:93:13 | var ...; | -| Test.kt:91:22:98:1 | { ... } | 4 | Test.kt:93:11:93:11 | o | -| Test.kt:91:22:98:1 | { ... } | 5 | Test.kt:93:11:93:13 | ...!! | -| Test.kt:93:3:93:13 | x | 0 | Test.kt:93:3:93:13 | x | -| Test.kt:93:3:93:13 | x | 1 | Test.kt:94:10:94:10 | 1 | -| Test.kt:93:3:93:13 | x | 2 | Test.kt:94:3:94:10 | return ... | +| Test.kt:93:11:93:13 | After ...!! | 0 | Test.kt:93:11:93:13 | After ...!! | +| Test.kt:93:11:93:13 | After ...!! | 1 | Test.kt:93:3:93:13 | x | +| Test.kt:93:11:93:13 | After ...!! | 2 | Test.kt:93:3:93:13 | After x | +| Test.kt:93:11:93:13 | After ...!! | 3 | Test.kt:93:3:93:13 | After var ...; | +| Test.kt:93:11:93:13 | After ...!! | 4 | Test.kt:94:3:94:10 | Before return ... | +| Test.kt:93:11:93:13 | After ...!! | 5 | Test.kt:94:10:94:10 | 1 | +| Test.kt:93:11:93:13 | After ...!! | 6 | Test.kt:94:3:94:10 | return ... | +| Test.kt:95:4:97:2 | After catch (...) [match] | 0 | Test.kt:95:4:97:2 | After catch (...) [match] | +| Test.kt:95:4:97:2 | After catch (...) [match] | 1 | Test.kt:95:11:95:33 | e | +| Test.kt:95:4:97:2 | After catch (...) [match] | 2 | Test.kt:95:36:97:2 | { ... } | +| Test.kt:95:4:97:2 | After catch (...) [match] | 3 | Test.kt:96:3:96:10 | Before return ... | +| Test.kt:95:4:97:2 | After catch (...) [match] | 4 | Test.kt:96:10:96:10 | 2 | +| Test.kt:95:4:97:2 | After catch (...) [match] | 5 | Test.kt:96:3:96:10 | return ... | +| Test.kt:95:4:97:2 | After catch (...) [no-match] | 0 | Test.kt:95:4:97:2 | After catch (...) [no-match] | +| Test.kt:95:4:97:2 | After catch (...) [no-match] | 1 | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:95:4:97:2 | catch (...) | 0 | Test.kt:95:4:97:2 | catch (...) | -| Test.kt:95:4:97:2 | catch (...) | 1 | Test.kt:95:11:95:33 | e | -| Test.kt:95:4:97:2 | catch (...) | 2 | Test.kt:95:36:97:2 | { ... } | -| Test.kt:95:4:97:2 | catch (...) | 3 | Test.kt:96:10:96:10 | 2 | -| Test.kt:95:4:97:2 | catch (...) | 4 | Test.kt:96:3:96:10 | return ... | +| Test.kt:100:1:110:1 | Entry | 0 | Test.kt:100:1:110:1 | Entry | +| Test.kt:100:1:110:1 | Entry | 1 | Test.kt:100:25:110:1 | { ... } | +| Test.kt:100:1:110:1 | Entry | 2 | Test.kt:101:5:103:5 | ; | +| Test.kt:100:1:110:1 | Entry | 3 | Test.kt:101:5:103:5 | when ... | +| Test.kt:100:1:110:1 | Entry | 4 | Test.kt:101:9:103:5 | ... -> ... | +| Test.kt:100:1:110:1 | Entry | 5 | Test.kt:101:9:101:30 | ... && ... | +| Test.kt:100:1:110:1 | Entry | 6 | Test.kt:101:9:101:17 | Before ... (value equals) ... | +| Test.kt:100:1:110:1 | Entry | 7 | Test.kt:101:9:101:9 | x | +| Test.kt:100:1:110:1 | Entry | 8 | Test.kt:101:14:101:17 | null | +| Test.kt:100:1:110:1 | Entry | 9 | Test.kt:101:9:101:17 | ... (value equals) ... | | Test.kt:100:1:110:1 | Exit | 0 | Test.kt:100:1:110:1 | Exit | -| Test.kt:100:1:110:1 | Normal Exit | 0 | Test.kt:100:1:110:1 | Normal Exit | -| Test.kt:100:25:110:1 | { ... } | 0 | Test.kt:100:25:110:1 | { ... } | -| Test.kt:100:25:110:1 | { ... } | 1 | Test.kt:101:5:103:5 | ; | -| Test.kt:100:25:110:1 | { ... } | 2 | Test.kt:101:5:103:5 | when ... | -| Test.kt:100:25:110:1 | { ... } | 3 | Test.kt:101:9:103:5 | ... -> ... | -| Test.kt:100:25:110:1 | { ... } | 4 | Test.kt:101:9:101:30 | ... && ... | -| Test.kt:100:25:110:1 | { ... } | 5 | Test.kt:101:9:101:9 | x | -| Test.kt:100:25:110:1 | { ... } | 6 | Test.kt:101:14:101:17 | null | -| Test.kt:100:25:110:1 | { ... } | 7 | Test.kt:101:9:101:17 | ... (value equals) ... | -| Test.kt:101:22:101:22 | y | 0 | Test.kt:101:22:101:22 | y | -| Test.kt:101:22:101:22 | y | 1 | Test.kt:101:27:101:30 | null | -| Test.kt:101:22:101:22 | y | 2 | Test.kt:101:22:101:30 | ... (value equals) ... | -| Test.kt:101:33:103:5 | { ... } | 0 | Test.kt:101:33:103:5 | { ... } | -| Test.kt:101:33:103:5 | { ... } | 1 | Test.kt:102:15:102:25 | new Exception(...) | -| Test.kt:101:33:103:5 | { ... } | 2 | Test.kt:102:9:102:25 | throw ... | -| Test.kt:101:33:103:5 | { ... } | 3 | Test.kt:100:1:110:1 | Exceptional Exit | -| Test.kt:105:5:109:5 | ; | 0 | Test.kt:105:5:109:5 | ; | -| Test.kt:105:5:109:5 | ; | 1 | Test.kt:105:5:109:5 | when ... | -| Test.kt:105:5:109:5 | ; | 2 | Test.kt:105:9:107:5 | ... -> ... | -| Test.kt:105:5:109:5 | ; | 3 | Test.kt:105:9:105:9 | x | -| Test.kt:105:5:109:5 | ; | 4 | Test.kt:105:14:105:17 | null | -| Test.kt:105:5:109:5 | ; | 5 | Test.kt:105:9:105:17 | ... (value not-equals) ... | -| Test.kt:105:20:107:5 | { ... } | 0 | Test.kt:105:20:107:5 | { ... } | -| Test.kt:105:20:107:5 | { ... } | 1 | Test.kt:106:9:106:29 | ; | -| Test.kt:105:20:107:5 | { ... } | 2 | Test.kt:106:17:106:28 | "x not null" | -| Test.kt:105:20:107:5 | { ... } | 3 | Test.kt:106:9:106:29 | println(...) | -| Test.kt:107:16:109:5 | ... -> ... | 0 | Test.kt:107:16:109:5 | ... -> ... | -| Test.kt:107:16:109:5 | ... -> ... | 1 | Test.kt:107:16:107:16 | y | -| Test.kt:107:16:109:5 | ... -> ... | 2 | Test.kt:107:21:107:24 | null | -| Test.kt:107:16:109:5 | ... -> ... | 3 | Test.kt:107:16:107:24 | ... (value not-equals) ... | -| Test.kt:107:27:109:5 | { ... } | 0 | Test.kt:107:27:109:5 | { ... } | -| Test.kt:107:27:109:5 | { ... } | 1 | Test.kt:108:9:108:29 | ; | -| Test.kt:107:27:109:5 | { ... } | 2 | Test.kt:108:17:108:28 | "y not null" | -| Test.kt:107:27:109:5 | { ... } | 3 | Test.kt:108:9:108:29 | println(...) | -| Test.kt:112:1:116:1 | Exceptional Exit | 0 | Test.kt:112:1:116:1 | Exceptional Exit | -| Test.kt:112:1:116:1 | Exit | 0 | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:1:116:1 | Normal Exit | 0 | Test.kt:112:1:116:1 | Normal Exit | -| Test.kt:112:32:116:1 | { ... } | 0 | Test.kt:112:32:116:1 | { ... } | -| Test.kt:112:32:116:1 | { ... } | 1 | Test.kt:113:5:115:5 | ; | -| Test.kt:112:32:116:1 | { ... } | 2 | Test.kt:113:5:115:5 | when ... | -| Test.kt:112:32:116:1 | { ... } | 3 | Test.kt:113:9:115:5 | ... -> ... | -| Test.kt:112:32:116:1 | { ... } | 4 | Test.kt:113:9:113:14 | ... && ... | -| Test.kt:112:32:116:1 | { ... } | 5 | Test.kt:113:9:113:9 | x | -| Test.kt:113:14:113:14 | y | 0 | Test.kt:113:14:113:14 | y | -| Test.kt:113:17:115:5 | { ... } | 0 | Test.kt:113:17:115:5 | { ... } | -| Test.kt:118:1:124:1 | Exceptional Exit | 0 | Test.kt:118:1:124:1 | Exceptional Exit | -| Test.kt:118:1:124:1 | Exit | 0 | Test.kt:118:1:124:1 | Exit | -| Test.kt:118:1:124:1 | Normal Exit | 0 | Test.kt:118:1:124:1 | Normal Exit | -| Test.kt:118:37:124:1 | { ... } | 0 | Test.kt:118:37:124:1 | { ... } | -| Test.kt:118:37:124:1 | { ... } | 1 | Test.kt:119:2:123:12 | ; | -| Test.kt:118:37:124:1 | { ... } | 2 | Test.kt:119:2:123:12 | when ... | -| Test.kt:118:37:124:1 | { ... } | 3 | Test.kt:120:3:123:10 | ... -> ... | -| Test.kt:118:37:124:1 | { ... } | 4 | Test.kt:120:3:123:3 | when ... | -| Test.kt:118:37:124:1 | { ... } | 5 | Test.kt:121:4:121:9 | ... -> ... | -| Test.kt:118:37:124:1 | { ... } | 6 | Test.kt:121:4:121:4 | x | -| Test.kt:121:9:121:9 | ; | 0 | Test.kt:121:9:121:9 | ; | -| Test.kt:121:9:121:9 | ; | 1 | Test.kt:121:9:121:9 | y | -| Test.kt:122:12:122:16 | ... -> ... | 0 | Test.kt:122:12:122:16 | ... -> ... | -| Test.kt:122:12:122:16 | ... -> ... | 1 | Test.kt:122:12:122:16 | true | -| Test.kt:122:12:122:16 | ... -> ... | 2 | Test.kt:122:12:122:16 | ; | -| Test.kt:122:12:122:16 | ... -> ... | 3 | Test.kt:122:12:122:16 | false | -| Test.kt:123:8:123:10 | { ... } | 0 | Test.kt:123:8:123:10 | { ... } | +| Test.kt:101:9:101:17 | After ... (value equals) ... [false] | 0 | Test.kt:101:9:101:17 | After ... (value equals) ... [false] | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 0 | Test.kt:101:9:101:17 | After ... (value equals) ... [true] | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 1 | Test.kt:101:22:101:30 | Before ... (value equals) ... | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 2 | Test.kt:101:22:101:22 | y | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 3 | Test.kt:101:27:101:30 | null | +| Test.kt:101:9:101:17 | After ... (value equals) ... [true] | 4 | Test.kt:101:22:101:30 | ... (value equals) ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 0 | Test.kt:101:9:101:30 | After ... && ... [false] | +| Test.kt:101:9:101:30 | After ... && ... [false] | 1 | Test.kt:101:5:103:5 | After when ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 2 | Test.kt:101:5:103:5 | After ; | +| Test.kt:101:9:101:30 | After ... && ... [false] | 3 | Test.kt:105:5:109:5 | ; | +| Test.kt:101:9:101:30 | After ... && ... [false] | 4 | Test.kt:105:5:109:5 | when ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 5 | Test.kt:105:9:107:5 | ... -> ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 6 | Test.kt:105:9:105:17 | Before ... (value not-equals) ... | +| Test.kt:101:9:101:30 | After ... && ... [false] | 7 | Test.kt:105:9:105:9 | x | +| Test.kt:101:9:101:30 | After ... && ... [false] | 8 | Test.kt:105:14:105:17 | null | +| Test.kt:101:9:101:30 | After ... && ... [false] | 9 | Test.kt:105:9:105:17 | ... (value not-equals) ... | +| Test.kt:101:22:101:30 | After ... (value equals) ... [false] | 0 | Test.kt:101:22:101:30 | After ... (value equals) ... [false] | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 0 | Test.kt:101:22:101:30 | After ... (value equals) ... [true] | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 1 | Test.kt:101:9:101:30 | After ... && ... [true] | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 2 | Test.kt:101:33:103:5 | { ... } | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 3 | Test.kt:102:9:102:25 | Before throw ... | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 4 | Test.kt:102:15:102:25 | Before new Exception(...) | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 5 | Test.kt:102:15:102:25 | new Exception(...) | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 6 | Test.kt:102:15:102:25 | After new Exception(...) | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 7 | Test.kt:102:9:102:25 | throw ... | +| Test.kt:101:22:101:30 | After ... (value equals) ... [true] | 8 | Test.kt:100:1:110:1 | Exceptional Exit | +| Test.kt:105:5:109:5 | After when ... | 0 | Test.kt:105:5:109:5 | After when ... | +| Test.kt:105:5:109:5 | After when ... | 1 | Test.kt:105:5:109:5 | After ; | +| Test.kt:105:5:109:5 | After when ... | 2 | Test.kt:100:25:110:1 | After { ... } | +| Test.kt:105:5:109:5 | After when ... | 3 | Test.kt:100:1:110:1 | Normal Exit | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 0 | Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 1 | Test.kt:107:16:109:5 | ... -> ... | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 2 | Test.kt:107:16:107:24 | Before ... (value not-equals) ... | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 3 | Test.kt:107:16:107:16 | y | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 4 | Test.kt:107:21:107:24 | null | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [false] | 5 | Test.kt:107:16:107:24 | ... (value not-equals) ... | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 0 | Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 1 | Test.kt:105:20:107:5 | { ... } | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 2 | Test.kt:106:9:106:29 | ; | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 3 | Test.kt:106:9:106:29 | Before println(...) | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 4 | Test.kt:106:17:106:28 | "x not null" | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 5 | Test.kt:106:9:106:29 | println(...) | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 6 | Test.kt:106:9:106:29 | After println(...) | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 7 | Test.kt:106:9:106:29 | After ; | +| Test.kt:105:9:105:17 | After ... (value not-equals) ... [true] | 8 | Test.kt:105:20:107:5 | After { ... } | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | 0 | Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 0 | Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 1 | Test.kt:107:27:109:5 | { ... } | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 2 | Test.kt:108:9:108:29 | ; | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 3 | Test.kt:108:9:108:29 | Before println(...) | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 4 | Test.kt:108:17:108:28 | "y not null" | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 5 | Test.kt:108:9:108:29 | println(...) | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 6 | Test.kt:108:9:108:29 | After println(...) | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 7 | Test.kt:108:9:108:29 | After ; | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [true] | 8 | Test.kt:107:27:109:5 | After { ... } | +| Test.kt:112:1:116:1 | Entry | 0 | Test.kt:112:1:116:1 | Entry | +| Test.kt:112:1:116:1 | Entry | 1 | Test.kt:112:32:116:1 | { ... } | +| Test.kt:112:1:116:1 | Entry | 2 | Test.kt:113:5:115:5 | ; | +| Test.kt:112:1:116:1 | Entry | 3 | Test.kt:113:5:115:5 | when ... | +| Test.kt:112:1:116:1 | Entry | 4 | Test.kt:113:9:115:5 | ... -> ... | +| Test.kt:112:1:116:1 | Entry | 5 | Test.kt:113:9:113:14 | ... && ... | +| Test.kt:112:1:116:1 | Entry | 6 | Test.kt:113:9:113:9 | x | +| Test.kt:113:5:115:5 | After when ... | 0 | Test.kt:113:5:115:5 | After when ... | +| Test.kt:113:5:115:5 | After when ... | 1 | Test.kt:113:5:115:5 | After ; | +| Test.kt:113:5:115:5 | After when ... | 2 | Test.kt:112:32:116:1 | After { ... } | +| Test.kt:113:5:115:5 | After when ... | 3 | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:113:5:115:5 | After when ... | 4 | Test.kt:112:1:116:1 | Exit | +| Test.kt:113:9:113:9 | After x [false] | 0 | Test.kt:113:9:113:9 | After x [false] | +| Test.kt:113:9:113:9 | After x [true] | 0 | Test.kt:113:9:113:9 | After x [true] | +| Test.kt:113:9:113:9 | After x [true] | 1 | Test.kt:113:14:113:14 | y | +| Test.kt:113:9:113:14 | After ... && ... [false] | 0 | Test.kt:113:9:113:14 | After ... && ... [false] | +| Test.kt:113:14:113:14 | After y [false] | 0 | Test.kt:113:14:113:14 | After y [false] | +| Test.kt:113:14:113:14 | After y [true] | 0 | Test.kt:113:14:113:14 | After y [true] | +| Test.kt:113:14:113:14 | After y [true] | 1 | Test.kt:113:9:113:14 | After ... && ... [true] | +| Test.kt:113:14:113:14 | After y [true] | 2 | Test.kt:113:17:115:5 | { ... } | +| Test.kt:118:1:124:1 | Entry | 0 | Test.kt:118:1:124:1 | Entry | +| Test.kt:118:1:124:1 | Entry | 1 | Test.kt:118:37:124:1 | { ... } | +| Test.kt:118:1:124:1 | Entry | 2 | Test.kt:119:2:123:12 | ; | +| Test.kt:118:1:124:1 | Entry | 3 | Test.kt:119:2:123:12 | when ... | +| Test.kt:118:1:124:1 | Entry | 4 | Test.kt:120:3:123:10 | ... -> ... | +| Test.kt:118:1:124:1 | Entry | 5 | Test.kt:120:3:123:3 | when ... | +| Test.kt:118:1:124:1 | Entry | 6 | Test.kt:121:4:121:9 | ... -> ... | +| Test.kt:118:1:124:1 | Entry | 7 | Test.kt:121:4:121:4 | x | +| Test.kt:119:2:123:12 | After when ... | 0 | Test.kt:119:2:123:12 | After when ... | +| Test.kt:119:2:123:12 | After when ... | 1 | Test.kt:119:2:123:12 | After ; | +| Test.kt:119:2:123:12 | After when ... | 2 | Test.kt:118:37:124:1 | After { ... } | +| Test.kt:119:2:123:12 | After when ... | 3 | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:119:2:123:12 | After when ... | 4 | Test.kt:118:1:124:1 | Exit | +| Test.kt:120:3:123:3 | After when ... [false] | 0 | Test.kt:120:3:123:3 | After when ... [false] | +| Test.kt:120:3:123:3 | After when ... [true] | 0 | Test.kt:120:3:123:3 | After when ... [true] | +| Test.kt:120:3:123:3 | After when ... [true] | 1 | Test.kt:123:8:123:10 | { ... } | +| Test.kt:121:4:121:4 | After x [false] | 0 | Test.kt:121:4:121:4 | After x [false] | +| Test.kt:121:4:121:4 | After x [false] | 1 | Test.kt:122:12:122:16 | ... -> ... | +| Test.kt:121:4:121:4 | After x [false] | 2 | Test.kt:122:12:122:16 | true | +| Test.kt:121:4:121:4 | After x [false] | 3 | Test.kt:122:12:122:16 | After true [true] | +| Test.kt:121:4:121:4 | After x [false] | 4 | Test.kt:122:12:122:16 | ; | +| Test.kt:121:4:121:4 | After x [false] | 5 | Test.kt:122:12:122:16 | false | +| Test.kt:121:4:121:4 | After x [false] | 6 | Test.kt:122:12:122:16 | After ; | +| Test.kt:121:4:121:4 | After x [true] | 0 | Test.kt:121:4:121:4 | After x [true] | +| Test.kt:121:4:121:4 | After x [true] | 1 | Test.kt:121:9:121:9 | ; | +| Test.kt:121:4:121:4 | After x [true] | 2 | Test.kt:121:9:121:9 | y | +| Test.kt:121:4:121:4 | After x [true] | 3 | Test.kt:121:9:121:9 | After ; | diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected index c7e225ecc6f4..a4a9b68d4041 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.expected @@ -1,6 +1,3 @@ -| Test.kt:3:1:80:1 | { ... } | Test.kt:3:1:80:1 | Exit | -| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit | -| Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Exit | | Test.kt:4:13:79:2 | { ... } | Test.kt:4:2:79:2 | Normal Exit | | Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } | | Test.kt:4:13:79:2 | { ... } | Test.kt:14:10:16:3 | ... -> ... | @@ -12,7 +9,6 @@ | Test.kt:4:13:79:2 | { ... } | Test.kt:38:9:38:9 | x | | Test.kt:4:13:79:2 | { ... } | Test.kt:38:16:41:3 | { ... } | | Test.kt:4:13:79:2 | { ... } | Test.kt:43:3:43:8 | ; | -| Test.kt:18:3:18:7 | ; | Test.kt:4:2:79:2 | Exit | | Test.kt:18:3:18:7 | ; | Test.kt:4:2:79:2 | Normal Exit | | Test.kt:18:3:18:7 | ; | Test.kt:22:4:22:9 | ; | | Test.kt:18:3:18:7 | ; | Test.kt:24:4:24:9 | ... -> ... | @@ -31,16 +27,22 @@ | Test.kt:35:3:35:8 | ; | Test.kt:43:3:43:8 | ; | | Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } | | Test.kt:38:9:38:9 | x | Test.kt:43:3:43:8 | ; | -| Test.kt:82:1:89:1 | Normal Exit | Test.kt:82:1:89:1 | Exit | +| Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exceptional Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x | | Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) | -| Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit | +| Test.kt:82:21:89:1 | { ... } | Test.kt:86:11:86:31 | e | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e | +| Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exceptional Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x | | Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) | +| Test.kt:91:22:98:1 | { ... } | Test.kt:95:11:95:33 | e | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e | | Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:100:1:110:1 | Normal Exit | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y | @@ -55,16 +57,11 @@ | Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... | | Test.kt:105:5:109:5 | ; | Test.kt:107:27:109:5 | { ... } | | Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } | -| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Exit | | Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit | | Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y | | Test.kt:112:32:116:1 | { ... } | Test.kt:113:17:115:5 | { ... } | | Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } | -| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit | -| Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Exit | | Test.kt:118:37:124:1 | { ... } | Test.kt:118:1:124:1 | Normal Exit | | Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; | | Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... | | Test.kt:118:37:124:1 | { ... } | Test.kt:123:8:123:10 | { ... } | -| Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } | diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.ql b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.ql index de1e23b649cc..72de0cc435d3 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.ql +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbStrictDominance.ql @@ -1,6 +1,7 @@ import java import semmle.code.java.controlflow.Dominance +import utils.test.BasicBlock from BasicBlock b, BasicBlock b2 where b.strictlyDominates(b2) -select b, b2 +select getFirstAstNode(b), getFirstAstNode(b2) diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected index 219779e73dc7..060e3fcae70d 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.expected @@ -1,16 +1,13 @@ -| Test.kt:3:1:80:1 | Exceptional Exit | Test.kt:3:1:80:1 | Exit | -| Test.kt:3:1:80:1 | { ... } | Test.kt:3:1:80:1 | Exit | -| Test.kt:4:2:79:2 | Exceptional Exit | Test.kt:4:2:79:2 | Exit | -| Test.kt:4:2:79:2 | Normal Exit | Test.kt:4:2:79:2 | Exit | | Test.kt:4:13:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } | | Test.kt:4:13:79:2 | { ... } | Test.kt:14:10:16:3 | ... -> ... | | Test.kt:11:14:14:3 | { ... } | Test.kt:18:3:18:7 | ; | | Test.kt:14:10:16:3 | ... -> ... | Test.kt:18:3:18:7 | ; | | Test.kt:18:3:18:7 | ; | Test.kt:22:4:22:9 | ; | | Test.kt:18:3:18:7 | ; | Test.kt:24:4:24:9 | ... -> ... | +| Test.kt:22:4:22:9 | ; | Test.kt:30:7:30:12 | After ... (value equals) ... [false] | | Test.kt:22:4:22:9 | ; | Test.kt:30:15:33:3 | { ... } | -| Test.kt:22:4:22:9 | ; | Test.kt:35:3:35:8 | ; | | Test.kt:24:4:24:9 | ... -> ... | Test.kt:4:2:79:2 | Normal Exit | +| Test.kt:30:7:30:12 | After ... (value equals) ... [false] | Test.kt:35:3:35:8 | ; | | Test.kt:30:15:33:3 | { ... } | Test.kt:35:3:35:8 | ; | | Test.kt:35:3:35:8 | ; | Test.kt:38:9:38:9 | x | | Test.kt:38:9:38:9 | x | Test.kt:38:16:41:3 | { ... } | @@ -22,37 +19,45 @@ | Test.kt:82:21:89:1 | { ... } | Test.kt:84:3:84:18 | x | | Test.kt:82:21:89:1 | { ... } | Test.kt:86:4:88:2 | catch (...) | | Test.kt:84:3:84:18 | x | Test.kt:82:1:89:1 | Normal Exit | -| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Normal Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:82:1:89:1 | Exceptional Exit | +| Test.kt:86:4:88:2 | catch (...) | Test.kt:86:11:86:31 | e | +| Test.kt:86:11:86:31 | e | Test.kt:82:1:89:1 | Normal Exit | | Test.kt:91:1:98:1 | Exceptional Exit | Test.kt:91:1:98:1 | Exit | | Test.kt:91:1:98:1 | Normal Exit | Test.kt:91:1:98:1 | Exit | | Test.kt:91:22:98:1 | { ... } | Test.kt:93:3:93:13 | x | | Test.kt:91:22:98:1 | { ... } | Test.kt:95:4:97:2 | catch (...) | | Test.kt:93:3:93:13 | x | Test.kt:91:1:98:1 | Normal Exit | -| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Normal Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:91:1:98:1 | Exceptional Exit | +| Test.kt:95:4:97:2 | catch (...) | Test.kt:95:11:95:33 | e | +| Test.kt:95:11:95:33 | e | Test.kt:91:1:98:1 | Normal Exit | | Test.kt:100:1:110:1 | Normal Exit | Test.kt:100:1:110:1 | Exit | +| Test.kt:100:25:110:1 | { ... } | Test.kt:101:9:101:17 | After ... (value equals) ... [false] | | Test.kt:100:25:110:1 | { ... } | Test.kt:101:22:101:22 | y | -| Test.kt:100:25:110:1 | { ... } | Test.kt:105:5:109:5 | ; | +| Test.kt:101:9:101:17 | After ... (value equals) ... [false] | Test.kt:105:5:109:5 | ; | +| Test.kt:101:22:101:22 | y | Test.kt:101:22:101:30 | After ... (value equals) ... [false] | | Test.kt:101:22:101:22 | y | Test.kt:101:33:103:5 | { ... } | -| Test.kt:101:22:101:22 | y | Test.kt:105:5:109:5 | ; | +| Test.kt:101:22:101:30 | After ... (value equals) ... [false] | Test.kt:105:5:109:5 | ; | | Test.kt:101:33:103:5 | { ... } | Test.kt:100:1:110:1 | Exit | | Test.kt:105:5:109:5 | ; | Test.kt:105:20:107:5 | { ... } | | Test.kt:105:5:109:5 | ; | Test.kt:107:16:109:5 | ... -> ... | | Test.kt:105:20:107:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit | -| Test.kt:107:16:109:5 | ... -> ... | Test.kt:100:1:110:1 | Normal Exit | +| Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | Test.kt:100:1:110:1 | Normal Exit | +| Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:16:107:24 | After ... (value not-equals) ... [false] | | Test.kt:107:16:109:5 | ... -> ... | Test.kt:107:27:109:5 | { ... } | | Test.kt:107:27:109:5 | { ... } | Test.kt:100:1:110:1 | Normal Exit | -| Test.kt:112:1:116:1 | Exceptional Exit | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:1:116:1 | Normal Exit | Test.kt:112:1:116:1 | Exit | -| Test.kt:112:32:116:1 | { ... } | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:112:32:116:1 | { ... } | Test.kt:113:9:113:9 | After x [false] | | Test.kt:112:32:116:1 | { ... } | Test.kt:113:14:113:14 | y | -| Test.kt:113:14:113:14 | y | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:113:9:113:9 | After x [false] | Test.kt:113:9:113:14 | After ... && ... [false] | +| Test.kt:113:9:113:14 | After ... && ... [false] | Test.kt:112:1:116:1 | Normal Exit | +| Test.kt:113:14:113:14 | After y [false] | Test.kt:113:9:113:14 | After ... && ... [false] | +| Test.kt:113:14:113:14 | y | Test.kt:113:14:113:14 | After y [false] | | Test.kt:113:14:113:14 | y | Test.kt:113:17:115:5 | { ... } | | Test.kt:113:17:115:5 | { ... } | Test.kt:112:1:116:1 | Normal Exit | -| Test.kt:118:1:124:1 | Exceptional Exit | Test.kt:118:1:124:1 | Exit | -| Test.kt:118:1:124:1 | Normal Exit | Test.kt:118:1:124:1 | Exit | | Test.kt:118:37:124:1 | { ... } | Test.kt:121:9:121:9 | ; | | Test.kt:118:37:124:1 | { ... } | Test.kt:122:12:122:16 | ... -> ... | -| Test.kt:121:9:121:9 | ; | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:120:3:123:3 | After when ... [false] | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:121:9:121:9 | ; | Test.kt:120:3:123:3 | After when ... [false] | | Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } | -| Test.kt:122:12:122:16 | ... -> ... | Test.kt:118:1:124:1 | Normal Exit | +| Test.kt:122:12:122:16 | ... -> ... | Test.kt:120:3:123:3 | After when ... [false] | +| Test.kt:122:12:122:16 | ... -> ... | Test.kt:123:8:123:10 | { ... } | | Test.kt:123:8:123:10 | { ... } | Test.kt:118:1:124:1 | Normal Exit | diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.ql b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.ql index ae2d8a393b47..ae8dc5d188d6 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.ql +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/bbSuccessor.ql @@ -1,5 +1,6 @@ import java +import utils.test.BasicBlock from BasicBlock b, BasicBlock b2 where b.getASuccessor() = b2 -select b, b2 +select getFirstAstNodeOrSynth(b), getFirstAstNodeOrSynth(b2) diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected index c4be613c5e99..d5483586e0b8 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.expected @@ -1,12 +1,10 @@ #select -| Test.kt:3:1:80:1 | Exceptional Exit | Constructor | Test.kt:3:1:80:1 | Exit | Constructor | -| Test.kt:3:1:80:1 | Exit | Constructor | file://:0:0:0:0 | | | +| Test.kt:3:1:80:1 | Entry | Constructor | Test.kt:3:1:80:1 | { ... } | BlockStmt | | Test.kt:3:1:80:1 | Normal Exit | Constructor | Test.kt:3:1:80:1 | Exit | Constructor | | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | Test.kt:3:1:80:1 | { ... } | BlockStmt | | Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | Normal Exit | Constructor | | Test.kt:3:1:80:1 | { ... } | BlockStmt | Test.kt:3:1:80:1 | super(...) | SuperConstructorInvocationStmt | -| Test.kt:4:2:79:2 | Exceptional Exit | Method | Test.kt:4:2:79:2 | Exit | Method | -| Test.kt:4:2:79:2 | Exit | Method | file://:0:0:0:0 | | | +| Test.kt:4:2:79:2 | Entry | Method | Test.kt:4:13:79:2 | { ... } | BlockStmt | | Test.kt:4:2:79:2 | Normal Exit | Method | Test.kt:4:2:79:2 | Exit | Method | | Test.kt:4:13:79:2 | { ... } | BlockStmt | Test.kt:5:3:5:16 | var ...; | LocalVariableDeclStmt | | Test.kt:5:3:5:16 | var ...; | LocalVariableDeclStmt | Test.kt:5:16:5:16 | 0 | IntegerLiteral | @@ -30,19 +28,23 @@ | Test.kt:11:11:11:11 | 0 | IntegerLiteral | Test.kt:11:7:11:11 | ... > ... | GTExpr | | Test.kt:11:14:14:3 | { ... } | BlockStmt | Test.kt:12:4:12:9 | ; | ExprStmt | | Test.kt:12:4:12:9 | ...=... | AssignExpr | Test.kt:13:4:13:9 | ; | ExprStmt | -| Test.kt:12:4:12:9 | ; | ExprStmt | Test.kt:12:8:12:9 | 20 | LongLiteral | +| Test.kt:12:4:12:9 | ; | ExprStmt | Test.kt:12:4:12:9 | y | VarAccess | +| Test.kt:12:4:12:9 | y | VarAccess | Test.kt:12:8:12:9 | 20 | LongLiteral | | Test.kt:12:8:12:9 | 20 | LongLiteral | Test.kt:12:4:12:9 | ...=... | AssignExpr | | Test.kt:13:4:13:9 | ...=... | AssignExpr | Test.kt:18:3:18:7 | ; | ExprStmt | -| Test.kt:13:4:13:9 | ; | ExprStmt | Test.kt:13:8:13:9 | 10 | IntegerLiteral | +| Test.kt:13:4:13:9 | ; | ExprStmt | Test.kt:13:4:13:9 | z | VarAccess | +| Test.kt:13:4:13:9 | z | VarAccess | Test.kt:13:8:13:9 | 10 | IntegerLiteral | | Test.kt:13:8:13:9 | 10 | IntegerLiteral | Test.kt:13:4:13:9 | ...=... | AssignExpr | | Test.kt:14:10:16:3 | ... -> ... | WhenBranch | Test.kt:14:10:16:3 | true | BooleanLiteral | | Test.kt:14:10:16:3 | true | BooleanLiteral | Test.kt:14:10:16:3 | { ... } | BlockStmt | | Test.kt:14:10:16:3 | { ... } | BlockStmt | Test.kt:15:4:15:9 | ; | ExprStmt | | Test.kt:15:4:15:9 | ...=... | AssignExpr | Test.kt:18:3:18:7 | ; | ExprStmt | -| Test.kt:15:4:15:9 | ; | ExprStmt | Test.kt:15:8:15:9 | 30 | LongLiteral | +| Test.kt:15:4:15:9 | ; | ExprStmt | Test.kt:15:4:15:9 | y | VarAccess | +| Test.kt:15:4:15:9 | y | VarAccess | Test.kt:15:8:15:9 | 30 | LongLiteral | | Test.kt:15:8:15:9 | 30 | LongLiteral | Test.kt:15:4:15:9 | ...=... | AssignExpr | | Test.kt:18:3:18:7 | ...=... | AssignExpr | Test.kt:21:3:24:9 | ; | ExprStmt | -| Test.kt:18:3:18:7 | ; | ExprStmt | Test.kt:18:7:18:7 | 0 | IntegerLiteral | +| Test.kt:18:3:18:7 | ; | ExprStmt | Test.kt:18:3:18:7 | z | VarAccess | +| Test.kt:18:3:18:7 | z | VarAccess | Test.kt:18:7:18:7 | 0 | IntegerLiteral | | Test.kt:18:7:18:7 | 0 | IntegerLiteral | Test.kt:18:3:18:7 | ...=... | AssignExpr | | Test.kt:21:3:24:9 | ; | ExprStmt | Test.kt:21:3:24:9 | when ... | WhenExpr | | Test.kt:21:3:24:9 | when ... | WhenExpr | Test.kt:21:6:22:9 | ... -> ... | WhenBranch | @@ -52,14 +54,16 @@ | Test.kt:21:6:22:9 | ... -> ... | WhenBranch | Test.kt:21:6:21:6 | x | VarAccess | | Test.kt:21:10:21:10 | 0 | IntegerLiteral | Test.kt:21:6:21:10 | ... < ... | LTExpr | | Test.kt:22:4:22:9 | ...=... | AssignExpr | Test.kt:27:3:27:8 | ; | ExprStmt | -| Test.kt:22:4:22:9 | ; | ExprStmt | Test.kt:22:8:22:9 | 40 | LongLiteral | +| Test.kt:22:4:22:9 | ; | ExprStmt | Test.kt:22:4:22:9 | y | VarAccess | +| Test.kt:22:4:22:9 | y | VarAccess | Test.kt:22:8:22:9 | 40 | LongLiteral | | Test.kt:22:8:22:9 | 40 | LongLiteral | Test.kt:22:4:22:9 | ...=... | AssignExpr | | Test.kt:24:4:24:9 | ... -> ... | WhenBranch | Test.kt:24:4:24:9 | true | BooleanLiteral | | Test.kt:24:4:24:9 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method | | Test.kt:24:4:24:9 | true | BooleanLiteral | Test.kt:24:10:24:10 | INSTANCE | VarAccess | | Test.kt:24:10:24:10 | INSTANCE | VarAccess | Test.kt:24:4:24:9 | return ... | ReturnStmt | | Test.kt:27:3:27:8 | ...=... | AssignExpr | Test.kt:30:3:33:3 | ; | ExprStmt | -| Test.kt:27:3:27:8 | ; | ExprStmt | Test.kt:27:7:27:8 | 10 | IntegerLiteral | +| Test.kt:27:3:27:8 | ; | ExprStmt | Test.kt:27:3:27:8 | z | VarAccess | +| Test.kt:27:3:27:8 | z | VarAccess | Test.kt:27:7:27:8 | 10 | IntegerLiteral | | Test.kt:27:7:27:8 | 10 | IntegerLiteral | Test.kt:27:3:27:8 | ...=... | AssignExpr | | Test.kt:30:3:33:3 | ; | ExprStmt | Test.kt:30:3:33:3 | when ... | WhenExpr | | Test.kt:30:3:33:3 | when ... | WhenExpr | Test.kt:30:7:33:3 | ... -> ... | WhenBranch | @@ -70,13 +74,16 @@ | Test.kt:30:12:30:12 | 0 | IntegerLiteral | Test.kt:30:7:30:12 | ... (value equals) ... | ValueEQExpr | | Test.kt:30:15:33:3 | { ... } | BlockStmt | Test.kt:31:4:31:9 | ; | ExprStmt | | Test.kt:31:4:31:9 | ...=... | AssignExpr | Test.kt:32:4:32:9 | ; | ExprStmt | -| Test.kt:31:4:31:9 | ; | ExprStmt | Test.kt:31:8:31:9 | 60 | LongLiteral | +| Test.kt:31:4:31:9 | ; | ExprStmt | Test.kt:31:4:31:9 | y | VarAccess | +| Test.kt:31:4:31:9 | y | VarAccess | Test.kt:31:8:31:9 | 60 | LongLiteral | | Test.kt:31:8:31:9 | 60 | LongLiteral | Test.kt:31:4:31:9 | ...=... | AssignExpr | | Test.kt:32:4:32:9 | ...=... | AssignExpr | Test.kt:35:3:35:8 | ; | ExprStmt | -| Test.kt:32:4:32:9 | ; | ExprStmt | Test.kt:32:8:32:9 | 10 | IntegerLiteral | +| Test.kt:32:4:32:9 | ; | ExprStmt | Test.kt:32:4:32:9 | z | VarAccess | +| Test.kt:32:4:32:9 | z | VarAccess | Test.kt:32:8:32:9 | 10 | IntegerLiteral | | Test.kt:32:8:32:9 | 10 | IntegerLiteral | Test.kt:32:4:32:9 | ...=... | AssignExpr | | Test.kt:35:3:35:8 | ...=... | AssignExpr | Test.kt:38:3:41:3 | while (...) | WhileStmt | -| Test.kt:35:3:35:8 | ; | ExprStmt | Test.kt:35:7:35:8 | 20 | IntegerLiteral | +| Test.kt:35:3:35:8 | ; | ExprStmt | Test.kt:35:3:35:8 | z | VarAccess | +| Test.kt:35:3:35:8 | z | VarAccess | Test.kt:35:7:35:8 | 20 | IntegerLiteral | | Test.kt:35:7:35:8 | 20 | IntegerLiteral | Test.kt:35:3:35:8 | ...=... | AssignExpr | | Test.kt:38:3:41:3 | while (...) | WhileStmt | Test.kt:38:9:38:9 | x | VarAccess | | Test.kt:38:9:38:9 | x | VarAccess | Test.kt:38:13:38:13 | 0 | IntegerLiteral | @@ -85,34 +92,39 @@ | Test.kt:38:13:38:13 | 0 | IntegerLiteral | Test.kt:38:9:38:13 | ... > ... | GTExpr | | Test.kt:38:16:41:3 | { ... } | BlockStmt | Test.kt:39:4:39:9 | ; | ExprStmt | | Test.kt:39:4:39:9 | ...=... | AssignExpr | Test.kt:40:4:40:6 | ; | ExprStmt | -| Test.kt:39:4:39:9 | ; | ExprStmt | Test.kt:39:8:39:9 | 10 | LongLiteral | +| Test.kt:39:4:39:9 | ; | ExprStmt | Test.kt:39:4:39:9 | y | VarAccess | +| Test.kt:39:4:39:9 | y | VarAccess | Test.kt:39:8:39:9 | 10 | LongLiteral | | Test.kt:39:8:39:9 | 10 | LongLiteral | Test.kt:39:4:39:9 | ...=... | AssignExpr | | Test.kt:40:4:40:4 | x | VarAccess | Test.kt:40:4:40:6 | | LocalVariableDeclExpr | | Test.kt:40:4:40:6 | ...=... | AssignExpr | Test.kt:40:4:40:6 | ; | ExprStmt | -| Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | | StmtExpr | | Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | | VarAccess | -| Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | | VarAccess | -| Test.kt:40:4:40:6 | | StmtExpr | Test.kt:40:4:40:6 | { ... } | BlockStmt | +| Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | x | VarAccess | +| Test.kt:40:4:40:6 | ; | ExprStmt | Test.kt:40:4:40:6 | { ... } | BlockStmt | +| Test.kt:40:4:40:6 | | StmtExpr | Test.kt:40:4:40:6 | | ImplicitCoercionToUnitExpr | | Test.kt:40:4:40:6 | | ImplicitCoercionToUnitExpr | Test.kt:38:9:38:9 | x | VarAccess | | Test.kt:40:4:40:6 | | LocalVariableDeclExpr | Test.kt:40:4:40:6 | ; | ExprStmt | -| Test.kt:40:4:40:6 | | VarAccess | Test.kt:40:4:40:6 | | ImplicitCoercionToUnitExpr | +| Test.kt:40:4:40:6 | | VarAccess | Test.kt:40:4:40:6 | | StmtExpr | | Test.kt:40:4:40:6 | | VarAccess | Test.kt:40:4:40:6 | dec(...) | MethodCall | | Test.kt:40:4:40:6 | dec(...) | MethodCall | Test.kt:40:4:40:6 | ...=... | AssignExpr | | Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt | Test.kt:40:4:40:4 | x | VarAccess | +| Test.kt:40:4:40:6 | x | VarAccess | Test.kt:40:4:40:6 | | VarAccess | | Test.kt:40:4:40:6 | { ... } | BlockStmt | Test.kt:40:4:40:6 | var ...; | LocalVariableDeclStmt | | Test.kt:43:3:43:8 | ...=... | AssignExpr | Test.kt:73:3:73:8 | ; | ExprStmt | -| Test.kt:43:3:43:8 | ; | ExprStmt | Test.kt:43:7:43:8 | 30 | IntegerLiteral | +| Test.kt:43:3:43:8 | ; | ExprStmt | Test.kt:43:3:43:8 | z | VarAccess | +| Test.kt:43:3:43:8 | z | VarAccess | Test.kt:43:7:43:8 | 30 | IntegerLiteral | | Test.kt:43:7:43:8 | 30 | IntegerLiteral | Test.kt:43:3:43:8 | ...=... | AssignExpr | | Test.kt:73:3:73:8 | ...=... | AssignExpr | Test.kt:77:3:77:8 | ; | ExprStmt | -| Test.kt:73:3:73:8 | ; | ExprStmt | Test.kt:73:7:73:8 | 50 | IntegerLiteral | +| Test.kt:73:3:73:8 | ; | ExprStmt | Test.kt:73:3:73:8 | z | VarAccess | +| Test.kt:73:3:73:8 | z | VarAccess | Test.kt:73:7:73:8 | 50 | IntegerLiteral | | Test.kt:73:7:73:8 | 50 | IntegerLiteral | Test.kt:73:3:73:8 | ...=... | AssignExpr | | Test.kt:77:3:77:8 | ...=... | AssignExpr | Test.kt:78:9:78:9 | INSTANCE | VarAccess | -| Test.kt:77:3:77:8 | ; | ExprStmt | Test.kt:77:7:77:8 | 40 | IntegerLiteral | +| Test.kt:77:3:77:8 | ; | ExprStmt | Test.kt:77:3:77:8 | w | VarAccess | +| Test.kt:77:3:77:8 | w | VarAccess | Test.kt:77:7:77:8 | 40 | IntegerLiteral | | Test.kt:77:7:77:8 | 40 | IntegerLiteral | Test.kt:77:3:77:8 | ...=... | AssignExpr | | Test.kt:78:3:78:8 | return ... | ReturnStmt | Test.kt:4:2:79:2 | Normal Exit | Method | | Test.kt:78:9:78:9 | INSTANCE | VarAccess | Test.kt:78:3:78:8 | return ... | ReturnStmt | +| Test.kt:82:1:89:1 | Entry | Method | Test.kt:82:21:89:1 | { ... } | BlockStmt | | Test.kt:82:1:89:1 | Exceptional Exit | Method | Test.kt:82:1:89:1 | Exit | Method | -| Test.kt:82:1:89:1 | Exit | Method | file://:0:0:0:0 | | | | Test.kt:82:1:89:1 | Normal Exit | Method | Test.kt:82:1:89:1 | Exit | Method | | Test.kt:82:21:89:1 | { ... } | BlockStmt | Test.kt:83:2:88:2 | try ... | TryStmt | | Test.kt:83:2:88:2 | try ... | TryStmt | Test.kt:83:6:86:2 | { ... } | BlockStmt | @@ -124,13 +136,14 @@ | Test.kt:84:11:84:18 | (...)... | CastExpr | Test.kt:86:4:88:2 | catch (...) | CatchClause | | Test.kt:85:3:85:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method | | Test.kt:85:10:85:10 | 1 | IntegerLiteral | Test.kt:85:3:85:10 | return ... | ReturnStmt | +| Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:82:1:89:1 | Exceptional Exit | Method | | Test.kt:86:4:88:2 | catch (...) | CatchClause | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | | Test.kt:86:11:86:31 | e | LocalVariableDeclExpr | Test.kt:86:34:88:2 | { ... } | BlockStmt | | Test.kt:86:34:88:2 | { ... } | BlockStmt | Test.kt:87:10:87:10 | 2 | IntegerLiteral | | Test.kt:87:3:87:10 | return ... | ReturnStmt | Test.kt:82:1:89:1 | Normal Exit | Method | | Test.kt:87:10:87:10 | 2 | IntegerLiteral | Test.kt:87:3:87:10 | return ... | ReturnStmt | +| Test.kt:91:1:98:1 | Entry | Method | Test.kt:91:22:98:1 | { ... } | BlockStmt | | Test.kt:91:1:98:1 | Exceptional Exit | Method | Test.kt:91:1:98:1 | Exit | Method | -| Test.kt:91:1:98:1 | Exit | Method | file://:0:0:0:0 | | | | Test.kt:91:1:98:1 | Normal Exit | Method | Test.kt:91:1:98:1 | Exit | Method | | Test.kt:91:22:98:1 | { ... } | BlockStmt | Test.kt:92:2:97:2 | try ... | TryStmt | | Test.kt:92:2:97:2 | try ... | TryStmt | Test.kt:92:6:95:2 | { ... } | BlockStmt | @@ -142,13 +155,14 @@ | Test.kt:93:11:93:13 | ...!! | NotNullExpr | Test.kt:95:4:97:2 | catch (...) | CatchClause | | Test.kt:94:3:94:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method | | Test.kt:94:10:94:10 | 1 | IntegerLiteral | Test.kt:94:3:94:10 | return ... | ReturnStmt | +| Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:91:1:98:1 | Exceptional Exit | Method | | Test.kt:95:4:97:2 | catch (...) | CatchClause | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | | Test.kt:95:11:95:33 | e | LocalVariableDeclExpr | Test.kt:95:36:97:2 | { ... } | BlockStmt | | Test.kt:95:36:97:2 | { ... } | BlockStmt | Test.kt:96:10:96:10 | 2 | IntegerLiteral | | Test.kt:96:3:96:10 | return ... | ReturnStmt | Test.kt:91:1:98:1 | Normal Exit | Method | | Test.kt:96:10:96:10 | 2 | IntegerLiteral | Test.kt:96:3:96:10 | return ... | ReturnStmt | +| Test.kt:100:1:110:1 | Entry | Method | Test.kt:100:25:110:1 | { ... } | BlockStmt | | Test.kt:100:1:110:1 | Exceptional Exit | Method | Test.kt:100:1:110:1 | Exit | Method | -| Test.kt:100:1:110:1 | Exit | Method | file://:0:0:0:0 | | | | Test.kt:100:1:110:1 | Normal Exit | Method | Test.kt:100:1:110:1 | Exit | Method | | Test.kt:100:25:110:1 | { ... } | BlockStmt | Test.kt:101:5:103:5 | ; | ExprStmt | | Test.kt:101:5:103:5 | ; | ExprStmt | Test.kt:101:5:103:5 | when ... | WhenExpr | @@ -186,8 +200,7 @@ | Test.kt:108:9:108:29 | ; | ExprStmt | Test.kt:108:17:108:28 | "y not null" | StringLiteral | | Test.kt:108:9:108:29 | println(...) | MethodCall | Test.kt:100:1:110:1 | Normal Exit | Method | | Test.kt:108:17:108:28 | "y not null" | StringLiteral | Test.kt:108:9:108:29 | println(...) | MethodCall | -| Test.kt:112:1:116:1 | Exceptional Exit | Method | Test.kt:112:1:116:1 | Exit | Method | -| Test.kt:112:1:116:1 | Exit | Method | file://:0:0:0:0 | | | +| Test.kt:112:1:116:1 | Entry | Method | Test.kt:112:32:116:1 | { ... } | BlockStmt | | Test.kt:112:1:116:1 | Normal Exit | Method | Test.kt:112:1:116:1 | Exit | Method | | Test.kt:112:32:116:1 | { ... } | BlockStmt | Test.kt:113:5:115:5 | ; | ExprStmt | | Test.kt:113:5:115:5 | ; | ExprStmt | Test.kt:113:5:115:5 | when ... | WhenExpr | @@ -199,8 +212,7 @@ | Test.kt:113:14:113:14 | y | VarAccess | Test.kt:112:1:116:1 | Normal Exit | Method | | Test.kt:113:14:113:14 | y | VarAccess | Test.kt:113:17:115:5 | { ... } | BlockStmt | | Test.kt:113:17:115:5 | { ... } | BlockStmt | Test.kt:112:1:116:1 | Normal Exit | Method | -| Test.kt:118:1:124:1 | Exceptional Exit | Method | Test.kt:118:1:124:1 | Exit | Method | -| Test.kt:118:1:124:1 | Exit | Method | file://:0:0:0:0 | | | +| Test.kt:118:1:124:1 | Entry | Method | Test.kt:118:37:124:1 | { ... } | BlockStmt | | Test.kt:118:1:124:1 | Normal Exit | Method | Test.kt:118:1:124:1 | Exit | Method | | Test.kt:118:37:124:1 | { ... } | BlockStmt | Test.kt:119:2:123:12 | ; | ExprStmt | | Test.kt:119:2:123:12 | ; | ExprStmt | Test.kt:119:2:123:12 | when ... | WhenExpr | @@ -216,6 +228,7 @@ | Test.kt:122:12:122:16 | ... -> ... | WhenBranch | Test.kt:122:12:122:16 | true | BooleanLiteral | | Test.kt:122:12:122:16 | ; | ExprStmt | Test.kt:122:12:122:16 | false | BooleanLiteral | | Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:118:1:124:1 | Normal Exit | Method | +| Test.kt:122:12:122:16 | false | BooleanLiteral | Test.kt:123:8:123:10 | { ... } | BlockStmt | | Test.kt:122:12:122:16 | true | BooleanLiteral | Test.kt:122:12:122:16 | ; | ExprStmt | | Test.kt:123:8:123:10 | { ... } | BlockStmt | Test.kt:118:1:124:1 | Normal Exit | Method | missingSuccessor diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.ql b/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.ql index 10a2568b0607..9a334d18aae7 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.ql +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/getASuccessor.ql @@ -1,54 +1,15 @@ import java +import utils.test.AstCfg -newtype TMaybeControlFlowNode = - TControlFlowNode(ControlFlowNode c) or - TNoControlFlowNode() - -class MaybeControlFlowNode extends TMaybeControlFlowNode { - abstract string toString(); - - abstract Location getLocation(); - - abstract string getPrimaryQlClasses(); -} - -class YesMaybeControlFlowNode extends MaybeControlFlowNode { - ControlFlowNode c; - - YesMaybeControlFlowNode() { this = TControlFlowNode(c) } - - override string toString() { result = c.toString() } - - override Location getLocation() { result = c.getLocation() } - - override string getPrimaryQlClasses() { result = c.getAstNode().getPrimaryQlClasses() } -} - -class NoMaybeControlFlowNode extends MaybeControlFlowNode { - NoMaybeControlFlowNode() { this = TNoControlFlowNode() } - - override string toString() { result = "" } - - override Location getLocation() { result.toString() = "file://:0:0:0:0" } - - override string getPrimaryQlClasses() { result = "" } -} - -MaybeControlFlowNode maybeSuccessor(ControlFlowNode n) { - if exists(n.getASuccessor()) - then result = TControlFlowNode(n.getASuccessor()) - else result = TNoControlFlowNode() -} - -from ControlFlowNode n, MaybeControlFlowNode m +from ControlFlowNode n, ControlFlowNode m where - m = maybeSuccessor(n) and + m = getAnAstSuccessor(n) and n.getLocation().getFile().(CompilationUnit).fromSource() -select n, n.getAstNode().getPrimaryQlClasses(), m, m.getPrimaryQlClasses() +select n, n.getAstNode().getPrimaryQlClasses(), m, m.getAstNode().getPrimaryQlClasses() -query predicate missingSuccessor(Expr n) { - maybeSuccessor(n.getControlFlowNode()) instanceof NoMaybeControlFlowNode and - n.getFile().(CompilationUnit).fromSource() and - not n instanceof TypeAccess and - not n instanceof VarWrite +query predicate missingSuccessor(Expr e) { + exists(ControlFlowNode n | n = e.getControlFlowNode() and not exists(n.getASuccessor())) and + e.getFile().(CompilationUnit).fromSource() and + not e instanceof TypeAccess and + not e instanceof VarWrite } diff --git a/java/ql/test-kotlin2/library-tests/controlflow/basic/strictDominance.expected b/java/ql/test-kotlin2/library-tests/controlflow/basic/strictDominance.expected index 4fb56510ed51..27595e7017b6 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/basic/strictDominance.expected +++ b/java/ql/test-kotlin2/library-tests/controlflow/basic/strictDominance.expected @@ -562,5 +562,4 @@ | Test.kt:121:4:121:9 | ... -> ... | Test.kt:122:12:122:16 | ... -> ... | | Test.kt:121:4:121:9 | ... -> ... | Test.kt:122:12:122:16 | ; | | Test.kt:121:4:121:9 | ... -> ... | Test.kt:123:8:123:10 | { ... } | -| Test.kt:121:9:121:9 | ; | Test.kt:123:8:123:10 | { ... } | | Test.kt:122:12:122:16 | ... -> ... | Test.kt:122:12:122:16 | ; | diff --git a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominanceWrong.ql b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominanceWrong.ql index 4eadcddc61a6..6deead2df73b 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominanceWrong.ql +++ b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominanceWrong.ql @@ -17,5 +17,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co from Callable c, ControlFlowNode dom, ControlFlowNode node where strictlyDominates(dom, node) and - dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node) + dominanceCounterExample(any(ControlFlow::EntryNode entry | entry.getEnclosingCallable() = c), dom, + node) select c, dom, node diff --git a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected index 75662bfacd49..6084c631b9df 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected +++ b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.expected @@ -1,157 +1,21 @@ -| Test.kt:2:43:79:2 | { ... } | Test.kt:3:9:3:18 | var ...; | -| Test.kt:3:9:3:18 | var ...; | Test.kt:3:17:3:18 | px | -| Test.kt:3:9:3:18 | x | Test.kt:4:9:4:18 | var ...; | -| Test.kt:3:17:3:18 | px | Test.kt:3:9:3:18 | x | -| Test.kt:4:9:4:18 | var ...; | Test.kt:4:17:4:18 | pw | -| Test.kt:4:9:4:18 | w | Test.kt:5:9:5:18 | var ...; | -| Test.kt:4:17:4:18 | pw | Test.kt:4:9:4:18 | w | -| Test.kt:5:9:5:18 | var ...; | Test.kt:5:17:5:18 | pz | -| Test.kt:5:9:5:18 | z | Test.kt:7:3:7:12 | var ...; | -| Test.kt:5:17:5:18 | pz | Test.kt:5:9:5:18 | z | -| Test.kt:7:3:7:12 | j | Test.kt:8:3:8:18 | var ...; | -| Test.kt:7:3:7:12 | var ...; | Test.kt:7:3:7:12 | j | -| Test.kt:8:3:8:18 | var ...; | Test.kt:8:17:8:18 | 50 | -| Test.kt:8:3:8:18 | y | Test.kt:11:3:16:3 | ; | -| Test.kt:8:17:8:18 | 50 | Test.kt:8:3:8:18 | y | -| Test.kt:11:3:16:3 | ; | Test.kt:11:3:16:3 | when ... | -| Test.kt:11:3:16:3 | when ... | Test.kt:11:7:14:3 | ... -> ... | -| Test.kt:11:7:11:7 | x | Test.kt:11:11:11:11 | 0 | -| Test.kt:11:7:11:11 | ... > ... | Test.kt:11:14:14:3 | { ... } | -| Test.kt:11:7:11:11 | ... > ... | Test.kt:14:10:16:3 | ... -> ... | -| Test.kt:11:7:11:11 | ... > ... | Test.kt:18:3:18:20 | ; | -| Test.kt:11:7:14:3 | ... -> ... | Test.kt:11:7:11:7 | x | -| Test.kt:11:11:11:11 | 0 | Test.kt:11:7:11:11 | ... > ... | -| Test.kt:11:14:14:3 | { ... } | Test.kt:12:4:12:9 | ; | -| Test.kt:12:4:12:9 | ...=... | Test.kt:13:4:13:9 | ; | -| Test.kt:12:4:12:9 | ; | Test.kt:12:8:12:9 | 20 | -| Test.kt:12:8:12:9 | 20 | Test.kt:12:4:12:9 | ...=... | -| Test.kt:13:4:13:9 | ; | Test.kt:13:8:13:9 | 10 | -| Test.kt:13:8:13:9 | 10 | Test.kt:13:4:13:9 | ...=... | -| Test.kt:14:10:16:3 | ... -> ... | Test.kt:14:10:16:3 | true | -| Test.kt:14:10:16:3 | true | Test.kt:14:10:16:3 | { ... } | -| Test.kt:14:10:16:3 | { ... } | Test.kt:15:4:15:9 | ; | -| Test.kt:15:4:15:9 | ; | Test.kt:15:8:15:9 | 30 | -| Test.kt:15:8:15:9 | 30 | Test.kt:15:4:15:9 | ...=... | -| Test.kt:18:3:18:20 | ...=... | Test.kt:21:3:24:11 | ; | -| Test.kt:18:3:18:20 | ; | Test.kt:18:8:18:8 | x | -| Test.kt:18:7:18:20 | (...)... | Test.kt:18:3:18:20 | ...=... | -| Test.kt:18:8:18:8 | x | Test.kt:18:12:18:12 | y | -| Test.kt:18:8:18:12 | ... + ... | Test.kt:18:7:18:20 | (...)... | -| Test.kt:18:12:18:12 | y | Test.kt:18:8:18:12 | ... + ... | -| Test.kt:21:3:24:11 | ; | Test.kt:21:3:24:11 | when ... | -| Test.kt:21:3:24:11 | when ... | Test.kt:21:7:22:9 | ... -> ... | -| Test.kt:21:7:21:7 | x | Test.kt:21:11:21:11 | 0 | -| Test.kt:21:7:21:11 | ... < ... | Test.kt:2:2:79:2 | Normal Exit | -| Test.kt:21:7:21:11 | ... < ... | Test.kt:22:4:22:9 | ; | -| Test.kt:21:7:21:11 | ... < ... | Test.kt:24:4:24:11 | ... -> ... | -| Test.kt:21:7:22:9 | ... -> ... | Test.kt:21:7:21:7 | x | -| Test.kt:21:11:21:11 | 0 | Test.kt:21:7:21:11 | ... < ... | -| Test.kt:22:4:22:9 | ...=... | Test.kt:27:3:27:8 | ; | -| Test.kt:22:4:22:9 | ; | Test.kt:22:8:22:9 | 40 | -| Test.kt:22:8:22:9 | 40 | Test.kt:22:4:22:9 | ...=... | -| Test.kt:24:4:24:11 | ... -> ... | Test.kt:24:4:24:11 | true | -| Test.kt:24:4:24:11 | true | Test.kt:24:11:24:11 | z | -| Test.kt:24:11:24:11 | z | Test.kt:24:4:24:11 | return ... | -| Test.kt:27:3:27:8 | ...=... | Test.kt:30:3:33:3 | ; | -| Test.kt:27:3:27:8 | ; | Test.kt:27:7:27:8 | 10 | -| Test.kt:27:7:27:8 | 10 | Test.kt:27:3:27:8 | ...=... | -| Test.kt:30:3:33:3 | ; | Test.kt:30:3:33:3 | when ... | -| Test.kt:30:3:33:3 | when ... | Test.kt:30:7:33:3 | ... -> ... | -| Test.kt:30:7:30:7 | x | Test.kt:30:12:30:12 | 0 | -| Test.kt:30:7:30:12 | ... (value equals) ... | Test.kt:30:15:33:3 | { ... } | -| Test.kt:30:7:30:12 | ... (value equals) ... | Test.kt:35:3:35:8 | ; | -| Test.kt:30:7:33:3 | ... -> ... | Test.kt:30:7:30:7 | x | -| Test.kt:30:12:30:12 | 0 | Test.kt:30:7:30:12 | ... (value equals) ... | -| Test.kt:30:15:33:3 | { ... } | Test.kt:31:4:31:9 | ; | -| Test.kt:31:4:31:9 | ...=... | Test.kt:32:4:32:9 | ; | -| Test.kt:31:4:31:9 | ; | Test.kt:31:8:31:9 | 60 | -| Test.kt:31:8:31:9 | 60 | Test.kt:31:4:31:9 | ...=... | -| Test.kt:32:4:32:9 | ; | Test.kt:32:8:32:9 | 10 | -| Test.kt:32:8:32:9 | 10 | Test.kt:32:4:32:9 | ...=... | -| Test.kt:35:3:35:8 | ...+=... | Test.kt:38:3:41:3 | while (...) | -| Test.kt:35:3:35:8 | ; | Test.kt:35:3:35:8 | z | -| Test.kt:35:3:35:8 | z | Test.kt:35:8:35:8 | x | -| Test.kt:35:8:35:8 | x | Test.kt:35:3:35:8 | ...+=... | -| Test.kt:38:3:41:3 | while (...) | Test.kt:38:10:38:10 | x | -| Test.kt:38:10:38:10 | x | Test.kt:38:14:38:14 | 0 | -| Test.kt:38:10:38:14 | ... > ... | Test.kt:38:17:41:3 | { ... } | -| Test.kt:38:10:38:14 | ... > ... | Test.kt:43:3:43:15 | ; | -| Test.kt:38:14:38:14 | 0 | Test.kt:38:10:38:14 | ... > ... | -| Test.kt:38:17:41:3 | { ... } | Test.kt:39:4:39:9 | ; | -| Test.kt:39:4:39:9 | ...=... | Test.kt:40:4:40:6 | ; | -| Test.kt:39:4:39:9 | ; | Test.kt:39:8:39:9 | 10 | -| Test.kt:39:8:39:9 | 10 | Test.kt:39:4:39:9 | ...=... | -| Test.kt:40:4:40:4 | x | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | ...=... | Test.kt:40:4:40:6 | ; | -| Test.kt:40:4:40:6 | ; | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | ; | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | ; | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | | Test.kt:40:4:40:6 | { ... } | -| Test.kt:40:4:40:6 | | Test.kt:40:4:40:6 | ; | -| Test.kt:40:4:40:6 | | Test.kt:40:4:40:6 | | -| Test.kt:40:4:40:6 | | Test.kt:40:4:40:6 | dec(...) | -| Test.kt:40:4:40:6 | dec(...) | Test.kt:40:4:40:6 | ...=... | -| Test.kt:40:4:40:6 | var ...; | Test.kt:40:4:40:4 | x | -| Test.kt:40:4:40:6 | { ... } | Test.kt:40:4:40:6 | var ...; | -| Test.kt:43:3:43:15 | ...+=... | Test.kt:73:3:73:16 | ; | -| Test.kt:43:3:43:15 | ; | Test.kt:43:3:43:15 | z | -| Test.kt:43:3:43:15 | z | Test.kt:43:8:43:8 | y | -| Test.kt:43:8:43:8 | y | Test.kt:43:8:43:15 | (...)... | -| Test.kt:43:8:43:15 | (...)... | Test.kt:43:3:43:15 | ...+=... | -| Test.kt:73:3:73:16 | ...+=... | Test.kt:77:3:77:8 | ; | -| Test.kt:73:3:73:16 | ; | Test.kt:73:3:73:16 | z | -| Test.kt:73:3:73:16 | z | Test.kt:73:8:73:8 | x | -| Test.kt:73:8:73:8 | x | Test.kt:73:12:73:12 | y | -| Test.kt:73:8:73:12 | ... + ... | Test.kt:73:16:73:16 | w | -| Test.kt:73:8:73:16 | ... + ... | Test.kt:73:3:73:16 | ...+=... | -| Test.kt:73:12:73:12 | | Test.kt:73:8:73:12 | ... + ... | -| Test.kt:73:12:73:12 | y | Test.kt:73:12:73:12 | | -| Test.kt:73:16:73:16 | w | Test.kt:73:8:73:16 | ... + ... | -| Test.kt:77:3:77:8 | ...=... | Test.kt:78:10:78:10 | w | -| Test.kt:77:3:77:8 | ; | Test.kt:77:7:77:8 | 40 | -| Test.kt:77:7:77:8 | 40 | Test.kt:77:3:77:8 | ...=... | -| Test.kt:78:10:78:10 | w | Test.kt:78:3:78:10 | return ... | -| Test.kt:81:25:98:2 | { ... } | Test.kt:83:3:83:12 | var ...; | -| Test.kt:83:3:83:12 | b | Test.kt:84:3:84:12 | var ...; | -| Test.kt:83:3:83:12 | var ...; | Test.kt:83:3:83:12 | b | -| Test.kt:84:3:84:12 | c | Test.kt:85:3:85:7 | ; | -| Test.kt:84:3:84:12 | var ...; | Test.kt:84:3:84:12 | c | -| Test.kt:85:3:85:7 | ...=... | Test.kt:86:3:96:3 | while (...) | -| Test.kt:85:3:85:7 | ; | Test.kt:85:7:85:7 | 0 | -| Test.kt:85:7:85:7 | 0 | Test.kt:85:3:85:7 | ...=... | -| Test.kt:86:3:96:3 | while (...) | Test.kt:86:9:86:12 | true | -| Test.kt:86:9:86:12 | true | Test.kt:86:15:96:3 | { ... } | -| Test.kt:86:15:96:3 | { ... } | Test.kt:87:4:87:9 | ; | -| Test.kt:87:4:87:9 | ...=... | Test.kt:88:4:91:4 | ; | -| Test.kt:87:4:87:9 | ; | Test.kt:87:8:87:9 | 10 | -| Test.kt:87:8:87:9 | 10 | Test.kt:87:4:87:9 | ...=... | -| Test.kt:88:4:91:4 | ; | Test.kt:88:4:91:4 | when ... | -| Test.kt:88:4:91:4 | when ... | Test.kt:88:8:91:4 | ... -> ... | -| Test.kt:88:8:88:8 | a | Test.kt:88:12:88:14 | 100 | -| Test.kt:88:8:88:14 | ... > ... | Test.kt:88:17:91:4 | { ... } | -| Test.kt:88:8:88:14 | ... > ... | Test.kt:92:4:93:9 | ; | -| Test.kt:88:8:91:4 | ... -> ... | Test.kt:88:8:88:8 | a | -| Test.kt:88:12:88:14 | 100 | Test.kt:88:8:88:14 | ... > ... | -| Test.kt:88:17:91:4 | { ... } | Test.kt:89:5:89:10 | ; | -| Test.kt:89:5:89:10 | ...=... | Test.kt:90:5:90:9 | ; | -| Test.kt:89:5:89:10 | ; | Test.kt:89:9:89:10 | 10 | -| Test.kt:89:9:89:10 | 10 | Test.kt:89:5:89:10 | ...=... | -| Test.kt:90:5:90:9 | ; | Test.kt:90:9:90:9 | c | -| Test.kt:90:9:90:9 | c | Test.kt:90:5:90:9 | ...=... | -| Test.kt:92:4:93:9 | ; | Test.kt:92:4:93:9 | when ... | -| Test.kt:92:4:93:9 | when ... | Test.kt:92:8:93:9 | ... -> ... | -| Test.kt:92:8:92:8 | a | Test.kt:92:13:92:14 | 10 | -| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:81:2:98:2 | Normal Exit | -| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:93:5:93:9 | break | -| Test.kt:92:8:92:14 | ... (value equals) ... | Test.kt:94:4:95:12 | ; | -| Test.kt:92:8:93:9 | ... -> ... | Test.kt:92:8:92:8 | a | -| Test.kt:92:13:92:14 | 10 | Test.kt:92:8:92:14 | ... (value equals) ... | -| Test.kt:93:5:93:9 | break | Test.kt:97:10:97:10 | b | -| Test.kt:94:4:95:12 | ; | Test.kt:94:4:95:12 | when ... | -| Test.kt:94:4:95:12 | when ... | Test.kt:94:8:95:12 | ... -> ... | -| Test.kt:94:8:94:8 | a | Test.kt:94:13:94:14 | 20 | -| Test.kt:94:8:94:14 | ... (value equals) ... | Test.kt:95:12:95:12 | c | -| Test.kt:94:8:95:12 | ... -> ... | Test.kt:94:8:94:8 | a | -| Test.kt:94:13:94:14 | 20 | Test.kt:94:8:94:14 | ... (value equals) ... | -| Test.kt:95:12:95:12 | c | Test.kt:95:5:95:12 | return ... | -| Test.kt:97:10:97:10 | b | Test.kt:97:3:97:10 | return ... | +| Test.kt:2:43:79:2 | { ... } | Test.kt:11:14:14:3 | { ... } | +| Test.kt:2:43:79:2 | { ... } | Test.kt:14:10:16:3 | ... -> ... | +| Test.kt:2:43:79:2 | { ... } | Test.kt:18:3:18:20 | ; | +| Test.kt:18:3:18:20 | ; | Test.kt:2:2:79:2 | Normal Exit | +| Test.kt:18:3:18:20 | ; | Test.kt:22:4:22:9 | ; | +| Test.kt:18:3:18:20 | ; | Test.kt:24:4:24:11 | ... -> ... | +| Test.kt:22:4:22:9 | ; | Test.kt:30:7:30:12 | After ... (value equals) ... [false] | +| Test.kt:22:4:22:9 | ; | Test.kt:30:15:33:3 | { ... } | +| Test.kt:22:4:22:9 | ; | Test.kt:35:3:35:8 | ; | +| Test.kt:35:3:35:8 | ; | Test.kt:38:10:38:10 | x | +| Test.kt:38:10:38:10 | x | Test.kt:38:17:41:3 | { ... } | +| Test.kt:38:10:38:10 | x | Test.kt:43:3:43:15 | ; | +| Test.kt:81:25:98:2 | { ... } | Test.kt:86:9:86:12 | true | +| Test.kt:86:9:86:12 | true | Test.kt:88:8:88:14 | After ... > ... [false] | +| Test.kt:86:9:86:12 | true | Test.kt:88:17:91:4 | { ... } | +| Test.kt:86:9:86:12 | true | Test.kt:92:4:93:9 | ; | +| Test.kt:92:4:93:9 | ; | Test.kt:81:2:98:2 | Normal Exit | +| Test.kt:92:4:93:9 | ; | Test.kt:93:5:93:9 | break | +| Test.kt:92:4:93:9 | ; | Test.kt:94:4:95:12 | ; | +| Test.kt:94:4:95:12 | ; | Test.kt:94:8:94:14 | After ... (value equals) ... [false] | +| Test.kt:94:4:95:12 | ; | Test.kt:95:12:95:12 | c | diff --git a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.ql b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.ql index 701640bf7209..7fc18484febf 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.ql +++ b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominator.ql @@ -1,9 +1,9 @@ -import default -import semmle.code.java.controlflow.Dominance +import java +import utils.test.BasicBlock -from Method func, ControlFlowNode dominator, ControlFlowNode node +from Method func, BasicBlock dominator, BasicBlock bb where - iDominates(dominator, node) and - dominator.getEnclosingStmt().getEnclosingCallable() = func and + dominator.immediatelyDominates(bb) and + dominator.getEnclosingCallable() = func and func.getDeclaringType().hasName("Test") -select dominator, node +select getFirstAstNodeOrSynth(dominator), getFirstAstNodeOrSynth(bb) diff --git a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominatorUnique.ql b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominatorUnique.ql index eaf75ab7bfaa..54b0d1863624 100644 --- a/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominatorUnique.ql +++ b/java/ql/test-kotlin2/library-tests/controlflow/dominance/dominatorUnique.ql @@ -7,5 +7,5 @@ where iDominates(dom1, node) and iDominates(dom2, node) and dom1 != dom2 and - func = node.getEnclosingStmt().getEnclosingCallable() + func = node.getEnclosingCallable() select func, node, dom1, dom2 diff --git a/java/ql/test-kotlin2/library-tests/exprs/binop.ql b/java/ql/test-kotlin2/library-tests/exprs/binop.ql index d865d83fcf90..303eccba5896 100644 --- a/java/ql/test-kotlin2/library-tests/exprs/binop.ql +++ b/java/ql/test-kotlin2/library-tests/exprs/binop.ql @@ -41,4 +41,5 @@ MaybeElement rhs(BinaryExpr e) { } from Expr e +where not e instanceof Assignment select e, lhs(e), rhs(e) diff --git a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptThenMac.expected b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptThenMac.expected index ba74f3dffce5..af36477b9172 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptThenMac.expected +++ b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptThenMac.expected @@ -30,7 +30,7 @@ nodes | BadMacUse.java:152:42:152:51 | ciphertext | semmle.label | ciphertext | subpaths testFailures -| BadMacUse.java:50:56:50:65 | // $Source | Missing result: Source | -| BadMacUse.java:63:118:63:127 | // $Source | Missing result: Source | +| BadMacUse.java:50:56:50:66 | // $ Source | Missing result: Source | +| BadMacUse.java:63:118:63:128 | // $ Source | Missing result: Source | | BadMacUse.java:92:31:92:35 | bytes : byte[] | Unexpected result: Source | -| BadMacUse.java:146:95:146:104 | // $Source | Missing result: Source | +| BadMacUse.java:146:95:146:105 | // $ Source | Missing result: Source | diff --git a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptToMac.expected b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptToMac.expected index f73f0f25e0aa..6fcff81b7f6a 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptToMac.expected +++ b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderDecryptToMac.expected @@ -31,7 +31,7 @@ nodes | BadMacUse.java:124:42:124:51 | ciphertext | semmle.label | ciphertext | subpaths testFailures -| BadMacUse.java:63:118:63:127 | // $Source | Missing result: Source | +| BadMacUse.java:63:118:63:128 | // $ Source | Missing result: Source | | BadMacUse.java:92:16:92:36 | doFinal(...) : byte[] | Unexpected result: Source | | BadMacUse.java:124:42:124:51 | ciphertext | Unexpected result: Alert | -| BadMacUse.java:146:95:146:104 | // $Source | Missing result: Source | +| BadMacUse.java:146:95:146:105 | // $ Source | Missing result: Source | diff --git a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderMacOnEncryptPlaintext.expected b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderMacOnEncryptPlaintext.expected index ea4273613611..2daa6405cd05 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderMacOnEncryptPlaintext.expected +++ b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacOrderMacOnEncryptPlaintext.expected @@ -45,7 +45,7 @@ nodes | BadMacUse.java:152:42:152:51 | ciphertext | semmle.label | ciphertext | subpaths testFailures -| BadMacUse.java:50:56:50:65 | // $Source | Missing result: Source | +| BadMacUse.java:50:56:50:66 | // $ Source | Missing result: Source | | BadMacUse.java:139:79:139:90 | input : byte[] | Unexpected result: Source | -| BadMacUse.java:146:95:146:104 | // $Source | Missing result: Source | +| BadMacUse.java:146:95:146:105 | // $ Source | Missing result: Source | | BadMacUse.java:152:42:152:51 | ciphertext | Unexpected result: Alert | diff --git a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacUse.java b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacUse.java index 5c442d4bca76..4c1ae5b36215 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacUse.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/BadMacUse/BadMacUse.java @@ -47,20 +47,20 @@ public void BadDecryptThenMacOnPlaintextVerify(byte[] encryptionKeyBytes, byte[] SecretKey encryptionKey = new SecretKeySpec(encryptionKeyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.DECRYPT_MODE, encryptionKey, new SecureRandom()); - byte[] plaintext = cipher.doFinal(ciphertext); // $Source + byte[] plaintext = cipher.doFinal(ciphertext); // $ Source // Now verify MAC (too late) SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(macKey); - byte[] computedMac = mac.doFinal(plaintext); // $Alert[java/quantum/examples/bad-mac-order-decrypt-to-mac] + byte[] computedMac = mac.doFinal(plaintext); // $ Alert[java/quantum/examples/bad-mac-order-decrypt-to-mac] if (!MessageDigest.isEqual(receivedMac, computedMac)) { throw new SecurityException("MAC verification failed"); } } - public void BadMacOnPlaintext(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] plaintext) throws Exception {// $Source + public void BadMacOnPlaintext(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] plaintext) throws Exception {// $ Source // Create keys directly from provided byte arrays SecretKey encryptionKey = new SecretKeySpec(encryptionKeyBytes, "AES"); SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256"); @@ -73,7 +73,7 @@ public void BadMacOnPlaintext(byte[] encryptionKeyBytes, byte[] macKeyBytes, byt // Encrypt the plaintext Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, encryptionKey, new SecureRandom()); - byte[] ciphertext = cipher.doFinal(plaintext); // $Alert[java/quantum/examples/bad-mac-order-encrypt-plaintext-also-in-mac] + byte[] ciphertext = cipher.doFinal(plaintext); // $ Alert[java/quantum/examples/bad-mac-order-encrypt-plaintext-also-in-mac] // Concatenate ciphertext and MAC byte[] output = new byte[ciphertext.length + computedMac.length]; @@ -132,7 +132,7 @@ public byte[] falsePositiveDecryptToMac(byte[] encryptionKeyBytes, byte[] macKey /** - * Correct inputs to a decrypt and MAC operation, but the ordering is unsafe. + * Correct inputs to a decrypt and MAC operation, but the ordering is unsafe. * The function decrypts THEN computes the MAC on the plaintext. * It should have the MAC computed on the ciphertext first. */ @@ -143,13 +143,13 @@ public void decryptThenMac(byte[] encryptionKeyBytes, byte[] macKeyBytes, byte[] byte[] receivedMac = Arrays.copyOfRange(input, input.length - macLength, input.length); // Decrypt first (unsafe) - byte[] plaintext = decryptUsingWrapper(ciphertext, encryptionKeyBytes, new byte[16]); // $Source + byte[] plaintext = decryptUsingWrapper(ciphertext, encryptionKeyBytes, new byte[16]); // $ Source // Now verify MAC (too late) SecretKey macKey = new SecretKeySpec(macKeyBytes, "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(macKey); - byte[] computedMac = mac.doFinal(ciphertext); // $Alert[java/quantum/examples/bad-mac-order-decrypt-then-mac], False positive for Plaintext reuse + byte[] computedMac = mac.doFinal(ciphertext); // $ Alert[java/quantum/examples/bad-mac-order-decrypt-then-mac], False positive for Plaintext reuse if (!MessageDigest.isEqual(receivedMac, computedMac)) { throw new SecurityException("MAC verification failed"); diff --git a/java/ql/test/experimental/query-tests/quantum/examples/InsecureOrUnknownNonceSource/InsecureIVorNonceSource.java b/java/ql/test/experimental/query-tests/quantum/examples/InsecureOrUnknownNonceSource/InsecureIVorNonceSource.java index 549c56dbd981..f9474681d196 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/InsecureOrUnknownNonceSource/InsecureIVorNonceSource.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/InsecureOrUnknownNonceSource/InsecureIVorNonceSource.java @@ -11,33 +11,33 @@ public class InsecureIVorNonceSource { // BAD: AES-GCM with static IV from a byte array public byte[] encryptWithStaticIvByteArrayWithInitializer(byte[] key, byte[] plaintext) throws Exception { - byte[] iv = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; // $Source + byte[] iv = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; // $ Source GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/insecure-iv-or-nonce] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/insecure-iv-or-nonce] cipher.update(plaintext); return cipher.doFinal(); } // BAD: AES-GCM with static IV from zero-initialized byte array public byte[] encryptWithZeroStaticIvByteArray(byte[] key, byte[] plaintext) throws Exception { - byte[] iv = new byte[16]; + byte[] iv = new byte[16]; GCMParameterSpec ivSpec = new GCMParameterSpec(128, iv); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/unknown-iv-or-nonce-source] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/unknown-iv-or-nonce-source] cipher.update(plaintext); return cipher.doFinal(); } // BAD: AES-CBC with static IV from 1-initialized byte array public byte[] encryptWithStaticIvByteArray(byte[] key, byte[] plaintext) throws Exception { - byte[] iv = new byte[16]; + byte[] iv = new byte[16]; for (byte i = 0; i < iv.length; i++) { iv[i] = 1; } @@ -46,7 +46,7 @@ public byte[] encryptWithStaticIvByteArray(byte[] key, byte[] plaintext) throws SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/insecure-iv-or-nonce] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/insecure-iv-or-nonce] cipher.update(plaintext); return cipher.doFinal(); } @@ -54,15 +54,15 @@ public byte[] encryptWithStaticIvByteArray(byte[] key, byte[] plaintext) throws // BAD: AES-GCM with static IV from a multidimensional byte array public byte[] encryptWithOneOfStaticIvs01(byte[] key, byte[] plaintext) throws Exception { byte[][] staticIvs = new byte[][] { - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }, // $Source - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 42 } // $Source - }; + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }, // $ Source + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 42 } // $ Source + }; GCMParameterSpec ivSpec = new GCMParameterSpec(128, staticIvs[1]); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/insecure-iv-or-nonce] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/insecure-iv-or-nonce] cipher.update(plaintext); return cipher.doFinal(); } @@ -70,15 +70,15 @@ public byte[] encryptWithOneOfStaticIvs01(byte[] key, byte[] plaintext) throws E // BAD: AES-GCM with static IV from a multidimensional byte array public byte[] encryptWithOneOfStaticIvs02(byte[] key, byte[] plaintext) throws Exception { byte[][] staticIvs = new byte[][] { - new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }, // $Source - new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 42 } // $Source - }; + new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }, // $ Source + new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 42 } // $ Source + }; GCMParameterSpec ivSpec = new GCMParameterSpec(128, staticIvs[1]); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/insecure-iv-or-nonce] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/insecure-iv-or-nonce] cipher.update(plaintext); return cipher.doFinal(); } @@ -86,15 +86,15 @@ public byte[] encryptWithOneOfStaticIvs02(byte[] key, byte[] plaintext) throws E // BAD: AES-GCM with static IV from a zero-initialized multidimensional byte array public byte[] encryptWithOneOfStaticZeroIvs(byte[] key, byte[] plaintext) throws Exception { byte[][] ivs = new byte[][] { - new byte[8], - new byte[16] + new byte[8], + new byte[16] }; GCMParameterSpec ivSpec = new GCMParameterSpec(128, ivs[1]); SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/GCM/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/unknown-iv-or-nonce-source] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/unknown-iv-or-nonce-source] cipher.update(plaintext); return cipher.doFinal(); } @@ -166,8 +166,8 @@ public byte[] encryptWithRandomIvWithArraysCopy(byte[] key, byte[] plaintext) th return cipher.doFinal(); } - public byte[] generate(int size) throws Exception { - if (size == 0) { + public byte[] generate(int size) throws Exception { + if (size == 0) { return new byte[0]; } byte[] randomBytes = new byte[size]; @@ -183,7 +183,7 @@ public byte[] encryptWithGeneratedIvByteArray(byte[] key, byte[] plaintext) thro SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); cipher.update(plaintext); return cipher.doFinal(); } @@ -191,7 +191,7 @@ public byte[] encryptWithGeneratedIvByteArray(byte[] key, byte[] plaintext) thro public byte[] generateInsecureRandomBytes(int numBytes) { Random random = new Random(); byte[] bytes = new byte[numBytes]; - random.nextBytes(bytes); // $Source + random.nextBytes(bytes); // $ Source return bytes; } @@ -203,7 +203,7 @@ public byte[] encryptWithGeneratedIvByteArrayInsecure(byte[] key, byte[] plainte SecretKeySpec keySpec = new SecretKeySpec(key, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $Alert[java/quantum/examples/insecure-iv-or-nonce]] + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); // $ Alert[java/quantum/examples/insecure-iv-or-nonce]] cipher.update(plaintext); return cipher.doFinal(); } diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownAsymmetricKeySize/InsufficientAsymmetricKeySize.java b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownAsymmetricKeySize/InsufficientAsymmetricKeySize.java index c330bf82a054..196696b6d542 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownAsymmetricKeySize/InsufficientAsymmetricKeySize.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownAsymmetricKeySize/InsufficientAsymmetricKeySize.java @@ -2,15 +2,15 @@ public class InsufficientAsymmetricKeySize{ public static void test() throws Exception{ KeyPairGenerator keyPairGen1 = KeyPairGenerator.getInstance("RSA"); - keyPairGen1.initialize(1024); // $Alert[java/quantum/examples/weak-asymmetric-key-gen-size] + keyPairGen1.initialize(1024); // $ Alert[java/quantum/examples/weak-asymmetric-key-gen-size] keyPairGen1.generateKeyPair(); KeyPairGenerator keyPairGen2 = KeyPairGenerator.getInstance("DSA"); - keyPairGen2.initialize(1024); // $Alert[java/quantum/examples/weak-asymmetric-key-gen-size] + keyPairGen2.initialize(1024); // $ Alert[java/quantum/examples/weak-asymmetric-key-gen-size] keyPairGen2.generateKeyPair(); KeyPairGenerator keyPairGen3 = KeyPairGenerator.getInstance("DH"); - keyPairGen3.initialize(1024); // $Alert[java/quantum/examples/weak-asymmetric-key-gen-size] + keyPairGen3.initialize(1024); // $ Alert[java/quantum/examples/weak-asymmetric-key-gen-size] keyPairGen3.generateKeyPair(); KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("RSA"); @@ -25,4 +25,4 @@ public static void test() throws Exception{ keyPairGen6.initialize(2048); // GOOD keyPairGen6.generateKeyPair(); } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownBlockMode/Test.java b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownBlockMode/Test.java index 0c8b3b6691db..38095e476ac9 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownBlockMode/Test.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownBlockMode/Test.java @@ -10,25 +10,25 @@ public static void main(String[] args) throws Exception { byte[] data = "SensitiveData".getBytes(); // Insecure block mode: ECB - Cipher cipherECB = Cipher.getInstance("AES/ECB/PKCS5Padding"); // $Alert + Cipher cipherECB = Cipher.getInstance("AES/ECB/PKCS5Padding"); // $ Alert cipherECB.init(Cipher.ENCRYPT_MODE, key); byte[] ecbEncrypted = cipherECB.doFinal(data); System.out.println("ECB encrypted: " + bytesToHex(ecbEncrypted)); // Insecure block mode: CFB - Cipher cipherCFB = Cipher.getInstance("AES/CFB/PKCS5Padding"); // $Alert + Cipher cipherCFB = Cipher.getInstance("AES/CFB/PKCS5Padding"); // $ Alert cipherCFB.init(Cipher.ENCRYPT_MODE, key, iv); byte[] cfbEncrypted = cipherCFB.doFinal(data); System.out.println("CFB encrypted: " + bytesToHex(cfbEncrypted)); // Insecure block mode: OFB - Cipher cipherOFB = Cipher.getInstance("AES/OFB/PKCS5Padding"); // $Alert + Cipher cipherOFB = Cipher.getInstance("AES/OFB/PKCS5Padding"); // $ Alert cipherOFB.init(Cipher.ENCRYPT_MODE, key, iv); byte[] ofbEncrypted = cipherOFB.doFinal(data); System.out.println("OFB encrypted: " + bytesToHex(ofbEncrypted)); // Insecure block mode: CTR - Cipher cipherCTR = Cipher.getInstance("AES/CTR/NoPadding"); // $Alert + Cipher cipherCTR = Cipher.getInstance("AES/CTR/NoPadding"); // $ Alert cipherCTR.init(Cipher.ENCRYPT_MODE, key, iv); byte[] ctrEncrypted = cipherCTR.doFinal(data); System.out.println("CTR encrypted: " + bytesToHex(ctrEncrypted)); @@ -54,4 +54,4 @@ private static String bytesToHex(byte[] bytes) { sb.append(String.format("%02x", b)); return sb.toString(); } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownHash/WeakHashing.java b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownHash/WeakHashing.java index cc3b9a859d1d..99d8ae4b4dad 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownHash/WeakHashing.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownHash/WeakHashing.java @@ -12,33 +12,33 @@ void hashing() throws NoSuchAlgorithmException, IOException { props.load(new FileInputStream("example.properties")); // BAD: Using a weak hashing algorithm even with a secure default - MessageDigest bad = MessageDigest.getInstance(props.getProperty("hashAlg1")); // $Alert[java/quantum/examples/weak-hash] + MessageDigest bad = MessageDigest.getInstance(props.getProperty("hashAlg1")); // $ Alert[java/quantum/examples/weak-hash] // BAD: Using a weak hashing algorithm even with a secure default - MessageDigest bad2 = MessageDigest.getInstance(props.getProperty("hashAlg1", "SHA-256")); // $Alert[java/quantum/examples/weak-hash] + MessageDigest bad2 = MessageDigest.getInstance(props.getProperty("hashAlg1", "SHA-256")); // $ Alert[java/quantum/examples/weak-hash] // BAD: Using a strong hashing algorithm but with a weak default - MessageDigest bad3 = MessageDigest.getInstance(props.getProperty("hashAlg2", "MD5")); // $Alert[java/quantum/examples/weak-hash] + MessageDigest bad3 = MessageDigest.getInstance(props.getProperty("hashAlg2", "MD5")); // $ Alert[java/quantum/examples/weak-hash] // BAD: Using a weak hash - MessageDigest bad4 = MessageDigest.getInstance("SHA-1"); // $Alert[java/quantum/examples/weak-hash] + MessageDigest bad4 = MessageDigest.getInstance("SHA-1"); // $ Alert[java/quantum/examples/weak-hash] // BAD: Property does not exist and default (used value) is unknown - MessageDigest bad5 = MessageDigest.getInstance(props.getProperty("non-existent_property", "non-existent_default")); // $Alert[java/quantum/examples/unknown-hash] + MessageDigest bad5 = MessageDigest.getInstance(props.getProperty("non-existent_property", "non-existent_default")); // $ Alert[java/quantum/examples/unknown-hash] java.util.Properties props2 = new java.util.Properties(); props2.load(new FileInputStream("unobserved-file.properties")); - // BAD: "hashAlg2" is not visible in the file loaded for props2, should be an unknown + // BAD: "hashAlg2" is not visible in the file loaded for props2, should be an unknown // FALSE NEGATIVE for unknown hash - MessageDigest bad6 = MessageDigest.getInstance(props2.getProperty("hashAlg2", "SHA-256")); // $Alert[java/quantum/examples/unknown-hash] + MessageDigest bad6 = MessageDigest.getInstance(props2.getProperty("hashAlg2", "SHA-256")); // $ Alert[java/quantum/examples/unknown-hash] // GOOD: Using a strong hashing algorithm MessageDigest ok = MessageDigest.getInstance(props.getProperty("hashAlg2")); // BAD?: Property does not exist (considered unknown) and but default is secure - MessageDigest ok2 = MessageDigest.getInstance(props.getProperty("non-existent-property", "SHA-256")); // $Alert[java/quantum/examples/unknown-hash] + MessageDigest ok2 = MessageDigest.getInstance(props.getProperty("non-existent-property", "SHA-256")); // $ Alert[java/quantum/examples/unknown-hash] // GOOD: Using a strong hashing algorithm MessageDigest ok3 = MessageDigest.getInstance("SHA3-512"); diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/Test.java b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/Test.java index 13f6d03ec720..50bc113b9000 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/Test.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/Test.java @@ -28,8 +28,8 @@ public static byte[] generateSalt(int length) { */ public void pbkdf2LowIteration(String password) throws Exception { byte[] salt = generateSalt(16); - int iterationCount = 10; // $Source - PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); // $Alert[java/quantum/examples/weak-kdf-iteration-count] + int iterationCount = 10; // $ Source + PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); // $ Alert[java/quantum/examples/weak-kdf-iteration-count] SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] key = factory.generateSecret(spec).getEncoded(); } @@ -40,9 +40,9 @@ public void pbkdf2LowIteration(String password) throws Exception { * SAST/CBOM: - Parent: PBKDF2. - Iteration count is only 10, which is far * below acceptable security standards. - Flagged as insecure. */ - public void pbkdf2LowIteration(String password, int iterationCount) throws Exception { // $Source + public void pbkdf2LowIteration(String password, int iterationCount) throws Exception { // $ Source byte[] salt = generateSalt(16); - PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); // $Alert[java/quantum/examples/unknown-kdf-iteration-count] + PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); // $ Alert[java/quantum/examples/unknown-kdf-iteration-count] SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] key = factory.generateSecret(spec).getEncoded(); } @@ -55,9 +55,9 @@ public void pbkdf2LowIteration(String password, int iterationCount) throws Excep */ public void pbkdf2HighIteration(String password) throws Exception { byte[] salt = generateSalt(16); - int iterationCount = 1_000_000; - PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); + int iterationCount = 1_000_000; + PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, 256); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] key = factory.generateSecret(spec).getEncoded(); } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/UnknownKDFIterationCount.expected b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/UnknownKDFIterationCount.expected index 472d79090496..192393ad0280 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/UnknownKDFIterationCount.expected +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/UnknownKDFIterationCount.expected @@ -1,5 +1,5 @@ #select | Test.java:47:22:47:49 | KeyDerivation | Key derivation operation with unknown iteration: $@ | Test.java:43:53:43:70 | iterationCount | iterationCount | testFailures -| Test.java:45:94:45:153 | // $Alert[java/quantum/examples/unknown-kdf-iteration-count] | Missing result: Alert[java/quantum/examples/unknown-kdf-iteration-count] | +| Test.java:45:94:45:154 | // $ Alert[java/quantum/examples/unknown-kdf-iteration-count] | Missing result: Alert[java/quantum/examples/unknown-kdf-iteration-count] | | Test.java:47:22:47:49 | Key derivation operation with unknown iteration: $@ | Unexpected result: Alert | diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/WeakKDFIterationCount.expected b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/WeakKDFIterationCount.expected index 3567afd03221..cd19c73a6653 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/WeakKDFIterationCount.expected +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFIterationCount/WeakKDFIterationCount.expected @@ -13,4 +13,4 @@ nodes | Test.java:59:72:59:85 | iterationCount | semmle.label | iterationCount | subpaths testFailures -| Test.java:43:92:43:101 | // $Source | Missing result: Source | +| Test.java:43:92:43:102 | // $ Source | Missing result: Source | diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFKeySize/Test.java b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFKeySize/Test.java index 21619c8c5743..014a0bfaf8f3 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFKeySize/Test.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownKDFKeySize/Test.java @@ -20,8 +20,8 @@ public static byte[] generateSalt(int length) { public void pbkdf2WeakKeySize(String password) throws Exception { byte[] salt = generateSalt(16); int iterationCount = 100_000; - int keySize = 64; // $Source - PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keySize); // $Alert[java/quantum/examples/weak-kdf-key-size] + int keySize = 64; // $ Source + PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keySize); // $ Alert[java/quantum/examples/weak-kdf-key-size] SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] key = factory.generateSecret(spec).getEncoded(); } @@ -39,4 +39,4 @@ public void pbkdf2SecureKeySize(String password) throws Exception { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); byte[] key = factory.generateSecret(spec).getEncoded(); } -} \ No newline at end of file +} diff --git a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownSymmetricCipher/Test.java b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownSymmetricCipher/Test.java index fde9f9a24d19..6c30dd2402d1 100644 --- a/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownSymmetricCipher/Test.java +++ b/java/ql/test/experimental/query-tests/quantum/examples/WeakOrUnknownSymmetricCipher/Test.java @@ -10,51 +10,51 @@ public static void main(String[] args) throws Exception { byte[] data = "Sensitive Data".getBytes(); // BAD: DES (unsafe) - KeyGenerator desKeyGen = KeyGenerator.getInstance("DES"); // $Alert + KeyGenerator desKeyGen = KeyGenerator.getInstance("DES"); // $ Alert SecretKey desKey = desKeyGen.generateKey(); - Cipher desCipher = Cipher.getInstance("DES"); // $Alert + Cipher desCipher = Cipher.getInstance("DES"); // $ Alert desCipher.init(Cipher.ENCRYPT_MODE, desKey); byte[] desEncrypted = desCipher.doFinal(data); // BAD: DESede (Triple DES, considered weak) - KeyGenerator desedeKeyGen = KeyGenerator.getInstance("DESede"); // $Alert + KeyGenerator desedeKeyGen = KeyGenerator.getInstance("DESede"); // $ Alert SecretKey desedeKey = desedeKeyGen.generateKey(); - Cipher desedeCipher = Cipher.getInstance("DESede"); // $Alert + Cipher desedeCipher = Cipher.getInstance("DESede"); // $ Alert desedeCipher.init(Cipher.ENCRYPT_MODE, desedeKey); byte[] desedeEncrypted = desedeCipher.doFinal(data); // BAD: Blowfish (considered weak) - KeyGenerator blowfishKeyGen = KeyGenerator.getInstance("Blowfish"); // $Alert + KeyGenerator blowfishKeyGen = KeyGenerator.getInstance("Blowfish"); // $ Alert SecretKey blowfishKey = blowfishKeyGen.generateKey(); - Cipher blowfishCipher = Cipher.getInstance("Blowfish"); // $Alert + Cipher blowfishCipher = Cipher.getInstance("Blowfish"); // $ Alert blowfishCipher.init(Cipher.ENCRYPT_MODE, blowfishKey); byte[] blowfishEncrypted = blowfishCipher.doFinal(data); // BAD: RC2 (unsafe) - KeyGenerator rc2KeyGen = KeyGenerator.getInstance("RC2"); // $Alert + KeyGenerator rc2KeyGen = KeyGenerator.getInstance("RC2"); // $ Alert SecretKey rc2Key = rc2KeyGen.generateKey(); - Cipher rc2Cipher = Cipher.getInstance("RC2"); // $Alert + Cipher rc2Cipher = Cipher.getInstance("RC2"); // $ Alert rc2Cipher.init(Cipher.ENCRYPT_MODE, rc2Key); byte[] rc2Encrypted = rc2Cipher.doFinal(data); // BAD: RC4 (stream cipher, unsafe) - KeyGenerator rc4KeyGen = KeyGenerator.getInstance("RC4"); // $Alert + KeyGenerator rc4KeyGen = KeyGenerator.getInstance("RC4"); // $ Alert SecretKey rc4Key = rc4KeyGen.generateKey(); - Cipher rc4Cipher = Cipher.getInstance("RC4"); // $Alert + Cipher rc4Cipher = Cipher.getInstance("RC4"); // $ Alert rc4Cipher.init(Cipher.ENCRYPT_MODE, rc4Key); byte[] rc4Encrypted = rc4Cipher.doFinal(data); // BAD: IDEA (considered weak) - KeyGenerator ideaKeyGen = KeyGenerator.getInstance("IDEA"); // $Alert + KeyGenerator ideaKeyGen = KeyGenerator.getInstance("IDEA"); // $ Alert SecretKey ideaKey = ideaKeyGen.generateKey(); - Cipher ideaCipher = Cipher.getInstance("IDEA"); // $Alert + Cipher ideaCipher = Cipher.getInstance("IDEA"); // $ Alert ideaCipher.init(Cipher.ENCRYPT_MODE, ideaKey); byte[] ideaEncrypted = ideaCipher.doFinal(data); // BAD: Skipjack (unsafe) - KeyGenerator skipjackKeyGen = KeyGenerator.getInstance("Skipjack"); // $Alert + KeyGenerator skipjackKeyGen = KeyGenerator.getInstance("Skipjack"); // $ Alert SecretKey skipjackKey = skipjackKeyGen.generateKey(); - Cipher skipjackCipher = Cipher.getInstance("Skipjack"); // $Alert + Cipher skipjackCipher = Cipher.getInstance("Skipjack"); // $ Alert skipjackCipher.init(Cipher.ENCRYPT_MODE, skipjackKey); byte[] skipjackEncrypted = skipjackCipher.doFinal(data); @@ -78,4 +78,4 @@ public static void main(String[] args) throws Exception { // GOOD: not a symmetric cipher (Sanity check) SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); } -} \ No newline at end of file +} diff --git a/java/ql/test/ext/TestModels/Test.java b/java/ql/test/ext/TestModels/Test.java index f54007ada9e4..084c844957cc 100644 --- a/java/ql/test/ext/TestModels/Test.java +++ b/java/ql/test/ext/TestModels/Test.java @@ -33,50 +33,50 @@ public void test() throws Exception { // top 100 JDK APIs tests { Exception e1 = new RuntimeException((String)source()); - sink((String)e1.getMessage()); // $hasValueFlow + sink((String)e1.getMessage()); // $ hasValueFlow Exception e2 = new RuntimeException((Throwable)source()); - sink((Throwable)e2.getCause()); // $hasValueFlow + sink((Throwable)e2.getCause()); // $ hasValueFlow Exception e3 = new IllegalArgumentException((String)source()); - sink((String)e3.getMessage()); // $hasValueFlow + sink((String)e3.getMessage()); // $ hasValueFlow Exception e4 = new IllegalStateException((String)source()); - sink((String)e4.getMessage()); // $hasValueFlow + sink((String)e4.getMessage()); // $ hasValueFlow Exception e5 = new UnsupportedOperationException((String)source()); - sink((String)e5.getMessage()); // $hasValueFlow + sink((String)e5.getMessage()); // $ hasValueFlow Throwable t = new Throwable((Throwable)source()); - sink((Throwable)t.getCause()); // $hasValueFlow + sink((Throwable)t.getCause()); // $ hasValueFlow String s2 = (String)source(); int i = 0; - sink(s2.charAt(i)); // $hasTaintFlow + sink(s2.charAt(i)); // $ hasTaintFlow ResultSet rs = (ResultSet)source(); - sink(rs.getString("")); // $hasTaintFlow + sink(rs.getString("")); // $ hasTaintFlow } // top 200 JDK APIs tests { // java.io Exception e1 = new IOException((String)source()); - sink((String)e1.getMessage()); // $hasValueFlow + sink((String)e1.getMessage()); // $ hasValueFlow File f = (File)source(); - sink(f.getName()); // $hasTaintFlow + sink(f.getName()); // $ hasTaintFlow // java.lang Exception e2 = new Exception((String)source()); - sink((String)e2.getMessage()); // $hasValueFlow + sink((String)e2.getMessage()); // $ hasValueFlow Exception e3 = new IndexOutOfBoundsException((String)source()); - sink((String)e3.getMessage()); // $hasValueFlow + sink((String)e3.getMessage()); // $ hasValueFlow Exception e4 = new RuntimeException((String)source(), (Throwable)source()); - sink((String)e4.getMessage()); // $hasValueFlow - sink((Throwable)e4.getCause()); // $hasValueFlow + sink((String)e4.getMessage()); // $ hasValueFlow + sink((Throwable)e4.getCause()); // $ hasValueFlow // java.sql Connection con = DriverManager.getConnection(""); @@ -86,14 +86,14 @@ public void test() throws Exception { // java.util.concurrent.atomic AtomicReference ar = new AtomicReference(source()); - sink(ar.get()); // $hasValueFlow + sink(ar.get()); // $ hasValueFlow // java.util StringJoiner sj1 = new StringJoiner(","); - sink(sj1.add((CharSequence)source())); // $hasTaintFlow + sink(sj1.add((CharSequence)source())); // $ hasTaintFlow StringJoiner sj2 = (StringJoiner)source(); - sink(sj2.add("test")); // $hasValueFlow + sink(sj2.add("test")); // $ hasValueFlow } // top 300-500 JDK APIs tests @@ -101,62 +101,62 @@ public void test() throws Exception { // java.awt Container container = new Container(); - sink(container.add((Component)source())); // $hasValueFlow + sink(container.add((Component)source())); // $ hasValueFlow // java.io File f1 = (File)source(); - sink(f1.getParentFile()); // $hasTaintFlow + sink(f1.getParentFile()); // $ hasTaintFlow File f2 = (File)source(); - sink(f2.getPath()); // $hasTaintFlow + sink(f2.getPath()); // $ hasTaintFlow StringWriter sw = (StringWriter)source(); - sink(sw.toString()); // $hasTaintFlow + sink(sw.toString()); // $ hasTaintFlow Exception e = new UncheckedIOException((IOException)source()); - sink((Throwable)e.getCause()); // $hasValueFlow + sink((Throwable)e.getCause()); // $ hasValueFlow // java.net URL url = (URL)source(); - sink(url.toURI()); // $hasTaintFlow + sink(url.toURI()); // $ hasTaintFlow // java.nio.file Path p = (Path)source(); - sink(p.getFileName()); // $hasTaintFlow + sink(p.getFileName()); // $ hasTaintFlow // java.util.concurrent.atomic AtomicReference ar = new AtomicReference(); ar.set(source()); - sink(ar.get()); // $hasValueFlow + sink(ar.get()); // $ hasValueFlow // java.util.concurrent // `ThreadPoolExecutor` implements the `java.util.concurrent.ExecutorService` interface ThreadPoolExecutor tpe = new ThreadPoolExecutor(0, 0, 0, null, null); - sink(tpe.submit((Runnable)source())); // $hasTaintFlow + sink(tpe.submit((Runnable)source())); // $ hasTaintFlow CompletionStage cs = (CompletionStage)source(); - sink(cs.toCompletableFuture()); // $hasTaintFlow + sink(cs.toCompletableFuture()); // $ hasTaintFlow CompletableFuture cf1 = new CompletableFuture(); cf1.complete(source()); - sink(cf1.get()); // $hasValueFlow - sink(cf1.join()); // $hasValueFlow + sink(cf1.get()); // $ hasValueFlow + sink(cf1.join()); // $ hasValueFlow CompletableFuture cf2 = CompletableFuture.completedFuture(source()); - sink(cf2.get()); // $hasValueFlow - sink(cf2.join()); // $hasValueFlow + sink(cf2.get()); // $ hasValueFlow + sink(cf2.join()); // $ hasValueFlow // java.util.logging Logger logger = Logger.getLogger((String)source()); - sink(logger.getName()); // $hasValueFlow + sink(logger.getName()); // $ hasValueFlow // java.util.regex Pattern pattern = Pattern.compile((String)source()); - sink(pattern); // $hasTaintFlow + sink(pattern); // $ hasTaintFlow // java.util EventObject eventObj = new EventObject(source()); - sink(eventObj.getSource()); // $hasValueFlow + sink(eventObj.getSource()); // $ hasValueFlow // "java.util;ResourceBundle;true;getString;(String);;Argument[-1].MapValue;ReturnValue;value;manual" String out = null; @@ -166,33 +166,33 @@ public void test() throws Exception { // java.lang AssertionError assertErr = new AssertionError(source()); - sink((String)assertErr.getMessage()); // $hasValueFlow + sink((String)assertErr.getMessage()); // $ hasValueFlow - sink(Test.class.cast(source())); // $hasValueFlow + sink(Test.class.cast(source())); // $ hasValueFlow Exception excep1 = new Exception((String)source(), (Throwable)source()); - sink((String)excep1.getMessage()); // $hasValueFlow - sink((Throwable)excep1.getCause()); // $hasValueFlow + sink((String)excep1.getMessage()); // $ hasValueFlow + sink((Throwable)excep1.getCause()); // $ hasValueFlow Exception excep2 = new NullPointerException((String)source()); - sink((String)excep2.getMessage()); // $hasValueFlow + sink((String)excep2.getMessage()); // $ hasValueFlow StringBuilder sb = (StringBuilder)source(); - sink(sb.delete(0, 1)); // $hasValueFlow + sink(sb.delete(0, 1)); // $ hasValueFlow Thread thread1 = new Thread((Runnable)source()); - sink(thread1); // $hasTaintFlow + sink(thread1); // $ hasTaintFlow Thread thread2 = new Thread((String)source()); - sink(thread2.getName()); // $hasValueFlow + sink(thread2.getName()); // $ hasValueFlow ThreadLocal threadloc = new ThreadLocal(); threadloc.set(source()); - sink(threadloc.get()); // $hasValueFlow + sink(threadloc.get()); // $ hasValueFlow Throwable th = new Throwable((String)source()); - sink((String)th.getLocalizedMessage()); // $hasValueFlow - sink(th.toString()); // $hasTaintFlow + sink((String)th.getLocalizedMessage()); // $ hasValueFlow + sink(th.toString()); // $ hasTaintFlow } } } diff --git a/java/ql/test/library-tests/controlflow/basic/bbStmts.expected b/java/ql/test/library-tests/controlflow/basic/bbStmts.expected index df336ce90a22..58b3e698771a 100644 --- a/java/ql/test/library-tests/controlflow/basic/bbStmts.expected +++ b/java/ql/test/library-tests/controlflow/basic/bbStmts.expected @@ -1,140 +1,296 @@ -| Test.java:3:14:3:17 | Exceptional Exit | 0 | Test.java:3:14:3:17 | Exceptional Exit | -| Test.java:3:14:3:17 | Exit | 0 | Test.java:3:14:3:17 | Exit | -| Test.java:3:14:3:17 | { ... } | 0 | Test.java:3:14:3:17 | { ... } | -| Test.java:3:14:3:17 | { ... } | 1 | Test.java:3:14:3:17 | super(...) | -| Test.java:3:14:3:17 | { ... } | 2 | Test.java:3:14:3:17 | Normal Exit | -| Test.java:4:14:4:17 | Exceptional Exit | 0 | Test.java:4:14:4:17 | Exceptional Exit | -| Test.java:4:14:4:17 | Exit | 0 | Test.java:4:14:4:17 | Exit | +| Test.java:3:14:3:17 | Entry | 0 | Test.java:3:14:3:17 | Entry | +| Test.java:3:14:3:17 | Entry | 1 | Test.java:3:14:3:17 | { ... } | +| Test.java:3:14:3:17 | Entry | 2 | Test.java:3:14:3:17 | Before super(...) | +| Test.java:3:14:3:17 | Entry | 3 | Test.java:3:14:3:17 | super(...) | +| Test.java:3:14:3:17 | Entry | 4 | Test.java:3:14:3:17 | After super(...) | +| Test.java:3:14:3:17 | Entry | 5 | Test.java:3:14:3:17 | After { ... } | +| Test.java:3:14:3:17 | Entry | 6 | Test.java:3:14:3:17 | Normal Exit | +| Test.java:3:14:3:17 | Entry | 7 | Test.java:3:14:3:17 | Exit | +| Test.java:4:14:4:17 | Entry | 0 | Test.java:4:14:4:17 | Entry | +| Test.java:4:14:4:17 | Entry | 1 | Test.java:4:21:76:2 | { ... } | +| Test.java:4:14:4:17 | Entry | 2 | Test.java:5:3:5:12 | var ...; | +| Test.java:4:14:4:17 | Entry | 3 | Test.java:5:7:5:11 | Before x | +| Test.java:4:14:4:17 | Entry | 4 | Test.java:5:11:5:11 | 0 | +| Test.java:4:14:4:17 | Entry | 5 | Test.java:5:7:5:11 | x | +| Test.java:4:14:4:17 | Entry | 6 | Test.java:5:7:5:11 | After x | +| Test.java:4:14:4:17 | Entry | 7 | Test.java:5:3:5:12 | After var ...; | +| Test.java:4:14:4:17 | Entry | 8 | Test.java:6:3:6:14 | var ...; | +| Test.java:4:14:4:17 | Entry | 9 | Test.java:6:8:6:13 | Before y | +| Test.java:4:14:4:17 | Entry | 10 | Test.java:6:12:6:13 | 50 | +| Test.java:4:14:4:17 | Entry | 11 | Test.java:6:8:6:13 | y | +| Test.java:4:14:4:17 | Entry | 12 | Test.java:6:8:6:13 | After y | +| Test.java:4:14:4:17 | Entry | 13 | Test.java:6:3:6:14 | After var ...; | +| Test.java:4:14:4:17 | Entry | 14 | Test.java:7:3:7:12 | var ...; | +| Test.java:4:14:4:17 | Entry | 15 | Test.java:7:7:7:11 | Before z | +| Test.java:4:14:4:17 | Entry | 16 | Test.java:7:11:7:11 | 0 | +| Test.java:4:14:4:17 | Entry | 17 | Test.java:7:7:7:11 | z | +| Test.java:4:14:4:17 | Entry | 18 | Test.java:7:7:7:11 | After z | +| Test.java:4:14:4:17 | Entry | 19 | Test.java:7:3:7:12 | After var ...; | +| Test.java:4:14:4:17 | Entry | 20 | Test.java:8:3:8:12 | var ...; | +| Test.java:4:14:4:17 | Entry | 21 | Test.java:8:7:8:11 | Before w | +| Test.java:4:14:4:17 | Entry | 22 | Test.java:8:11:8:11 | 0 | +| Test.java:4:14:4:17 | Entry | 23 | Test.java:8:7:8:11 | w | +| Test.java:4:14:4:17 | Entry | 24 | Test.java:8:7:8:11 | After w | +| Test.java:4:14:4:17 | Entry | 25 | Test.java:8:3:8:12 | After var ...; | +| Test.java:4:14:4:17 | Entry | 26 | Test.java:11:3:11:12 | if (...) | +| Test.java:4:14:4:17 | Entry | 27 | Test.java:11:7:11:11 | Before ... > ... | +| Test.java:4:14:4:17 | Entry | 28 | Test.java:11:7:11:7 | x | +| Test.java:4:14:4:17 | Entry | 29 | Test.java:11:11:11:11 | 0 | +| Test.java:4:14:4:17 | Entry | 30 | Test.java:11:7:11:11 | ... > ... | | Test.java:4:14:4:17 | Normal Exit | 0 | Test.java:4:14:4:17 | Normal Exit | -| Test.java:4:21:76:2 | { ... } | 0 | Test.java:4:21:76:2 | { ... } | -| Test.java:4:21:76:2 | { ... } | 1 | Test.java:5:3:5:12 | var ...; | -| Test.java:4:21:76:2 | { ... } | 2 | Test.java:5:11:5:11 | 0 | -| Test.java:4:21:76:2 | { ... } | 3 | Test.java:5:7:5:11 | x | -| Test.java:4:21:76:2 | { ... } | 4 | Test.java:6:3:6:14 | var ...; | -| Test.java:4:21:76:2 | { ... } | 5 | Test.java:6:12:6:13 | 50 | -| Test.java:4:21:76:2 | { ... } | 6 | Test.java:6:8:6:13 | y | -| Test.java:4:21:76:2 | { ... } | 7 | Test.java:7:3:7:12 | var ...; | -| Test.java:4:21:76:2 | { ... } | 8 | Test.java:7:11:7:11 | 0 | -| Test.java:4:21:76:2 | { ... } | 9 | Test.java:7:7:7:11 | z | -| Test.java:4:21:76:2 | { ... } | 10 | Test.java:8:3:8:12 | var ...; | -| Test.java:4:21:76:2 | { ... } | 11 | Test.java:8:11:8:11 | 0 | -| Test.java:4:21:76:2 | { ... } | 12 | Test.java:8:7:8:11 | w | -| Test.java:4:21:76:2 | { ... } | 13 | Test.java:11:3:11:12 | if (...) | -| Test.java:4:21:76:2 | { ... } | 14 | Test.java:11:7:11:7 | x | -| Test.java:4:21:76:2 | { ... } | 15 | Test.java:11:11:11:11 | 0 | -| Test.java:4:21:76:2 | { ... } | 16 | Test.java:11:7:11:11 | ... > ... | -| Test.java:11:14:14:3 | { ... } | 0 | Test.java:11:14:14:3 | { ... } | -| Test.java:11:14:14:3 | { ... } | 1 | Test.java:12:4:12:10 | ; | -| Test.java:11:14:14:3 | { ... } | 2 | Test.java:12:8:12:9 | 20 | -| Test.java:11:14:14:3 | { ... } | 3 | Test.java:12:4:12:9 | ...=... | -| Test.java:11:14:14:3 | { ... } | 4 | Test.java:13:4:13:10 | ; | -| Test.java:11:14:14:3 | { ... } | 5 | Test.java:13:8:13:9 | 10 | -| Test.java:11:14:14:3 | { ... } | 6 | Test.java:13:4:13:9 | ...=... | -| Test.java:14:10:16:3 | { ... } | 0 | Test.java:14:10:16:3 | { ... } | -| Test.java:14:10:16:3 | { ... } | 1 | Test.java:15:4:15:10 | ; | -| Test.java:14:10:16:3 | { ... } | 2 | Test.java:15:8:15:9 | 30 | -| Test.java:14:10:16:3 | { ... } | 3 | Test.java:15:4:15:9 | ...=... | -| Test.java:18:3:18:8 | ; | 0 | Test.java:18:3:18:8 | ; | -| Test.java:18:3:18:8 | ; | 1 | Test.java:18:7:18:7 | 0 | -| Test.java:18:3:18:8 | ; | 2 | Test.java:18:3:18:7 | ...=... | -| Test.java:18:3:18:8 | ; | 3 | Test.java:21:3:21:11 | if (...) | -| Test.java:18:3:18:8 | ; | 4 | Test.java:21:6:21:6 | x | -| Test.java:18:3:18:8 | ; | 5 | Test.java:21:10:21:10 | 0 | -| Test.java:18:3:18:8 | ; | 6 | Test.java:21:6:21:10 | ... < ... | -| Test.java:22:4:22:10 | ; | 0 | Test.java:22:4:22:10 | ; | -| Test.java:22:4:22:10 | ; | 1 | Test.java:22:8:22:9 | 40 | -| Test.java:22:4:22:10 | ; | 2 | Test.java:22:4:22:9 | ...=... | -| Test.java:22:4:22:10 | ; | 3 | Test.java:27:3:27:9 | ; | -| Test.java:22:4:22:10 | ; | 4 | Test.java:27:7:27:8 | 10 | -| Test.java:22:4:22:10 | ; | 5 | Test.java:27:3:27:8 | ...=... | -| Test.java:22:4:22:10 | ; | 6 | Test.java:30:3:30:13 | if (...) | -| Test.java:22:4:22:10 | ; | 7 | Test.java:30:7:30:7 | x | -| Test.java:22:4:22:10 | ; | 8 | Test.java:30:12:30:12 | 0 | -| Test.java:22:4:22:10 | ; | 9 | Test.java:30:7:30:12 | ... == ... | -| Test.java:24:4:24:10 | return ... | 0 | Test.java:24:4:24:10 | return ... | -| Test.java:30:15:33:3 | { ... } | 0 | Test.java:30:15:33:3 | { ... } | -| Test.java:30:15:33:3 | { ... } | 1 | Test.java:31:4:31:10 | ; | -| Test.java:30:15:33:3 | { ... } | 2 | Test.java:31:8:31:9 | 60 | -| Test.java:30:15:33:3 | { ... } | 3 | Test.java:31:4:31:9 | ...=... | -| Test.java:30:15:33:3 | { ... } | 4 | Test.java:32:4:32:10 | ; | -| Test.java:30:15:33:3 | { ... } | 5 | Test.java:32:8:32:9 | 10 | -| Test.java:30:15:33:3 | { ... } | 6 | Test.java:32:4:32:9 | ...=... | -| Test.java:35:3:35:9 | ; | 0 | Test.java:35:3:35:9 | ; | -| Test.java:35:3:35:9 | ; | 1 | Test.java:35:7:35:8 | 20 | -| Test.java:35:3:35:9 | ; | 2 | Test.java:35:3:35:8 | ...=... | -| Test.java:35:3:35:9 | ; | 3 | Test.java:38:3:38:14 | while (...) | -| Test.java:38:9:38:9 | x | 0 | Test.java:38:9:38:9 | x | -| Test.java:38:9:38:9 | x | 1 | Test.java:38:13:38:13 | 0 | -| Test.java:38:9:38:9 | x | 2 | Test.java:38:9:38:13 | ... > ... | -| Test.java:38:16:41:3 | { ... } | 0 | Test.java:38:16:41:3 | { ... } | -| Test.java:38:16:41:3 | { ... } | 1 | Test.java:39:4:39:10 | ; | -| Test.java:38:16:41:3 | { ... } | 2 | Test.java:39:8:39:9 | 10 | -| Test.java:38:16:41:3 | { ... } | 3 | Test.java:39:4:39:9 | ...=... | -| Test.java:38:16:41:3 | { ... } | 4 | Test.java:40:4:40:7 | ; | -| Test.java:38:16:41:3 | { ... } | 5 | Test.java:40:4:40:4 | x | -| Test.java:38:16:41:3 | { ... } | 6 | Test.java:40:4:40:6 | ...-- | -| Test.java:43:3:43:9 | ; | 0 | Test.java:43:3:43:9 | ; | -| Test.java:43:3:43:9 | ; | 1 | Test.java:43:7:43:8 | 30 | -| Test.java:43:3:43:9 | ; | 2 | Test.java:43:3:43:8 | ...=... | -| Test.java:43:3:43:9 | ; | 3 | Test.java:46:3:46:29 | for (...;...;...) | -| Test.java:43:3:43:9 | ; | 4 | Test.java:46:15:46:15 | 0 | -| Test.java:43:3:43:9 | ; | 5 | Test.java:46:11:46:15 | j | -| Test.java:46:18:46:18 | j | 0 | Test.java:46:18:46:18 | j | -| Test.java:46:18:46:18 | j | 1 | Test.java:46:22:46:23 | 10 | -| Test.java:46:18:46:18 | j | 2 | Test.java:46:18:46:23 | ... < ... | -| Test.java:46:31:49:3 | { ... } | 0 | Test.java:46:31:49:3 | { ... } | -| Test.java:46:31:49:3 | { ... } | 1 | Test.java:47:4:47:9 | ; | -| Test.java:46:31:49:3 | { ... } | 2 | Test.java:47:8:47:8 | 0 | -| Test.java:46:31:49:3 | { ... } | 3 | Test.java:47:4:47:8 | ...=... | -| Test.java:46:31:49:3 | { ... } | 4 | Test.java:48:4:48:10 | ; | -| Test.java:46:31:49:3 | { ... } | 5 | Test.java:48:8:48:9 | 10 | -| Test.java:46:31:49:3 | { ... } | 6 | Test.java:48:4:48:9 | ...=... | -| Test.java:46:31:49:3 | { ... } | 7 | Test.java:46:26:46:26 | j | -| Test.java:46:31:49:3 | { ... } | 8 | Test.java:46:26:46:28 | ...++ | -| Test.java:51:3:51:9 | ; | 0 | Test.java:51:3:51:9 | ; | -| Test.java:51:3:51:9 | ; | 1 | Test.java:51:7:51:8 | 40 | -| Test.java:51:3:51:9 | ; | 2 | Test.java:51:3:51:8 | ...=... | -| Test.java:51:3:51:9 | ; | 3 | Test.java:54:3:54:29 | for (...;...;...) | -| Test.java:51:3:51:9 | ; | 4 | Test.java:54:15:54:15 | 0 | -| Test.java:51:3:51:9 | ; | 5 | Test.java:54:11:54:15 | j | -| Test.java:54:18:54:18 | j | 0 | Test.java:54:18:54:18 | j | -| Test.java:54:18:54:18 | j | 1 | Test.java:54:22:54:23 | 10 | -| Test.java:54:18:54:18 | j | 2 | Test.java:54:18:54:23 | ... < ... | -| Test.java:54:26:54:26 | j | 0 | Test.java:54:26:54:26 | j | -| Test.java:54:26:54:26 | j | 1 | Test.java:54:26:54:28 | ...++ | -| Test.java:54:31:68:3 | { ... } | 0 | Test.java:54:31:68:3 | { ... } | -| Test.java:54:31:68:3 | { ... } | 1 | Test.java:55:4:55:10 | ; | -| Test.java:54:31:68:3 | { ... } | 2 | Test.java:55:8:55:9 | 30 | -| Test.java:54:31:68:3 | { ... } | 3 | Test.java:55:4:55:9 | ...=... | -| Test.java:54:31:68:3 | { ... } | 4 | Test.java:56:4:56:12 | if (...) | -| Test.java:54:31:68:3 | { ... } | 5 | Test.java:56:7:56:7 | z | -| Test.java:54:31:68:3 | { ... } | 6 | Test.java:56:11:56:11 | 0 | -| Test.java:54:31:68:3 | { ... } | 7 | Test.java:56:7:56:11 | ... > ... | -| Test.java:57:5:57:13 | if (...) | 0 | Test.java:57:5:57:13 | if (...) | -| Test.java:57:5:57:13 | if (...) | 1 | Test.java:57:8:57:8 | y | -| Test.java:57:5:57:13 | if (...) | 2 | Test.java:57:12:57:12 | 0 | -| Test.java:57:5:57:13 | if (...) | 3 | Test.java:57:8:57:12 | ... > ... | -| Test.java:57:15:60:5 | { ... } | 0 | Test.java:57:15:60:5 | { ... } | -| Test.java:57:15:60:5 | { ... } | 1 | Test.java:58:6:58:11 | ; | -| Test.java:57:15:60:5 | { ... } | 2 | Test.java:58:10:58:10 | 0 | -| Test.java:57:15:60:5 | { ... } | 3 | Test.java:58:6:58:10 | ...=... | -| Test.java:57:15:60:5 | { ... } | 4 | Test.java:59:6:59:11 | break | -| Test.java:60:12:62:5 | { ... } | 0 | Test.java:60:12:62:5 | { ... } | -| Test.java:60:12:62:5 | { ... } | 1 | Test.java:61:6:61:12 | ; | -| Test.java:60:12:62:5 | { ... } | 2 | Test.java:61:10:61:11 | 20 | -| Test.java:60:12:62:5 | { ... } | 3 | Test.java:61:6:61:11 | ...=... | -| Test.java:60:12:62:5 | { ... } | 4 | Test.java:67:4:67:9 | ; | -| Test.java:60:12:62:5 | { ... } | 5 | Test.java:67:8:67:8 | 0 | -| Test.java:60:12:62:5 | { ... } | 6 | Test.java:67:4:67:8 | ...=... | -| Test.java:63:9:66:4 | { ... } | 0 | Test.java:63:9:66:4 | { ... } | -| Test.java:63:9:66:4 | { ... } | 1 | Test.java:64:5:64:11 | ; | -| Test.java:63:9:66:4 | { ... } | 2 | Test.java:64:9:64:10 | 10 | -| Test.java:63:9:66:4 | { ... } | 3 | Test.java:64:5:64:10 | ...=... | -| Test.java:63:9:66:4 | { ... } | 4 | Test.java:65:5:65:13 | continue | -| Test.java:70:3:70:9 | ; | 0 | Test.java:70:3:70:9 | ; | -| Test.java:70:3:70:9 | ; | 1 | Test.java:70:7:70:8 | 50 | -| Test.java:70:3:70:9 | ; | 2 | Test.java:70:3:70:8 | ...=... | -| Test.java:70:3:70:9 | ; | 3 | Test.java:74:3:74:9 | ; | -| Test.java:70:3:70:9 | ; | 4 | Test.java:74:7:74:8 | 40 | -| Test.java:70:3:70:9 | ; | 5 | Test.java:74:3:74:8 | ...=... | -| Test.java:70:3:70:9 | ; | 6 | Test.java:75:3:75:9 | return ... | +| Test.java:4:14:4:17 | Normal Exit | 1 | Test.java:4:14:4:17 | Exit | +| Test.java:11:3:11:12 | After if (...) | 0 | Test.java:11:3:11:12 | After if (...) | +| Test.java:11:3:11:12 | After if (...) | 1 | Test.java:18:3:18:8 | ; | +| Test.java:11:3:11:12 | After if (...) | 2 | Test.java:18:3:18:7 | Before ...=... | +| Test.java:11:3:11:12 | After if (...) | 3 | Test.java:18:3:18:3 | z | +| Test.java:11:3:11:12 | After if (...) | 4 | Test.java:18:7:18:7 | 0 | +| Test.java:11:3:11:12 | After if (...) | 5 | Test.java:18:3:18:7 | ...=... | +| Test.java:11:3:11:12 | After if (...) | 6 | Test.java:18:3:18:7 | After ...=... | +| Test.java:11:3:11:12 | After if (...) | 7 | Test.java:18:3:18:8 | After ; | +| Test.java:11:3:11:12 | After if (...) | 8 | Test.java:21:3:21:11 | if (...) | +| Test.java:11:3:11:12 | After if (...) | 9 | Test.java:21:6:21:10 | Before ... < ... | +| Test.java:11:3:11:12 | After if (...) | 10 | Test.java:21:6:21:6 | x | +| Test.java:11:3:11:12 | After if (...) | 11 | Test.java:21:10:21:10 | 0 | +| Test.java:11:3:11:12 | After if (...) | 12 | Test.java:21:6:21:10 | ... < ... | +| Test.java:11:7:11:11 | After ... > ... [false] | 0 | Test.java:11:7:11:11 | After ... > ... [false] | +| Test.java:11:7:11:11 | After ... > ... [false] | 1 | Test.java:14:10:16:3 | { ... } | +| Test.java:11:7:11:11 | After ... > ... [false] | 2 | Test.java:15:4:15:10 | ; | +| Test.java:11:7:11:11 | After ... > ... [false] | 3 | Test.java:15:4:15:9 | Before ...=... | +| Test.java:11:7:11:11 | After ... > ... [false] | 4 | Test.java:15:4:15:4 | y | +| Test.java:11:7:11:11 | After ... > ... [false] | 5 | Test.java:15:8:15:9 | 30 | +| Test.java:11:7:11:11 | After ... > ... [false] | 6 | Test.java:15:4:15:9 | ...=... | +| Test.java:11:7:11:11 | After ... > ... [false] | 7 | Test.java:15:4:15:9 | After ...=... | +| Test.java:11:7:11:11 | After ... > ... [false] | 8 | Test.java:15:4:15:10 | After ; | +| Test.java:11:7:11:11 | After ... > ... [false] | 9 | Test.java:14:10:16:3 | After { ... } | +| Test.java:11:7:11:11 | After ... > ... [true] | 0 | Test.java:11:7:11:11 | After ... > ... [true] | +| Test.java:11:7:11:11 | After ... > ... [true] | 1 | Test.java:11:14:14:3 | { ... } | +| Test.java:11:7:11:11 | After ... > ... [true] | 2 | Test.java:12:4:12:10 | ; | +| Test.java:11:7:11:11 | After ... > ... [true] | 3 | Test.java:12:4:12:9 | Before ...=... | +| Test.java:11:7:11:11 | After ... > ... [true] | 4 | Test.java:12:4:12:4 | y | +| Test.java:11:7:11:11 | After ... > ... [true] | 5 | Test.java:12:8:12:9 | 20 | +| Test.java:11:7:11:11 | After ... > ... [true] | 6 | Test.java:12:4:12:9 | ...=... | +| Test.java:11:7:11:11 | After ... > ... [true] | 7 | Test.java:12:4:12:9 | After ...=... | +| Test.java:11:7:11:11 | After ... > ... [true] | 8 | Test.java:12:4:12:10 | After ; | +| Test.java:11:7:11:11 | After ... > ... [true] | 9 | Test.java:13:4:13:10 | ; | +| Test.java:11:7:11:11 | After ... > ... [true] | 10 | Test.java:13:4:13:9 | Before ...=... | +| Test.java:11:7:11:11 | After ... > ... [true] | 11 | Test.java:13:4:13:4 | z | +| Test.java:11:7:11:11 | After ... > ... [true] | 12 | Test.java:13:8:13:9 | 10 | +| Test.java:11:7:11:11 | After ... > ... [true] | 13 | Test.java:13:4:13:9 | ...=... | +| Test.java:11:7:11:11 | After ... > ... [true] | 14 | Test.java:13:4:13:9 | After ...=... | +| Test.java:11:7:11:11 | After ... > ... [true] | 15 | Test.java:13:4:13:10 | After ; | +| Test.java:11:7:11:11 | After ... > ... [true] | 16 | Test.java:11:14:14:3 | After { ... } | +| Test.java:21:6:21:10 | After ... < ... [false] | 0 | Test.java:21:6:21:10 | After ... < ... [false] | +| Test.java:21:6:21:10 | After ... < ... [false] | 1 | Test.java:24:4:24:10 | Before return ... | +| Test.java:21:6:21:10 | After ... < ... [false] | 2 | Test.java:24:4:24:10 | return ... | +| Test.java:21:6:21:10 | After ... < ... [true] | 0 | Test.java:21:6:21:10 | After ... < ... [true] | +| Test.java:21:6:21:10 | After ... < ... [true] | 1 | Test.java:22:4:22:10 | ; | +| Test.java:21:6:21:10 | After ... < ... [true] | 2 | Test.java:22:4:22:9 | Before ...=... | +| Test.java:21:6:21:10 | After ... < ... [true] | 3 | Test.java:22:4:22:4 | y | +| Test.java:21:6:21:10 | After ... < ... [true] | 4 | Test.java:22:8:22:9 | 40 | +| Test.java:21:6:21:10 | After ... < ... [true] | 5 | Test.java:22:4:22:9 | ...=... | +| Test.java:21:6:21:10 | After ... < ... [true] | 6 | Test.java:22:4:22:9 | After ...=... | +| Test.java:21:6:21:10 | After ... < ... [true] | 7 | Test.java:22:4:22:10 | After ; | +| Test.java:21:6:21:10 | After ... < ... [true] | 8 | Test.java:21:3:21:11 | After if (...) | +| Test.java:21:6:21:10 | After ... < ... [true] | 9 | Test.java:27:3:27:9 | ; | +| Test.java:21:6:21:10 | After ... < ... [true] | 10 | Test.java:27:3:27:8 | Before ...=... | +| Test.java:21:6:21:10 | After ... < ... [true] | 11 | Test.java:27:3:27:3 | z | +| Test.java:21:6:21:10 | After ... < ... [true] | 12 | Test.java:27:7:27:8 | 10 | +| Test.java:21:6:21:10 | After ... < ... [true] | 13 | Test.java:27:3:27:8 | ...=... | +| Test.java:21:6:21:10 | After ... < ... [true] | 14 | Test.java:27:3:27:8 | After ...=... | +| Test.java:21:6:21:10 | After ... < ... [true] | 15 | Test.java:27:3:27:9 | After ; | +| Test.java:21:6:21:10 | After ... < ... [true] | 16 | Test.java:30:3:30:13 | if (...) | +| Test.java:21:6:21:10 | After ... < ... [true] | 17 | Test.java:30:7:30:12 | Before ... == ... | +| Test.java:21:6:21:10 | After ... < ... [true] | 18 | Test.java:30:7:30:7 | x | +| Test.java:21:6:21:10 | After ... < ... [true] | 19 | Test.java:30:12:30:12 | 0 | +| Test.java:21:6:21:10 | After ... < ... [true] | 20 | Test.java:30:7:30:12 | ... == ... | +| Test.java:30:3:30:13 | After if (...) | 0 | Test.java:30:3:30:13 | After if (...) | +| Test.java:30:3:30:13 | After if (...) | 1 | Test.java:35:3:35:9 | ; | +| Test.java:30:3:30:13 | After if (...) | 2 | Test.java:35:3:35:8 | Before ...=... | +| Test.java:30:3:30:13 | After if (...) | 3 | Test.java:35:3:35:3 | z | +| Test.java:30:3:30:13 | After if (...) | 4 | Test.java:35:7:35:8 | 20 | +| Test.java:30:3:30:13 | After if (...) | 5 | Test.java:35:3:35:8 | ...=... | +| Test.java:30:3:30:13 | After if (...) | 6 | Test.java:35:3:35:8 | After ...=... | +| Test.java:30:3:30:13 | After if (...) | 7 | Test.java:35:3:35:9 | After ; | +| Test.java:30:3:30:13 | After if (...) | 8 | Test.java:38:3:38:14 | while (...) | +| Test.java:30:7:30:12 | After ... == ... [false] | 0 | Test.java:30:7:30:12 | After ... == ... [false] | +| Test.java:30:7:30:12 | After ... == ... [true] | 0 | Test.java:30:7:30:12 | After ... == ... [true] | +| Test.java:30:7:30:12 | After ... == ... [true] | 1 | Test.java:30:15:33:3 | { ... } | +| Test.java:30:7:30:12 | After ... == ... [true] | 2 | Test.java:31:4:31:10 | ; | +| Test.java:30:7:30:12 | After ... == ... [true] | 3 | Test.java:31:4:31:9 | Before ...=... | +| Test.java:30:7:30:12 | After ... == ... [true] | 4 | Test.java:31:4:31:4 | y | +| Test.java:30:7:30:12 | After ... == ... [true] | 5 | Test.java:31:8:31:9 | 60 | +| Test.java:30:7:30:12 | After ... == ... [true] | 6 | Test.java:31:4:31:9 | ...=... | +| Test.java:30:7:30:12 | After ... == ... [true] | 7 | Test.java:31:4:31:9 | After ...=... | +| Test.java:30:7:30:12 | After ... == ... [true] | 8 | Test.java:31:4:31:10 | After ; | +| Test.java:30:7:30:12 | After ... == ... [true] | 9 | Test.java:32:4:32:10 | ; | +| Test.java:30:7:30:12 | After ... == ... [true] | 10 | Test.java:32:4:32:9 | Before ...=... | +| Test.java:30:7:30:12 | After ... == ... [true] | 11 | Test.java:32:4:32:4 | z | +| Test.java:30:7:30:12 | After ... == ... [true] | 12 | Test.java:32:8:32:9 | 10 | +| Test.java:30:7:30:12 | After ... == ... [true] | 13 | Test.java:32:4:32:9 | ...=... | +| Test.java:30:7:30:12 | After ... == ... [true] | 14 | Test.java:32:4:32:9 | After ...=... | +| Test.java:30:7:30:12 | After ... == ... [true] | 15 | Test.java:32:4:32:10 | After ; | +| Test.java:30:7:30:12 | After ... == ... [true] | 16 | Test.java:30:15:33:3 | After { ... } | +| Test.java:38:3:38:14 | [LoopHeader] while (...) | 0 | Test.java:38:3:38:14 | [LoopHeader] while (...) | +| Test.java:38:3:38:14 | [LoopHeader] while (...) | 1 | Test.java:38:9:38:13 | Before ... > ... | +| Test.java:38:3:38:14 | [LoopHeader] while (...) | 2 | Test.java:38:9:38:9 | x | +| Test.java:38:3:38:14 | [LoopHeader] while (...) | 3 | Test.java:38:13:38:13 | 0 | +| Test.java:38:3:38:14 | [LoopHeader] while (...) | 4 | Test.java:38:9:38:13 | ... > ... | +| Test.java:38:9:38:13 | After ... > ... [false] | 0 | Test.java:38:9:38:13 | After ... > ... [false] | +| Test.java:38:9:38:13 | After ... > ... [false] | 1 | Test.java:38:3:38:14 | After while (...) | +| Test.java:38:9:38:13 | After ... > ... [false] | 2 | Test.java:43:3:43:9 | ; | +| Test.java:38:9:38:13 | After ... > ... [false] | 3 | Test.java:43:3:43:8 | Before ...=... | +| Test.java:38:9:38:13 | After ... > ... [false] | 4 | Test.java:43:3:43:3 | z | +| Test.java:38:9:38:13 | After ... > ... [false] | 5 | Test.java:43:7:43:8 | 30 | +| Test.java:38:9:38:13 | After ... > ... [false] | 6 | Test.java:43:3:43:8 | ...=... | +| Test.java:38:9:38:13 | After ... > ... [false] | 7 | Test.java:43:3:43:8 | After ...=... | +| Test.java:38:9:38:13 | After ... > ... [false] | 8 | Test.java:43:3:43:9 | After ; | +| Test.java:38:9:38:13 | After ... > ... [false] | 9 | Test.java:46:3:46:29 | for (...;...;...) | +| Test.java:38:9:38:13 | After ... > ... [false] | 10 | Test.java:46:11:46:15 | Before j | +| Test.java:38:9:38:13 | After ... > ... [false] | 11 | Test.java:46:15:46:15 | 0 | +| Test.java:38:9:38:13 | After ... > ... [false] | 12 | Test.java:46:11:46:15 | j | +| Test.java:38:9:38:13 | After ... > ... [false] | 13 | Test.java:46:11:46:15 | After j | +| Test.java:38:9:38:13 | After ... > ... [true] | 0 | Test.java:38:9:38:13 | After ... > ... [true] | +| Test.java:38:9:38:13 | After ... > ... [true] | 1 | Test.java:38:16:41:3 | { ... } | +| Test.java:38:9:38:13 | After ... > ... [true] | 2 | Test.java:39:4:39:10 | ; | +| Test.java:38:9:38:13 | After ... > ... [true] | 3 | Test.java:39:4:39:9 | Before ...=... | +| Test.java:38:9:38:13 | After ... > ... [true] | 4 | Test.java:39:4:39:4 | y | +| Test.java:38:9:38:13 | After ... > ... [true] | 5 | Test.java:39:8:39:9 | 10 | +| Test.java:38:9:38:13 | After ... > ... [true] | 6 | Test.java:39:4:39:9 | ...=... | +| Test.java:38:9:38:13 | After ... > ... [true] | 7 | Test.java:39:4:39:9 | After ...=... | +| Test.java:38:9:38:13 | After ... > ... [true] | 8 | Test.java:39:4:39:10 | After ; | +| Test.java:38:9:38:13 | After ... > ... [true] | 9 | Test.java:40:4:40:7 | ; | +| Test.java:38:9:38:13 | After ... > ... [true] | 10 | Test.java:40:4:40:6 | Before ...-- | +| Test.java:38:9:38:13 | After ... > ... [true] | 11 | Test.java:40:4:40:4 | x | +| Test.java:38:9:38:13 | After ... > ... [true] | 12 | Test.java:40:4:40:6 | ...-- | +| Test.java:38:9:38:13 | After ... > ... [true] | 13 | Test.java:40:4:40:6 | After ...-- | +| Test.java:38:9:38:13 | After ... > ... [true] | 14 | Test.java:40:4:40:7 | After ; | +| Test.java:38:9:38:13 | After ... > ... [true] | 15 | Test.java:38:16:41:3 | After { ... } | +| Test.java:46:18:46:23 | After ... < ... [false] | 0 | Test.java:46:18:46:23 | After ... < ... [false] | +| Test.java:46:18:46:23 | After ... < ... [false] | 1 | Test.java:46:3:46:29 | After for (...;...;...) | +| Test.java:46:18:46:23 | After ... < ... [false] | 2 | Test.java:51:3:51:9 | ; | +| Test.java:46:18:46:23 | After ... < ... [false] | 3 | Test.java:51:3:51:8 | Before ...=... | +| Test.java:46:18:46:23 | After ... < ... [false] | 4 | Test.java:51:3:51:3 | z | +| Test.java:46:18:46:23 | After ... < ... [false] | 5 | Test.java:51:7:51:8 | 40 | +| Test.java:46:18:46:23 | After ... < ... [false] | 6 | Test.java:51:3:51:8 | ...=... | +| Test.java:46:18:46:23 | After ... < ... [false] | 7 | Test.java:51:3:51:8 | After ...=... | +| Test.java:46:18:46:23 | After ... < ... [false] | 8 | Test.java:51:3:51:9 | After ; | +| Test.java:46:18:46:23 | After ... < ... [false] | 9 | Test.java:54:3:54:29 | for (...;...;...) | +| Test.java:46:18:46:23 | After ... < ... [false] | 10 | Test.java:54:11:54:15 | Before j | +| Test.java:46:18:46:23 | After ... < ... [false] | 11 | Test.java:54:15:54:15 | 0 | +| Test.java:46:18:46:23 | After ... < ... [false] | 12 | Test.java:54:11:54:15 | j | +| Test.java:46:18:46:23 | After ... < ... [false] | 13 | Test.java:54:11:54:15 | After j | +| Test.java:46:18:46:23 | After ... < ... [true] | 0 | Test.java:46:18:46:23 | After ... < ... [true] | +| Test.java:46:18:46:23 | After ... < ... [true] | 1 | Test.java:46:31:49:3 | { ... } | +| Test.java:46:18:46:23 | After ... < ... [true] | 2 | Test.java:47:4:47:9 | ; | +| Test.java:46:18:46:23 | After ... < ... [true] | 3 | Test.java:47:4:47:8 | Before ...=... | +| Test.java:46:18:46:23 | After ... < ... [true] | 4 | Test.java:47:4:47:4 | y | +| Test.java:46:18:46:23 | After ... < ... [true] | 5 | Test.java:47:8:47:8 | 0 | +| Test.java:46:18:46:23 | After ... < ... [true] | 6 | Test.java:47:4:47:8 | ...=... | +| Test.java:46:18:46:23 | After ... < ... [true] | 7 | Test.java:47:4:47:8 | After ...=... | +| Test.java:46:18:46:23 | After ... < ... [true] | 8 | Test.java:47:4:47:9 | After ; | +| Test.java:46:18:46:23 | After ... < ... [true] | 9 | Test.java:48:4:48:10 | ; | +| Test.java:46:18:46:23 | After ... < ... [true] | 10 | Test.java:48:4:48:9 | Before ...=... | +| Test.java:46:18:46:23 | After ... < ... [true] | 11 | Test.java:48:4:48:4 | w | +| Test.java:46:18:46:23 | After ... < ... [true] | 12 | Test.java:48:8:48:9 | 10 | +| Test.java:46:18:46:23 | After ... < ... [true] | 13 | Test.java:48:4:48:9 | ...=... | +| Test.java:46:18:46:23 | After ... < ... [true] | 14 | Test.java:48:4:48:9 | After ...=... | +| Test.java:46:18:46:23 | After ... < ... [true] | 15 | Test.java:48:4:48:10 | After ; | +| Test.java:46:18:46:23 | After ... < ... [true] | 16 | Test.java:46:31:49:3 | After { ... } | +| Test.java:46:18:46:23 | After ... < ... [true] | 17 | Test.java:46:3:46:29 | [LoopHeader] for (...;...;...) | +| Test.java:46:18:46:23 | After ... < ... [true] | 18 | Test.java:46:26:46:28 | Before ...++ | +| Test.java:46:18:46:23 | After ... < ... [true] | 19 | Test.java:46:26:46:26 | j | +| Test.java:46:18:46:23 | After ... < ... [true] | 20 | Test.java:46:26:46:28 | ...++ | +| Test.java:46:18:46:23 | After ... < ... [true] | 21 | Test.java:46:26:46:28 | After ...++ | +| Test.java:46:18:46:23 | Before ... < ... | 0 | Test.java:46:18:46:23 | Before ... < ... | +| Test.java:46:18:46:23 | Before ... < ... | 1 | Test.java:46:18:46:18 | j | +| Test.java:46:18:46:23 | Before ... < ... | 2 | Test.java:46:22:46:23 | 10 | +| Test.java:46:18:46:23 | Before ... < ... | 3 | Test.java:46:18:46:23 | ... < ... | +| Test.java:54:3:54:29 | After for (...;...;...) | 0 | Test.java:54:3:54:29 | After for (...;...;...) | +| Test.java:54:3:54:29 | After for (...;...;...) | 1 | Test.java:70:3:70:9 | ; | +| Test.java:54:3:54:29 | After for (...;...;...) | 2 | Test.java:70:3:70:8 | Before ...=... | +| Test.java:54:3:54:29 | After for (...;...;...) | 3 | Test.java:70:3:70:3 | z | +| Test.java:54:3:54:29 | After for (...;...;...) | 4 | Test.java:70:7:70:8 | 50 | +| Test.java:54:3:54:29 | After for (...;...;...) | 5 | Test.java:70:3:70:8 | ...=... | +| Test.java:54:3:54:29 | After for (...;...;...) | 6 | Test.java:70:3:70:8 | After ...=... | +| Test.java:54:3:54:29 | After for (...;...;...) | 7 | Test.java:70:3:70:9 | After ; | +| Test.java:54:3:54:29 | After for (...;...;...) | 8 | Test.java:74:3:74:9 | ; | +| Test.java:54:3:54:29 | After for (...;...;...) | 9 | Test.java:74:3:74:8 | Before ...=... | +| Test.java:54:3:54:29 | After for (...;...;...) | 10 | Test.java:74:3:74:3 | w | +| Test.java:54:3:54:29 | After for (...;...;...) | 11 | Test.java:74:7:74:8 | 40 | +| Test.java:54:3:54:29 | After for (...;...;...) | 12 | Test.java:74:3:74:8 | ...=... | +| Test.java:54:3:54:29 | After for (...;...;...) | 13 | Test.java:74:3:74:8 | After ...=... | +| Test.java:54:3:54:29 | After for (...;...;...) | 14 | Test.java:74:3:74:9 | After ; | +| Test.java:54:3:54:29 | After for (...;...;...) | 15 | Test.java:75:3:75:9 | Before return ... | +| Test.java:54:3:54:29 | After for (...;...;...) | 16 | Test.java:75:3:75:9 | return ... | +| Test.java:54:3:54:29 | [LoopHeader] for (...;...;...) | 0 | Test.java:54:3:54:29 | [LoopHeader] for (...;...;...) | +| Test.java:54:3:54:29 | [LoopHeader] for (...;...;...) | 1 | Test.java:54:26:54:28 | Before ...++ | +| Test.java:54:3:54:29 | [LoopHeader] for (...;...;...) | 2 | Test.java:54:26:54:26 | j | +| Test.java:54:3:54:29 | [LoopHeader] for (...;...;...) | 3 | Test.java:54:26:54:28 | ...++ | +| Test.java:54:3:54:29 | [LoopHeader] for (...;...;...) | 4 | Test.java:54:26:54:28 | After ...++ | +| Test.java:54:18:54:23 | After ... < ... [false] | 0 | Test.java:54:18:54:23 | After ... < ... [false] | +| Test.java:54:18:54:23 | After ... < ... [true] | 0 | Test.java:54:18:54:23 | After ... < ... [true] | +| Test.java:54:18:54:23 | After ... < ... [true] | 1 | Test.java:54:31:68:3 | { ... } | +| Test.java:54:18:54:23 | After ... < ... [true] | 2 | Test.java:55:4:55:10 | ; | +| Test.java:54:18:54:23 | After ... < ... [true] | 3 | Test.java:55:4:55:9 | Before ...=... | +| Test.java:54:18:54:23 | After ... < ... [true] | 4 | Test.java:55:4:55:4 | y | +| Test.java:54:18:54:23 | After ... < ... [true] | 5 | Test.java:55:8:55:9 | 30 | +| Test.java:54:18:54:23 | After ... < ... [true] | 6 | Test.java:55:4:55:9 | ...=... | +| Test.java:54:18:54:23 | After ... < ... [true] | 7 | Test.java:55:4:55:9 | After ...=... | +| Test.java:54:18:54:23 | After ... < ... [true] | 8 | Test.java:55:4:55:10 | After ; | +| Test.java:54:18:54:23 | After ... < ... [true] | 9 | Test.java:56:4:56:12 | if (...) | +| Test.java:54:18:54:23 | After ... < ... [true] | 10 | Test.java:56:7:56:11 | Before ... > ... | +| Test.java:54:18:54:23 | After ... < ... [true] | 11 | Test.java:56:7:56:7 | z | +| Test.java:54:18:54:23 | After ... < ... [true] | 12 | Test.java:56:11:56:11 | 0 | +| Test.java:54:18:54:23 | After ... < ... [true] | 13 | Test.java:56:7:56:11 | ... > ... | +| Test.java:54:18:54:23 | Before ... < ... | 0 | Test.java:54:18:54:23 | Before ... < ... | +| Test.java:54:18:54:23 | Before ... < ... | 1 | Test.java:54:18:54:18 | j | +| Test.java:54:18:54:23 | Before ... < ... | 2 | Test.java:54:22:54:23 | 10 | +| Test.java:54:18:54:23 | Before ... < ... | 3 | Test.java:54:18:54:23 | ... < ... | +| Test.java:56:7:56:11 | After ... > ... [false] | 0 | Test.java:56:7:56:11 | After ... > ... [false] | +| Test.java:56:7:56:11 | After ... > ... [false] | 1 | Test.java:63:9:66:4 | { ... } | +| Test.java:56:7:56:11 | After ... > ... [false] | 2 | Test.java:64:5:64:11 | ; | +| Test.java:56:7:56:11 | After ... > ... [false] | 3 | Test.java:64:5:64:10 | Before ...=... | +| Test.java:56:7:56:11 | After ... > ... [false] | 4 | Test.java:64:5:64:5 | w | +| Test.java:56:7:56:11 | After ... > ... [false] | 5 | Test.java:64:9:64:10 | 10 | +| Test.java:56:7:56:11 | After ... > ... [false] | 6 | Test.java:64:5:64:10 | ...=... | +| Test.java:56:7:56:11 | After ... > ... [false] | 7 | Test.java:64:5:64:10 | After ...=... | +| Test.java:56:7:56:11 | After ... > ... [false] | 8 | Test.java:64:5:64:11 | After ; | +| Test.java:56:7:56:11 | After ... > ... [false] | 9 | Test.java:65:5:65:13 | Before continue | +| Test.java:56:7:56:11 | After ... > ... [false] | 10 | Test.java:65:5:65:13 | continue | +| Test.java:56:7:56:11 | After ... > ... [true] | 0 | Test.java:56:7:56:11 | After ... > ... [true] | +| Test.java:56:7:56:11 | After ... > ... [true] | 1 | Test.java:57:5:57:13 | if (...) | +| Test.java:56:7:56:11 | After ... > ... [true] | 2 | Test.java:57:8:57:12 | Before ... > ... | +| Test.java:56:7:56:11 | After ... > ... [true] | 3 | Test.java:57:8:57:8 | y | +| Test.java:56:7:56:11 | After ... > ... [true] | 4 | Test.java:57:12:57:12 | 0 | +| Test.java:56:7:56:11 | After ... > ... [true] | 5 | Test.java:57:8:57:12 | ... > ... | +| Test.java:57:8:57:12 | After ... > ... [false] | 0 | Test.java:57:8:57:12 | After ... > ... [false] | +| Test.java:57:8:57:12 | After ... > ... [false] | 1 | Test.java:60:12:62:5 | { ... } | +| Test.java:57:8:57:12 | After ... > ... [false] | 2 | Test.java:61:6:61:12 | ; | +| Test.java:57:8:57:12 | After ... > ... [false] | 3 | Test.java:61:6:61:11 | Before ...=... | +| Test.java:57:8:57:12 | After ... > ... [false] | 4 | Test.java:61:6:61:6 | w | +| Test.java:57:8:57:12 | After ... > ... [false] | 5 | Test.java:61:10:61:11 | 20 | +| Test.java:57:8:57:12 | After ... > ... [false] | 6 | Test.java:61:6:61:11 | ...=... | +| Test.java:57:8:57:12 | After ... > ... [false] | 7 | Test.java:61:6:61:11 | After ...=... | +| Test.java:57:8:57:12 | After ... > ... [false] | 8 | Test.java:61:6:61:12 | After ; | +| Test.java:57:8:57:12 | After ... > ... [false] | 9 | Test.java:60:12:62:5 | After { ... } | +| Test.java:57:8:57:12 | After ... > ... [false] | 10 | Test.java:57:5:57:13 | After if (...) | +| Test.java:57:8:57:12 | After ... > ... [false] | 11 | Test.java:56:4:56:12 | After if (...) | +| Test.java:57:8:57:12 | After ... > ... [false] | 12 | Test.java:67:4:67:9 | ; | +| Test.java:57:8:57:12 | After ... > ... [false] | 13 | Test.java:67:4:67:8 | Before ...=... | +| Test.java:57:8:57:12 | After ... > ... [false] | 14 | Test.java:67:4:67:4 | x | +| Test.java:57:8:57:12 | After ... > ... [false] | 15 | Test.java:67:8:67:8 | 0 | +| Test.java:57:8:57:12 | After ... > ... [false] | 16 | Test.java:67:4:67:8 | ...=... | +| Test.java:57:8:57:12 | After ... > ... [false] | 17 | Test.java:67:4:67:8 | After ...=... | +| Test.java:57:8:57:12 | After ... > ... [false] | 18 | Test.java:67:4:67:9 | After ; | +| Test.java:57:8:57:12 | After ... > ... [false] | 19 | Test.java:54:31:68:3 | After { ... } | +| Test.java:57:8:57:12 | After ... > ... [true] | 0 | Test.java:57:8:57:12 | After ... > ... [true] | +| Test.java:57:8:57:12 | After ... > ... [true] | 1 | Test.java:57:15:60:5 | { ... } | +| Test.java:57:8:57:12 | After ... > ... [true] | 2 | Test.java:58:6:58:11 | ; | +| Test.java:57:8:57:12 | After ... > ... [true] | 3 | Test.java:58:6:58:10 | Before ...=... | +| Test.java:57:8:57:12 | After ... > ... [true] | 4 | Test.java:58:6:58:6 | w | +| Test.java:57:8:57:12 | After ... > ... [true] | 5 | Test.java:58:10:58:10 | 0 | +| Test.java:57:8:57:12 | After ... > ... [true] | 6 | Test.java:58:6:58:10 | ...=... | +| Test.java:57:8:57:12 | After ... > ... [true] | 7 | Test.java:58:6:58:10 | After ...=... | +| Test.java:57:8:57:12 | After ... > ... [true] | 8 | Test.java:58:6:58:11 | After ; | +| Test.java:57:8:57:12 | After ... > ... [true] | 9 | Test.java:59:6:59:11 | Before break | +| Test.java:57:8:57:12 | After ... > ... [true] | 10 | Test.java:59:6:59:11 | break | diff --git a/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected b/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected index be658fb29158..afa917bf12ca 100644 --- a/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected +++ b/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.expected @@ -1,6 +1,3 @@ -| Test.java:3:14:3:17 | { ... } | Test.java:3:14:3:17 | Exit | -| Test.java:4:14:4:17 | Normal Exit | Test.java:4:14:4:17 | Exit | -| Test.java:4:21:76:2 | { ... } | Test.java:4:14:4:17 | Exit | | Test.java:4:21:76:2 | { ... } | Test.java:4:14:4:17 | Normal Exit | | Test.java:4:21:76:2 | { ... } | Test.java:11:14:14:3 | { ... } | | Test.java:4:21:76:2 | { ... } | Test.java:14:10:16:3 | { ... } | @@ -23,7 +20,6 @@ | Test.java:4:21:76:2 | { ... } | Test.java:60:12:62:5 | { ... } | | Test.java:4:21:76:2 | { ... } | Test.java:63:9:66:4 | { ... } | | Test.java:4:21:76:2 | { ... } | Test.java:70:3:70:9 | ; | -| Test.java:18:3:18:8 | ; | Test.java:4:14:4:17 | Exit | | Test.java:18:3:18:8 | ; | Test.java:4:14:4:17 | Normal Exit | | Test.java:18:3:18:8 | ; | Test.java:22:4:22:10 | ; | | Test.java:18:3:18:8 | ; | Test.java:24:4:24:10 | return ... | diff --git a/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.ql b/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.ql index de1e23b649cc..72de0cc435d3 100644 --- a/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.ql +++ b/java/ql/test/library-tests/controlflow/basic/bbStrictDominance.ql @@ -1,6 +1,7 @@ import java import semmle.code.java.controlflow.Dominance +import utils.test.BasicBlock from BasicBlock b, BasicBlock b2 where b.strictlyDominates(b2) -select b, b2 +select getFirstAstNode(b), getFirstAstNode(b2) diff --git a/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected b/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected index a6e5d8430c12..95799e5862b0 100644 --- a/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected +++ b/java/ql/test/library-tests/controlflow/basic/bbSuccessor.expected @@ -1,16 +1,13 @@ -| Test.java:3:14:3:17 | Exceptional Exit | Test.java:3:14:3:17 | Exit | -| Test.java:3:14:3:17 | { ... } | Test.java:3:14:3:17 | Exit | -| Test.java:4:14:4:17 | Exceptional Exit | Test.java:4:14:4:17 | Exit | -| Test.java:4:14:4:17 | Normal Exit | Test.java:4:14:4:17 | Exit | | Test.java:4:21:76:2 | { ... } | Test.java:11:14:14:3 | { ... } | | Test.java:4:21:76:2 | { ... } | Test.java:14:10:16:3 | { ... } | | Test.java:11:14:14:3 | { ... } | Test.java:18:3:18:8 | ; | | Test.java:14:10:16:3 | { ... } | Test.java:18:3:18:8 | ; | | Test.java:18:3:18:8 | ; | Test.java:22:4:22:10 | ; | | Test.java:18:3:18:8 | ; | Test.java:24:4:24:10 | return ... | +| Test.java:22:4:22:10 | ; | Test.java:30:7:30:12 | After ... == ... [false] | | Test.java:22:4:22:10 | ; | Test.java:30:15:33:3 | { ... } | -| Test.java:22:4:22:10 | ; | Test.java:35:3:35:9 | ; | | Test.java:24:4:24:10 | return ... | Test.java:4:14:4:17 | Normal Exit | +| Test.java:30:7:30:12 | After ... == ... [false] | Test.java:35:3:35:9 | ; | | Test.java:30:15:33:3 | { ... } | Test.java:35:3:35:9 | ; | | Test.java:35:3:35:9 | ; | Test.java:38:9:38:9 | x | | Test.java:38:9:38:9 | x | Test.java:38:16:41:3 | { ... } | @@ -21,8 +18,9 @@ | Test.java:46:18:46:18 | j | Test.java:51:3:51:9 | ; | | Test.java:46:31:49:3 | { ... } | Test.java:46:18:46:18 | j | | Test.java:51:3:51:9 | ; | Test.java:54:18:54:18 | j | +| Test.java:54:18:54:18 | j | Test.java:54:18:54:23 | After ... < ... [false] | | Test.java:54:18:54:18 | j | Test.java:54:31:68:3 | { ... } | -| Test.java:54:18:54:18 | j | Test.java:70:3:70:9 | ; | +| Test.java:54:18:54:23 | After ... < ... [false] | Test.java:70:3:70:9 | ; | | Test.java:54:26:54:26 | j | Test.java:54:18:54:18 | j | | Test.java:54:31:68:3 | { ... } | Test.java:57:5:57:13 | if (...) | | Test.java:54:31:68:3 | { ... } | Test.java:63:9:66:4 | { ... } | diff --git a/java/ql/test/library-tests/controlflow/basic/bbSuccessor.ql b/java/ql/test/library-tests/controlflow/basic/bbSuccessor.ql index ae2d8a393b47..ae8dc5d188d6 100644 --- a/java/ql/test/library-tests/controlflow/basic/bbSuccessor.ql +++ b/java/ql/test/library-tests/controlflow/basic/bbSuccessor.ql @@ -1,5 +1,6 @@ import java +import utils.test.BasicBlock from BasicBlock b, BasicBlock b2 where b.getASuccessor() = b2 -select b, b2 +select getFirstAstNodeOrSynth(b), getFirstAstNodeOrSynth(b2) diff --git a/java/ql/test/library-tests/controlflow/dominance/dominanceWrong.ql b/java/ql/test/library-tests/controlflow/dominance/dominanceWrong.ql index 4eadcddc61a6..6deead2df73b 100644 --- a/java/ql/test/library-tests/controlflow/dominance/dominanceWrong.ql +++ b/java/ql/test/library-tests/controlflow/dominance/dominanceWrong.ql @@ -17,5 +17,6 @@ predicate dominanceCounterExample(ControlFlowNode entry, ControlFlowNode dom, Co from Callable c, ControlFlowNode dom, ControlFlowNode node where strictlyDominates(dom, node) and - dominanceCounterExample(c.getBody().getControlFlowNode(), dom, node) + dominanceCounterExample(any(ControlFlow::EntryNode entry | entry.getEnclosingCallable() = c), dom, + node) select c, dom, node diff --git a/java/ql/test/library-tests/controlflow/dominance/dominator.expected b/java/ql/test/library-tests/controlflow/dominance/dominator.expected index 1e385c4fd62f..9836d4eed50c 100644 --- a/java/ql/test/library-tests/controlflow/dominance/dominator.expected +++ b/java/ql/test/library-tests/controlflow/dominance/dominator.expected @@ -1,176 +1,33 @@ -| Test.java:2:32:72:2 | { ... } | Test.java:3:3:3:8 | var ...; | -| Test.java:3:3:3:8 | var ...; | Test.java:3:7:3:7 | j | -| Test.java:3:7:3:7 | j | Test.java:4:3:4:14 | var ...; | -| Test.java:4:3:4:14 | var ...; | Test.java:4:12:4:13 | 50 | -| Test.java:4:8:4:13 | y | Test.java:7:3:7:12 | if (...) | -| Test.java:4:12:4:13 | 50 | Test.java:4:8:4:13 | y | -| Test.java:7:3:7:12 | if (...) | Test.java:7:7:7:7 | x | -| Test.java:7:7:7:7 | x | Test.java:7:11:7:11 | 0 | -| Test.java:7:7:7:11 | ... > ... | Test.java:7:14:10:3 | { ... } | -| Test.java:7:7:7:11 | ... > ... | Test.java:10:10:12:3 | { ... } | -| Test.java:7:7:7:11 | ... > ... | Test.java:14:3:14:20 | ; | -| Test.java:7:11:7:11 | 0 | Test.java:7:7:7:11 | ... > ... | -| Test.java:7:14:10:3 | { ... } | Test.java:8:4:8:10 | ; | -| Test.java:8:4:8:9 | ...=... | Test.java:9:4:9:10 | ; | -| Test.java:8:4:8:10 | ; | Test.java:8:8:8:9 | 20 | -| Test.java:8:8:8:9 | 20 | Test.java:8:4:8:9 | ...=... | -| Test.java:9:4:9:10 | ; | Test.java:9:8:9:9 | 10 | -| Test.java:9:8:9:9 | 10 | Test.java:9:4:9:9 | ...=... | -| Test.java:10:10:12:3 | { ... } | Test.java:11:4:11:10 | ; | -| Test.java:11:4:11:10 | ; | Test.java:11:8:11:9 | 30 | -| Test.java:11:8:11:9 | 30 | Test.java:11:4:11:9 | ...=... | -| Test.java:14:3:14:19 | ...=... | Test.java:17:3:17:12 | if (...) | -| Test.java:14:3:14:20 | ; | Test.java:14:14:14:14 | x | -| Test.java:14:7:14:19 | (...)... | Test.java:14:3:14:19 | ...=... | -| Test.java:14:14:14:14 | x | Test.java:14:18:14:18 | y | -| Test.java:14:14:14:18 | ... + ... | Test.java:14:7:14:19 | (...)... | -| Test.java:14:18:14:18 | y | Test.java:14:14:14:18 | ... + ... | -| Test.java:17:3:17:12 | if (...) | Test.java:17:7:17:7 | x | -| Test.java:17:7:17:7 | x | Test.java:17:11:17:11 | 0 | -| Test.java:17:7:17:11 | ... < ... | Test.java:2:6:2:9 | Normal Exit | -| Test.java:17:7:17:11 | ... < ... | Test.java:18:4:18:10 | ; | -| Test.java:17:7:17:11 | ... < ... | Test.java:20:11:20:11 | z | -| Test.java:17:11:17:11 | 0 | Test.java:17:7:17:11 | ... < ... | -| Test.java:18:4:18:9 | ...=... | Test.java:23:3:23:9 | ; | -| Test.java:18:4:18:10 | ; | Test.java:18:8:18:9 | 40 | -| Test.java:18:8:18:9 | 40 | Test.java:18:4:18:9 | ...=... | -| Test.java:20:11:20:11 | z | Test.java:20:4:20:12 | return ... | -| Test.java:23:3:23:8 | ...=... | Test.java:26:3:26:13 | if (...) | -| Test.java:23:3:23:9 | ; | Test.java:23:7:23:8 | 10 | -| Test.java:23:7:23:8 | 10 | Test.java:23:3:23:8 | ...=... | -| Test.java:26:3:26:13 | if (...) | Test.java:26:7:26:7 | x | -| Test.java:26:7:26:7 | x | Test.java:26:12:26:12 | 0 | -| Test.java:26:7:26:12 | ... == ... | Test.java:26:15:29:3 | { ... } | -| Test.java:26:7:26:12 | ... == ... | Test.java:31:3:31:9 | ; | -| Test.java:26:12:26:12 | 0 | Test.java:26:7:26:12 | ... == ... | -| Test.java:26:15:29:3 | { ... } | Test.java:27:4:27:10 | ; | -| Test.java:27:4:27:9 | ...=... | Test.java:28:4:28:10 | ; | -| Test.java:27:4:27:10 | ; | Test.java:27:8:27:9 | 60 | -| Test.java:27:8:27:9 | 60 | Test.java:27:4:27:9 | ...=... | -| Test.java:28:4:28:10 | ; | Test.java:28:8:28:9 | 10 | -| Test.java:28:8:28:9 | 10 | Test.java:28:4:28:9 | ...=... | -| Test.java:31:3:31:3 | z | Test.java:31:8:31:8 | x | -| Test.java:31:3:31:8 | ...+=... | Test.java:34:3:34:15 | while (...) | -| Test.java:31:3:31:9 | ; | Test.java:31:3:31:3 | z | -| Test.java:31:8:31:8 | x | Test.java:31:3:31:8 | ...+=... | -| Test.java:34:3:34:15 | while (...) | Test.java:34:10:34:10 | x | -| Test.java:34:10:34:10 | x | Test.java:34:14:34:14 | 0 | -| Test.java:34:10:34:14 | ... > ... | Test.java:34:17:37:3 | { ... } | -| Test.java:34:10:34:14 | ... > ... | Test.java:39:3:39:9 | ; | -| Test.java:34:14:34:14 | 0 | Test.java:34:10:34:14 | ... > ... | -| Test.java:34:17:37:3 | { ... } | Test.java:35:4:35:10 | ; | -| Test.java:35:4:35:9 | ...=... | Test.java:36:4:36:7 | ; | -| Test.java:35:4:35:10 | ; | Test.java:35:8:35:9 | 10 | -| Test.java:35:8:35:9 | 10 | Test.java:35:4:35:9 | ...=... | -| Test.java:36:4:36:4 | x | Test.java:36:4:36:6 | ...-- | -| Test.java:36:4:36:7 | ; | Test.java:36:4:36:4 | x | -| Test.java:39:3:39:3 | z | Test.java:39:8:39:8 | y | -| Test.java:39:3:39:8 | ...+=... | Test.java:42:3:42:26 | for (...;...;...) | -| Test.java:39:3:39:9 | ; | Test.java:39:3:39:3 | z | -| Test.java:39:8:39:8 | y | Test.java:39:3:39:8 | ...+=... | -| Test.java:42:3:42:26 | for (...;...;...) | Test.java:42:12:42:12 | 0 | -| Test.java:42:8:42:12 | ...=... | Test.java:42:15:42:15 | j | -| Test.java:42:12:42:12 | 0 | Test.java:42:8:42:12 | ...=... | -| Test.java:42:15:42:15 | j | Test.java:42:19:42:20 | 10 | -| Test.java:42:15:42:20 | ... < ... | Test.java:42:28:45:3 | { ... } | -| Test.java:42:15:42:20 | ... < ... | Test.java:47:3:47:9 | ; | -| Test.java:42:19:42:20 | 10 | Test.java:42:15:42:20 | ... < ... | -| Test.java:42:23:42:23 | j | Test.java:42:23:42:25 | ...++ | -| Test.java:42:28:45:3 | { ... } | Test.java:43:4:43:9 | ; | -| Test.java:43:4:43:8 | ...=... | Test.java:44:4:44:10 | ; | -| Test.java:43:4:43:9 | ; | Test.java:43:8:43:8 | 0 | -| Test.java:43:8:43:8 | 0 | Test.java:43:4:43:8 | ...=... | -| Test.java:44:4:44:9 | ...=... | Test.java:42:23:42:23 | j | -| Test.java:44:4:44:10 | ; | Test.java:44:8:44:9 | 10 | -| Test.java:44:8:44:9 | 10 | Test.java:44:4:44:9 | ...=... | -| Test.java:47:3:47:3 | z | Test.java:47:8:47:8 | w | -| Test.java:47:3:47:8 | ...+=... | Test.java:50:3:50:26 | for (...;...;...) | -| Test.java:47:3:47:9 | ; | Test.java:47:3:47:3 | z | -| Test.java:47:8:47:8 | w | Test.java:47:3:47:8 | ...+=... | -| Test.java:50:3:50:26 | for (...;...;...) | Test.java:50:12:50:12 | 0 | -| Test.java:50:8:50:12 | ...=... | Test.java:50:15:50:15 | j | -| Test.java:50:12:50:12 | 0 | Test.java:50:8:50:12 | ...=... | -| Test.java:50:15:50:15 | j | Test.java:50:19:50:20 | 10 | -| Test.java:50:15:50:20 | ... < ... | Test.java:50:28:64:3 | { ... } | -| Test.java:50:15:50:20 | ... < ... | Test.java:66:3:66:17 | ; | -| Test.java:50:19:50:20 | 10 | Test.java:50:15:50:20 | ... < ... | -| Test.java:50:23:50:23 | j | Test.java:50:23:50:25 | ...++ | -| Test.java:50:28:64:3 | { ... } | Test.java:51:4:51:10 | ; | -| Test.java:51:4:51:9 | ...=... | Test.java:52:4:52:13 | if (...) | -| Test.java:51:4:51:10 | ; | Test.java:51:8:51:9 | 30 | -| Test.java:51:8:51:9 | 30 | Test.java:51:4:51:9 | ...=... | -| Test.java:52:4:52:13 | if (...) | Test.java:52:8:52:8 | z | -| Test.java:52:8:52:8 | z | Test.java:52:12:52:12 | 0 | -| Test.java:52:8:52:12 | ... > ... | Test.java:50:23:50:23 | j | -| Test.java:52:8:52:12 | ... > ... | Test.java:53:5:53:14 | if (...) | -| Test.java:52:8:52:12 | ... > ... | Test.java:59:9:62:4 | { ... } | -| Test.java:52:12:52:12 | 0 | Test.java:52:8:52:12 | ... > ... | -| Test.java:53:5:53:14 | if (...) | Test.java:53:9:53:9 | y | -| Test.java:53:9:53:9 | y | Test.java:53:13:53:13 | 0 | -| Test.java:53:9:53:13 | ... > ... | Test.java:53:16:56:5 | { ... } | -| Test.java:53:9:53:13 | ... > ... | Test.java:56:12:58:5 | { ... } | -| Test.java:53:13:53:13 | 0 | Test.java:53:9:53:13 | ... > ... | -| Test.java:53:16:56:5 | { ... } | Test.java:54:6:54:11 | ; | -| Test.java:54:6:54:10 | ...=... | Test.java:55:6:55:11 | break | -| Test.java:54:6:54:11 | ; | Test.java:54:10:54:10 | 0 | -| Test.java:54:10:54:10 | 0 | Test.java:54:6:54:10 | ...=... | -| Test.java:56:12:58:5 | { ... } | Test.java:57:6:57:12 | ; | -| Test.java:57:6:57:11 | ...=... | Test.java:63:4:63:9 | ; | -| Test.java:57:6:57:12 | ; | Test.java:57:10:57:11 | 20 | -| Test.java:57:10:57:11 | 20 | Test.java:57:6:57:11 | ...=... | -| Test.java:59:9:62:4 | { ... } | Test.java:60:5:60:11 | ; | -| Test.java:60:5:60:10 | ...=... | Test.java:61:5:61:13 | continue | -| Test.java:60:5:60:11 | ; | Test.java:60:9:60:10 | 10 | -| Test.java:60:9:60:10 | 10 | Test.java:60:5:60:10 | ...=... | -| Test.java:63:4:63:9 | ; | Test.java:63:8:63:8 | 0 | -| Test.java:63:8:63:8 | 0 | Test.java:63:4:63:8 | ...=... | -| Test.java:66:3:66:3 | z | Test.java:66:8:66:8 | x | -| Test.java:66:3:66:16 | ...+=... | Test.java:70:3:70:9 | ; | -| Test.java:66:3:66:17 | ; | Test.java:66:3:66:3 | z | -| Test.java:66:8:66:8 | x | Test.java:66:12:66:12 | y | -| Test.java:66:8:66:12 | ... + ... | Test.java:66:16:66:16 | w | -| Test.java:66:8:66:16 | ... + ... | Test.java:66:3:66:16 | ...+=... | -| Test.java:66:12:66:12 | y | Test.java:66:8:66:12 | ... + ... | -| Test.java:66:16:66:16 | w | Test.java:66:8:66:16 | ... + ... | -| Test.java:70:3:70:8 | ...=... | Test.java:71:10:71:10 | w | -| Test.java:70:3:70:9 | ; | Test.java:70:7:70:8 | 40 | -| Test.java:70:7:70:8 | 40 | Test.java:70:3:70:8 | ...=... | -| Test.java:71:10:71:10 | w | Test.java:71:3:71:11 | return ... | -| Test.java:74:19:91:2 | { ... } | Test.java:76:3:76:8 | var ...; | -| Test.java:76:3:76:8 | var ...; | Test.java:76:7:76:7 | b | -| Test.java:76:7:76:7 | b | Test.java:77:3:77:8 | var ...; | -| Test.java:77:3:77:8 | var ...; | Test.java:77:7:77:7 | c | -| Test.java:77:7:77:7 | c | Test.java:78:3:78:8 | ; | -| Test.java:78:3:78:7 | ...=... | Test.java:79:3:79:13 | while (...) | -| Test.java:78:3:78:8 | ; | Test.java:78:7:78:7 | 0 | -| Test.java:78:7:78:7 | 0 | Test.java:78:3:78:7 | ...=... | -| Test.java:79:3:79:13 | while (...) | Test.java:79:9:79:12 | true | -| Test.java:79:9:79:12 | true | Test.java:79:15:89:3 | { ... } | -| Test.java:79:15:89:3 | { ... } | Test.java:80:4:80:10 | ; | -| Test.java:80:4:80:9 | ...=... | Test.java:81:4:81:15 | if (...) | -| Test.java:80:4:80:10 | ; | Test.java:80:8:80:9 | 10 | -| Test.java:80:8:80:9 | 10 | Test.java:80:4:80:9 | ...=... | -| Test.java:81:4:81:15 | if (...) | Test.java:81:8:81:8 | a | -| Test.java:81:8:81:8 | a | Test.java:81:12:81:14 | 100 | -| Test.java:81:8:81:14 | ... > ... | Test.java:81:17:84:4 | { ... } | -| Test.java:81:8:81:14 | ... > ... | Test.java:85:4:85:15 | if (...) | -| Test.java:81:12:81:14 | 100 | Test.java:81:8:81:14 | ... > ... | -| Test.java:81:17:84:4 | { ... } | Test.java:82:5:82:11 | ; | -| Test.java:82:5:82:10 | ...=... | Test.java:83:5:83:10 | ; | -| Test.java:82:5:82:11 | ; | Test.java:82:9:82:10 | 10 | -| Test.java:82:9:82:10 | 10 | Test.java:82:5:82:10 | ...=... | -| Test.java:83:5:83:10 | ; | Test.java:83:9:83:9 | c | -| Test.java:83:9:83:9 | c | Test.java:83:5:83:9 | ...=... | -| Test.java:85:4:85:15 | if (...) | Test.java:85:8:85:8 | a | -| Test.java:85:8:85:8 | a | Test.java:85:13:85:14 | 10 | -| Test.java:85:8:85:14 | ... == ... | Test.java:74:6:74:10 | Normal Exit | -| Test.java:85:8:85:14 | ... == ... | Test.java:86:5:86:10 | break | -| Test.java:85:8:85:14 | ... == ... | Test.java:87:4:87:15 | if (...) | -| Test.java:85:13:85:14 | 10 | Test.java:85:8:85:14 | ... == ... | -| Test.java:86:5:86:10 | break | Test.java:90:10:90:10 | b | -| Test.java:87:4:87:15 | if (...) | Test.java:87:8:87:8 | a | -| Test.java:87:8:87:8 | a | Test.java:87:13:87:14 | 20 | -| Test.java:87:8:87:14 | ... == ... | Test.java:88:12:88:12 | c | -| Test.java:87:13:87:14 | 20 | Test.java:87:8:87:14 | ... == ... | -| Test.java:88:12:88:12 | c | Test.java:88:5:88:13 | return ... | -| Test.java:90:10:90:10 | b | Test.java:90:3:90:11 | return ... | +| Test.java:2:32:72:2 | { ... } | Test.java:7:14:10:3 | { ... } | +| Test.java:2:32:72:2 | { ... } | Test.java:10:10:12:3 | { ... } | +| Test.java:2:32:72:2 | { ... } | Test.java:14:3:14:20 | ; | +| Test.java:14:3:14:20 | ; | Test.java:2:6:2:9 | Normal Exit | +| Test.java:14:3:14:20 | ; | Test.java:18:4:18:10 | ; | +| Test.java:14:3:14:20 | ; | Test.java:20:11:20:11 | z | +| Test.java:18:4:18:10 | ; | Test.java:26:7:26:12 | After ... == ... [false] | +| Test.java:18:4:18:10 | ; | Test.java:26:15:29:3 | { ... } | +| Test.java:18:4:18:10 | ; | Test.java:31:3:31:9 | ; | +| Test.java:31:3:31:9 | ; | Test.java:34:10:34:10 | x | +| Test.java:34:10:34:10 | x | Test.java:34:17:37:3 | { ... } | +| Test.java:34:10:34:10 | x | Test.java:39:3:39:9 | ; | +| Test.java:39:3:39:9 | ; | Test.java:42:15:42:15 | j | +| Test.java:42:15:42:15 | j | Test.java:42:28:45:3 | { ... } | +| Test.java:42:15:42:15 | j | Test.java:47:3:47:9 | ; | +| Test.java:47:3:47:9 | ; | Test.java:50:15:50:15 | j | +| Test.java:50:15:50:15 | j | Test.java:50:15:50:20 | After ... < ... [false] | +| Test.java:50:15:50:15 | j | Test.java:50:28:64:3 | { ... } | +| Test.java:50:15:50:15 | j | Test.java:66:3:66:17 | ; | +| Test.java:50:28:64:3 | { ... } | Test.java:50:23:50:23 | j | +| Test.java:50:28:64:3 | { ... } | Test.java:53:5:53:14 | if (...) | +| Test.java:50:28:64:3 | { ... } | Test.java:59:9:62:4 | { ... } | +| Test.java:53:5:53:14 | if (...) | Test.java:53:16:56:5 | { ... } | +| Test.java:53:5:53:14 | if (...) | Test.java:56:12:58:5 | { ... } | +| Test.java:74:19:91:2 | { ... } | Test.java:79:9:79:12 | true | +| Test.java:79:9:79:12 | true | Test.java:81:8:81:14 | After ... > ... [false] | +| Test.java:79:9:79:12 | true | Test.java:81:17:84:4 | { ... } | +| Test.java:79:9:79:12 | true | Test.java:85:4:85:15 | if (...) | +| Test.java:85:4:85:15 | if (...) | Test.java:74:6:74:10 | Normal Exit | +| Test.java:85:4:85:15 | if (...) | Test.java:86:5:86:10 | break | +| Test.java:85:4:85:15 | if (...) | Test.java:87:4:87:15 | if (...) | +| Test.java:87:4:87:15 | if (...) | Test.java:87:8:87:14 | After ... == ... [false] | +| Test.java:87:4:87:15 | if (...) | Test.java:88:12:88:12 | c | diff --git a/java/ql/test/library-tests/controlflow/dominance/dominator.ql b/java/ql/test/library-tests/controlflow/dominance/dominator.ql index 701640bf7209..7fc18484febf 100644 --- a/java/ql/test/library-tests/controlflow/dominance/dominator.ql +++ b/java/ql/test/library-tests/controlflow/dominance/dominator.ql @@ -1,9 +1,9 @@ -import default -import semmle.code.java.controlflow.Dominance +import java +import utils.test.BasicBlock -from Method func, ControlFlowNode dominator, ControlFlowNode node +from Method func, BasicBlock dominator, BasicBlock bb where - iDominates(dominator, node) and - dominator.getEnclosingStmt().getEnclosingCallable() = func and + dominator.immediatelyDominates(bb) and + dominator.getEnclosingCallable() = func and func.getDeclaringType().hasName("Test") -select dominator, node +select getFirstAstNodeOrSynth(dominator), getFirstAstNodeOrSynth(bb) diff --git a/java/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql b/java/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql index eaf75ab7bfaa..54b0d1863624 100644 --- a/java/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql +++ b/java/ql/test/library-tests/controlflow/dominance/dominatorUnique.ql @@ -7,5 +7,5 @@ where iDominates(dom1, node) and iDominates(dom2, node) and dom1 != dom2 and - func = node.getEnclosingStmt().getEnclosingCallable() + func = node.getEnclosingCallable() select func, node, dom1, dom2 diff --git a/java/ql/test/library-tests/dataflow/capture/test.expected b/java/ql/test/library-tests/dataflow/capture/test.expected index a744f468fbe9..16ec39314eb0 100644 --- a/java/ql/test/library-tests/dataflow/capture/test.expected +++ b/java/ql/test/library-tests/dataflow/capture/test.expected @@ -16,8 +16,8 @@ | A.java:21:11:21:13 | "B" : String | A.java:14:11:14:20 | f2(...) : new A(...) { ... } [String s] | | A.java:21:11:21:13 | "B" : String | A.java:15:16:15:16 | a : new A(...) { ... } [String s] | | A.java:21:11:21:13 | "B" : String | A.java:15:16:15:22 | get(...) : String | +| A.java:21:11:21:13 | "B" : String | A.java:20:5:20:15 | SSA phi(s) : String | | A.java:21:11:21:13 | "B" : String | A.java:21:7:21:13 | ...=... : String | -| A.java:21:11:21:13 | "B" : String | A.java:25:5:25:26 | SSA phi(s) : String | | A.java:21:11:21:13 | "B" : String | A.java:28:11:38:5 | String s : String | | A.java:21:11:21:13 | "B" : String | A.java:28:11:38:5 | new (...) : new A(...) { ... } [String s] | | A.java:21:11:21:13 | "B" : String | A.java:30:14:30:16 | parameter this : new A(...) { ... } [String s] | @@ -32,8 +32,8 @@ | A.java:23:11:23:13 | "C" : String | A.java:14:11:14:20 | f2(...) : new A(...) { ... } [String s] | | A.java:23:11:23:13 | "C" : String | A.java:15:16:15:16 | a : new A(...) { ... } [String s] | | A.java:23:11:23:13 | "C" : String | A.java:15:16:15:22 | get(...) : String | +| A.java:23:11:23:13 | "C" : String | A.java:20:5:20:15 | SSA phi(s) : String | | A.java:23:11:23:13 | "C" : String | A.java:23:7:23:13 | ...=... : String | -| A.java:23:11:23:13 | "C" : String | A.java:25:5:25:26 | SSA phi(s) : String | | A.java:23:11:23:13 | "C" : String | A.java:28:11:38:5 | String s : String | | A.java:23:11:23:13 | "C" : String | A.java:28:11:38:5 | new (...) : new A(...) { ... } [String s] | | A.java:23:11:23:13 | "C" : String | A.java:30:14:30:16 | parameter this : new A(...) { ... } [String s] | diff --git a/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.java b/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.java index 52d26974373d..80cf48de6650 100644 --- a/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.java +++ b/java/ql/test/library-tests/dataflow/entrypoint-types/EntryPointTypesTest.java @@ -48,34 +48,34 @@ static class ArrayElemObject { private static void sink(String sink) {} public static void test(TestObject source) { - sink(source.field1); // $hasTaintFlow - sink(source.getField2()); // $hasTaintFlow - sink(source.getField3().field4); // $hasTaintFlow - sink(source.getField3().getField5()); // $hasTaintFlow + sink(source.field1); // $ hasTaintFlow + sink(source.getField2()); // $ hasTaintFlow + sink(source.getField3().field4); // $ hasTaintFlow + sink(source.getField3().getField5()); // $ hasTaintFlow } public static void testParameterized( ParameterizedTestObject source) { - sink(source.field6); // $hasTaintFlow - sink(source.field7.field1); // $hasTaintFlow - sink(source.field7.getField2()); // $hasTaintFlow - sink(source.getField8().field4); // $hasTaintFlow - sink(source.getField8().getField5()); // $hasTaintFlow + sink(source.field6); // $ hasTaintFlow + sink(source.field7.field1); // $ hasTaintFlow + sink(source.field7.getField2()); // $ hasTaintFlow + sink(source.getField8().field4); // $ hasTaintFlow + sink(source.getField8().getField5()); // $ hasTaintFlow } public static void testSubtype(ParameterizedTestObject source) { ChildObject subtypeSource = (ChildObject) source; - sink(subtypeSource.field6); // $hasTaintFlow - sink(subtypeSource.field7.field1); // $hasTaintFlow - sink(subtypeSource.field7.getField2()); // $hasTaintFlow - sink((String) subtypeSource.getField8()); // $hasTaintFlow - sink((String) subtypeSource.field9); // $hasTaintFlow + sink(subtypeSource.field6); // $ hasTaintFlow + sink(subtypeSource.field7.field1); // $ hasTaintFlow + sink(subtypeSource.field7.getField2()); // $ hasTaintFlow + sink((String) subtypeSource.getField8()); // $ hasTaintFlow + sink((String) subtypeSource.field9); // $ hasTaintFlow // Ensure that we are not tainting every subclass of Object UnrelatedObject unrelated = (UnrelatedObject) subtypeSource.getField8(); sink(unrelated.safeField); // Safe } public static void testArray(ArrayElemObject[] source) { - sink(source[0].field); // $hasTaintFlow + sink(source[0].field); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/Test.java b/java/ql/test/library-tests/dataflow/fluent-methods/Test.java index d776d85a5f6b..d47c566e13da 100644 --- a/java/ql/test/library-tests/dataflow/fluent-methods/Test.java +++ b/java/ql/test/library-tests/dataflow/fluent-methods/Test.java @@ -42,31 +42,31 @@ public static void sink(String s) {} public static void test1() { Test t = new Test(); t.fluentNoop().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasValueFlow + sink(t.get()); // $ hasValueFlow } public static void test2() { Test t = new Test(); Test.identity(t).fluentNoop().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasValueFlow + sink(t.get()); // $ hasValueFlow } public static void test3() { Test t = new Test(); t.indirectlyFluentNoop().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasValueFlow + sink(t.get()); // $ hasValueFlow } public static void testModel1() { Test t = new Test(); t.indirectlyFluentNoop().modelledFluentMethod().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasValueFlow + sink(t.get()); // $ hasValueFlow } public static void testModel2() { Test t = new Test(); Test.modelledIdentity(t).indirectlyFluentNoop().modelledFluentMethod().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasValueFlow + sink(t.get()); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java index d3f8766de704..96be33ae0b2e 100644 --- a/java/ql/test/library-tests/dataflow/taint-jackson/Test.java +++ b/java/ql/test/library-tests/dataflow/taint-jackson/Test.java @@ -34,22 +34,22 @@ public static void jacksonObjectMapper() throws Exception { ObjectMapper om = new ObjectMapper(); File file = new File("testFile"); om.writeValue(file, s); - sink(file); //$hasTaintFlow + sink(file); // $ hasTaintFlow OutputStream out = new FileOutputStream(file); om.writeValue(out, s); - sink(file); //$hasTaintFlow + sink(file); // $ hasTaintFlow Writer writer = new StringWriter(); om.writeValue(writer, s); - sink(writer); //$hasTaintFlow + sink(writer); // $ hasTaintFlow JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter()); om.writeValue(generator, s); - sink(generator); //$hasTaintFlow + sink(generator); // $ hasTaintFlow String t = om.writeValueAsString(s); - sink(t); //$hasTaintFlow + sink(t); // $ hasTaintFlow byte[] bs = om.writeValueAsBytes(s); String reconstructed = new String(bs, "utf-8"); - sink(bs); //$hasTaintFlow - sink(reconstructed); //$hasTaintFlow + sink(bs); // $ hasTaintFlow + sink(reconstructed); // $ hasTaintFlow } public static void jacksonObjectWriter() throws Exception { @@ -57,44 +57,44 @@ public static void jacksonObjectWriter() throws Exception { ObjectWriter ow = new ObjectWriter(); File file = new File("testFile"); ow.writeValue(file, s); - sink(file); //$hasTaintFlow + sink(file); // $ hasTaintFlow OutputStream out = new FileOutputStream(file); ow.writeValue(out, s); - sink(out); //$hasTaintFlow + sink(out); // $ hasTaintFlow Writer writer = new StringWriter(); ow.writeValue(writer, s); - sink(writer); //$hasTaintFlow + sink(writer); // $ hasTaintFlow JsonGenerator generator = new JsonFactory().createGenerator(new StringWriter()); ow.writeValue(generator, s); - sink(generator); //$hasTaintFlow + sink(generator); // $ hasTaintFlow String t = ow.writeValueAsString(s); - sink(t); //$hasTaintFlow + sink(t); // $ hasTaintFlow byte[] bs = ow.writeValueAsBytes(s); String reconstructed = new String(bs, "utf-8"); - sink(bs); //$hasTaintFlow - sink(reconstructed); //$hasTaintFlow + sink(bs); // $ hasTaintFlow + sink(reconstructed); // $ hasTaintFlow } public static void jacksonObjectReader() throws java.io.IOException { String s = taint(); ObjectMapper om = new ObjectMapper(); ObjectReader reader = om.readerFor(Potato.class); - sink(reader.readValue(s)); //$hasTaintFlow - sink(reader.readValue(s, Potato.class).name); //$hasTaintFlow - sink(reader.readValue(s, Potato.class).getName()); //$hasTaintFlow + sink(reader.readValue(s)); // $ hasTaintFlow + sink(reader.readValue(s, Potato.class).name); // $ hasTaintFlow + sink(reader.readValue(s, Potato.class).getName()); // $ hasTaintFlow } public static void jacksonObjectReaderIterable() throws java.io.IOException { String s = taint(); ObjectMapper om = new ObjectMapper(); ObjectReader reader = om.readerFor(Potato.class); - sink(reader.readValues(s)); //$hasTaintFlow + sink(reader.readValues(s)); // $ hasTaintFlow Iterator pIterator = reader.readValues(s); while(pIterator.hasNext()) { Potato p = pIterator.next(); - sink(p); //$hasTaintFlow - sink(p.name); //$hasTaintFlow - sink(p.getName()); //$hasTaintFlow + sink(p); // $ hasTaintFlow + sink(p.name); // $ hasTaintFlow + sink(p.getName()); // $ hasTaintFlow } } @@ -104,9 +104,9 @@ public static void jacksonTwoStepDeserialization() throws java.io.IOException { taintedParams.put("name", s); ObjectMapper om = new ObjectMapper(); JsonNode jn = om.valueToTree(taintedParams); - sink(jn); //$hasTaintFlow + sink(jn); // $ hasTaintFlow Potato p = om.convertValue(jn, Potato.class); - sink(p); //$hasTaintFlow - sink(p.getName()); //$hasTaintFlow + sink(p); // $ hasTaintFlow + sink(p.getName()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/A.java b/java/ql/test/library-tests/dataflow/taintsources/A.java index f28834e58375..37051a328c4e 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/A.java +++ b/java/ql/test/library-tests/dataflow/taintsources/A.java @@ -18,40 +18,40 @@ public class A { private static void sink(Object o) {} public static void main(String[] args) { - sink(args); // $hasLocalValueFlow - sink(args[0]); // $hasLocalTaintFlow + sink(args); // $ hasLocalValueFlow + sink(args[0]); // $ hasLocalTaintFlow } public static void userInput() throws SQLException, IOException, MalformedURLException { - sink(System.getenv("test")); // $hasLocalValueFlow + sink(System.getenv("test")); // $ hasLocalValueFlow class TestServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - sink(req.getParameter("test")); // $hasRemoteValueFlow - sink(req.getHeader("test")); // $hasRemoteValueFlow - sink(req.getQueryString()); // $hasRemoteValueFlow - sink(req.getCookies()[0].getValue()); // $hasRemoteValueFlow + sink(req.getParameter("test")); // $ hasRemoteValueFlow + sink(req.getHeader("test")); // $ hasRemoteValueFlow + sink(req.getQueryString()); // $ hasRemoteValueFlow + sink(req.getCookies()[0].getValue()); // $ hasRemoteValueFlow } } - sink(new Properties().getProperty("test")); // $hasLocalValueFlow - sink(System.getProperty("test")); // $hasLocalValueFlow + sink(new Properties().getProperty("test")); // $ hasLocalValueFlow + sink(System.getProperty("test")); // $ hasLocalValueFlow new Object() { public void test(ResultSet rs) throws SQLException { - sink(rs.getString(0)); // $hasLocalValueFlow + sink(rs.getString(0)); // $ hasLocalValueFlow } }; - sink(new URL("test").openConnection().getInputStream()); // $hasRemoteValueFlow - sink(new Socket("test", 1234).getInputStream()); // $hasRemoteValueFlow - sink(InetAddress.getByName("test").getHostName()); // $hasReverseDnsValueFlow + sink(new URL("test").openConnection().getInputStream()); // $ hasRemoteValueFlow + sink(new Socket("test", 1234).getInputStream()); // $ hasRemoteValueFlow + sink(InetAddress.getByName("test").getHostName()); // $ hasReverseDnsValueFlow sink(InetAddress.getLocalHost().getHostName()); sink(InetAddress.getLoopbackAddress().getHostName()); - sink(InetAddress.getByName("test").getCanonicalHostName()); // $hasReverseDnsValueFlow + sink(InetAddress.getByName("test").getCanonicalHostName()); // $ hasReverseDnsValueFlow sink(InetAddress.getLocalHost().getCanonicalHostName()); sink(InetAddress.getLoopbackAddress().getCanonicalHostName()); - sink(System.in); // $hasLocalValueFlow - sink(new FileInputStream("test")); // $hasLocalValueFlow + sink(System.in); // $ hasLocalValueFlow + sink(new FileInputStream("test")); // $ hasLocalValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/AndroidExposedObject.java b/java/ql/test/library-tests/dataflow/taintsources/AndroidExposedObject.java index 2460781e1965..50d5a8a38ea4 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/AndroidExposedObject.java +++ b/java/ql/test/library-tests/dataflow/taintsources/AndroidExposedObject.java @@ -6,6 +6,6 @@ public void sink(Object o) { @JavascriptInterface public void test(String arg) { - sink(arg); // $hasRemoteValueFlow + sink(arg); // $ hasRemoteValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/Hudson.java b/java/ql/test/library-tests/dataflow/taintsources/Hudson.java index 2a180eeb5fbd..b7586cbfc852 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/Hudson.java +++ b/java/ql/test/library-tests/dataflow/taintsources/Hudson.java @@ -6,11 +6,11 @@ private static void sink(Object o) {} public static void test() throws Exception { FilePath fp = null; - sink(FilePath.newInputStreamDenyingSymlinkAsNeeded(null, null, null)); // $hasLocalValueFlow - sink(FilePath.openInputStream(null, null)); // $hasLocalValueFlow - sink(fp.read()); // $hasLocalValueFlow - sink(fp.read(null)); // $hasLocalValueFlow - sink(fp.readFromOffset(-1)); // $hasLocalValueFlow - sink(fp.readToString()); // $hasLocalValueFlow + sink(FilePath.newInputStreamDenyingSymlinkAsNeeded(null, null, null)); // $ hasLocalValueFlow + sink(FilePath.openInputStream(null, null)); // $ hasLocalValueFlow + sink(fp.read()); // $ hasLocalValueFlow + sink(fp.read(null)); // $ hasLocalValueFlow + sink(fp.readFromOffset(-1)); // $ hasLocalValueFlow + sink(fp.readToString()); // $ hasLocalValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/IntentSourcesActivity.java b/java/ql/test/library-tests/dataflow/taintsources/IntentSourcesActivity.java index 3cd324a05db9..99d701adca03 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/IntentSourcesActivity.java +++ b/java/ql/test/library-tests/dataflow/taintsources/IntentSourcesActivity.java @@ -9,21 +9,21 @@ private static void sink(Object o) {} public void test() throws java.io.IOException { String trouble = this.getIntent().getStringExtra("key"); - sink(trouble); // $hasRemoteTaintFlow + sink(trouble); // $ hasRemoteTaintFlow } public void test2() throws java.io.IOException { String trouble = getIntent().getStringExtra("key"); - sink(trouble); // $hasRemoteTaintFlow + sink(trouble); // $ hasRemoteTaintFlow } public void test3() throws java.io.IOException { String trouble = getIntent().getExtras().getString("key"); - sink(trouble); // $hasRemoteTaintFlow + sink(trouble); // $ hasRemoteTaintFlow } } @@ -34,7 +34,7 @@ private static void sink(Object o) {} public void test(IntentSourcesActivity is) throws java.io.IOException { String trouble = is.getIntent().getStringExtra("key"); - sink(trouble); // $hasRemoteTaintFlow + sink(trouble); // $ hasRemoteTaintFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java b/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java index 9e814bf72016..bed290c08bc9 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java +++ b/java/ql/test/library-tests/dataflow/taintsources/RmiFlowImpl.java @@ -6,7 +6,7 @@ private static void sink(Object o) {} public String listDirectory(String path) throws java.io.IOException { String command = "ls " + path; - sink(command); // $hasRemoteTaintFlow + sink(command); // $ hasRemoteTaintFlow return "pretend there are some results here"; } diff --git a/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java b/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java index 33eeced2a4e6..7e1846480eab 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java +++ b/java/ql/test/library-tests/dataflow/taintsources/SpringMultiPart.java @@ -7,21 +7,21 @@ public class SpringMultiPart { private static void sink(Object o) {} public void test() throws Exception { - sink(file.getBytes()); // $hasRemoteValueFlow + sink(file.getBytes()); // $ hasRemoteValueFlow sink(file.isEmpty()); // Safe - sink(file.getInputStream()); // $hasRemoteValueFlow - sink(file.getResource()); // $hasRemoteValueFlow - sink(file.getName()); // $hasRemoteValueFlow - sink(file.getContentType()); // $hasRemoteValueFlow - sink(file.getOriginalFilename()); // $hasRemoteValueFlow + sink(file.getInputStream()); // $ hasRemoteValueFlow + sink(file.getResource()); // $ hasRemoteValueFlow + sink(file.getName()); // $ hasRemoteValueFlow + sink(file.getContentType()); // $ hasRemoteValueFlow + sink(file.getOriginalFilename()); // $ hasRemoteValueFlow } public void test(MultipartRequest request) { - sink(request.getFile("name"));// $hasRemoteValueFlow - sink(request.getFileMap());// $hasRemoteValueFlow - sink(request.getFileNames());// $hasRemoteValueFlow - sink(request.getFiles("name"));// $hasRemoteValueFlow - sink(request.getMultiFileMap());// $hasRemoteValueFlow - sink(request.getMultipartContentType("name")); // $hasRemoteValueFlow + sink(request.getFile("name"));// $ hasRemoteValueFlow + sink(request.getFileMap());// $ hasRemoteValueFlow + sink(request.getFileNames());// $ hasRemoteValueFlow + sink(request.getFiles("name"));// $ hasRemoteValueFlow + sink(request.getMultiFileMap());// $ hasRemoteValueFlow + sink(request.getMultipartContentType("name")); // $ hasRemoteValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java b/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java index e61e0cbb827d..a14269fced05 100644 --- a/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java +++ b/java/ql/test/library-tests/dataflow/taintsources/SpringSavedRequest.java @@ -7,22 +7,22 @@ public class SpringSavedRequest { private static void sink(Object o) {} public void test() { - sink(sr.getRedirectUrl()); // $hasRemoteValueFlow - sink(sr.getCookies()); // $hasRemoteValueFlow - sink(sr.getHeaderValues("name")); // $hasRemoteValueFlow - sink(sr.getHeaderNames()); // $hasRemoteValueFlow - sink(sr.getParameterValues("name")); // $hasRemoteValueFlow - sink(sr.getParameterMap()); // $hasRemoteValueFlow + sink(sr.getRedirectUrl()); // $ hasRemoteValueFlow + sink(sr.getCookies()); // $ hasRemoteValueFlow + sink(sr.getHeaderValues("name")); // $ hasRemoteValueFlow + sink(sr.getHeaderNames()); // $ hasRemoteValueFlow + sink(sr.getParameterValues("name")); // $ hasRemoteValueFlow + sink(sr.getParameterMap()); // $ hasRemoteValueFlow } SimpleSavedRequest ssr; public void test2() { - sink(ssr.getRedirectUrl()); // $hasRemoteValueFlow - sink(ssr.getCookies()); // $hasRemoteValueFlow - sink(ssr.getHeaderValues("name")); // $hasRemoteValueFlow - sink(ssr.getHeaderNames()); // $hasRemoteValueFlow - sink(ssr.getParameterValues("name")); // $hasRemoteValueFlow - sink(ssr.getParameterMap()); // $hasRemoteValueFlow + sink(ssr.getRedirectUrl()); // $ hasRemoteValueFlow + sink(ssr.getCookies()); // $ hasRemoteValueFlow + sink(ssr.getHeaderValues("name")); // $ hasRemoteValueFlow + sink(ssr.getHeaderNames()); // $ hasRemoteValueFlow + sink(ssr.getParameterValues("name")); // $ hasRemoteValueFlow + sink(ssr.getParameterMap()); // $ hasRemoteValueFlow } } diff --git a/java/ql/test/library-tests/flexible-constructors/SuperPredecessor.expected b/java/ql/test/library-tests/flexible-constructors/SuperPredecessor.expected deleted file mode 100644 index dba8b4acf988..000000000000 --- a/java/ql/test/library-tests/flexible-constructors/SuperPredecessor.expected +++ /dev/null @@ -1,7 +0,0 @@ -| FlexibleConstructors.java:10:15:10:17 | msg | FlexibleConstructors.java:10:9:10:19 | super(...) | predecessor of explicit super() | -| FlexibleConstructors.java:18:13:18:17 | ... < ... | FlexibleConstructors.java:19:9:19:16 | super(...) | predecessor of explicit super() | -| FlexibleConstructors.java:38:17:38:48 | combined | FlexibleConstructors.java:39:13:39:20 | super(...) | predecessor of explicit super() | -| FlexibleConstructors.java:52:9:52:40 | ...=... | FlexibleConstructors.java:53:9:53:16 | super(...) | predecessor of explicit super() | -| FlexibleConstructors.java:65:15:65:18 | temp | FlexibleConstructors.java:65:9:65:20 | super(...) | predecessor of explicit super() | -| FlexibleConstructors.java:77:9:77:24 | ...=... | FlexibleConstructors.java:78:9:78:16 | super(...) | predecessor of explicit super() | -| FlexibleConstructors.java:91:13:91:41 | string | FlexibleConstructors.java:92:9:92:16 | super(...) | predecessor of explicit super() | diff --git a/java/ql/test/library-tests/flexible-constructors/SuperPredecessor.ql b/java/ql/test/library-tests/flexible-constructors/SuperPredecessor.ql deleted file mode 100644 index 2a291c5e82a3..000000000000 --- a/java/ql/test/library-tests/flexible-constructors/SuperPredecessor.ql +++ /dev/null @@ -1,11 +0,0 @@ -import java - -from ControlFlowNode pred, ControlFlowNode supNode, SuperConstructorInvocationStmt sc -where - supNode.asStmt() = sc and - pred.getASuccessor() = supNode and - pred != supNode and - not pred.asStmt() instanceof BlockStmt and - exists(sc.getEnclosingCallable().getFile().getRelativePath()) and - sc.getLocation().getEndColumn() > sc.getLocation().getStartColumn() -select pred, sc, "predecessor of explicit super()" diff --git a/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java b/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java index f317b3ed2e83..22be5f8534eb 100644 --- a/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java +++ b/java/ql/test/library-tests/frameworks/android/intent/TestStartBroadcastReceiverToIntent.java @@ -79,7 +79,7 @@ static class SomeBroadcastReceiver extends BroadcastReceiver { // test method that receives an Intent as a parameter @Override public void onReceive(Context context, Intent intent) { - sink(intent.getStringExtra("data")); // $ hasValueFlow=send hasValueFlow=send-as-user hasValueFlow=send-with-perm hasValueFlow=send-ordered hasValueFlow=send-ordered-as-user hasValueFlow=send-sticky hasValueFlow=send-sticky-as-user hasValueFlow=send-sticky-ordered hasValueFlow=send-sticky-ordered-as-user hasValueFlow=4-arg + sink(intent.getStringExtra("data")); // $ hasValueFlow=send hasValueFlow=send-as-user hasValueFlow=send-with-perm hasValueFlow=send-ordered hasValueFlow=send-ordered-as-user hasValueFlow=send-sticky hasValueFlow=send-sticky-as-user hasValueFlow=send-sticky-ordered hasValueFlow=send-sticky-ordered-as-user hasValueFlow=4-arg } } diff --git a/java/ql/test/library-tests/frameworks/android/slice/TestSources.java b/java/ql/test/library-tests/frameworks/android/slice/TestSources.java index 7f51442c8ea8..f50f6fb09d73 100644 --- a/java/ql/test/library-tests/frameworks/android/slice/TestSources.java +++ b/java/ql/test/library-tests/frameworks/android/slice/TestSources.java @@ -18,14 +18,14 @@ void sink(Object o) {} // "androidx.slice;SliceProvider;true;onBindSlice;;;Parameter[0];contentprovider;manual", @Override public Slice onBindSlice(Uri sliceUri) { - sink(sliceUri); // $hasValueFlow + sink(sliceUri); // $ hasValueFlow return null; } // "androidx.slice;SliceProvider;true;onCreatePermissionRequest;;;Parameter[0];contentprovider;manual", @Override public PendingIntent onCreatePermissionRequest(Uri sliceUri, String callingPackage) { - sink(sliceUri); // $hasValueFlow + sink(sliceUri); // $ hasValueFlow sink(callingPackage); // Safe return null; } @@ -33,18 +33,18 @@ public PendingIntent onCreatePermissionRequest(Uri sliceUri, String callingPacka // "androidx.slice;SliceProvider;true;onMapIntentToUri;;;Parameter[0];contentprovider;manual", @Override public Uri onMapIntentToUri(Intent intent) { - sink(intent); // $hasValueFlow + sink(intent); // $ hasValueFlow return null; } // "androidx.slice;SliceProvider;true;onSlicePinned;;;Parameter[0];contentprovider;manual", public void onSlicePinned(Uri sliceUri) { - sink(sliceUri); // $hasValueFlow + sink(sliceUri); // $ hasValueFlow } // "androidx.slice;SliceProvider;true;onSliceUnpinned;;;Parameter[0];contentprovider;manual" public void onSliceUnpinned(Uri sliceUri) { - sink(sliceUri); // $hasValueFlow + sink(sliceUri); // $ hasValueFlow } // Methods needed for compilation diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java b/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java index edf290c4cef3..5a204fc2c072 100644 --- a/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java +++ b/java/ql/test/library-tests/frameworks/android/taint-database/FlowSteps.java @@ -29,96 +29,96 @@ private static abstract class MySQLiteQueryBuilder extends SQLiteQueryBuilder { } public static String appendSelectionArgs() { - String[] originalValues = {taint()}; // $taintReachesReturn - String[] newValues = {taint()}; // $taintReachesReturn + String[] originalValues = {taint()}; // $ taintReachesReturn + String[] newValues = {taint()}; // $ taintReachesReturn return DatabaseUtils.appendSelectionArgs(originalValues, newValues)[0]; } public static String concatenateWhere() { - String a = taint(); // $taintReachesReturn - String b = taint(); // $taintReachesReturn + String a = taint(); // $ taintReachesReturn + String b = taint(); // $ taintReachesReturn return DatabaseUtils.concatenateWhere(a, b); } public static String buildQueryString(MySQLiteQueryBuilder target) { target = taint(); - boolean distinct = taint(); - String tables = taint(); // $taintReachesReturn - String[] columns = {taint()}; // $taintReachesReturn - String where = taint(); // $taintReachesReturn - String groupBy = taint(); // $taintReachesReturn - String having = taint(); // $taintReachesReturn - String orderBy = taint(); // $taintReachesReturn - String limit = taint(); // $taintReachesReturn + boolean distinct = taint(); + String tables = taint(); // $ taintReachesReturn + String[] columns = {taint()}; // $ taintReachesReturn + String where = taint(); // $ taintReachesReturn + String groupBy = taint(); // $ taintReachesReturn + String having = taint(); // $ taintReachesReturn + String orderBy = taint(); // $ taintReachesReturn + String limit = taint(); // $ taintReachesReturn return SQLiteQueryBuilder.buildQueryString(distinct, tables, columns, where, groupBy, having, orderBy, limit); } public static String buildQuery(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - String[] projectionIn = {taint()}; // $taintReachesReturn - String selection = taint(); // $taintReachesReturn - String groupBy = taint(); // $taintReachesReturn - String having = taint(); // $taintReachesReturn - String sortOrder = taint(); // $taintReachesReturn - String limit = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + String[] projectionIn = {taint()}; // $ taintReachesReturn + String selection = taint(); // $ taintReachesReturn + String groupBy = taint(); // $ taintReachesReturn + String having = taint(); // $ taintReachesReturn + String sortOrder = taint(); // $ taintReachesReturn + String limit = taint(); // $ taintReachesReturn return target.buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit); } public static String buildQuery2(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - String[] projectionIn = {taint()}; // $taintReachesReturn - String selection = taint(); // $taintReachesReturn - String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesReturn - String having = taint(); // $taintReachesReturn - String sortOrder = taint(); // $taintReachesReturn - String limit = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + String[] projectionIn = {taint()}; // $ taintReachesReturn + String selection = taint(); // $ taintReachesReturn + String[] selectionArgs = {taint()}; + String groupBy = taint(); // $ taintReachesReturn + String having = taint(); // $ taintReachesReturn + String sortOrder = taint(); // $ taintReachesReturn + String limit = taint(); // $ taintReachesReturn return target.buildQuery(projectionIn, selection, selectionArgs, groupBy, having, sortOrder, limit); } public static String buildUnionQuery(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - String[] subQueries = {taint()}; // $taintReachesReturn - String sortOrder = taint(); // $taintReachesReturn - String limit = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + String[] subQueries = {taint()}; // $ taintReachesReturn + String sortOrder = taint(); // $ taintReachesReturn + String limit = taint(); // $ taintReachesReturn return target.buildUnionQuery(subQueries, sortOrder, limit); } public static String buildUnionSubQuery2(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - String typeDiscriminatorColumn = taint(); // $taintReachesReturn - String[] unionColumns = {taint()}; // $taintReachesReturn + target = taint(); // $ taintReachesReturn + String typeDiscriminatorColumn = taint(); // $ taintReachesReturn + String[] unionColumns = {taint()}; // $ taintReachesReturn Set columnsPresentInTable = new HashSet(); - columnsPresentInTable.add(taint()); // $taintReachesReturn + columnsPresentInTable.add(taint()); // $ taintReachesReturn int computedColumnsOffset = taint(); - String typeDiscriminatorValue = taint(); // $taintReachesReturn - String selection = taint(); // $taintReachesReturn + String typeDiscriminatorValue = taint(); // $ taintReachesReturn + String selection = taint(); // $ taintReachesReturn String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesReturn - String having = taint(); // $taintReachesReturn + String groupBy = taint(); // $ taintReachesReturn + String having = taint(); // $ taintReachesReturn return target.buildUnionSubQuery(typeDiscriminatorColumn, unionColumns, columnsPresentInTable, computedColumnsOffset, typeDiscriminatorValue, selection, selectionArgs, groupBy, having); } public static String buildUnionSubQuery3(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - String typeDiscriminatorColumn = taint(); // $taintReachesReturn - String[] unionColumns = {taint()}; // $taintReachesReturn + target = taint(); // $ taintReachesReturn + String typeDiscriminatorColumn = taint(); // $ taintReachesReturn + String[] unionColumns = {taint()}; // $ taintReachesReturn Set columnsPresentInTable = new HashSet(); - columnsPresentInTable.add(taint()); // $taintReachesReturn + columnsPresentInTable.add(taint()); // $ taintReachesReturn int computedColumnsOffset = taint(); - String typeDiscriminatorValue = taint(); // $taintReachesReturn - String selection = taint(); // $taintReachesReturn - String groupBy = taint(); // $taintReachesReturn - String having = taint(); // $taintReachesReturn + String typeDiscriminatorValue = taint(); // $ taintReachesReturn + String selection = taint(); // $ taintReachesReturn + String groupBy = taint(); // $ taintReachesReturn + String having = taint(); // $ taintReachesReturn return target.buildUnionSubQuery(typeDiscriminatorColumn, unionColumns, columnsPresentInTable, computedColumnsOffset, typeDiscriminatorValue, selection, groupBy, having); } public static Cursor query(MyContentResolver target) { - Uri uri = taint(); // $taintReachesReturn + Uri uri = taint(); // $ taintReachesReturn String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); CancellationSignal cancellationSignal = taint(); @@ -126,9 +126,9 @@ public static Cursor query(MyContentResolver target) { } public static Cursor query(MyContentProvider target) { - Uri uri = taint(); // $taintReachesReturn + Uri uri = taint(); // $ taintReachesReturn String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); CancellationSignal cancellationSignal = taint(); @@ -136,57 +136,57 @@ public static Cursor query(MyContentProvider target) { } public static Cursor query2(MyContentResolver target) { - Uri uri = taint(); // $taintReachesReturn + Uri uri = taint(); // $ taintReachesReturn String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); return target.query(uri, projection, selection, selectionArgs, sortOrder); } public static Cursor query2(MyContentProvider target) { - Uri uri = taint(); // $taintReachesReturn + Uri uri = taint(); // $ taintReachesReturn String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); return target.query(uri, projection, selection, selectionArgs, sortOrder); } public static StringBuilder appendColumns() { - StringBuilder s = taint(); // $taintReachesReturn - String[] columns = {taint()}; // $taintReachesReturn + StringBuilder s = taint(); // $ taintReachesReturn + String[] columns = {taint()}; // $ taintReachesReturn SQLiteQueryBuilder.appendColumns(s, columns); return s; } public static SQLiteQueryBuilder setProjectionMap(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - Map columnMap = new HashMap(); - String k = taint(); // $taintReachesReturn - String v = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + Map columnMap = new HashMap(); + String k = taint(); // $ taintReachesReturn + String v = taint(); // $ taintReachesReturn columnMap.put(k, v); target.setProjectionMap(columnMap); return target; } public static SQLiteQueryBuilder setTables(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - String inTables = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + String inTables = taint(); // $ taintReachesReturn target.setTables(inTables); return target; } public static SQLiteQueryBuilder appendWhere(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - CharSequence inWhere = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + CharSequence inWhere = taint(); // $ taintReachesReturn target.appendWhere(inWhere); return target; } public static SQLiteQueryBuilder appendWhereStandalone(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesReturn - CharSequence inWhere = taint(); // $taintReachesReturn + target = taint(); // $ taintReachesReturn + CharSequence inWhere = taint(); // $ taintReachesReturn target.appendWhereStandalone(inWhere); return target; } diff --git a/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java b/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java index d236368e089c..61775f41556e 100644 --- a/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java +++ b/java/ql/test/library-tests/frameworks/android/taint-database/Sinks.java @@ -25,58 +25,58 @@ private static abstract class MySQLiteQueryBuilder extends SQLiteQueryBuilder { } public static void compileStatement(SQLiteDatabase target) { - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink target.compileStatement(sql); } public static void delete1(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesSink + target = taint(); // $ taintReachesSink SQLiteDatabase db = taint(); - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.delete(db, selection, selectionArgs); } public static void delete(SQLiteDatabase target) { - String table = taint(); // $taintReachesSink - String whereClause = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String whereClause = taint(); // $ taintReachesSink String[] whereArgs = {taint()}; target.delete(table, whereClause, whereArgs); } public static void delete(MyContentResolver target) { Uri uri = taint(); - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.delete(uri, selection, selectionArgs); } public static void delete(MyContentProvider target) { Uri uri = taint(); - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.delete(uri, selection, selectionArgs); } public static void execPerConnectionSQL(SQLiteDatabase target) { - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink Object[] bindArgs = {taint()}; target.execPerConnectionSQL(sql, bindArgs); } public static void execSQL(SQLiteDatabase target) { - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink target.execSQL(sql); } public static void execSQL2(SQLiteDatabase target) { - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink Object[] bindArgs = {taint()}; target.execSQL(sql, bindArgs); } public static void insert(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesSink + target = taint(); // $ taintReachesSink SQLiteDatabase db = taint(); ContentValues values = taint(); target.insert(db, values); @@ -84,90 +84,90 @@ public static void insert(MySQLiteQueryBuilder target) { public static void query(SQLiteDatabase target) { boolean distinct = taint(); - String table = taint(); // $taintReachesSink - String[] columns = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String[] columns = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String orderBy = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String orderBy = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink target.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); } public static void query2(SQLiteDatabase target) { boolean distinct = taint(); - String table = taint(); // $taintReachesSink - String[] columns = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String[] columns = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String orderBy = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String orderBy = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink CancellationSignal cancellationSignal = taint(); target.query(distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit, cancellationSignal); } public static void query3(SQLiteDatabase target) { - String table = taint(); // $taintReachesSink - String[] columns = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String[] columns = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String orderBy = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String orderBy = taint(); // $ taintReachesSink target.query(table, columns, selection, selectionArgs, groupBy, having, orderBy); } public static void query4(SQLiteDatabase target) { - String table = taint(); // $taintReachesSink - String[] columns = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String[] columns = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String orderBy = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String orderBy = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink target.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); } public static void query(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesSink + target = taint(); // $ taintReachesSink SQLiteDatabase db = taint(); - String[] projectionIn = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String[] projectionIn = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String sortOrder = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String sortOrder = taint(); // $ taintReachesSink target.query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder); } public static void query2(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesSink + target = taint(); // $ taintReachesSink SQLiteDatabase db = taint(); - String[] projectionIn = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String[] projectionIn = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String sortOrder = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String sortOrder = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink target.query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder, limit); } public static void query3(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesSink + target = taint(); // $ taintReachesSink SQLiteDatabase db = taint(); - String[] projectionIn = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String[] projectionIn = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String sortOrder = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String sortOrder = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink CancellationSignal cancellationSignal = taint(); target.query(db, projectionIn, selection, selectionArgs, groupBy, having, sortOrder, limit, cancellationSignal); } @@ -175,7 +175,7 @@ public static void query3(MySQLiteQueryBuilder target) { public static void query3(MyContentProvider target) { Uri uri = taint(); String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); target.query(uri, projection, selection, selectionArgs, sortOrder); @@ -184,7 +184,7 @@ public static void query3(MyContentProvider target) { public static void query(MyContentProvider target) { Uri uri = taint(); String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); CancellationSignal cancellationSignal = taint(); @@ -194,7 +194,7 @@ public static void query(MyContentProvider target) { public static void query3(MyContentResolver target) { Uri uri = taint(); String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); target.query(uri, projection, selection, selectionArgs, sortOrder); @@ -203,7 +203,7 @@ public static void query3(MyContentResolver target) { public static void query(MyContentResolver target) { Uri uri = taint(); String[] projection = {taint()}; - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String sortOrder = taint(); CancellationSignal cancellationSignal = taint(); @@ -213,14 +213,14 @@ public static void query(MyContentResolver target) { public static void queryWithFactory(SQLiteDatabase target) { SQLiteDatabase.CursorFactory cursorFactory = taint(); boolean distinct = taint(); - String table = taint(); // $taintReachesSink - String[] columns = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String[] columns = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String orderBy = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String orderBy = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink target.queryWithFactory(cursorFactory, distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit); } @@ -228,27 +228,27 @@ public static void queryWithFactory(SQLiteDatabase target) { public static void queryWithFactory2(SQLiteDatabase target) { SQLiteDatabase.CursorFactory cursorFactory = taint(); boolean distinct = taint(); - String table = taint(); // $taintReachesSink - String[] columns = {taint()}; // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String[] columns = {taint()}; // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; - String groupBy = taint(); // $taintReachesSink - String having = taint(); // $taintReachesSink - String orderBy = taint(); // $taintReachesSink - String limit = taint(); // $taintReachesSink + String groupBy = taint(); // $ taintReachesSink + String having = taint(); // $ taintReachesSink + String orderBy = taint(); // $ taintReachesSink + String limit = taint(); // $ taintReachesSink CancellationSignal cancellationSignal = taint(); target.queryWithFactory(cursorFactory, distinct, table, columns, selection, selectionArgs, groupBy, having, orderBy, limit, cancellationSignal); } public static void rawQuery(SQLiteDatabase target) { - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.rawQuery(sql, selectionArgs); } public static void rawQuery2(SQLiteDatabase target) { - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; CancellationSignal cancellationSignal = taint(); target.rawQuery(sql, selectionArgs, cancellationSignal); @@ -256,7 +256,7 @@ public static void rawQuery2(SQLiteDatabase target) { public static void rawQueryWithFactory(SQLiteDatabase target) { SQLiteDatabase.CursorFactory cursorFactory = taint(); - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String editTable = taint(); target.rawQueryWithFactory(cursorFactory, sql, selectionArgs, editTable); @@ -264,7 +264,7 @@ public static void rawQueryWithFactory(SQLiteDatabase target) { public static void rawQueryWithFactory2(SQLiteDatabase target) { SQLiteDatabase.CursorFactory cursorFactory = taint(); - String sql = taint(); // $taintReachesSink + String sql = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; String editTable = taint(); CancellationSignal cancellationSignal = taint(); @@ -272,18 +272,18 @@ public static void rawQueryWithFactory2(SQLiteDatabase target) { } public static void update(MySQLiteQueryBuilder target) { - target = taint(); // $taintReachesSink + target = taint(); // $ taintReachesSink SQLiteDatabase db = taint(); ContentValues values = taint(); - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.update(db, values, selection, selectionArgs); } public static void update(SQLiteDatabase target) { - String table = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink ContentValues values = taint(); - String whereClause = taint(); // $taintReachesSink + String whereClause = taint(); // $ taintReachesSink String[] whereArgs = {taint()}; target.update(table, values, whereClause, whereArgs); } @@ -291,7 +291,7 @@ public static void update(SQLiteDatabase target) { public static void update(MyContentResolver target) { Uri uri = taint(); ContentValues values = taint(); - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.update(uri, values, selection, selectionArgs); } @@ -299,15 +299,15 @@ public static void update(MyContentResolver target) { public static void update(MyContentProvider target) { Uri uri = taint(); ContentValues values = taint(); - String selection = taint(); // $taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; target.update(uri, values, selection, selectionArgs); } public static void updateWithOnConflict(SQLiteDatabase target) { - String table = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink ContentValues values = taint(); - String whereClause = taint(); // $taintReachesSink + String whereClause = taint(); // $ taintReachesSink String[] whereArgs = {taint()}; int conflictAlgorithm = taint(); target.updateWithOnConflict(table, values, whereClause, whereArgs, conflictAlgorithm); @@ -315,15 +315,15 @@ public static void updateWithOnConflict(SQLiteDatabase target) { public static void queryNumEntries() { SQLiteDatabase db = taint(); - String table = taint(); // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String selection = taint(); // $ taintReachesSink DatabaseUtils.queryNumEntries(db, table, selection); } public static void queryNumEntries2() { SQLiteDatabase db = taint(); - String table = taint(); // $taintReachesSink - String selection = taint(); // $taintReachesSink + String table = taint(); // $ taintReachesSink + String selection = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; DatabaseUtils.queryNumEntries(db, table, selection, selectionArgs); } @@ -332,27 +332,27 @@ public static void createDbFromSqlStatements() { Context context = taint(); String dbName = taint(); int dbVersion = taint(); - String sqlStatements = taint(); // $taintReachesSink + String sqlStatements = taint(); // $ taintReachesSink DatabaseUtils.createDbFromSqlStatements(context, dbName, dbVersion, sqlStatements); } public static void blobFileDescriptorForQuery() { SQLiteDatabase db = taint(); - String query = taint(); // $taintReachesSink + String query = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; DatabaseUtils.blobFileDescriptorForQuery(db, query, selectionArgs); } public static void longForQuery() { SQLiteDatabase db = taint(); - String query = taint(); // $taintReachesSink + String query = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; DatabaseUtils.longForQuery(db, query, selectionArgs); } public static void stringForQuery() { SQLiteDatabase db = taint(); - String query = taint(); // $taintReachesSink + String query = taint(); // $ taintReachesSink String[] selectionArgs = {taint()}; DatabaseUtils.stringForQuery(db, query, selectionArgs); } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/ArrayUtilsTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/ArrayUtilsTest.java index c37d5844232a..d54f3b2942ea 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/ArrayUtilsTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/ArrayUtilsTest.java @@ -20,56 +20,56 @@ void test() throws Exception { String[] alreadyTainted = new String[] { taint() }; String[] clean = new String[] { "Untainted" }; - sink(ArrayUtils.add(clean, 0, taint())); // $hasTaintFlow - sink(ArrayUtils.add(alreadyTainted, 0, "clean")); // $hasTaintFlow + sink(ArrayUtils.add(clean, 0, taint())); // $ hasTaintFlow + sink(ArrayUtils.add(alreadyTainted, 0, "clean")); // $ hasTaintFlow sink(ArrayUtils.add(clean, IntSource.taint(), "clean")); // Index argument does not contribute taint - sink(ArrayUtils.add(clean, taint())); // $hasTaintFlow - sink(ArrayUtils.add(alreadyTainted, "clean")); // $hasTaintFlow - sink(ArrayUtils.addAll(clean, "clean", taint())); // $hasTaintFlow - sink(ArrayUtils.addAll(clean, taint(), "clean")); // $hasTaintFlow - sink(ArrayUtils.addAll(alreadyTainted, "clean", "also clean")); // $hasTaintFlow - sink(ArrayUtils.addFirst(clean, taint())); // $hasTaintFlow - sink(ArrayUtils.addFirst(alreadyTainted, "clean")); // $hasTaintFlow - sink(ArrayUtils.clone(alreadyTainted)); // $hasTaintFlow - sink(ArrayUtils.get(alreadyTainted, 0)); // $hasValueFlow + sink(ArrayUtils.add(clean, taint())); // $ hasTaintFlow + sink(ArrayUtils.add(alreadyTainted, "clean")); // $ hasTaintFlow + sink(ArrayUtils.addAll(clean, "clean", taint())); // $ hasTaintFlow + sink(ArrayUtils.addAll(clean, taint(), "clean")); // $ hasTaintFlow + sink(ArrayUtils.addAll(alreadyTainted, "clean", "also clean")); // $ hasTaintFlow + sink(ArrayUtils.addFirst(clean, taint())); // $ hasTaintFlow + sink(ArrayUtils.addFirst(alreadyTainted, "clean")); // $ hasTaintFlow + sink(ArrayUtils.clone(alreadyTainted)); // $ hasTaintFlow + sink(ArrayUtils.get(alreadyTainted, 0)); // $ hasValueFlow sink(ArrayUtils.get(clean, IntSource.taint())); // Index argument does not contribute taint - sink(ArrayUtils.get(alreadyTainted, 0, "default value")); // $hasValueFlow + sink(ArrayUtils.get(alreadyTainted, 0, "default value")); // $ hasValueFlow sink(ArrayUtils.get(clean, IntSource.taint(), "default value")); // Index argument does not contribute taint - sink(ArrayUtils.get(clean, 0, taint())); // $hasValueFlow + sink(ArrayUtils.get(clean, 0, taint())); // $ hasValueFlow sink(ArrayUtils.insert(IntSource.taint(), clean, "value1", "value2")); // Index argument does not contribute taint - sink(ArrayUtils.insert(0, alreadyTainted, "value1", "value2")); // $hasTaintFlow - sink(ArrayUtils.insert(0, clean, taint(), "value2")); // $hasTaintFlow - sink(ArrayUtils.insert(0, clean, "value1", taint())); // $hasTaintFlow - sink(ArrayUtils.nullToEmpty(alreadyTainted)); // $hasTaintFlow - sink(ArrayUtils.nullToEmpty(alreadyTainted, String[].class)); // $hasTaintFlow - sink(ArrayUtils.remove(alreadyTainted, 0)); // $hasTaintFlow + sink(ArrayUtils.insert(0, alreadyTainted, "value1", "value2")); // $ hasTaintFlow + sink(ArrayUtils.insert(0, clean, taint(), "value2")); // $ hasTaintFlow + sink(ArrayUtils.insert(0, clean, "value1", taint())); // $ hasTaintFlow + sink(ArrayUtils.nullToEmpty(alreadyTainted)); // $ hasTaintFlow + sink(ArrayUtils.nullToEmpty(alreadyTainted, String[].class)); // $ hasTaintFlow + sink(ArrayUtils.remove(alreadyTainted, 0)); // $ hasTaintFlow sink(ArrayUtils.remove(clean, IntSource.taint())); // Index argument does not contribute taint - sink(ArrayUtils.removeAll(alreadyTainted, 0, 1)); // $hasTaintFlow + sink(ArrayUtils.removeAll(alreadyTainted, 0, 1)); // $ hasTaintFlow sink(ArrayUtils.removeAll(clean, IntSource.taint(), 1)); // Index argument does not contribute taint sink(ArrayUtils.removeAll(clean, 0, IntSource.taint())); // Index argument does not contribute taint sink(ArrayUtils.removeAllOccurences(clean, taint())); // Removed argument does not contribute taint - sink(ArrayUtils.removeAllOccurences(alreadyTainted, "value to remove")); // $hasTaintFlow + sink(ArrayUtils.removeAllOccurences(alreadyTainted, "value to remove")); // $ hasTaintFlow sink(ArrayUtils.removeAllOccurrences(clean, taint())); // Removed argument does not contribute taint - sink(ArrayUtils.removeAllOccurrences(alreadyTainted, "value to remove")); // $hasTaintFlow + sink(ArrayUtils.removeAllOccurrences(alreadyTainted, "value to remove")); // $ hasTaintFlow sink(ArrayUtils.removeElement(clean, taint())); // Removed argument does not contribute taint - sink(ArrayUtils.removeElement(alreadyTainted, "value to remove")); // $hasTaintFlow - sink(ArrayUtils.removeElements(alreadyTainted, 0, 1)); // $hasTaintFlow + sink(ArrayUtils.removeElement(alreadyTainted, "value to remove")); // $ hasTaintFlow + sink(ArrayUtils.removeElements(alreadyTainted, 0, 1)); // $ hasTaintFlow sink(ArrayUtils.removeElements(clean, IntSource.taint(), 1)); // Index argument does not contribute taint sink(ArrayUtils.removeElements(clean, 0, IntSource.taint())); // Index argument does not contribute taint - sink(ArrayUtils.subarray(alreadyTainted, 0, 0)); // $hasTaintFlow + sink(ArrayUtils.subarray(alreadyTainted, 0, 0)); // $ hasTaintFlow sink(ArrayUtils.subarray(clean, IntSource.taint(), IntSource.taint())); // Index arguments do not contribute taint - sink(ArrayUtils.toArray("clean", taint())); // $hasTaintFlow - sink(ArrayUtils.toArray(taint(), "clean")); // $hasTaintFlow - sink(ArrayUtils.toMap(alreadyTainted).get("key")); // $hasTaintFlow + sink(ArrayUtils.toArray("clean", taint())); // $ hasTaintFlow + sink(ArrayUtils.toArray(taint(), "clean")); // $ hasTaintFlow + sink(ArrayUtils.toMap(alreadyTainted).get("key")); // $ hasTaintFlow // Check that none of the above had an effect on `clean`: sink(clean); int[] taintedInts = new int[] { IntSource.taint() }; Integer[] taintedBoxedInts = ArrayUtils.toObject(taintedInts); - sink(taintedBoxedInts); // $hasTaintFlow - sink(ArrayUtils.toPrimitive(taintedBoxedInts)); // $hasTaintFlow - sink(ArrayUtils.toPrimitive(new Integer[] {}, IntSource.taint())); // $hasTaintFlow + sink(taintedBoxedInts); // $ hasTaintFlow + sink(ArrayUtils.toPrimitive(taintedBoxedInts)); // $ hasTaintFlow + sink(ArrayUtils.toPrimitive(new Integer[] {}, IntSource.taint())); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/MutableTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/MutableTest.java index 76db0fee0e74..30332dcc5f74 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/MutableTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/MutableTest.java @@ -17,14 +17,14 @@ void test() throws Exception { Mutable taintSetAlias = taintSet; Mutable taintClearedAlias = taintCleared; - sink(tainted.getValue()); // $hasValueFlow - sink(taintedAlias.getValue()); // $hasValueFlow - sink(taintSet.getValue()); // $hasValueFlow - sink(taintSetAlias.getValue()); // $hasValueFlow + sink(tainted.getValue()); // $ hasValueFlow + sink(taintedAlias.getValue()); // $ hasValueFlow + sink(taintSet.getValue()); // $ hasValueFlow + sink(taintSetAlias.getValue()); // $ hasValueFlow // These two cases don't work currently because synthetic fields are always weakly updated, // so no taint clearing takes place. - sink(taintCleared.getValue()); // $SPURIOUS: hasValueFlow - sink(taintClearedAlias.getValue()); // $SPURIOUS: hasValueFlow + sink(taintCleared.getValue()); // $ SPURIOUS: hasValueFlow + sink(taintClearedAlias.getValue()); // $ SPURIOUS: hasValueFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/ObjectUtilsTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/ObjectUtilsTest.java index 5b2eda3c30f5..6239bfb271da 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/ObjectUtilsTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/ObjectUtilsTest.java @@ -10,17 +10,17 @@ private static class IntSource { void sink(Object o) {} void test() throws Exception { - sink(ObjectUtils.clone(taint())); // $hasValueFlow - sink(ObjectUtils.cloneIfPossible(taint())); // $hasValueFlow - sink(ObjectUtils.CONST(taint())); // $hasValueFlow - sink(ObjectUtils.CONST_SHORT(IntSource.taint())); // $hasValueFlow - sink(ObjectUtils.CONST_BYTE(IntSource.taint())); // $hasValueFlow - sink(ObjectUtils.defaultIfNull(taint(), null)); // $hasValueFlow - sink(ObjectUtils.defaultIfNull(null, taint())); // $hasValueFlow + sink(ObjectUtils.clone(taint())); // $ hasValueFlow + sink(ObjectUtils.cloneIfPossible(taint())); // $ hasValueFlow + sink(ObjectUtils.CONST(taint())); // $ hasValueFlow + sink(ObjectUtils.CONST_SHORT(IntSource.taint())); // $ hasValueFlow + sink(ObjectUtils.CONST_BYTE(IntSource.taint())); // $ hasValueFlow + sink(ObjectUtils.defaultIfNull(taint(), null)); // $ hasValueFlow + sink(ObjectUtils.defaultIfNull(null, taint())); // $ hasValueFlow sink(ObjectUtils.firstNonNull(taint(), null, null)); // $ hasValueFlow sink(ObjectUtils.firstNonNull(null, taint(), null)); // $ hasValueFlow sink(ObjectUtils.firstNonNull(null, null, taint())); // $ hasValueFlow - sink(ObjectUtils.getIfNull(taint(), null)); // $hasValueFlow + sink(ObjectUtils.getIfNull(taint(), null)); // $ hasValueFlow sink(ObjectUtils.max(taint(), null, null)); // $ hasValueFlow sink(ObjectUtils.max(null, taint(), null)); // $ hasValueFlow sink(ObjectUtils.max(null, null, taint())); // $ hasValueFlow @@ -33,9 +33,9 @@ void test() throws Exception { sink(ObjectUtils.mode(taint(), null, null)); // $ hasValueFlow sink(ObjectUtils.mode(null, taint(), null)); // $ hasValueFlow sink(ObjectUtils.mode(null, null, taint())); // $ hasValueFlow - sink(ObjectUtils.requireNonEmpty(taint(), "message")); // $hasValueFlow + sink(ObjectUtils.requireNonEmpty(taint(), "message")); // $ hasValueFlow sink(ObjectUtils.requireNonEmpty("not null", taint())); // GOOD (message doesn't propagate to the return) sink(ObjectUtils.toString(taint(), "default string")); // GOOD (first argument is stringified) - sink(ObjectUtils.toString(null, taint())); // $hasValueFlow + sink(ObjectUtils.toString(null, taint())); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java index 6db15beb1816..a3a25326191e 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/PairTest.java @@ -25,60 +25,60 @@ void test() throws Exception { ImmutablePair taintedRight4 = new ImmutablePair("clean-left", taint()); // Check flow through ImmutablePairs: - sink(taintedLeft.getLeft()); // $hasValueFlow + sink(taintedLeft.getLeft()); // $ hasValueFlow sink(taintedLeft.getRight()); - sink(taintedLeft.getKey()); // $hasValueFlow + sink(taintedLeft.getKey()); // $ hasValueFlow sink(taintedLeft.getValue()); - sink(taintedLeft.left); // $hasValueFlow + sink(taintedLeft.left); // $ hasValueFlow sink(taintedLeft.right); sink(taintedRight.getLeft()); - sink(taintedRight.getRight()); // $hasValueFlow + sink(taintedRight.getRight()); // $ hasValueFlow sink(taintedRight.getKey()); - sink(taintedRight.getValue()); // $hasValueFlow + sink(taintedRight.getValue()); // $ hasValueFlow sink(taintedRight.left); - sink(taintedRight.right); // $hasValueFlow - sink(taintedLeft2.getLeft()); // $hasValueFlow + sink(taintedRight.right); // $ hasValueFlow + sink(taintedLeft2.getLeft()); // $ hasValueFlow sink(taintedLeft2.getRight()); - sink(taintedLeft2.getKey()); // $hasValueFlow + sink(taintedLeft2.getKey()); // $ hasValueFlow sink(taintedLeft2.getValue()); - sink(taintedLeft2.left); // $hasValueFlow + sink(taintedLeft2.left); // $ hasValueFlow sink(taintedLeft2.right); sink(taintedRight2.getLeft()); - sink(taintedRight2.getRight()); // $hasValueFlow + sink(taintedRight2.getRight()); // $ hasValueFlow sink(taintedRight2.getKey()); - sink(taintedRight2.getValue()); // $hasValueFlow + sink(taintedRight2.getValue()); // $ hasValueFlow sink(taintedRight2.left); - sink(taintedRight2.right); // $hasValueFlow - sink(taintedLeft3.getLeft()); // $hasValueFlow + sink(taintedRight2.right); // $ hasValueFlow + sink(taintedLeft3.getLeft()); // $ hasValueFlow sink(taintedLeft3.getRight()); - sink(taintedLeft3.getKey()); // $hasValueFlow + sink(taintedLeft3.getKey()); // $ hasValueFlow sink(taintedLeft3.getValue()); sink(taintedRight3.getLeft()); - sink(taintedRight3.getRight()); // $hasValueFlow + sink(taintedRight3.getRight()); // $ hasValueFlow sink(taintedRight3.getKey()); - sink(taintedRight3.getValue()); // $hasValueFlow - sink(taintedLeft4.getLeft()); // $hasValueFlow + sink(taintedRight3.getValue()); // $ hasValueFlow + sink(taintedLeft4.getLeft()); // $ hasValueFlow sink(taintedLeft4.getRight()); - sink(taintedLeft4.getKey()); // $hasValueFlow + sink(taintedLeft4.getKey()); // $ hasValueFlow sink(taintedLeft4.getValue()); - sink(taintedLeft4.left); // $hasValueFlow + sink(taintedLeft4.left); // $ hasValueFlow sink(taintedLeft4.right); sink(taintedRight4.getLeft()); - sink(taintedRight4.getRight()); // $hasValueFlow + sink(taintedRight4.getRight()); // $ hasValueFlow sink(taintedRight4.getKey()); - sink(taintedRight4.getValue()); // $hasValueFlow + sink(taintedRight4.getValue()); // $ hasValueFlow sink(taintedRight4.left); - sink(taintedRight4.right); // $hasValueFlow + sink(taintedRight4.right); // $ hasValueFlow // Check flow also works via an alias of type Pair: - sink(taintedLeft2_.getLeft()); // $hasValueFlow + sink(taintedLeft2_.getLeft()); // $ hasValueFlow sink(taintedLeft2_.getRight()); - sink(taintedLeft2_.getKey()); // $hasValueFlow + sink(taintedLeft2_.getKey()); // $ hasValueFlow sink(taintedLeft2_.getValue()); sink(taintedRight2_.getLeft()); - sink(taintedRight2_.getRight()); // $hasValueFlow + sink(taintedRight2_.getRight()); // $ hasValueFlow sink(taintedRight2_.getKey()); - sink(taintedRight2_.getValue()); // $hasValueFlow + sink(taintedRight2_.getValue()); // $ hasValueFlow // Check flow through MutablePairs: MutablePair taintedLeftMutable = MutablePair.of(taint(), "clean-right"); @@ -92,59 +92,59 @@ void test() throws Exception { MutablePair taintedLeftMutableConstructed = new MutablePair(taint(), "clean-right"); MutablePair taintedRightMutableConstructed = new MutablePair("clean-left", taint()); - sink(taintedLeftMutable.getLeft()); // $hasValueFlow + sink(taintedLeftMutable.getLeft()); // $ hasValueFlow sink(taintedLeftMutable.getRight()); - sink(taintedLeftMutable.getKey()); // $hasValueFlow + sink(taintedLeftMutable.getKey()); // $ hasValueFlow sink(taintedLeftMutable.getValue()); - sink(taintedLeftMutable.left); // $hasValueFlow + sink(taintedLeftMutable.left); // $ hasValueFlow sink(taintedLeftMutable.right); sink(taintedRightMutable.getLeft()); - sink(taintedRightMutable.getRight()); // $hasValueFlow + sink(taintedRightMutable.getRight()); // $ hasValueFlow sink(taintedRightMutable.getKey()); - sink(taintedRightMutable.getValue()); // $hasValueFlow + sink(taintedRightMutable.getValue()); // $ hasValueFlow sink(taintedRightMutable.left); - sink(taintedRightMutable.right); // $hasValueFlow - sink(setTaintLeft.getLeft()); // $hasValueFlow + sink(taintedRightMutable.right); // $ hasValueFlow + sink(setTaintLeft.getLeft()); // $ hasValueFlow sink(setTaintLeft.getRight()); - sink(setTaintLeft.getKey()); // $hasValueFlow + sink(setTaintLeft.getKey()); // $ hasValueFlow sink(setTaintLeft.getValue()); - sink(setTaintLeft.left); // $hasValueFlow + sink(setTaintLeft.left); // $ hasValueFlow sink(setTaintLeft.right); sink(setTaintRight.getLeft()); - sink(setTaintRight.getRight()); // $hasValueFlow + sink(setTaintRight.getRight()); // $ hasValueFlow sink(setTaintRight.getKey()); - sink(setTaintRight.getValue()); // $hasValueFlow + sink(setTaintRight.getValue()); // $ hasValueFlow sink(setTaintRight.left); - sink(setTaintRight.right); // $hasValueFlow + sink(setTaintRight.right); // $ hasValueFlow sink(setTaintValue.getLeft()); - sink(setTaintValue.getRight()); // $hasValueFlow + sink(setTaintValue.getRight()); // $ hasValueFlow sink(setTaintValue.getKey()); - sink(setTaintValue.getValue()); // $hasValueFlow + sink(setTaintValue.getValue()); // $ hasValueFlow sink(setTaintValue.left); - sink(setTaintValue.right); // $hasValueFlow - sink(taintedLeftMutableConstructed.getLeft()); // $hasValueFlow + sink(setTaintValue.right); // $ hasValueFlow + sink(taintedLeftMutableConstructed.getLeft()); // $ hasValueFlow sink(taintedLeftMutableConstructed.getRight()); - sink(taintedLeftMutableConstructed.getKey()); // $hasValueFlow + sink(taintedLeftMutableConstructed.getKey()); // $ hasValueFlow sink(taintedLeftMutableConstructed.getValue()); - sink(taintedLeftMutableConstructed.left); // $hasValueFlow + sink(taintedLeftMutableConstructed.left); // $ hasValueFlow sink(taintedLeftMutableConstructed.right); sink(taintedRightMutableConstructed.getLeft()); - sink(taintedRightMutableConstructed.getRight()); // $hasValueFlow + sink(taintedRightMutableConstructed.getRight()); // $ hasValueFlow sink(taintedRightMutableConstructed.getKey()); - sink(taintedRightMutableConstructed.getValue()); // $hasValueFlow + sink(taintedRightMutableConstructed.getValue()); // $ hasValueFlow sink(taintedRightMutableConstructed.left); - sink(taintedRightMutableConstructed.right); // $hasValueFlow + sink(taintedRightMutableConstructed.right); // $ hasValueFlow // Check flow also works via an alias of type Pair: Pair taintedLeftMutableAlias = taintedLeftMutable; Pair taintedRightMutableAlias = taintedRightMutable; - sink(taintedLeftMutableAlias.getLeft()); // $hasValueFlow + sink(taintedLeftMutableAlias.getLeft()); // $ hasValueFlow sink(taintedLeftMutableAlias.getRight()); - sink(taintedLeftMutableAlias.getKey()); // $hasValueFlow + sink(taintedLeftMutableAlias.getKey()); // $ hasValueFlow sink(taintedLeftMutableAlias.getValue()); sink(taintedRightMutableAlias.getLeft()); - sink(taintedRightMutableAlias.getRight()); // $hasValueFlow + sink(taintedRightMutableAlias.getRight()); // $ hasValueFlow sink(taintedRightMutableAlias.getKey()); - sink(taintedRightMutableAlias.getValue()); // $hasValueFlow + sink(taintedRightMutableAlias.getValue()); // $ hasValueFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/RegExUtilsTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/RegExUtilsTest.java index 59db473d886c..7e99dd2813bc 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/RegExUtilsTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/RegExUtilsTest.java @@ -10,21 +10,21 @@ void test() throws Exception { Pattern cleanPattern = Pattern.compile("clean"); Pattern taintedPattern = Pattern.compile(taint()); - sink(RegExUtils.removeAll(taint(), cleanPattern)); // $hasTaintFlow - sink(RegExUtils.removeAll(taint(), "clean")); // $hasTaintFlow - sink(RegExUtils.removeFirst(taint(), cleanPattern)); // $hasTaintFlow - sink(RegExUtils.removeFirst(taint(), "clean")); // $hasTaintFlow - sink(RegExUtils.removePattern(taint(), "clean")); // $hasTaintFlow - sink(RegExUtils.replaceAll(taint(), cleanPattern, "replacement")); // $hasTaintFlow - sink(RegExUtils.replaceAll(taint(), "clean", "replacement")); // $hasTaintFlow - sink(RegExUtils.replaceFirst(taint(), cleanPattern, "replacement")); // $hasTaintFlow - sink(RegExUtils.replaceFirst(taint(), "clean", "replacement")); // $hasTaintFlow - sink(RegExUtils.replacePattern(taint(), "clean", "replacement")); // $hasTaintFlow - sink(RegExUtils.replaceAll("original", cleanPattern, taint())); // $hasTaintFlow - sink(RegExUtils.replaceAll("original", "clean", taint())); // $hasTaintFlow - sink(RegExUtils.replaceFirst("original", cleanPattern, taint())); // $hasTaintFlow - sink(RegExUtils.replaceFirst("original", "clean", taint())); // $hasTaintFlow - sink(RegExUtils.replacePattern("original", "clean", taint())); // $hasTaintFlow + sink(RegExUtils.removeAll(taint(), cleanPattern)); // $ hasTaintFlow + sink(RegExUtils.removeAll(taint(), "clean")); // $ hasTaintFlow + sink(RegExUtils.removeFirst(taint(), cleanPattern)); // $ hasTaintFlow + sink(RegExUtils.removeFirst(taint(), "clean")); // $ hasTaintFlow + sink(RegExUtils.removePattern(taint(), "clean")); // $ hasTaintFlow + sink(RegExUtils.replaceAll(taint(), cleanPattern, "replacement")); // $ hasTaintFlow + sink(RegExUtils.replaceAll(taint(), "clean", "replacement")); // $ hasTaintFlow + sink(RegExUtils.replaceFirst(taint(), cleanPattern, "replacement")); // $ hasTaintFlow + sink(RegExUtils.replaceFirst(taint(), "clean", "replacement")); // $ hasTaintFlow + sink(RegExUtils.replacePattern(taint(), "clean", "replacement")); // $ hasTaintFlow + sink(RegExUtils.replaceAll("original", cleanPattern, taint())); // $ hasTaintFlow + sink(RegExUtils.replaceAll("original", "clean", taint())); // $ hasTaintFlow + sink(RegExUtils.replaceFirst("original", cleanPattern, taint())); // $ hasTaintFlow + sink(RegExUtils.replaceFirst("original", "clean", taint())); // $ hasTaintFlow + sink(RegExUtils.replacePattern("original", "clean", taint())); // $ hasTaintFlow // Subsequent calls don't propagate taint, as regex search patterns don't propagate to the return value. sink(RegExUtils.removeAll("original", taintedPattern)); sink(RegExUtils.removeAll("original", taint())); @@ -42,4 +42,4 @@ void test() throws Exception { sink(RegExUtils.replaceFirst("original", taint(), "replacement")); sink(RegExUtils.replacePattern("original", taint(), "replacement")); } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java index fe197b4f264d..e402638655d2 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java @@ -14,134 +14,134 @@ void sink(Object o) {} void test() throws Exception { - StrBuilder cons1 = new StrBuilder(taint()); sink(cons1.toString()); // $hasTaintFlow + StrBuilder cons1 = new StrBuilder(taint()); sink(cons1.toString()); // $ hasTaintFlow - StrBuilder sb1 = new StrBuilder(); sb1.append(taint().toCharArray()); sink(sb1.toString()); // $hasTaintFlow - StrBuilder sb2 = new StrBuilder(); sb2.append(taint().toCharArray(), 0, 0); sink(sb2.toString()); // $hasTaintFlow + StrBuilder sb1 = new StrBuilder(); sb1.append(taint().toCharArray()); sink(sb1.toString()); // $ hasTaintFlow + StrBuilder sb2 = new StrBuilder(); sb2.append(taint().toCharArray(), 0, 0); sink(sb2.toString()); // $ hasTaintFlow StrBuilder sb3 = new StrBuilder(); sb3.append(CharBuffer.wrap(taint().toCharArray())); sink(sb3.toString()); // $ hasTaintFlow StrBuilder sb4 = new StrBuilder(); sb4.append(CharBuffer.wrap(taint().toCharArray()), 0, 0); sink(sb4.toString()); // $ hasTaintFlow - StrBuilder sb5 = new StrBuilder(); sb5.append((CharSequence)taint()); sink(sb5.toString()); // $hasTaintFlow - StrBuilder sb6 = new StrBuilder(); sb6.append((CharSequence)taint(), 0, 0); sink(sb6.toString()); // $hasTaintFlow - StrBuilder sb7 = new StrBuilder(); sb7.append((Object)taint()); sink(sb7.toString()); // $hasTaintFlow + StrBuilder sb5 = new StrBuilder(); sb5.append((CharSequence)taint()); sink(sb5.toString()); // $ hasTaintFlow + StrBuilder sb6 = new StrBuilder(); sb6.append((CharSequence)taint(), 0, 0); sink(sb6.toString()); // $ hasTaintFlow + StrBuilder sb7 = new StrBuilder(); sb7.append((Object)taint()); sink(sb7.toString()); // $ hasTaintFlow { StrBuilder auxsb = new StrBuilder(); auxsb.append(taint()); - StrBuilder sb8 = new StrBuilder(); sb8.append(auxsb); sink(sb8.toString()); // $hasTaintFlow + StrBuilder sb8 = new StrBuilder(); sb8.append(auxsb); sink(sb8.toString()); // $ hasTaintFlow } - StrBuilder sb9 = new StrBuilder(); sb9.append(new StringBuffer(taint())); sink(sb9.toString()); // $hasTaintFlow - StrBuilder sb10 = new StrBuilder(); sb10.append(new StringBuffer(taint()), 0, 0); sink(sb10.toString()); // $hasTaintFlow - StrBuilder sb11 = new StrBuilder(); sb11.append(new StringBuilder(taint())); sink(sb11.toString()); // $hasTaintFlow - StrBuilder sb12 = new StrBuilder(); sb12.append(new StringBuilder(taint()), 0, 0); sink(sb12.toString()); // $hasTaintFlow - StrBuilder sb13 = new StrBuilder(); sb13.append(taint()); sink(sb13.toString()); // $hasTaintFlow - StrBuilder sb14 = new StrBuilder(); sb14.append(taint(), 0, 0); sink(sb14.toString()); // $hasTaintFlow - StrBuilder sb15 = new StrBuilder(); sb15.append(taint(), "format", "args"); sink(sb15.toString()); // $hasTaintFlow - StrBuilder sb16 = new StrBuilder(); sb16.append("Format string", taint(), "args"); sink(sb16.toString()); // $hasTaintFlow + StrBuilder sb9 = new StrBuilder(); sb9.append(new StringBuffer(taint())); sink(sb9.toString()); // $ hasTaintFlow + StrBuilder sb10 = new StrBuilder(); sb10.append(new StringBuffer(taint()), 0, 0); sink(sb10.toString()); // $ hasTaintFlow + StrBuilder sb11 = new StrBuilder(); sb11.append(new StringBuilder(taint())); sink(sb11.toString()); // $ hasTaintFlow + StrBuilder sb12 = new StrBuilder(); sb12.append(new StringBuilder(taint()), 0, 0); sink(sb12.toString()); // $ hasTaintFlow + StrBuilder sb13 = new StrBuilder(); sb13.append(taint()); sink(sb13.toString()); // $ hasTaintFlow + StrBuilder sb14 = new StrBuilder(); sb14.append(taint(), 0, 0); sink(sb14.toString()); // $ hasTaintFlow + StrBuilder sb15 = new StrBuilder(); sb15.append(taint(), "format", "args"); sink(sb15.toString()); // $ hasTaintFlow + StrBuilder sb16 = new StrBuilder(); sb16.append("Format string", taint(), "args"); sink(sb16.toString()); // $ hasTaintFlow { List taintedList = new ArrayList<>(); taintedList.add(taint()); - StrBuilder sb17 = new StrBuilder(); sb17.appendAll(taintedList); sink(sb17.toString()); // $hasTaintFlow - StrBuilder sb18 = new StrBuilder(); sb18.appendAll(taintedList.iterator()); sink(sb18.toString()); // $hasTaintFlow + StrBuilder sb17 = new StrBuilder(); sb17.appendAll(taintedList); sink(sb17.toString()); // $ hasTaintFlow + StrBuilder sb18 = new StrBuilder(); sb18.appendAll(taintedList.iterator()); sink(sb18.toString()); // $ hasTaintFlow } - StrBuilder sb19 = new StrBuilder(); sb19.appendAll("clean", taint()); sink(sb19.toString()); // $hasTaintFlow - StrBuilder sb20 = new StrBuilder(); sb20.appendAll(taint(), "clean"); sink(sb20.toString()); // $hasTaintFlow - StrBuilder sb21 = new StrBuilder(); sb21.appendFixedWidthPadLeft(taint(), 0, ' '); sink(sb21.toString()); // $hasTaintFlow - StrBuilder sb22 = new StrBuilder(); sb22.appendFixedWidthPadRight(taint(), 0, ' '); sink(sb22.toString()); // $hasTaintFlow - StrBuilder sb23 = new StrBuilder(); sb23.appendln(taint().toCharArray()); sink(sb23.toString()); // $hasTaintFlow - StrBuilder sb24 = new StrBuilder(); sb24.appendln(taint().toCharArray(), 0, 0); sink(sb24.toString()); // $hasTaintFlow - StrBuilder sb25 = new StrBuilder(); sb25.appendln((Object)taint()); sink(sb25.toString()); // $hasTaintFlow + StrBuilder sb19 = new StrBuilder(); sb19.appendAll("clean", taint()); sink(sb19.toString()); // $ hasTaintFlow + StrBuilder sb20 = new StrBuilder(); sb20.appendAll(taint(), "clean"); sink(sb20.toString()); // $ hasTaintFlow + StrBuilder sb21 = new StrBuilder(); sb21.appendFixedWidthPadLeft(taint(), 0, ' '); sink(sb21.toString()); // $ hasTaintFlow + StrBuilder sb22 = new StrBuilder(); sb22.appendFixedWidthPadRight(taint(), 0, ' '); sink(sb22.toString()); // $ hasTaintFlow + StrBuilder sb23 = new StrBuilder(); sb23.appendln(taint().toCharArray()); sink(sb23.toString()); // $ hasTaintFlow + StrBuilder sb24 = new StrBuilder(); sb24.appendln(taint().toCharArray(), 0, 0); sink(sb24.toString()); // $ hasTaintFlow + StrBuilder sb25 = new StrBuilder(); sb25.appendln((Object)taint()); sink(sb25.toString()); // $ hasTaintFlow { StrBuilder auxsb = new StrBuilder(); auxsb.appendln(taint()); - StrBuilder sb26 = new StrBuilder(); sb26.appendln(auxsb); sink(sb26.toString()); // $hasTaintFlow + StrBuilder sb26 = new StrBuilder(); sb26.appendln(auxsb); sink(sb26.toString()); // $ hasTaintFlow } - StrBuilder sb27 = new StrBuilder(); sb27.appendln(new StringBuffer(taint())); sink(sb27.toString()); // $hasTaintFlow - StrBuilder sb28 = new StrBuilder(); sb28.appendln(new StringBuffer(taint()), 0, 0); sink(sb28.toString()); // $hasTaintFlow - StrBuilder sb29 = new StrBuilder(); sb29.appendln(new StringBuilder(taint())); sink(sb29.toString()); // $hasTaintFlow - StrBuilder sb30 = new StrBuilder(); sb30.appendln(new StringBuilder(taint()), 0, 0); sink(sb30.toString()); // $hasTaintFlow - StrBuilder sb31 = new StrBuilder(); sb31.appendln(taint()); sink(sb31.toString()); // $hasTaintFlow - StrBuilder sb32 = new StrBuilder(); sb32.appendln(taint(), 0, 0); sink(sb32.toString()); // $hasTaintFlow - StrBuilder sb33 = new StrBuilder(); sb33.appendln(taint(), "format", "args"); sink(sb33.toString()); // $hasTaintFlow - StrBuilder sb34 = new StrBuilder(); sb34.appendln("Format string", taint(), "args"); sink(sb34.toString()); // $hasTaintFlow - StrBuilder sb35 = new StrBuilder(); sb35.appendSeparator(taint()); sink(sb35.toString()); // $hasTaintFlow - StrBuilder sb36 = new StrBuilder(); sb36.appendSeparator(taint(), 0); sink(sb36.toString()); // $hasTaintFlow - StrBuilder sb37 = new StrBuilder(); sb37.appendSeparator(taint(), "default"); sink(sb37.toString()); // $hasTaintFlow - StrBuilder sb38 = new StrBuilder(); sb38.appendSeparator("", taint()); sink(sb38.toString()); // $hasTaintFlow + StrBuilder sb27 = new StrBuilder(); sb27.appendln(new StringBuffer(taint())); sink(sb27.toString()); // $ hasTaintFlow + StrBuilder sb28 = new StrBuilder(); sb28.appendln(new StringBuffer(taint()), 0, 0); sink(sb28.toString()); // $ hasTaintFlow + StrBuilder sb29 = new StrBuilder(); sb29.appendln(new StringBuilder(taint())); sink(sb29.toString()); // $ hasTaintFlow + StrBuilder sb30 = new StrBuilder(); sb30.appendln(new StringBuilder(taint()), 0, 0); sink(sb30.toString()); // $ hasTaintFlow + StrBuilder sb31 = new StrBuilder(); sb31.appendln(taint()); sink(sb31.toString()); // $ hasTaintFlow + StrBuilder sb32 = new StrBuilder(); sb32.appendln(taint(), 0, 0); sink(sb32.toString()); // $ hasTaintFlow + StrBuilder sb33 = new StrBuilder(); sb33.appendln(taint(), "format", "args"); sink(sb33.toString()); // $ hasTaintFlow + StrBuilder sb34 = new StrBuilder(); sb34.appendln("Format string", taint(), "args"); sink(sb34.toString()); // $ hasTaintFlow + StrBuilder sb35 = new StrBuilder(); sb35.appendSeparator(taint()); sink(sb35.toString()); // $ hasTaintFlow + StrBuilder sb36 = new StrBuilder(); sb36.appendSeparator(taint(), 0); sink(sb36.toString()); // $ hasTaintFlow + StrBuilder sb37 = new StrBuilder(); sb37.appendSeparator(taint(), "default"); sink(sb37.toString()); // $ hasTaintFlow + StrBuilder sb38 = new StrBuilder(); sb38.appendSeparator("", taint()); sink(sb38.toString()); // $ hasTaintFlow { StrBuilder auxsb = new StrBuilder(); auxsb.appendln(taint()); - StrBuilder sb39 = new StrBuilder(); auxsb.appendTo(sb39); sink(sb39.toString()); // $hasTaintFlow + StrBuilder sb39 = new StrBuilder(); auxsb.appendTo(sb39); sink(sb39.toString()); // $ hasTaintFlow } { List taintedList = new ArrayList<>(); taintedList.add(taint()); - StrBuilder sb40 = new StrBuilder(); sb40.appendWithSeparators(taintedList, ", "); sink(sb40.toString()); // $hasTaintFlow - StrBuilder sb41 = new StrBuilder(); sb41.appendWithSeparators(taintedList.iterator(), ", "); sink(sb41.toString()); // $hasTaintFlow + StrBuilder sb40 = new StrBuilder(); sb40.appendWithSeparators(taintedList, ", "); sink(sb40.toString()); // $ hasTaintFlow + StrBuilder sb41 = new StrBuilder(); sb41.appendWithSeparators(taintedList.iterator(), ", "); sink(sb41.toString()); // $ hasTaintFlow List untaintedList = new ArrayList<>(); - StrBuilder sb42 = new StrBuilder(); sb42.appendWithSeparators(untaintedList, taint()); sink(sb42.toString()); // $hasTaintFlow - StrBuilder sb43 = new StrBuilder(); sb43.appendWithSeparators(untaintedList.iterator(), taint()); sink(sb43.toString()); // $hasTaintFlow + StrBuilder sb42 = new StrBuilder(); sb42.appendWithSeparators(untaintedList, taint()); sink(sb42.toString()); // $ hasTaintFlow + StrBuilder sb43 = new StrBuilder(); sb43.appendWithSeparators(untaintedList.iterator(), taint()); sink(sb43.toString()); // $ hasTaintFlow String[] taintedArray = new String[] { taint() }; String[] untaintedArray = new String[] {}; - StrBuilder sb44 = new StrBuilder(); sb44.appendWithSeparators(taintedArray, ", "); sink(sb44.toString()); // $hasTaintFlow - StrBuilder sb45 = new StrBuilder(); sb45.appendWithSeparators(untaintedArray, taint()); sink(sb45.toString()); // $hasTaintFlow + StrBuilder sb44 = new StrBuilder(); sb44.appendWithSeparators(taintedArray, ", "); sink(sb44.toString()); // $ hasTaintFlow + StrBuilder sb45 = new StrBuilder(); sb45.appendWithSeparators(untaintedArray, taint()); sink(sb45.toString()); // $ hasTaintFlow } { StrBuilder sb46 = new StrBuilder(); sb46.append(taint()); char[] target = new char[100]; sb46.asReader().read(target); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } - StrBuilder sb47 = new StrBuilder(); sb47.append(taint()); sink(sb47.asTokenizer().next()); // $hasTaintFlow - StrBuilder sb48 = new StrBuilder(); sb48.append(taint()); sink(sb48.build()); // $hasTaintFlow - StrBuilder sb49 = new StrBuilder(); sb49.append(taint()); sink(sb49.getChars(null)); // $hasTaintFlow + StrBuilder sb47 = new StrBuilder(); sb47.append(taint()); sink(sb47.asTokenizer().next()); // $ hasTaintFlow + StrBuilder sb48 = new StrBuilder(); sb48.append(taint()); sink(sb48.build()); // $ hasTaintFlow + StrBuilder sb49 = new StrBuilder(); sb49.append(taint()); sink(sb49.getChars(null)); // $ hasTaintFlow { StrBuilder sb50 = new StrBuilder(); sb50.append(taint()); char[] target = new char[100]; sb50.getChars(target); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } { StrBuilder sb51 = new StrBuilder(); sb51.append(taint()); char[] target = new char[100]; sb51.getChars(0, 0, target, 0); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } - StrBuilder sb52 = new StrBuilder(); sb52.insert(0, taint().toCharArray()); sink(sb52.toString()); // $hasTaintFlow - StrBuilder sb53 = new StrBuilder(); sb53.insert(0, taint().toCharArray(), 0, 0); sink(sb53.toString()); // $hasTaintFlow - StrBuilder sb54 = new StrBuilder(); sb54.insert(0, taint()); sink(sb54.toString()); // $hasTaintFlow - StrBuilder sb55 = new StrBuilder(); sb55.insert(0, (Object)taint()); sink(sb55.toString()); // $hasTaintFlow - StrBuilder sb56 = new StrBuilder(); sb56.append(taint()); sink(sb56.leftString(0)); // $hasTaintFlow - StrBuilder sb57 = new StrBuilder(); sb57.append(taint()); sink(sb57.midString(0, 0)); // $hasTaintFlow + StrBuilder sb52 = new StrBuilder(); sb52.insert(0, taint().toCharArray()); sink(sb52.toString()); // $ hasTaintFlow + StrBuilder sb53 = new StrBuilder(); sb53.insert(0, taint().toCharArray(), 0, 0); sink(sb53.toString()); // $ hasTaintFlow + StrBuilder sb54 = new StrBuilder(); sb54.insert(0, taint()); sink(sb54.toString()); // $ hasTaintFlow + StrBuilder sb55 = new StrBuilder(); sb55.insert(0, (Object)taint()); sink(sb55.toString()); // $ hasTaintFlow + StrBuilder sb56 = new StrBuilder(); sb56.append(taint()); sink(sb56.leftString(0)); // $ hasTaintFlow + StrBuilder sb57 = new StrBuilder(); sb57.append(taint()); sink(sb57.midString(0, 0)); // $ hasTaintFlow { StringReader reader = new StringReader(taint()); - StrBuilder sb58 = new StrBuilder(); sb58.readFrom(reader); sink(sb58.toString()); // $hasTaintFlow + StrBuilder sb58 = new StrBuilder(); sb58.readFrom(reader); sink(sb58.toString()); // $ hasTaintFlow } - StrBuilder sb59 = new StrBuilder(); sb59.replace(0, 0, taint()); sink(sb59.toString()); // $hasTaintFlow - StrBuilder sb60 = new StrBuilder(); sb60.replace(null, taint(), 0, 0, 0); sink(sb60.toString()); // $hasTaintFlow - StrBuilder sb61 = new StrBuilder(); sb61.replaceAll((StrMatcher)null, taint()); sink(sb61.toString()); // $hasTaintFlow - StrBuilder sb62 = new StrBuilder(); sb62.replaceAll("search", taint()); sink(sb62.toString()); // $hasTaintFlow + StrBuilder sb59 = new StrBuilder(); sb59.replace(0, 0, taint()); sink(sb59.toString()); // $ hasTaintFlow + StrBuilder sb60 = new StrBuilder(); sb60.replace(null, taint(), 0, 0, 0); sink(sb60.toString()); // $ hasTaintFlow + StrBuilder sb61 = new StrBuilder(); sb61.replaceAll((StrMatcher)null, taint()); sink(sb61.toString()); // $ hasTaintFlow + StrBuilder sb62 = new StrBuilder(); sb62.replaceAll("search", taint()); sink(sb62.toString()); // $ hasTaintFlow StrBuilder sb63 = new StrBuilder(); sb63.replaceAll(taint(), "replace"); sink(sb63.toString()); // GOOD (search string doesn't convey taint) - StrBuilder sb64 = new StrBuilder(); sb64.replaceFirst((StrMatcher)null, taint()); sink(sb64.toString()); // $hasTaintFlow - StrBuilder sb65 = new StrBuilder(); sb65.replaceFirst("search", taint()); sink(sb65.toString()); // $hasTaintFlow + StrBuilder sb64 = new StrBuilder(); sb64.replaceFirst((StrMatcher)null, taint()); sink(sb64.toString()); // $ hasTaintFlow + StrBuilder sb65 = new StrBuilder(); sb65.replaceFirst("search", taint()); sink(sb65.toString()); // $ hasTaintFlow StrBuilder sb66 = new StrBuilder(); sb66.replaceFirst(taint(), "replace"); sink(sb66.toString()); // GOOD (search string doesn't convey taint) - StrBuilder sb67 = new StrBuilder(); sb67.append(taint()); sink(sb67.rightString(0)); // $hasTaintFlow - StrBuilder sb68 = new StrBuilder(); sb68.append(taint()); sink(sb68.subSequence(0, 0)); // $hasTaintFlow - StrBuilder sb69 = new StrBuilder(); sb69.append(taint()); sink(sb69.substring(0)); // $hasTaintFlow - StrBuilder sb70 = new StrBuilder(); sb70.append(taint()); sink(sb70.substring(0, 0)); // $hasTaintFlow - StrBuilder sb71 = new StrBuilder(); sb71.append(taint()); sink(sb71.toCharArray()); // $hasTaintFlow - StrBuilder sb72 = new StrBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $hasTaintFlow - StrBuilder sb73 = new StrBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $hasTaintFlow - StrBuilder sb74 = new StrBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $hasTaintFlow + StrBuilder sb67 = new StrBuilder(); sb67.append(taint()); sink(sb67.rightString(0)); // $ hasTaintFlow + StrBuilder sb68 = new StrBuilder(); sb68.append(taint()); sink(sb68.subSequence(0, 0)); // $ hasTaintFlow + StrBuilder sb69 = new StrBuilder(); sb69.append(taint()); sink(sb69.substring(0)); // $ hasTaintFlow + StrBuilder sb70 = new StrBuilder(); sb70.append(taint()); sink(sb70.substring(0, 0)); // $ hasTaintFlow + StrBuilder sb71 = new StrBuilder(); sb71.append(taint()); sink(sb71.toCharArray()); // $ hasTaintFlow + StrBuilder sb72 = new StrBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $ hasTaintFlow + StrBuilder sb73 = new StrBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $ hasTaintFlow + StrBuilder sb74 = new StrBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $ hasTaintFlow // Tests for fluent methods (those returning `this`): StrBuilder fluentTest = new StrBuilder(); - sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $hasTaintFlow + sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $ hasTaintFlow StrBuilder fluentBackflowTest = new StrBuilder(); fluentBackflowTest.append("Harmless").append(taint()).append("Also harmless"); - sink(fluentBackflowTest.toString()); // $hasTaintFlow + sink(fluentBackflowTest.toString()); // $ hasTaintFlow // Test the case where the fluent method contributing taint is at the end of a statement: StrBuilder fluentBackflowTest2 = new StrBuilder(); fluentBackflowTest2.append("Harmless").append(taint()); - sink(fluentBackflowTest2.toString()); // $hasTaintFlow + sink(fluentBackflowTest2.toString()); // $ hasTaintFlow // Test all fluent methods are passing taint through to their result: StrBuilder fluentAllMethodsTest = new StrBuilder(taint()); @@ -171,7 +171,7 @@ void test() throws Exception { .setLength(500) .setNewLineText("newline") .setNullText("NULL") - .trim()); // $hasTaintFlow + .trim()); // $ hasTaintFlow // Test all fluent methods are passing taint back to their qualifier: StrBuilder fluentAllMethodsTest2 = new StrBuilder(); @@ -203,7 +203,7 @@ void test() throws Exception { .setNullText("NULL") .trim() .append(taint()); - sink(fluentAllMethodsTest2); // $hasTaintFlow + sink(fluentAllMethodsTest2); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java index b3aa3ed9997b..ddb56e8d2e67 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java @@ -14,134 +14,134 @@ void sink(Object o) {} void test() throws Exception { - StrBuilder cons1 = new StrBuilder(taint()); sink(cons1.toString()); // $hasTaintFlow + StrBuilder cons1 = new StrBuilder(taint()); sink(cons1.toString()); // $ hasTaintFlow - StrBuilder sb1 = new StrBuilder(); sb1.append(taint().toCharArray()); sink(sb1.toString()); // $hasTaintFlow - StrBuilder sb2 = new StrBuilder(); sb2.append(taint().toCharArray(), 0, 0); sink(sb2.toString()); // $hasTaintFlow + StrBuilder sb1 = new StrBuilder(); sb1.append(taint().toCharArray()); sink(sb1.toString()); // $ hasTaintFlow + StrBuilder sb2 = new StrBuilder(); sb2.append(taint().toCharArray(), 0, 0); sink(sb2.toString()); // $ hasTaintFlow StrBuilder sb3 = new StrBuilder(); sb3.append(CharBuffer.wrap(taint().toCharArray())); sink(sb3.toString()); // $ hasTaintFlow StrBuilder sb4 = new StrBuilder(); sb4.append(CharBuffer.wrap(taint().toCharArray()), 0, 0); sink(sb4.toString()); // $ hasTaintFlow - StrBuilder sb5 = new StrBuilder(); sb5.append((CharSequence)taint()); sink(sb5.toString()); // $hasTaintFlow - StrBuilder sb6 = new StrBuilder(); sb6.append((CharSequence)taint(), 0, 0); sink(sb6.toString()); // $hasTaintFlow - StrBuilder sb7 = new StrBuilder(); sb7.append((Object)taint()); sink(sb7.toString()); // $hasTaintFlow + StrBuilder sb5 = new StrBuilder(); sb5.append((CharSequence)taint()); sink(sb5.toString()); // $ hasTaintFlow + StrBuilder sb6 = new StrBuilder(); sb6.append((CharSequence)taint(), 0, 0); sink(sb6.toString()); // $ hasTaintFlow + StrBuilder sb7 = new StrBuilder(); sb7.append((Object)taint()); sink(sb7.toString()); // $ hasTaintFlow { StrBuilder auxsb = new StrBuilder(); auxsb.append(taint()); - StrBuilder sb8 = new StrBuilder(); sb8.append(auxsb); sink(sb8.toString()); // $hasTaintFlow + StrBuilder sb8 = new StrBuilder(); sb8.append(auxsb); sink(sb8.toString()); // $ hasTaintFlow } - StrBuilder sb9 = new StrBuilder(); sb9.append(new StringBuffer(taint())); sink(sb9.toString()); // $hasTaintFlow - StrBuilder sb10 = new StrBuilder(); sb10.append(new StringBuffer(taint()), 0, 0); sink(sb10.toString()); // $hasTaintFlow - StrBuilder sb11 = new StrBuilder(); sb11.append(new StringBuilder(taint())); sink(sb11.toString()); // $hasTaintFlow - StrBuilder sb12 = new StrBuilder(); sb12.append(new StringBuilder(taint()), 0, 0); sink(sb12.toString()); // $hasTaintFlow - StrBuilder sb13 = new StrBuilder(); sb13.append(taint()); sink(sb13.toString()); // $hasTaintFlow - StrBuilder sb14 = new StrBuilder(); sb14.append(taint(), 0, 0); sink(sb14.toString()); // $hasTaintFlow - StrBuilder sb15 = new StrBuilder(); sb15.append(taint(), "format", "args"); sink(sb15.toString()); // $hasTaintFlow - StrBuilder sb16 = new StrBuilder(); sb16.append("Format string", taint(), "args"); sink(sb16.toString()); // $hasTaintFlow + StrBuilder sb9 = new StrBuilder(); sb9.append(new StringBuffer(taint())); sink(sb9.toString()); // $ hasTaintFlow + StrBuilder sb10 = new StrBuilder(); sb10.append(new StringBuffer(taint()), 0, 0); sink(sb10.toString()); // $ hasTaintFlow + StrBuilder sb11 = new StrBuilder(); sb11.append(new StringBuilder(taint())); sink(sb11.toString()); // $ hasTaintFlow + StrBuilder sb12 = new StrBuilder(); sb12.append(new StringBuilder(taint()), 0, 0); sink(sb12.toString()); // $ hasTaintFlow + StrBuilder sb13 = new StrBuilder(); sb13.append(taint()); sink(sb13.toString()); // $ hasTaintFlow + StrBuilder sb14 = new StrBuilder(); sb14.append(taint(), 0, 0); sink(sb14.toString()); // $ hasTaintFlow + StrBuilder sb15 = new StrBuilder(); sb15.append(taint(), "format", "args"); sink(sb15.toString()); // $ hasTaintFlow + StrBuilder sb16 = new StrBuilder(); sb16.append("Format string", taint(), "args"); sink(sb16.toString()); // $ hasTaintFlow { List taintedList = new ArrayList<>(); taintedList.add(taint()); - StrBuilder sb17 = new StrBuilder(); sb17.appendAll(taintedList); sink(sb17.toString()); // $hasTaintFlow - StrBuilder sb18 = new StrBuilder(); sb18.appendAll(taintedList.iterator()); sink(sb18.toString()); // $hasTaintFlow + StrBuilder sb17 = new StrBuilder(); sb17.appendAll(taintedList); sink(sb17.toString()); // $ hasTaintFlow + StrBuilder sb18 = new StrBuilder(); sb18.appendAll(taintedList.iterator()); sink(sb18.toString()); // $ hasTaintFlow } - StrBuilder sb19 = new StrBuilder(); sb19.appendAll("clean", taint()); sink(sb19.toString()); // $hasTaintFlow - StrBuilder sb20 = new StrBuilder(); sb20.appendAll(taint(), "clean"); sink(sb20.toString()); // $hasTaintFlow - StrBuilder sb21 = new StrBuilder(); sb21.appendFixedWidthPadLeft(taint(), 0, ' '); sink(sb21.toString()); // $hasTaintFlow - StrBuilder sb22 = new StrBuilder(); sb22.appendFixedWidthPadRight(taint(), 0, ' '); sink(sb22.toString()); // $hasTaintFlow - StrBuilder sb23 = new StrBuilder(); sb23.appendln(taint().toCharArray()); sink(sb23.toString()); // $hasTaintFlow - StrBuilder sb24 = new StrBuilder(); sb24.appendln(taint().toCharArray(), 0, 0); sink(sb24.toString()); // $hasTaintFlow - StrBuilder sb25 = new StrBuilder(); sb25.appendln((Object)taint()); sink(sb25.toString()); // $hasTaintFlow + StrBuilder sb19 = new StrBuilder(); sb19.appendAll("clean", taint()); sink(sb19.toString()); // $ hasTaintFlow + StrBuilder sb20 = new StrBuilder(); sb20.appendAll(taint(), "clean"); sink(sb20.toString()); // $ hasTaintFlow + StrBuilder sb21 = new StrBuilder(); sb21.appendFixedWidthPadLeft(taint(), 0, ' '); sink(sb21.toString()); // $ hasTaintFlow + StrBuilder sb22 = new StrBuilder(); sb22.appendFixedWidthPadRight(taint(), 0, ' '); sink(sb22.toString()); // $ hasTaintFlow + StrBuilder sb23 = new StrBuilder(); sb23.appendln(taint().toCharArray()); sink(sb23.toString()); // $ hasTaintFlow + StrBuilder sb24 = new StrBuilder(); sb24.appendln(taint().toCharArray(), 0, 0); sink(sb24.toString()); // $ hasTaintFlow + StrBuilder sb25 = new StrBuilder(); sb25.appendln((Object)taint()); sink(sb25.toString()); // $ hasTaintFlow { StrBuilder auxsb = new StrBuilder(); auxsb.appendln(taint()); - StrBuilder sb26 = new StrBuilder(); sb26.appendln(auxsb); sink(sb26.toString()); // $hasTaintFlow + StrBuilder sb26 = new StrBuilder(); sb26.appendln(auxsb); sink(sb26.toString()); // $ hasTaintFlow } - StrBuilder sb27 = new StrBuilder(); sb27.appendln(new StringBuffer(taint())); sink(sb27.toString()); // $hasTaintFlow - StrBuilder sb28 = new StrBuilder(); sb28.appendln(new StringBuffer(taint()), 0, 0); sink(sb28.toString()); // $hasTaintFlow - StrBuilder sb29 = new StrBuilder(); sb29.appendln(new StringBuilder(taint())); sink(sb29.toString()); // $hasTaintFlow - StrBuilder sb30 = new StrBuilder(); sb30.appendln(new StringBuilder(taint()), 0, 0); sink(sb30.toString()); // $hasTaintFlow - StrBuilder sb31 = new StrBuilder(); sb31.appendln(taint()); sink(sb31.toString()); // $hasTaintFlow - StrBuilder sb32 = new StrBuilder(); sb32.appendln(taint(), 0, 0); sink(sb32.toString()); // $hasTaintFlow - StrBuilder sb33 = new StrBuilder(); sb33.appendln(taint(), "format", "args"); sink(sb33.toString()); // $hasTaintFlow - StrBuilder sb34 = new StrBuilder(); sb34.appendln("Format string", taint(), "args"); sink(sb34.toString()); // $hasTaintFlow - StrBuilder sb35 = new StrBuilder(); sb35.appendSeparator(taint()); sink(sb35.toString()); // $hasTaintFlow - StrBuilder sb36 = new StrBuilder(); sb36.appendSeparator(taint(), 0); sink(sb36.toString()); // $hasTaintFlow - StrBuilder sb37 = new StrBuilder(); sb37.appendSeparator(taint(), "default"); sink(sb37.toString()); // $hasTaintFlow - StrBuilder sb38 = new StrBuilder(); sb38.appendSeparator("", taint()); sink(sb38.toString()); // $hasTaintFlow + StrBuilder sb27 = new StrBuilder(); sb27.appendln(new StringBuffer(taint())); sink(sb27.toString()); // $ hasTaintFlow + StrBuilder sb28 = new StrBuilder(); sb28.appendln(new StringBuffer(taint()), 0, 0); sink(sb28.toString()); // $ hasTaintFlow + StrBuilder sb29 = new StrBuilder(); sb29.appendln(new StringBuilder(taint())); sink(sb29.toString()); // $ hasTaintFlow + StrBuilder sb30 = new StrBuilder(); sb30.appendln(new StringBuilder(taint()), 0, 0); sink(sb30.toString()); // $ hasTaintFlow + StrBuilder sb31 = new StrBuilder(); sb31.appendln(taint()); sink(sb31.toString()); // $ hasTaintFlow + StrBuilder sb32 = new StrBuilder(); sb32.appendln(taint(), 0, 0); sink(sb32.toString()); // $ hasTaintFlow + StrBuilder sb33 = new StrBuilder(); sb33.appendln(taint(), "format", "args"); sink(sb33.toString()); // $ hasTaintFlow + StrBuilder sb34 = new StrBuilder(); sb34.appendln("Format string", taint(), "args"); sink(sb34.toString()); // $ hasTaintFlow + StrBuilder sb35 = new StrBuilder(); sb35.appendSeparator(taint()); sink(sb35.toString()); // $ hasTaintFlow + StrBuilder sb36 = new StrBuilder(); sb36.appendSeparator(taint(), 0); sink(sb36.toString()); // $ hasTaintFlow + StrBuilder sb37 = new StrBuilder(); sb37.appendSeparator(taint(), "default"); sink(sb37.toString()); // $ hasTaintFlow + StrBuilder sb38 = new StrBuilder(); sb38.appendSeparator("", taint()); sink(sb38.toString()); // $ hasTaintFlow { StrBuilder auxsb = new StrBuilder(); auxsb.appendln(taint()); - StrBuilder sb39 = new StrBuilder(); auxsb.appendTo(sb39); sink(sb39.toString()); // $hasTaintFlow + StrBuilder sb39 = new StrBuilder(); auxsb.appendTo(sb39); sink(sb39.toString()); // $ hasTaintFlow } { List taintedList = new ArrayList<>(); taintedList.add(taint()); - StrBuilder sb40 = new StrBuilder(); sb40.appendWithSeparators(taintedList, ", "); sink(sb40.toString()); // $hasTaintFlow - StrBuilder sb41 = new StrBuilder(); sb41.appendWithSeparators(taintedList.iterator(), ", "); sink(sb41.toString()); // $hasTaintFlow + StrBuilder sb40 = new StrBuilder(); sb40.appendWithSeparators(taintedList, ", "); sink(sb40.toString()); // $ hasTaintFlow + StrBuilder sb41 = new StrBuilder(); sb41.appendWithSeparators(taintedList.iterator(), ", "); sink(sb41.toString()); // $ hasTaintFlow List untaintedList = new ArrayList<>(); - StrBuilder sb42 = new StrBuilder(); sb42.appendWithSeparators(untaintedList, taint()); sink(sb42.toString()); // $hasTaintFlow - StrBuilder sb43 = new StrBuilder(); sb43.appendWithSeparators(untaintedList.iterator(), taint()); sink(sb43.toString()); // $hasTaintFlow + StrBuilder sb42 = new StrBuilder(); sb42.appendWithSeparators(untaintedList, taint()); sink(sb42.toString()); // $ hasTaintFlow + StrBuilder sb43 = new StrBuilder(); sb43.appendWithSeparators(untaintedList.iterator(), taint()); sink(sb43.toString()); // $ hasTaintFlow String[] taintedArray = new String[] { taint() }; String[] untaintedArray = new String[] {}; - StrBuilder sb44 = new StrBuilder(); sb44.appendWithSeparators(taintedArray, ", "); sink(sb44.toString()); // $hasTaintFlow - StrBuilder sb45 = new StrBuilder(); sb45.appendWithSeparators(untaintedArray, taint()); sink(sb45.toString()); // $hasTaintFlow + StrBuilder sb44 = new StrBuilder(); sb44.appendWithSeparators(taintedArray, ", "); sink(sb44.toString()); // $ hasTaintFlow + StrBuilder sb45 = new StrBuilder(); sb45.appendWithSeparators(untaintedArray, taint()); sink(sb45.toString()); // $ hasTaintFlow } { StrBuilder sb46 = new StrBuilder(); sb46.append(taint()); char[] target = new char[100]; sb46.asReader().read(target); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } - StrBuilder sb47 = new StrBuilder(); sb47.append(taint()); sink(sb47.asTokenizer().next()); // $hasTaintFlow - StrBuilder sb48 = new StrBuilder(); sb48.append(taint()); sink(sb48.build()); // $hasTaintFlow - StrBuilder sb49 = new StrBuilder(); sb49.append(taint()); sink(sb49.getChars(null)); // $hasTaintFlow + StrBuilder sb47 = new StrBuilder(); sb47.append(taint()); sink(sb47.asTokenizer().next()); // $ hasTaintFlow + StrBuilder sb48 = new StrBuilder(); sb48.append(taint()); sink(sb48.build()); // $ hasTaintFlow + StrBuilder sb49 = new StrBuilder(); sb49.append(taint()); sink(sb49.getChars(null)); // $ hasTaintFlow { StrBuilder sb50 = new StrBuilder(); sb50.append(taint()); char[] target = new char[100]; sb50.getChars(target); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } { StrBuilder sb51 = new StrBuilder(); sb51.append(taint()); char[] target = new char[100]; sb51.getChars(0, 0, target, 0); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } - StrBuilder sb52 = new StrBuilder(); sb52.insert(0, taint().toCharArray()); sink(sb52.toString()); // $hasTaintFlow - StrBuilder sb53 = new StrBuilder(); sb53.insert(0, taint().toCharArray(), 0, 0); sink(sb53.toString()); // $hasTaintFlow - StrBuilder sb54 = new StrBuilder(); sb54.insert(0, taint()); sink(sb54.toString()); // $hasTaintFlow - StrBuilder sb55 = new StrBuilder(); sb55.insert(0, (Object)taint()); sink(sb55.toString()); // $hasTaintFlow - StrBuilder sb56 = new StrBuilder(); sb56.append(taint()); sink(sb56.leftString(0)); // $hasTaintFlow - StrBuilder sb57 = new StrBuilder(); sb57.append(taint()); sink(sb57.midString(0, 0)); // $hasTaintFlow + StrBuilder sb52 = new StrBuilder(); sb52.insert(0, taint().toCharArray()); sink(sb52.toString()); // $ hasTaintFlow + StrBuilder sb53 = new StrBuilder(); sb53.insert(0, taint().toCharArray(), 0, 0); sink(sb53.toString()); // $ hasTaintFlow + StrBuilder sb54 = new StrBuilder(); sb54.insert(0, taint()); sink(sb54.toString()); // $ hasTaintFlow + StrBuilder sb55 = new StrBuilder(); sb55.insert(0, (Object)taint()); sink(sb55.toString()); // $ hasTaintFlow + StrBuilder sb56 = new StrBuilder(); sb56.append(taint()); sink(sb56.leftString(0)); // $ hasTaintFlow + StrBuilder sb57 = new StrBuilder(); sb57.append(taint()); sink(sb57.midString(0, 0)); // $ hasTaintFlow { StringReader reader = new StringReader(taint()); - StrBuilder sb58 = new StrBuilder(); sb58.readFrom(reader); sink(sb58.toString()); // $hasTaintFlow + StrBuilder sb58 = new StrBuilder(); sb58.readFrom(reader); sink(sb58.toString()); // $ hasTaintFlow } - StrBuilder sb59 = new StrBuilder(); sb59.replace(0, 0, taint()); sink(sb59.toString()); // $hasTaintFlow - StrBuilder sb60 = new StrBuilder(); sb60.replace(null, taint(), 0, 0, 0); sink(sb60.toString()); // $hasTaintFlow - StrBuilder sb61 = new StrBuilder(); sb61.replaceAll((StrMatcher)null, taint()); sink(sb61.toString()); // $hasTaintFlow - StrBuilder sb62 = new StrBuilder(); sb62.replaceAll("search", taint()); sink(sb62.toString()); // $hasTaintFlow + StrBuilder sb59 = new StrBuilder(); sb59.replace(0, 0, taint()); sink(sb59.toString()); // $ hasTaintFlow + StrBuilder sb60 = new StrBuilder(); sb60.replace(null, taint(), 0, 0, 0); sink(sb60.toString()); // $ hasTaintFlow + StrBuilder sb61 = new StrBuilder(); sb61.replaceAll((StrMatcher)null, taint()); sink(sb61.toString()); // $ hasTaintFlow + StrBuilder sb62 = new StrBuilder(); sb62.replaceAll("search", taint()); sink(sb62.toString()); // $ hasTaintFlow StrBuilder sb63 = new StrBuilder(); sb63.replaceAll(taint(), "replace"); sink(sb63.toString()); // GOOD (search string doesn't convey taint) - StrBuilder sb64 = new StrBuilder(); sb64.replaceFirst((StrMatcher)null, taint()); sink(sb64.toString()); // $hasTaintFlow - StrBuilder sb65 = new StrBuilder(); sb65.replaceFirst("search", taint()); sink(sb65.toString()); // $hasTaintFlow + StrBuilder sb64 = new StrBuilder(); sb64.replaceFirst((StrMatcher)null, taint()); sink(sb64.toString()); // $ hasTaintFlow + StrBuilder sb65 = new StrBuilder(); sb65.replaceFirst("search", taint()); sink(sb65.toString()); // $ hasTaintFlow StrBuilder sb66 = new StrBuilder(); sb66.replaceFirst(taint(), "replace"); sink(sb66.toString()); // GOOD (search string doesn't convey taint) - StrBuilder sb67 = new StrBuilder(); sb67.append(taint()); sink(sb67.rightString(0)); // $hasTaintFlow - StrBuilder sb68 = new StrBuilder(); sb68.append(taint()); sink(sb68.subSequence(0, 0)); // $hasTaintFlow - StrBuilder sb69 = new StrBuilder(); sb69.append(taint()); sink(sb69.substring(0)); // $hasTaintFlow - StrBuilder sb70 = new StrBuilder(); sb70.append(taint()); sink(sb70.substring(0, 0)); // $hasTaintFlow - StrBuilder sb71 = new StrBuilder(); sb71.append(taint()); sink(sb71.toCharArray()); // $hasTaintFlow - StrBuilder sb72 = new StrBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $hasTaintFlow - StrBuilder sb73 = new StrBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $hasTaintFlow - StrBuilder sb74 = new StrBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $hasTaintFlow + StrBuilder sb67 = new StrBuilder(); sb67.append(taint()); sink(sb67.rightString(0)); // $ hasTaintFlow + StrBuilder sb68 = new StrBuilder(); sb68.append(taint()); sink(sb68.subSequence(0, 0)); // $ hasTaintFlow + StrBuilder sb69 = new StrBuilder(); sb69.append(taint()); sink(sb69.substring(0)); // $ hasTaintFlow + StrBuilder sb70 = new StrBuilder(); sb70.append(taint()); sink(sb70.substring(0, 0)); // $ hasTaintFlow + StrBuilder sb71 = new StrBuilder(); sb71.append(taint()); sink(sb71.toCharArray()); // $ hasTaintFlow + StrBuilder sb72 = new StrBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $ hasTaintFlow + StrBuilder sb73 = new StrBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $ hasTaintFlow + StrBuilder sb74 = new StrBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $ hasTaintFlow // Tests for fluent methods (those returning `this`): StrBuilder fluentTest = new StrBuilder(); - sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $hasTaintFlow + sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $ hasTaintFlow StrBuilder fluentBackflowTest = new StrBuilder(); fluentBackflowTest.append("Harmless").append(taint()).append("Also harmless"); - sink(fluentBackflowTest.toString()); // $hasTaintFlow + sink(fluentBackflowTest.toString()); // $ hasTaintFlow // Test the case where the fluent method contributing taint is at the end of a statement: StrBuilder fluentBackflowTest2 = new StrBuilder(); fluentBackflowTest2.append("Harmless").append(taint()); - sink(fluentBackflowTest2.toString()); // $hasTaintFlow + sink(fluentBackflowTest2.toString()); // $ hasTaintFlow // Test all fluent methods are passing taint through to their result: StrBuilder fluentAllMethodsTest = new StrBuilder(taint()); @@ -171,7 +171,7 @@ void test() throws Exception { .setLength(500) .setNewLineText("newline") .setNullText("NULL") - .trim()); // $hasTaintFlow + .trim()); // $ hasTaintFlow // Test all fluent methods are passing taint back to their qualifier: StrBuilder fluentAllMethodsTest2 = new StrBuilder(); @@ -203,7 +203,7 @@ void test() throws Exception { .setNullText("NULL") .trim() .append(taint()); - sink(fluentAllMethodsTest2); // $hasTaintFlow + sink(fluentAllMethodsTest2); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrLookupTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrLookupTest.java index 64f53265bb63..38bcd0a85b52 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrLookupTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrLookupTest.java @@ -11,7 +11,7 @@ void test() throws Exception { Map map = new HashMap(); map.put("key", taint()); StrLookup lookup = StrLookup.mapLookup(map); - sink(lookup.lookup("key")); // $hasTaintFlow + sink(lookup.lookup("key")); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrSubstitutorTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrSubstitutorTest.java index 5e40da1958d7..c0ce5ca054e6 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrSubstitutorTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrSubstitutorTest.java @@ -17,66 +17,66 @@ void test() throws Exception { StrLookup taintedLookup = StrLookup.mapLookup(taintedMap); // Test constructors: - StrSubstitutor ss1 = new StrSubstitutor(); ss1.setVariableResolver(taintedLookup); sink(ss1.replace("input")); // $hasTaintFlow - StrSubstitutor ss2 = new StrSubstitutor(taintedMap); sink(ss2.replace("input")); // $hasTaintFlow - StrSubstitutor ss3 = new StrSubstitutor(taintedMap, "{", "}"); sink(ss3.replace("input")); // $hasTaintFlow - StrSubstitutor ss4 = new StrSubstitutor(taintedMap, "{", "}", ' '); sink(ss4.replace("input")); // $hasTaintFlow - StrSubstitutor ss5 = new StrSubstitutor(taintedMap, "{", "}", ' ', ","); sink(ss5.replace("input")); // $hasTaintFlow - StrSubstitutor ss6 = new StrSubstitutor(taintedLookup); sink(ss6.replace("input")); // $hasTaintFlow - StrSubstitutor ss7 = new StrSubstitutor(taintedLookup, "{", "}", ' '); sink(ss7.replace("input")); // $hasTaintFlow - StrSubstitutor ss8 = new StrSubstitutor(taintedLookup, "{", "}", ' ', ","); sink(ss8.replace("input")); // $hasTaintFlow - StrSubstitutor ss9 = new StrSubstitutor(taintedLookup, (StrMatcher)null, null, ' '); sink(ss9.replace("input")); // $hasTaintFlow - StrSubstitutor ss10 = new StrSubstitutor(taintedLookup, (StrMatcher)null, null, ' ', null); sink(ss10.replace("input")); // $hasTaintFlow + StrSubstitutor ss1 = new StrSubstitutor(); ss1.setVariableResolver(taintedLookup); sink(ss1.replace("input")); // $ hasTaintFlow + StrSubstitutor ss2 = new StrSubstitutor(taintedMap); sink(ss2.replace("input")); // $ hasTaintFlow + StrSubstitutor ss3 = new StrSubstitutor(taintedMap, "{", "}"); sink(ss3.replace("input")); // $ hasTaintFlow + StrSubstitutor ss4 = new StrSubstitutor(taintedMap, "{", "}", ' '); sink(ss4.replace("input")); // $ hasTaintFlow + StrSubstitutor ss5 = new StrSubstitutor(taintedMap, "{", "}", ' ', ","); sink(ss5.replace("input")); // $ hasTaintFlow + StrSubstitutor ss6 = new StrSubstitutor(taintedLookup); sink(ss6.replace("input")); // $ hasTaintFlow + StrSubstitutor ss7 = new StrSubstitutor(taintedLookup, "{", "}", ' '); sink(ss7.replace("input")); // $ hasTaintFlow + StrSubstitutor ss8 = new StrSubstitutor(taintedLookup, "{", "}", ' ', ","); sink(ss8.replace("input")); // $ hasTaintFlow + StrSubstitutor ss9 = new StrSubstitutor(taintedLookup, (StrMatcher)null, null, ' '); sink(ss9.replace("input")); // $ hasTaintFlow + StrSubstitutor ss10 = new StrSubstitutor(taintedLookup, (StrMatcher)null, null, ' ', null); sink(ss10.replace("input")); // $ hasTaintFlow // Test replace overloads (tainted substitution map): StrSubstitutor taintedSubst = ss2; - sink(taintedSubst.replace((Object)"input")); // $hasTaintFlow - sink(taintedSubst.replace("input")); // $hasTaintFlow - sink(taintedSubst.replace("input", 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace("input".toCharArray())); // $hasTaintFlow - sink(taintedSubst.replace("input".toCharArray(), 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace((CharSequence)"input")); // $hasTaintFlow - sink(taintedSubst.replace((CharSequence)"input", 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace(new StrBuilder("input"))); // $hasTaintFlow - sink(taintedSubst.replace(new StrBuilder("input"), 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuilder("input"))); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuilder("input"), 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuffer("input"))); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuffer("input"), 0, 0)); // $hasTaintFlow + sink(taintedSubst.replace((Object)"input")); // $ hasTaintFlow + sink(taintedSubst.replace("input")); // $ hasTaintFlow + sink(taintedSubst.replace("input", 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace("input".toCharArray())); // $ hasTaintFlow + sink(taintedSubst.replace("input".toCharArray(), 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace((CharSequence)"input")); // $ hasTaintFlow + sink(taintedSubst.replace((CharSequence)"input", 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace(new StrBuilder("input"))); // $ hasTaintFlow + sink(taintedSubst.replace(new StrBuilder("input"), 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuilder("input"))); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuilder("input"), 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuffer("input"))); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuffer("input"), 0, 0)); // $ hasTaintFlow // Test replace overloads (tainted input): StrSubstitutor untaintedSubst = ss1; - sink(untaintedSubst.replace((Object)taint())); // $hasTaintFlow - sink(untaintedSubst.replace(taint())); // $hasTaintFlow - sink(untaintedSubst.replace(taint(), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(taint().toCharArray())); // $hasTaintFlow - sink(untaintedSubst.replace(taint().toCharArray(), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace((CharSequence)taint())); // $hasTaintFlow - sink(untaintedSubst.replace((CharSequence)taint(), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(new StrBuilder(taint()))); // $hasTaintFlow - sink(untaintedSubst.replace(new StrBuilder(taint()), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuilder(taint()))); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuilder(taint()), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuffer(taint()))); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuffer(taint()), 0, 0)); // $hasTaintFlow + sink(untaintedSubst.replace((Object)taint())); // $ hasTaintFlow + sink(untaintedSubst.replace(taint())); // $ hasTaintFlow + sink(untaintedSubst.replace(taint(), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(taint().toCharArray())); // $ hasTaintFlow + sink(untaintedSubst.replace(taint().toCharArray(), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace((CharSequence)taint())); // $ hasTaintFlow + sink(untaintedSubst.replace((CharSequence)taint(), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(new StrBuilder(taint()))); // $ hasTaintFlow + sink(untaintedSubst.replace(new StrBuilder(taint()), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuilder(taint()))); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuilder(taint()), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuffer(taint()))); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuffer(taint()), 0, 0)); // $ hasTaintFlow // Test static replace methods: - sink(StrSubstitutor.replace(taint(), new HashMap())); // $hasTaintFlow - sink(StrSubstitutor.replace(taint(), new HashMap(), "{", "}")); // $hasTaintFlow - sink(StrSubstitutor.replace("input", taintedMap)); // $hasTaintFlow - sink(StrSubstitutor.replace("input", taintedMap, "{", "}")); // $hasTaintFlow + sink(StrSubstitutor.replace(taint(), new HashMap())); // $ hasTaintFlow + sink(StrSubstitutor.replace(taint(), new HashMap(), "{", "}")); // $ hasTaintFlow + sink(StrSubstitutor.replace("input", taintedMap)); // $ hasTaintFlow + sink(StrSubstitutor.replace("input", taintedMap, "{", "}")); // $ hasTaintFlow Properties taintedProps = new Properties(); taintedProps.put("key", taint()); - sink(StrSubstitutor.replace(taint(), new Properties())); // $hasTaintFlow - sink(StrSubstitutor.replace("input", taintedProps)); // $hasTaintFlow + sink(StrSubstitutor.replace(taint(), new Properties())); // $ hasTaintFlow + sink(StrSubstitutor.replace("input", taintedProps)); // $ hasTaintFlow // Test replaceIn methods: - StrBuilder strBuilder1 = new StrBuilder(); taintedSubst.replaceIn(strBuilder1); sink(strBuilder1.toString()); // $hasTaintFlow - StrBuilder strBuilder2 = new StrBuilder(); taintedSubst.replaceIn(strBuilder2, 0, 0); sink(strBuilder2.toString()); // $hasTaintFlow - StringBuilder stringBuilder1 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder1); sink(stringBuilder1.toString()); // $hasTaintFlow - StringBuilder stringBuilder2 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder2, 0, 0); sink(stringBuilder2.toString()); // $hasTaintFlow - StringBuffer stringBuffer1 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer1); sink(stringBuffer1.toString()); // $hasTaintFlow - StringBuffer stringBuffer2 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer2, 0, 0); sink(stringBuffer2.toString()); // $hasTaintFlow + StrBuilder strBuilder1 = new StrBuilder(); taintedSubst.replaceIn(strBuilder1); sink(strBuilder1.toString()); // $ hasTaintFlow + StrBuilder strBuilder2 = new StrBuilder(); taintedSubst.replaceIn(strBuilder2, 0, 0); sink(strBuilder2.toString()); // $ hasTaintFlow + StringBuilder stringBuilder1 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder1); sink(stringBuilder1.toString()); // $ hasTaintFlow + StringBuilder stringBuilder2 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder2, 0, 0); sink(stringBuilder2.toString()); // $ hasTaintFlow + StringBuffer stringBuffer1 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer1); sink(stringBuffer1.toString()); // $ hasTaintFlow + StringBuffer stringBuffer2 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer2, 0, 0); sink(stringBuffer2.toString()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTest.java index 2872a179c4ab..517a52dca393 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTest.java @@ -9,38 +9,38 @@ void sink(Object o) {} void test() throws Exception { // Test constructors: - sink((new StrTokenizer(taint().toCharArray())).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), ',')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), ',', '"')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), ",")).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null)).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint())).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), ',')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), ',', '"')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), ",")).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), (StrMatcher)null)).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow + sink((new StrTokenizer(taint().toCharArray())).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), ',')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), ',', '"')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), ",")).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null)).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null, (StrMatcher)null)).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), ',')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), ',', '"')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), ",")).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), (StrMatcher)null)).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), (StrMatcher)null, (StrMatcher)null)).toString()); // $ hasTaintFlow // Test constructing static methods: - sink(StrTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow - sink(StrTokenizer.getCSVInstance(taint()).toString()); // $hasTaintFlow - sink(StrTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow - sink(StrTokenizer.getTSVInstance(taint()).toString()); // $hasTaintFlow + sink(StrTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $ hasTaintFlow + sink(StrTokenizer.getCSVInstance(taint()).toString()); // $ hasTaintFlow + sink(StrTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $ hasTaintFlow + sink(StrTokenizer.getTSVInstance(taint()).toString()); // $ hasTaintFlow // Test accessors: - sink((new StrTokenizer(taint())).clone()); // $hasTaintFlow - sink((new StrTokenizer(taint())).getContent()); // $hasTaintFlow - sink((new StrTokenizer(taint())).getTokenArray()); // $hasTaintFlow - sink((new StrTokenizer(taint())).getTokenList()); // $hasTaintFlow - sink((new StrTokenizer(taint())).next()); // $hasTaintFlow - sink((new StrTokenizer(taint())).nextToken()); // $hasTaintFlow - sink((new StrTokenizer(taint())).previous()); // $hasTaintFlow - sink((new StrTokenizer(taint())).previousToken()); // $hasTaintFlow + sink((new StrTokenizer(taint())).clone()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).getContent()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).getTokenArray()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).getTokenList()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).next()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).nextToken()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).previous()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).previousToken()); // $ hasTaintFlow // Test mutators: - sink((new StrTokenizer()).reset(taint().toCharArray()).toString()); // $hasTaintFlow - sink((new StrTokenizer()).reset(taint()).toString()); // $hasTaintFlow + sink((new StrTokenizer()).reset(taint().toCharArray()).toString()); // $ hasTaintFlow + sink((new StrTokenizer()).reset(taint()).toString()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTextTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTextTest.java index 4758a7d4b9db..4ee6ebb5c1b1 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTextTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StrTokenizerTextTest.java @@ -9,38 +9,38 @@ void sink(Object o) {} void test() throws Exception { // Test constructors: - sink((new StrTokenizer(taint().toCharArray())).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), ',')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), ',', '"')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), ",")).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null)).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint())).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), ',')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), ',', '"')).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), ",")).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), (StrMatcher)null)).toString()); // $hasTaintFlow - sink((new StrTokenizer(taint(), (StrMatcher)null, (StrMatcher)null)).toString()); // $hasTaintFlow + sink((new StrTokenizer(taint().toCharArray())).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), ',')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), ',', '"')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), ",")).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null)).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint().toCharArray(), (StrMatcher)null, (StrMatcher)null)).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), ',')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), ',', '"')).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), ",")).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), (StrMatcher)null)).toString()); // $ hasTaintFlow + sink((new StrTokenizer(taint(), (StrMatcher)null, (StrMatcher)null)).toString()); // $ hasTaintFlow // Test constructing static methods: - sink(StrTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow - sink(StrTokenizer.getCSVInstance(taint()).toString()); // $hasTaintFlow - sink(StrTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow - sink(StrTokenizer.getTSVInstance(taint()).toString()); // $hasTaintFlow + sink(StrTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $ hasTaintFlow + sink(StrTokenizer.getCSVInstance(taint()).toString()); // $ hasTaintFlow + sink(StrTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $ hasTaintFlow + sink(StrTokenizer.getTSVInstance(taint()).toString()); // $ hasTaintFlow // Test accessors: - sink((new StrTokenizer(taint())).clone()); // $hasTaintFlow - sink((new StrTokenizer(taint())).getContent()); // $hasTaintFlow - sink((new StrTokenizer(taint())).getTokenArray()); // $hasTaintFlow - sink((new StrTokenizer(taint())).getTokenList()); // $hasTaintFlow - sink((new StrTokenizer(taint())).next()); // $hasTaintFlow - sink((new StrTokenizer(taint())).nextToken()); // $hasTaintFlow - sink((new StrTokenizer(taint())).previous()); // $hasTaintFlow - sink((new StrTokenizer(taint())).previousToken()); // $hasTaintFlow + sink((new StrTokenizer(taint())).clone()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).getContent()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).getTokenArray()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).getTokenList()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).next()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).nextToken()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).previous()); // $ hasTaintFlow + sink((new StrTokenizer(taint())).previousToken()); // $ hasTaintFlow // Test mutators: - sink((new StrTokenizer()).reset(taint().toCharArray()).toString()); // $hasTaintFlow - sink((new StrTokenizer()).reset(taint()).toString()); // $hasTaintFlow + sink((new StrTokenizer()).reset(taint().toCharArray()).toString()); // $ hasTaintFlow + sink((new StrTokenizer()).reset(taint()).toString()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringEscapeUtilsTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringEscapeUtilsTest.java index eae03dd6e56b..abcae1e8b841 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringEscapeUtilsTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringEscapeUtilsTest.java @@ -6,6 +6,6 @@ public class StringEscapeUtilsTest { void sink(Object o) {} void test() throws Exception { - sink(StringEscapeUtils.escapeJson(taint())); // $hasTaintFlow + sink(StringEscapeUtils.escapeJson(taint())); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringLookupTextTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringLookupTextTest.java index 4c346a4fedd5..723d7e3de7c3 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringLookupTextTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringLookupTextTest.java @@ -12,7 +12,7 @@ void test() throws Exception { Map map = new HashMap(); map.put("key", taint()); StringLookup lookup = StringLookupFactory.INSTANCE.mapStringLookup(map); - sink(lookup.lookup("key")); // $hasTaintFlow + sink(lookup.lookup("key")); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringSubstitutorTextTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringSubstitutorTextTest.java index ddf23e06c09c..387b0630c4e7 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringSubstitutorTextTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringSubstitutorTextTest.java @@ -18,66 +18,66 @@ void test() throws Exception { StringLookup taintedLookup = StringLookupFactory.INSTANCE.mapStringLookup(taintedMap); // Test constructors: - StringSubstitutor ss1 = new StringSubstitutor(); ss1.setVariableResolver(taintedLookup); sink(ss1.replace("input")); // $hasTaintFlow - StringSubstitutor ss2 = new StringSubstitutor(taintedMap); sink(ss2.replace("input")); // $hasTaintFlow - StringSubstitutor ss3 = new StringSubstitutor(taintedMap, "{", "}"); sink(ss3.replace("input")); // $hasTaintFlow - StringSubstitutor ss4 = new StringSubstitutor(taintedMap, "{", "}", ' '); sink(ss4.replace("input")); // $hasTaintFlow - StringSubstitutor ss5 = new StringSubstitutor(taintedMap, "{", "}", ' ', ","); sink(ss5.replace("input")); // $hasTaintFlow - StringSubstitutor ss6 = new StringSubstitutor(taintedLookup); sink(ss6.replace("input")); // $hasTaintFlow - StringSubstitutor ss7 = new StringSubstitutor(taintedLookup, "{", "}", ' '); sink(ss7.replace("input")); // $hasTaintFlow - StringSubstitutor ss8 = new StringSubstitutor(taintedLookup, "{", "}", ' ', ","); sink(ss8.replace("input")); // $hasTaintFlow - StringSubstitutor ss9 = new StringSubstitutor(taintedLookup, (StringMatcher)null, null, ' '); sink(ss9.replace("input")); // $hasTaintFlow - StringSubstitutor ss10 = new StringSubstitutor(taintedLookup, (StringMatcher)null, null, ' ', null); sink(ss10.replace("input")); // $hasTaintFlow + StringSubstitutor ss1 = new StringSubstitutor(); ss1.setVariableResolver(taintedLookup); sink(ss1.replace("input")); // $ hasTaintFlow + StringSubstitutor ss2 = new StringSubstitutor(taintedMap); sink(ss2.replace("input")); // $ hasTaintFlow + StringSubstitutor ss3 = new StringSubstitutor(taintedMap, "{", "}"); sink(ss3.replace("input")); // $ hasTaintFlow + StringSubstitutor ss4 = new StringSubstitutor(taintedMap, "{", "}", ' '); sink(ss4.replace("input")); // $ hasTaintFlow + StringSubstitutor ss5 = new StringSubstitutor(taintedMap, "{", "}", ' ', ","); sink(ss5.replace("input")); // $ hasTaintFlow + StringSubstitutor ss6 = new StringSubstitutor(taintedLookup); sink(ss6.replace("input")); // $ hasTaintFlow + StringSubstitutor ss7 = new StringSubstitutor(taintedLookup, "{", "}", ' '); sink(ss7.replace("input")); // $ hasTaintFlow + StringSubstitutor ss8 = new StringSubstitutor(taintedLookup, "{", "}", ' ', ","); sink(ss8.replace("input")); // $ hasTaintFlow + StringSubstitutor ss9 = new StringSubstitutor(taintedLookup, (StringMatcher)null, null, ' '); sink(ss9.replace("input")); // $ hasTaintFlow + StringSubstitutor ss10 = new StringSubstitutor(taintedLookup, (StringMatcher)null, null, ' ', null); sink(ss10.replace("input")); // $ hasTaintFlow // Test replace overloads (tainted substitution map): StringSubstitutor taintedSubst = ss2; - sink(taintedSubst.replace((Object)"input")); // $hasTaintFlow - sink(taintedSubst.replace("input")); // $hasTaintFlow - sink(taintedSubst.replace("input", 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace("input".toCharArray())); // $hasTaintFlow - sink(taintedSubst.replace("input".toCharArray(), 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace((CharSequence)"input")); // $hasTaintFlow - sink(taintedSubst.replace((CharSequence)"input", 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace(new TextStringBuilder("input"))); // $hasTaintFlow - sink(taintedSubst.replace(new TextStringBuilder("input"), 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuilder("input"))); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuilder("input"), 0, 0)); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuffer("input"))); // $hasTaintFlow - sink(taintedSubst.replace(new StringBuffer("input"), 0, 0)); // $hasTaintFlow + sink(taintedSubst.replace((Object)"input")); // $ hasTaintFlow + sink(taintedSubst.replace("input")); // $ hasTaintFlow + sink(taintedSubst.replace("input", 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace("input".toCharArray())); // $ hasTaintFlow + sink(taintedSubst.replace("input".toCharArray(), 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace((CharSequence)"input")); // $ hasTaintFlow + sink(taintedSubst.replace((CharSequence)"input", 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace(new TextStringBuilder("input"))); // $ hasTaintFlow + sink(taintedSubst.replace(new TextStringBuilder("input"), 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuilder("input"))); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuilder("input"), 0, 0)); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuffer("input"))); // $ hasTaintFlow + sink(taintedSubst.replace(new StringBuffer("input"), 0, 0)); // $ hasTaintFlow // Test replace overloads (tainted input): StringSubstitutor untaintedSubst = ss1; - sink(untaintedSubst.replace((Object)taint())); // $hasTaintFlow - sink(untaintedSubst.replace(taint())); // $hasTaintFlow - sink(untaintedSubst.replace(taint(), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(taint().toCharArray())); // $hasTaintFlow - sink(untaintedSubst.replace(taint().toCharArray(), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace((CharSequence)taint())); // $hasTaintFlow - sink(untaintedSubst.replace((CharSequence)taint(), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(new TextStringBuilder(taint()))); // $hasTaintFlow - sink(untaintedSubst.replace(new TextStringBuilder(taint()), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuilder(taint()))); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuilder(taint()), 0, 0)); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuffer(taint()))); // $hasTaintFlow - sink(untaintedSubst.replace(new StringBuffer(taint()), 0, 0)); // $hasTaintFlow + sink(untaintedSubst.replace((Object)taint())); // $ hasTaintFlow + sink(untaintedSubst.replace(taint())); // $ hasTaintFlow + sink(untaintedSubst.replace(taint(), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(taint().toCharArray())); // $ hasTaintFlow + sink(untaintedSubst.replace(taint().toCharArray(), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace((CharSequence)taint())); // $ hasTaintFlow + sink(untaintedSubst.replace((CharSequence)taint(), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(new TextStringBuilder(taint()))); // $ hasTaintFlow + sink(untaintedSubst.replace(new TextStringBuilder(taint()), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuilder(taint()))); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuilder(taint()), 0, 0)); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuffer(taint()))); // $ hasTaintFlow + sink(untaintedSubst.replace(new StringBuffer(taint()), 0, 0)); // $ hasTaintFlow // Test static replace methods: - sink(StringSubstitutor.replace(taint(), new HashMap())); // $hasTaintFlow - sink(StringSubstitutor.replace(taint(), new HashMap(), "{", "}")); // $hasTaintFlow - sink(StringSubstitutor.replace("input", taintedMap)); // $hasTaintFlow - sink(StringSubstitutor.replace("input", taintedMap, "{", "}")); // $hasTaintFlow + sink(StringSubstitutor.replace(taint(), new HashMap())); // $ hasTaintFlow + sink(StringSubstitutor.replace(taint(), new HashMap(), "{", "}")); // $ hasTaintFlow + sink(StringSubstitutor.replace("input", taintedMap)); // $ hasTaintFlow + sink(StringSubstitutor.replace("input", taintedMap, "{", "}")); // $ hasTaintFlow Properties taintedProps = new Properties(); taintedProps.put("key", taint()); - sink(StringSubstitutor.replace(taint(), new Properties())); // $hasTaintFlow - sink(StringSubstitutor.replace("input", taintedProps)); // $hasTaintFlow + sink(StringSubstitutor.replace(taint(), new Properties())); // $ hasTaintFlow + sink(StringSubstitutor.replace("input", taintedProps)); // $ hasTaintFlow // Test replaceIn methods: - TextStringBuilder strBuilder1 = new TextStringBuilder(); taintedSubst.replaceIn(strBuilder1); sink(strBuilder1.toString()); // $hasTaintFlow - TextStringBuilder strBuilder2 = new TextStringBuilder(); taintedSubst.replaceIn(strBuilder2, 0, 0); sink(strBuilder2.toString()); // $hasTaintFlow - StringBuilder stringBuilder1 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder1); sink(stringBuilder1.toString()); // $hasTaintFlow - StringBuilder stringBuilder2 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder2, 0, 0); sink(stringBuilder2.toString()); // $hasTaintFlow - StringBuffer stringBuffer1 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer1); sink(stringBuffer1.toString()); // $hasTaintFlow - StringBuffer stringBuffer2 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer2, 0, 0); sink(stringBuffer2.toString()); // $hasTaintFlow + TextStringBuilder strBuilder1 = new TextStringBuilder(); taintedSubst.replaceIn(strBuilder1); sink(strBuilder1.toString()); // $ hasTaintFlow + TextStringBuilder strBuilder2 = new TextStringBuilder(); taintedSubst.replaceIn(strBuilder2, 0, 0); sink(strBuilder2.toString()); // $ hasTaintFlow + StringBuilder stringBuilder1 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder1); sink(stringBuilder1.toString()); // $ hasTaintFlow + StringBuilder stringBuilder2 = new StringBuilder(); taintedSubst.replaceIn(stringBuilder2, 0, 0); sink(stringBuilder2.toString()); // $ hasTaintFlow + StringBuffer stringBuffer1 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer1); sink(stringBuffer1.toString()); // $ hasTaintFlow + StringBuffer stringBuffer2 = new StringBuffer(); taintedSubst.replaceIn(stringBuffer2, 0, 0); sink(stringBuffer2.toString()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringTokenizerTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringTokenizerTest.java index 330ee39acb90..5e93bc98391e 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringTokenizerTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/StringTokenizerTest.java @@ -9,38 +9,38 @@ void sink(Object o) {} void test() throws Exception { // Test constructors: - sink((new StringTokenizer(taint().toCharArray())).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint().toCharArray(), ',')).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint().toCharArray(), ',', '"')).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint().toCharArray(), ",")).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint().toCharArray(), (StringMatcher)null)).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint().toCharArray(), (StringMatcher)null, (StringMatcher)null)).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint())).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint(), ',')).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint(), ',', '"')).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint(), ",")).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint(), (StringMatcher)null)).toString()); // $hasTaintFlow - sink((new StringTokenizer(taint(), (StringMatcher)null, (StringMatcher)null)).toString()); // $hasTaintFlow + sink((new StringTokenizer(taint().toCharArray())).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint().toCharArray(), ',')).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint().toCharArray(), ',', '"')).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint().toCharArray(), ",")).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint().toCharArray(), (StringMatcher)null)).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint().toCharArray(), (StringMatcher)null, (StringMatcher)null)).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint(), ',')).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint(), ',', '"')).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint(), ",")).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint(), (StringMatcher)null)).toString()); // $ hasTaintFlow + sink((new StringTokenizer(taint(), (StringMatcher)null, (StringMatcher)null)).toString()); // $ hasTaintFlow // Test constructing static methods: - sink(StringTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow - sink(StringTokenizer.getCSVInstance(taint()).toString()); // $hasTaintFlow - sink(StringTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $hasTaintFlow - sink(StringTokenizer.getTSVInstance(taint()).toString()); // $hasTaintFlow + sink(StringTokenizer.getCSVInstance(taint().toCharArray()).toString()); // $ hasTaintFlow + sink(StringTokenizer.getCSVInstance(taint()).toString()); // $ hasTaintFlow + sink(StringTokenizer.getTSVInstance(taint().toCharArray()).toString()); // $ hasTaintFlow + sink(StringTokenizer.getTSVInstance(taint()).toString()); // $ hasTaintFlow // Test accessors: - sink((new StringTokenizer(taint())).clone()); // $hasTaintFlow - sink((new StringTokenizer(taint())).getContent()); // $hasTaintFlow - sink((new StringTokenizer(taint())).getTokenArray()); // $hasTaintFlow - sink((new StringTokenizer(taint())).getTokenList()); // $hasTaintFlow - sink((new StringTokenizer(taint())).next()); // $hasTaintFlow - sink((new StringTokenizer(taint())).nextToken()); // $hasTaintFlow - sink((new StringTokenizer(taint())).previous()); // $hasTaintFlow - sink((new StringTokenizer(taint())).previousToken()); // $hasTaintFlow + sink((new StringTokenizer(taint())).clone()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).getContent()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).getTokenArray()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).getTokenList()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).next()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).nextToken()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).previous()); // $ hasTaintFlow + sink((new StringTokenizer(taint())).previousToken()); // $ hasTaintFlow // Test mutators: - sink((new StringTokenizer()).reset(taint().toCharArray()).toString()); // $hasTaintFlow - sink((new StringTokenizer()).reset(taint()).toString()); // $hasTaintFlow + sink((new StringTokenizer()).reset(taint().toCharArray()).toString()); // $ hasTaintFlow + sink((new StringTokenizer()).reset(taint()).toString()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/Test.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/Test.java index 6cfa278a1685..4ac4a13f6dcd 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/Test.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/Test.java @@ -12,57 +12,57 @@ void sink(Object o) {} void test() throws Exception { // All these calls should convey taint to `sink` except as noted. - sink(StringUtils.abbreviate(taint(), 0)); // $hasTaintFlow - sink(StringUtils.abbreviate(taint(), 0, 0)); // $hasTaintFlow - sink(StringUtils.abbreviate(taint(), "...", 0)); // $hasTaintFlow - sink(StringUtils.abbreviate("Untainted", taint(), 0)); // $hasTaintFlow - sink(StringUtils.abbreviate(taint(), "...", 0, 0)); // $hasTaintFlow - sink(StringUtils.abbreviate("Untainted", taint(), 0, 0)); // $hasTaintFlow - sink(StringUtils.abbreviateMiddle(taint(), "...", 0)); // $hasTaintFlow - sink(StringUtils.abbreviateMiddle("Untainted", taint(), 0)); // $hasTaintFlow - sink(StringUtils.appendIfMissing(taint(), "suffix", "candsuffix1", "candsuffix2")); // $hasTaintFlow - sink(StringUtils.appendIfMissing("prefix", taint(), "candsuffix1", "candsuffix2")); // $hasTaintFlow + sink(StringUtils.abbreviate(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.abbreviate(taint(), 0, 0)); // $ hasTaintFlow + sink(StringUtils.abbreviate(taint(), "...", 0)); // $ hasTaintFlow + sink(StringUtils.abbreviate("Untainted", taint(), 0)); // $ hasTaintFlow + sink(StringUtils.abbreviate(taint(), "...", 0, 0)); // $ hasTaintFlow + sink(StringUtils.abbreviate("Untainted", taint(), 0, 0)); // $ hasTaintFlow + sink(StringUtils.abbreviateMiddle(taint(), "...", 0)); // $ hasTaintFlow + sink(StringUtils.abbreviateMiddle("Untainted", taint(), 0)); // $ hasTaintFlow + sink(StringUtils.appendIfMissing(taint(), "suffix", "candsuffix1", "candsuffix2")); // $ hasTaintFlow + sink(StringUtils.appendIfMissing("prefix", taint(), "candsuffix1", "candsuffix2")); // $ hasTaintFlow // (next 2 calls) GOOD: candidate suffixes do not flow to the return value. sink(StringUtils.appendIfMissing("prefix", "suffix", taint(), "candsuffix2")); sink(StringUtils.appendIfMissing("prefix", "suffix", "candsuffix1", taint())); - sink(StringUtils.appendIfMissingIgnoreCase(taint(), "suffix", "candsuffix1", "candsuffix2")); // $hasTaintFlow - sink(StringUtils.appendIfMissingIgnoreCase("prefix", taint(), "candsuffix1", "candsuffix2")); // $hasTaintFlow + sink(StringUtils.appendIfMissingIgnoreCase(taint(), "suffix", "candsuffix1", "candsuffix2")); // $ hasTaintFlow + sink(StringUtils.appendIfMissingIgnoreCase("prefix", taint(), "candsuffix1", "candsuffix2")); // $ hasTaintFlow // (next 2 calls) GOOD: candidate suffixes do not flow to the return value. sink(StringUtils.appendIfMissingIgnoreCase("prefix", "suffix", taint(), "candsuffix2")); sink(StringUtils.appendIfMissingIgnoreCase("prefix", "suffix", "candsuffix1", taint())); - sink(StringUtils.capitalize(taint())); // $hasTaintFlow - sink(StringUtils.center(taint(), 0)); // $hasTaintFlow - sink(StringUtils.center(taint(), 0, 'x')); // $hasTaintFlow - sink(StringUtils.center(taint(), 0, "padding string")); // $hasTaintFlow - sink(StringUtils.center("Center me", 0, taint())); // $hasTaintFlow - sink(StringUtils.chomp(taint())); // $hasTaintFlow - sink(StringUtils.chomp(taint(), "separator")); // $hasTaintFlow + sink(StringUtils.capitalize(taint())); // $ hasTaintFlow + sink(StringUtils.center(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.center(taint(), 0, 'x')); // $ hasTaintFlow + sink(StringUtils.center(taint(), 0, "padding string")); // $ hasTaintFlow + sink(StringUtils.center("Center me", 0, taint())); // $ hasTaintFlow + sink(StringUtils.chomp(taint())); // $ hasTaintFlow + sink(StringUtils.chomp(taint(), "separator")); // $ hasTaintFlow // GOOD: separator does not flow to the return value. sink(StringUtils.chomp("Chomp me", taint())); - sink(StringUtils.chop(taint())); // $hasTaintFlow - sink(StringUtils.defaultIfBlank(taint(), "default")); // $hasTaintFlow - sink(StringUtils.defaultIfBlank("Perhaps blank", taint())); // $hasTaintFlow - sink(StringUtils.defaultIfEmpty(taint(), "default")); // $hasTaintFlow - sink(StringUtils.defaultIfEmpty("Perhaps empty", taint())); // $hasTaintFlow - sink(StringUtils.defaultString(taint())); // $hasTaintFlow - sink(StringUtils.defaultString(taint(), "default string")); // $hasTaintFlow - sink(StringUtils.defaultString("perhaps null", taint())); // $hasTaintFlow - sink(StringUtils.deleteWhitespace(taint())); // $hasTaintFlow - sink(StringUtils.difference(taint(), "rhs")); // $hasTaintFlow - sink(StringUtils.difference("lhs", taint())); // $hasTaintFlow - sink(StringUtils.firstNonBlank(taint(), "second string")); // $hasValueFlow - sink(StringUtils.firstNonBlank("first string", taint())); // $hasValueFlow - sink(StringUtils.firstNonEmpty(taint(), "second string")); // $hasValueFlow - sink(StringUtils.firstNonEmpty("first string", taint())); // $hasValueFlow - sink(StringUtils.getBytes(taint(), (Charset)null)); // $hasTaintFlow - sink(StringUtils.getBytes(taint(), "some charset")); // $hasTaintFlow + sink(StringUtils.chop(taint())); // $ hasTaintFlow + sink(StringUtils.defaultIfBlank(taint(), "default")); // $ hasTaintFlow + sink(StringUtils.defaultIfBlank("Perhaps blank", taint())); // $ hasTaintFlow + sink(StringUtils.defaultIfEmpty(taint(), "default")); // $ hasTaintFlow + sink(StringUtils.defaultIfEmpty("Perhaps empty", taint())); // $ hasTaintFlow + sink(StringUtils.defaultString(taint())); // $ hasTaintFlow + sink(StringUtils.defaultString(taint(), "default string")); // $ hasTaintFlow + sink(StringUtils.defaultString("perhaps null", taint())); // $ hasTaintFlow + sink(StringUtils.deleteWhitespace(taint())); // $ hasTaintFlow + sink(StringUtils.difference(taint(), "rhs")); // $ hasTaintFlow + sink(StringUtils.difference("lhs", taint())); // $ hasTaintFlow + sink(StringUtils.firstNonBlank(taint(), "second string")); // $ hasValueFlow + sink(StringUtils.firstNonBlank("first string", taint())); // $ hasValueFlow + sink(StringUtils.firstNonEmpty(taint(), "second string")); // $ hasValueFlow + sink(StringUtils.firstNonEmpty("first string", taint())); // $ hasValueFlow + sink(StringUtils.getBytes(taint(), (Charset)null)); // $ hasTaintFlow + sink(StringUtils.getBytes(taint(), "some charset")); // $ hasTaintFlow // GOOD: charset names are not a source of taint sink(StringUtils.getBytes("some string", taint())); - sink(StringUtils.getCommonPrefix(taint(), "second string")); // $hasTaintFlow - sink(StringUtils.getCommonPrefix("first string", taint())); // $hasTaintFlow - sink(StringUtils.getDigits(taint())); // $hasTaintFlow - sink(StringUtils.getIfBlank(taint(), () -> "default")); // $hasTaintFlow - sink(StringUtils.getIfEmpty(taint(), () -> "default")); // $hasTaintFlow + sink(StringUtils.getCommonPrefix(taint(), "second string")); // $ hasTaintFlow + sink(StringUtils.getCommonPrefix("first string", taint())); // $ hasTaintFlow + sink(StringUtils.getDigits(taint())); // $ hasTaintFlow + sink(StringUtils.getIfBlank(taint(), () -> "default")); // $ hasTaintFlow + sink(StringUtils.getIfEmpty(taint(), () -> "default")); // $ hasTaintFlow // BAD (but not detected yet): latent taint in lambdas sink(StringUtils.getIfBlank("maybe blank", () -> taint())); sink(StringUtils.getIfEmpty("maybe blank", () -> taint())); @@ -70,70 +70,70 @@ void test() throws Exception { // of tainted data. sink(StringUtils.join(StringUtils.getBytes(taint(), "UTF-8"), ' ')); sink(StringUtils.join(StringUtils.getBytes(taint(), "UTF-8"), ' ', 0, 0)); - sink(StringUtils.join(taint().toCharArray(), ' ')); // $hasTaintFlow - sink(StringUtils.join(taint().toCharArray(), ' ', 0, 0)); // $hasTaintFlow + sink(StringUtils.join(taint().toCharArray(), ' ')); // $ hasTaintFlow + sink(StringUtils.join(taint().toCharArray(), ' ', 0, 0)); // $ hasTaintFlow // Testing the Iterable overloads of `join` List taintedList = new ArrayList<>(); taintedList.add(taint()); - sink(StringUtils.join(taintedList, ' ')); // $hasTaintFlow - sink(StringUtils.join(taintedList, "sep")); // $hasTaintFlow + sink(StringUtils.join(taintedList, ' ')); // $ hasTaintFlow + sink(StringUtils.join(taintedList, "sep")); // $ hasTaintFlow List untaintedList = new ArrayList<>(); - sink(StringUtils.join(untaintedList, taint())); // $hasTaintFlow + sink(StringUtils.join(untaintedList, taint())); // $ hasTaintFlow // Testing the Iterator overloads of `join` - sink(StringUtils.join(taintedList.iterator(), ' ')); // $hasTaintFlow - sink(StringUtils.join(taintedList.iterator(), "sep")); // $hasTaintFlow - sink(StringUtils.join(untaintedList.iterator(), taint())); // $hasTaintFlow + sink(StringUtils.join(taintedList.iterator(), ' ')); // $ hasTaintFlow + sink(StringUtils.join(taintedList.iterator(), "sep")); // $ hasTaintFlow + sink(StringUtils.join(untaintedList.iterator(), taint())); // $ hasTaintFlow // Testing the List overloads of `join`, which have start/end indices - sink(StringUtils.join(taintedList, ' ', 0, 0)); // $hasTaintFlow - sink(StringUtils.join(taintedList, "sep", 0, 0)); // $hasTaintFlow - sink(StringUtils.join(untaintedList, taint(), 0, 0)); // $hasTaintFlow + sink(StringUtils.join(taintedList, ' ', 0, 0)); // $ hasTaintFlow + sink(StringUtils.join(taintedList, "sep", 0, 0)); // $ hasTaintFlow + sink(StringUtils.join(untaintedList, taint(), 0, 0)); // $ hasTaintFlow // Testing the Object[] overloads of `join`, which may have start/end indices Object[] taintedArray = new Object[] { taint() }; - sink(StringUtils.join(taintedArray, ' ')); // $hasTaintFlow - sink(StringUtils.join(taintedArray, "sep")); // $hasTaintFlow - sink(StringUtils.join(taintedArray, ' ', 0, 0)); // $hasTaintFlow - sink(StringUtils.join(taintedArray, "sep", 0, 0)); // $hasTaintFlow + sink(StringUtils.join(taintedArray, ' ')); // $ hasTaintFlow + sink(StringUtils.join(taintedArray, "sep")); // $ hasTaintFlow + sink(StringUtils.join(taintedArray, ' ', 0, 0)); // $ hasTaintFlow + sink(StringUtils.join(taintedArray, "sep", 0, 0)); // $ hasTaintFlow Object[] untaintedArray = new Object[] { "safe" }; - sink(StringUtils.join(untaintedArray, taint())); // $hasTaintFlow - sink(StringUtils.join(untaintedArray, taint(), 0, 0)); // $hasTaintFlow + sink(StringUtils.join(untaintedArray, taint())); // $ hasTaintFlow + sink(StringUtils.join(untaintedArray, taint(), 0, 0)); // $ hasTaintFlow // Testing the variadic overload of `join` and `joinWith` - sink(StringUtils.join(taint(), "other string")); // $hasTaintFlow - sink(StringUtils.join("other string before", taint())); // $hasTaintFlow - sink(StringUtils.joinWith("separator", taint(), "other string")); // $hasTaintFlow - sink(StringUtils.joinWith("separator", "other string before", taint())); // $hasTaintFlow - sink(StringUtils.joinWith(taint(), "other string before", "other string after")); // $hasTaintFlow + sink(StringUtils.join(taint(), "other string")); // $ hasTaintFlow + sink(StringUtils.join("other string before", taint())); // $ hasTaintFlow + sink(StringUtils.joinWith("separator", taint(), "other string")); // $ hasTaintFlow + sink(StringUtils.joinWith("separator", "other string before", taint())); // $ hasTaintFlow + sink(StringUtils.joinWith(taint(), "other string before", "other string after")); // $ hasTaintFlow // End of `join` tests - sink(StringUtils.left(taint(), 0)); // $hasTaintFlow - sink(StringUtils.leftPad(taint(), 0)); // $hasTaintFlow - sink(StringUtils.leftPad(taint(), 0, ' ')); // $hasTaintFlow - sink(StringUtils.leftPad(taint(), 0, "padding")); // $hasTaintFlow - sink(StringUtils.leftPad("to pad", 0, taint())); // $hasTaintFlow - sink(StringUtils.lowerCase(taint())); // $hasTaintFlow - sink(StringUtils.lowerCase(taint(), Locale.UK)); // $hasTaintFlow - sink(StringUtils.mid(taint(), 0, 0)); // $hasTaintFlow - sink(StringUtils.normalizeSpace(taint())); // $hasTaintFlow - sink(StringUtils.overlay(taint(), "overlay", 0, 0)); // $hasTaintFlow - sink(StringUtils.overlay("underlay", taint(), 0, 0)); // $hasTaintFlow - sink(StringUtils.prependIfMissing(taint(), "append prefix", "check prefix 1", "check prefix 2")); // $hasTaintFlow - sink(StringUtils.prependIfMissing("original string", taint(), "check prefix 1", "check prefix 2")); // $hasTaintFlow + sink(StringUtils.left(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.leftPad(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.leftPad(taint(), 0, ' ')); // $ hasTaintFlow + sink(StringUtils.leftPad(taint(), 0, "padding")); // $ hasTaintFlow + sink(StringUtils.leftPad("to pad", 0, taint())); // $ hasTaintFlow + sink(StringUtils.lowerCase(taint())); // $ hasTaintFlow + sink(StringUtils.lowerCase(taint(), Locale.UK)); // $ hasTaintFlow + sink(StringUtils.mid(taint(), 0, 0)); // $ hasTaintFlow + sink(StringUtils.normalizeSpace(taint())); // $ hasTaintFlow + sink(StringUtils.overlay(taint(), "overlay", 0, 0)); // $ hasTaintFlow + sink(StringUtils.overlay("underlay", taint(), 0, 0)); // $ hasTaintFlow + sink(StringUtils.prependIfMissing(taint(), "append prefix", "check prefix 1", "check prefix 2")); // $ hasTaintFlow + sink(StringUtils.prependIfMissing("original string", taint(), "check prefix 1", "check prefix 2")); // $ hasTaintFlow // (next 2 calls) GOOD: args 3+ are checked against but do not propagate to the return value sink(StringUtils.prependIfMissing("original string", "append prefix", taint(), "check prefix 2")); sink(StringUtils.prependIfMissing("original string", "append prefix", "check prefix 1", taint())); - sink(StringUtils.prependIfMissingIgnoreCase(taint(), "append prefix", "check prefix 1", "check prefix 2")); // $hasTaintFlow - sink(StringUtils.prependIfMissingIgnoreCase("original string", taint(), "check prefix 1", "check prefix 2")); // $hasTaintFlow + sink(StringUtils.prependIfMissingIgnoreCase(taint(), "append prefix", "check prefix 1", "check prefix 2")); // $ hasTaintFlow + sink(StringUtils.prependIfMissingIgnoreCase("original string", taint(), "check prefix 1", "check prefix 2")); // $ hasTaintFlow // (next 2 calls) GOOD: args 3+ are checked against but do not propagate to the return value sink(StringUtils.prependIfMissingIgnoreCase("original string", "append prefix", taint(), "check prefix 2")); sink(StringUtils.prependIfMissingIgnoreCase("original string", "append prefix", "check prefix 1", taint())); - sink(StringUtils.remove(taint(), ' ')); // $hasTaintFlow - sink(StringUtils.remove(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeAll(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeEnd(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeEndIgnoreCase(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeFirst(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeIgnoreCase(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removePattern(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeStart(taint(), "delete me")); // $hasTaintFlow - sink(StringUtils.removeStartIgnoreCase(taint(), "delete me")); // $hasTaintFlow + sink(StringUtils.remove(taint(), ' ')); // $ hasTaintFlow + sink(StringUtils.remove(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeAll(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeEnd(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeEndIgnoreCase(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeFirst(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeIgnoreCase(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removePattern(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeStart(taint(), "delete me")); // $ hasTaintFlow + sink(StringUtils.removeStartIgnoreCase(taint(), "delete me")); // $ hasTaintFlow // GOOD (next 9 calls): the removed string doesn't propagate to the return value sink(StringUtils.remove("remove from", taint())); sink(StringUtils.removeAll("remove from", taint())); @@ -144,32 +144,32 @@ void test() throws Exception { sink(StringUtils.removePattern("remove from", taint())); sink(StringUtils.removeStart("remove from", taint())); sink(StringUtils.removeStartIgnoreCase("remove from", taint())); - sink(StringUtils.repeat(taint(), 1)); // $hasTaintFlow - sink(StringUtils.repeat(taint(), "separator", 1)); // $hasTaintFlow - sink(StringUtils.repeat("repeat me", taint(), 1)); // $hasTaintFlow - sink(StringUtils.replace(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replace("haystack", "search", taint())); // $hasTaintFlow - sink(StringUtils.replace(taint(), "search", "replacement", 0)); // $hasTaintFlow - sink(StringUtils.replace("haystack", "search", taint(), 0)); // $hasTaintFlow - sink(StringUtils.replaceAll(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replaceAll("haystack", "search", taint())); // $hasTaintFlow - sink(StringUtils.replaceChars(taint(), 'a', 'b')); // $hasTaintFlow - sink(StringUtils.replaceChars(taint(), "abc", "xyz")); // $hasTaintFlow - sink(StringUtils.replaceChars("haystack", "abc", taint())); // $hasTaintFlow - sink(StringUtils.replaceEach(taint(), new String[] { "search" }, new String[] { "replacement" })); // $hasTaintFlow - sink(StringUtils.replaceEach("haystack", new String[] { "search" }, new String[] { taint() })); // $hasTaintFlow - sink(StringUtils.replaceEachRepeatedly(taint(), new String[] { "search" }, new String[] { "replacement" })); // $hasTaintFlow - sink(StringUtils.replaceEachRepeatedly("haystack", new String[] { "search" }, new String[] { taint() })); // $hasTaintFlow - sink(StringUtils.replaceFirst(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replaceFirst("haystack", "search", taint())); // $hasTaintFlow - sink(StringUtils.replaceIgnoreCase(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replaceIgnoreCase("haystack", "search", taint())); // $hasTaintFlow - sink(StringUtils.replaceOnce(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replaceOnce("haystack", "search", taint())); // $hasTaintFlow - sink(StringUtils.replaceOnceIgnoreCase(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replaceOnceIgnoreCase("haystack", "search", taint())); // $hasTaintFlow - sink(StringUtils.replacePattern(taint(), "search", "replacement")); // $hasTaintFlow - sink(StringUtils.replacePattern("haystack", "search", taint())); // $hasTaintFlow + sink(StringUtils.repeat(taint(), 1)); // $ hasTaintFlow + sink(StringUtils.repeat(taint(), "separator", 1)); // $ hasTaintFlow + sink(StringUtils.repeat("repeat me", taint(), 1)); // $ hasTaintFlow + sink(StringUtils.replace(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replace("haystack", "search", taint())); // $ hasTaintFlow + sink(StringUtils.replace(taint(), "search", "replacement", 0)); // $ hasTaintFlow + sink(StringUtils.replace("haystack", "search", taint(), 0)); // $ hasTaintFlow + sink(StringUtils.replaceAll(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replaceAll("haystack", "search", taint())); // $ hasTaintFlow + sink(StringUtils.replaceChars(taint(), 'a', 'b')); // $ hasTaintFlow + sink(StringUtils.replaceChars(taint(), "abc", "xyz")); // $ hasTaintFlow + sink(StringUtils.replaceChars("haystack", "abc", taint())); // $ hasTaintFlow + sink(StringUtils.replaceEach(taint(), new String[] { "search" }, new String[] { "replacement" })); // $ hasTaintFlow + sink(StringUtils.replaceEach("haystack", new String[] { "search" }, new String[] { taint() })); // $ hasTaintFlow + sink(StringUtils.replaceEachRepeatedly(taint(), new String[] { "search" }, new String[] { "replacement" })); // $ hasTaintFlow + sink(StringUtils.replaceEachRepeatedly("haystack", new String[] { "search" }, new String[] { taint() })); // $ hasTaintFlow + sink(StringUtils.replaceFirst(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replaceFirst("haystack", "search", taint())); // $ hasTaintFlow + sink(StringUtils.replaceIgnoreCase(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replaceIgnoreCase("haystack", "search", taint())); // $ hasTaintFlow + sink(StringUtils.replaceOnce(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replaceOnce("haystack", "search", taint())); // $ hasTaintFlow + sink(StringUtils.replaceOnceIgnoreCase(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replaceOnceIgnoreCase("haystack", "search", taint())); // $ hasTaintFlow + sink(StringUtils.replacePattern(taint(), "search", "replacement")); // $ hasTaintFlow + sink(StringUtils.replacePattern("haystack", "search", taint())); // $ hasTaintFlow // GOOD (next 11 calls): searched string in replace methods does not flow to the return value. sink(StringUtils.replace("haystack", taint(), "replacement")); sink(StringUtils.replace("haystack", taint(), "replacement", 0)); @@ -182,28 +182,28 @@ void test() throws Exception { sink(StringUtils.replaceOnce("haystack", taint(), "replacement")); sink(StringUtils.replaceOnceIgnoreCase("haystack", taint(), "replacement")); sink(StringUtils.replacePattern("haystack", taint(), "replacement")); - sink(StringUtils.reverse(taint())); // $hasTaintFlow - sink(StringUtils.reverseDelimited(taint(), ',')); // $hasTaintFlow - sink(StringUtils.right(taint(), 0)); // $hasTaintFlow - sink(StringUtils.rightPad(taint(), 0)); // $hasTaintFlow - sink(StringUtils.rightPad(taint(), 0, ' ')); // $hasTaintFlow - sink(StringUtils.rightPad(taint(), 0, "padding")); // $hasTaintFlow - sink(StringUtils.rightPad("to pad", 0, taint())); // $hasTaintFlow - sink(StringUtils.rotate(taint(), 0)); // $hasTaintFlow - sink(StringUtils.split(taint())); // $hasTaintFlow - sink(StringUtils.split(taint(), ' ')); // $hasTaintFlow - sink(StringUtils.split(taint(), " ,;")); // $hasTaintFlow - sink(StringUtils.split(taint(), " ,;", 0)); // $hasTaintFlow - sink(StringUtils.splitByCharacterType(taint())); // $hasTaintFlow - sink(StringUtils.splitByCharacterTypeCamelCase(taint())); // $hasTaintFlow - sink(StringUtils.splitByWholeSeparator(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.splitByWholeSeparator(taint(), "separator", 0)); // $hasTaintFlow - sink(StringUtils.splitByWholeSeparatorPreserveAllTokens(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.splitByWholeSeparatorPreserveAllTokens(taint(), "separator", 0)); // $hasTaintFlow - sink(StringUtils.splitPreserveAllTokens(taint())); // $hasTaintFlow - sink(StringUtils.splitPreserveAllTokens(taint(), ' ')); // $hasTaintFlow - sink(StringUtils.splitPreserveAllTokens(taint(), " ,;")); // $hasTaintFlow - sink(StringUtils.splitPreserveAllTokens(taint(), " ,;", 0)); // $hasTaintFlow + sink(StringUtils.reverse(taint())); // $ hasTaintFlow + sink(StringUtils.reverseDelimited(taint(), ',')); // $ hasTaintFlow + sink(StringUtils.right(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.rightPad(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.rightPad(taint(), 0, ' ')); // $ hasTaintFlow + sink(StringUtils.rightPad(taint(), 0, "padding")); // $ hasTaintFlow + sink(StringUtils.rightPad("to pad", 0, taint())); // $ hasTaintFlow + sink(StringUtils.rotate(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.split(taint())); // $ hasTaintFlow + sink(StringUtils.split(taint(), ' ')); // $ hasTaintFlow + sink(StringUtils.split(taint(), " ,;")); // $ hasTaintFlow + sink(StringUtils.split(taint(), " ,;", 0)); // $ hasTaintFlow + sink(StringUtils.splitByCharacterType(taint())); // $ hasTaintFlow + sink(StringUtils.splitByCharacterTypeCamelCase(taint())); // $ hasTaintFlow + sink(StringUtils.splitByWholeSeparator(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.splitByWholeSeparator(taint(), "separator", 0)); // $ hasTaintFlow + sink(StringUtils.splitByWholeSeparatorPreserveAllTokens(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.splitByWholeSeparatorPreserveAllTokens(taint(), "separator", 0)); // $ hasTaintFlow + sink(StringUtils.splitPreserveAllTokens(taint())); // $ hasTaintFlow + sink(StringUtils.splitPreserveAllTokens(taint(), ' ')); // $ hasTaintFlow + sink(StringUtils.splitPreserveAllTokens(taint(), " ,;")); // $ hasTaintFlow + sink(StringUtils.splitPreserveAllTokens(taint(), " ,;", 0)); // $ hasTaintFlow // GOOD (next 8 calls): separators don't propagate to the return value sink(StringUtils.split("to split", taint())); sink(StringUtils.split("to split", taint(), 0)); @@ -213,30 +213,30 @@ void test() throws Exception { sink(StringUtils.splitByWholeSeparatorPreserveAllTokens("to split", taint())); sink(StringUtils.splitByWholeSeparatorPreserveAllTokens("to split", taint(), 0)); sink(StringUtils.splitPreserveAllTokens("to split", taint())); - sink(StringUtils.strip(taint())); // $hasTaintFlow - sink(StringUtils.strip(taint(), "charstoremove")); // $hasTaintFlow - sink(StringUtils.stripAccents(taint())); // $hasTaintFlow - sink(StringUtils.stripAll(new String[] { taint() }, "charstoremove")[0]); // $hasTaintFlow - sink(StringUtils.stripEnd(taint(), "charstoremove")); // $hasTaintFlow - sink(StringUtils.stripStart(taint(), "charstoremove")); // $hasTaintFlow + sink(StringUtils.strip(taint())); // $ hasTaintFlow + sink(StringUtils.strip(taint(), "charstoremove")); // $ hasTaintFlow + sink(StringUtils.stripAccents(taint())); // $ hasTaintFlow + sink(StringUtils.stripAll(new String[] { taint() }, "charstoremove")[0]); // $ hasTaintFlow + sink(StringUtils.stripEnd(taint(), "charstoremove")); // $ hasTaintFlow + sink(StringUtils.stripStart(taint(), "charstoremove")); // $ hasTaintFlow // GOOD (next 4 calls): stripped chars do not flow to the return value. sink(StringUtils.strip("original text", taint())); sink(StringUtils.stripAll(new String[] { "original text" }, taint())[0]); sink(StringUtils.stripEnd("original text", taint())); sink(StringUtils.stripStart("original text", taint())); - sink(StringUtils.stripToEmpty(taint())); // $hasTaintFlow - sink(StringUtils.stripToNull(taint())); // $hasTaintFlow - sink(StringUtils.substring(taint(), 0)); // $hasTaintFlow - sink(StringUtils.substring(taint(), 0, 0)); // $hasTaintFlow - sink(StringUtils.substringAfter(taint(), 0)); // $hasTaintFlow - sink(StringUtils.substringAfter(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.substringAfterLast(taint(), 0)); // $hasTaintFlow - sink(StringUtils.substringAfterLast(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.substringBefore(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.substringBeforeLast(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.substringBetween(taint(), "separator")); // $hasTaintFlow - sink(StringUtils.substringBetween(taint(), "start-tag", "end-tag")); // $hasTaintFlow - sink(StringUtils.substringsBetween(taint(), "start-tag", "end-tag")[0]); // $hasTaintFlow + sink(StringUtils.stripToEmpty(taint())); // $ hasTaintFlow + sink(StringUtils.stripToNull(taint())); // $ hasTaintFlow + sink(StringUtils.substring(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.substring(taint(), 0, 0)); // $ hasTaintFlow + sink(StringUtils.substringAfter(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.substringAfter(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.substringAfterLast(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.substringAfterLast(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.substringBefore(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.substringBeforeLast(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.substringBetween(taint(), "separator")); // $ hasTaintFlow + sink(StringUtils.substringBetween(taint(), "start-tag", "end-tag")); // $ hasTaintFlow + sink(StringUtils.substringsBetween(taint(), "start-tag", "end-tag")[0]); // $ hasTaintFlow // GOOD (next 9 calls): separators and bounding tags do not flow to the return value. sink(StringUtils.substringAfter("original text", taint())); sink(StringUtils.substringAfterLast("original text", taint())); @@ -247,31 +247,31 @@ void test() throws Exception { sink(StringUtils.substringBetween("original text", "start-tag", taint())); sink(StringUtils.substringsBetween("original text", taint(), "end-tag")[0]); sink(StringUtils.substringsBetween("original text", "start-tag", taint())[0]); - sink(StringUtils.swapCase(taint())); // $hasTaintFlow - sink(StringUtils.toCodePoints(taint())); // $hasTaintFlow - sink(StringUtils.toEncodedString(StringUtils.getBytes(taint(), "charset"), null)); // $hasTaintFlow - sink(StringUtils.toRootLowerCase(taint())); // $hasTaintFlow - sink(StringUtils.toRootUpperCase(taint())); // $hasTaintFlow - sink(StringUtils.toString(StringUtils.getBytes(taint(), "charset"), "charset")); // $hasTaintFlow - sink(StringUtils.trim(taint())); // $hasTaintFlow - sink(StringUtils.trimToEmpty(taint())); // $hasTaintFlow - sink(StringUtils.trimToNull(taint())); // $hasTaintFlow - sink(StringUtils.truncate(taint(), 0)); // $hasTaintFlow - sink(StringUtils.truncate(taint(), 0, 0)); // $hasTaintFlow - sink(StringUtils.uncapitalize(taint())); // $hasTaintFlow - sink(StringUtils.unwrap(taint(), '"')); // $hasTaintFlow - sink(StringUtils.unwrap(taint(), "separator")); // $hasTaintFlow + sink(StringUtils.swapCase(taint())); // $ hasTaintFlow + sink(StringUtils.toCodePoints(taint())); // $ hasTaintFlow + sink(StringUtils.toEncodedString(StringUtils.getBytes(taint(), "charset"), null)); // $ hasTaintFlow + sink(StringUtils.toRootLowerCase(taint())); // $ hasTaintFlow + sink(StringUtils.toRootUpperCase(taint())); // $ hasTaintFlow + sink(StringUtils.toString(StringUtils.getBytes(taint(), "charset"), "charset")); // $ hasTaintFlow + sink(StringUtils.trim(taint())); // $ hasTaintFlow + sink(StringUtils.trimToEmpty(taint())); // $ hasTaintFlow + sink(StringUtils.trimToNull(taint())); // $ hasTaintFlow + sink(StringUtils.truncate(taint(), 0)); // $ hasTaintFlow + sink(StringUtils.truncate(taint(), 0, 0)); // $ hasTaintFlow + sink(StringUtils.uncapitalize(taint())); // $ hasTaintFlow + sink(StringUtils.unwrap(taint(), '"')); // $ hasTaintFlow + sink(StringUtils.unwrap(taint(), "separator")); // $ hasTaintFlow // GOOD: the wrapper string does not flow to the return value. sink(StringUtils.unwrap("original string", taint())); - sink(StringUtils.upperCase(taint())); // $hasTaintFlow - sink(StringUtils.upperCase(taint(), null)); // $hasTaintFlow - sink(StringUtils.valueOf(taint().toCharArray())); // $hasTaintFlow - sink(StringUtils.wrap(taint(), '"')); // $hasTaintFlow - sink(StringUtils.wrap(taint(), "wrapper token")); // $hasTaintFlow - sink(StringUtils.wrap("wrap me", taint())); // $hasTaintFlow - sink(StringUtils.wrapIfMissing(taint(), '"')); // $hasTaintFlow - sink(StringUtils.wrapIfMissing(taint(), "wrapper token")); // $hasTaintFlow - sink(StringUtils.wrapIfMissing("wrap me", taint())); // $hasTaintFlow + sink(StringUtils.upperCase(taint())); // $ hasTaintFlow + sink(StringUtils.upperCase(taint(), null)); // $ hasTaintFlow + sink(StringUtils.valueOf(taint().toCharArray())); // $ hasTaintFlow + sink(StringUtils.wrap(taint(), '"')); // $ hasTaintFlow + sink(StringUtils.wrap(taint(), "wrapper token")); // $ hasTaintFlow + sink(StringUtils.wrap("wrap me", taint())); // $ hasTaintFlow + sink(StringUtils.wrapIfMissing(taint(), '"')); // $ hasTaintFlow + sink(StringUtils.wrapIfMissing(taint(), "wrapper token")); // $ hasTaintFlow + sink(StringUtils.wrapIfMissing("wrap me", taint())); // $ hasTaintFlow } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java index 5a7c66c75260..42a696a0c2c8 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java @@ -14,135 +14,135 @@ void sink(Object o) {} void test() throws Exception { - TextStringBuilder cons1 = new TextStringBuilder(taint()); sink(cons1.toString()); // $hasTaintFlow - TextStringBuilder cons2 = new TextStringBuilder((CharSequence)taint()); sink(cons2.toString()); // $hasTaintFlow + TextStringBuilder cons1 = new TextStringBuilder(taint()); sink(cons1.toString()); // $ hasTaintFlow + TextStringBuilder cons2 = new TextStringBuilder((CharSequence)taint()); sink(cons2.toString()); // $ hasTaintFlow - TextStringBuilder sb1 = new TextStringBuilder(); sb1.append(taint().toCharArray()); sink(sb1.toString()); // $hasTaintFlow - TextStringBuilder sb2 = new TextStringBuilder(); sb2.append(taint().toCharArray(), 0, 0); sink(sb2.toString()); // $hasTaintFlow + TextStringBuilder sb1 = new TextStringBuilder(); sb1.append(taint().toCharArray()); sink(sb1.toString()); // $ hasTaintFlow + TextStringBuilder sb2 = new TextStringBuilder(); sb2.append(taint().toCharArray(), 0, 0); sink(sb2.toString()); // $ hasTaintFlow TextStringBuilder sb3 = new TextStringBuilder(); sb3.append(CharBuffer.wrap(taint().toCharArray())); sink(sb3.toString()); // $ hasTaintFlow TextStringBuilder sb4 = new TextStringBuilder(); sb4.append(CharBuffer.wrap(taint().toCharArray()), 0, 0); sink(sb4.toString()); // $ hasTaintFlow - TextStringBuilder sb5 = new TextStringBuilder(); sb5.append((CharSequence)taint()); sink(sb5.toString()); // $hasTaintFlow - TextStringBuilder sb6 = new TextStringBuilder(); sb6.append((CharSequence)taint(), 0, 0); sink(sb6.toString()); // $hasTaintFlow - TextStringBuilder sb7 = new TextStringBuilder(); sb7.append((Object)taint()); sink(sb7.toString()); // $hasTaintFlow + TextStringBuilder sb5 = new TextStringBuilder(); sb5.append((CharSequence)taint()); sink(sb5.toString()); // $ hasTaintFlow + TextStringBuilder sb6 = new TextStringBuilder(); sb6.append((CharSequence)taint(), 0, 0); sink(sb6.toString()); // $ hasTaintFlow + TextStringBuilder sb7 = new TextStringBuilder(); sb7.append((Object)taint()); sink(sb7.toString()); // $ hasTaintFlow { TextStringBuilder auxsb = new TextStringBuilder(); auxsb.append(taint()); - TextStringBuilder sb8 = new TextStringBuilder(); sb8.append(auxsb); sink(sb8.toString()); // $hasTaintFlow + TextStringBuilder sb8 = new TextStringBuilder(); sb8.append(auxsb); sink(sb8.toString()); // $ hasTaintFlow } - TextStringBuilder sb9 = new TextStringBuilder(); sb9.append(new StringBuffer(taint())); sink(sb9.toString()); // $hasTaintFlow - TextStringBuilder sb10 = new TextStringBuilder(); sb10.append(new StringBuffer(taint()), 0, 0); sink(sb10.toString()); // $hasTaintFlow - TextStringBuilder sb11 = new TextStringBuilder(); sb11.append(new StringBuilder(taint())); sink(sb11.toString()); // $hasTaintFlow - TextStringBuilder sb12 = new TextStringBuilder(); sb12.append(new StringBuilder(taint()), 0, 0); sink(sb12.toString()); // $hasTaintFlow - TextStringBuilder sb13 = new TextStringBuilder(); sb13.append(taint()); sink(sb13.toString()); // $hasTaintFlow - TextStringBuilder sb14 = new TextStringBuilder(); sb14.append(taint(), 0, 0); sink(sb14.toString()); // $hasTaintFlow - TextStringBuilder sb15 = new TextStringBuilder(); sb15.append(taint(), "format", "args"); sink(sb15.toString()); // $hasTaintFlow - TextStringBuilder sb16 = new TextStringBuilder(); sb16.append("Format string", taint(), "args"); sink(sb16.toString()); // $hasTaintFlow + TextStringBuilder sb9 = new TextStringBuilder(); sb9.append(new StringBuffer(taint())); sink(sb9.toString()); // $ hasTaintFlow + TextStringBuilder sb10 = new TextStringBuilder(); sb10.append(new StringBuffer(taint()), 0, 0); sink(sb10.toString()); // $ hasTaintFlow + TextStringBuilder sb11 = new TextStringBuilder(); sb11.append(new StringBuilder(taint())); sink(sb11.toString()); // $ hasTaintFlow + TextStringBuilder sb12 = new TextStringBuilder(); sb12.append(new StringBuilder(taint()), 0, 0); sink(sb12.toString()); // $ hasTaintFlow + TextStringBuilder sb13 = new TextStringBuilder(); sb13.append(taint()); sink(sb13.toString()); // $ hasTaintFlow + TextStringBuilder sb14 = new TextStringBuilder(); sb14.append(taint(), 0, 0); sink(sb14.toString()); // $ hasTaintFlow + TextStringBuilder sb15 = new TextStringBuilder(); sb15.append(taint(), "format", "args"); sink(sb15.toString()); // $ hasTaintFlow + TextStringBuilder sb16 = new TextStringBuilder(); sb16.append("Format string", taint(), "args"); sink(sb16.toString()); // $ hasTaintFlow { List taintedList = new ArrayList<>(); taintedList.add(taint()); - TextStringBuilder sb17 = new TextStringBuilder(); sb17.appendAll(taintedList); sink(sb17.toString()); // $hasTaintFlow - TextStringBuilder sb18 = new TextStringBuilder(); sb18.appendAll(taintedList.iterator()); sink(sb18.toString()); // $hasTaintFlow + TextStringBuilder sb17 = new TextStringBuilder(); sb17.appendAll(taintedList); sink(sb17.toString()); // $ hasTaintFlow + TextStringBuilder sb18 = new TextStringBuilder(); sb18.appendAll(taintedList.iterator()); sink(sb18.toString()); // $ hasTaintFlow } - TextStringBuilder sb19 = new TextStringBuilder(); sb19.appendAll("clean", taint()); sink(sb19.toString()); // $hasTaintFlow - TextStringBuilder sb20 = new TextStringBuilder(); sb20.appendAll(taint(), "clean"); sink(sb20.toString()); // $hasTaintFlow - TextStringBuilder sb21 = new TextStringBuilder(); sb21.appendFixedWidthPadLeft(taint(), 0, ' '); sink(sb21.toString()); // $hasTaintFlow - TextStringBuilder sb22 = new TextStringBuilder(); sb22.appendFixedWidthPadRight(taint(), 0, ' '); sink(sb22.toString()); // $hasTaintFlow - TextStringBuilder sb23 = new TextStringBuilder(); sb23.appendln(taint().toCharArray()); sink(sb23.toString()); // $hasTaintFlow - TextStringBuilder sb24 = new TextStringBuilder(); sb24.appendln(taint().toCharArray(), 0, 0); sink(sb24.toString()); // $hasTaintFlow - TextStringBuilder sb25 = new TextStringBuilder(); sb25.appendln((Object)taint()); sink(sb25.toString()); // $hasTaintFlow + TextStringBuilder sb19 = new TextStringBuilder(); sb19.appendAll("clean", taint()); sink(sb19.toString()); // $ hasTaintFlow + TextStringBuilder sb20 = new TextStringBuilder(); sb20.appendAll(taint(), "clean"); sink(sb20.toString()); // $ hasTaintFlow + TextStringBuilder sb21 = new TextStringBuilder(); sb21.appendFixedWidthPadLeft(taint(), 0, ' '); sink(sb21.toString()); // $ hasTaintFlow + TextStringBuilder sb22 = new TextStringBuilder(); sb22.appendFixedWidthPadRight(taint(), 0, ' '); sink(sb22.toString()); // $ hasTaintFlow + TextStringBuilder sb23 = new TextStringBuilder(); sb23.appendln(taint().toCharArray()); sink(sb23.toString()); // $ hasTaintFlow + TextStringBuilder sb24 = new TextStringBuilder(); sb24.appendln(taint().toCharArray(), 0, 0); sink(sb24.toString()); // $ hasTaintFlow + TextStringBuilder sb25 = new TextStringBuilder(); sb25.appendln((Object)taint()); sink(sb25.toString()); // $ hasTaintFlow { TextStringBuilder auxsb = new TextStringBuilder(); auxsb.appendln(taint()); - TextStringBuilder sb26 = new TextStringBuilder(); sb26.appendln(auxsb); sink(sb26.toString()); // $hasTaintFlow + TextStringBuilder sb26 = new TextStringBuilder(); sb26.appendln(auxsb); sink(sb26.toString()); // $ hasTaintFlow } - TextStringBuilder sb27 = new TextStringBuilder(); sb27.appendln(new StringBuffer(taint())); sink(sb27.toString()); // $hasTaintFlow - TextStringBuilder sb28 = new TextStringBuilder(); sb28.appendln(new StringBuffer(taint()), 0, 0); sink(sb28.toString()); // $hasTaintFlow - TextStringBuilder sb29 = new TextStringBuilder(); sb29.appendln(new StringBuilder(taint())); sink(sb29.toString()); // $hasTaintFlow - TextStringBuilder sb30 = new TextStringBuilder(); sb30.appendln(new StringBuilder(taint()), 0, 0); sink(sb30.toString()); // $hasTaintFlow - TextStringBuilder sb31 = new TextStringBuilder(); sb31.appendln(taint()); sink(sb31.toString()); // $hasTaintFlow - TextStringBuilder sb32 = new TextStringBuilder(); sb32.appendln(taint(), 0, 0); sink(sb32.toString()); // $hasTaintFlow - TextStringBuilder sb33 = new TextStringBuilder(); sb33.appendln(taint(), "format", "args"); sink(sb33.toString()); // $hasTaintFlow - TextStringBuilder sb34 = new TextStringBuilder(); sb34.appendln("Format string", taint(), "args"); sink(sb34.toString()); // $hasTaintFlow - TextStringBuilder sb35 = new TextStringBuilder(); sb35.appendSeparator(taint()); sink(sb35.toString()); // $hasTaintFlow - TextStringBuilder sb36 = new TextStringBuilder(); sb36.appendSeparator(taint(), 0); sink(sb36.toString()); // $hasTaintFlow - TextStringBuilder sb37 = new TextStringBuilder(); sb37.appendSeparator(taint(), "default"); sink(sb37.toString()); // $hasTaintFlow - TextStringBuilder sb38 = new TextStringBuilder(); sb38.appendSeparator("", taint()); sink(sb38.toString()); // $hasTaintFlow + TextStringBuilder sb27 = new TextStringBuilder(); sb27.appendln(new StringBuffer(taint())); sink(sb27.toString()); // $ hasTaintFlow + TextStringBuilder sb28 = new TextStringBuilder(); sb28.appendln(new StringBuffer(taint()), 0, 0); sink(sb28.toString()); // $ hasTaintFlow + TextStringBuilder sb29 = new TextStringBuilder(); sb29.appendln(new StringBuilder(taint())); sink(sb29.toString()); // $ hasTaintFlow + TextStringBuilder sb30 = new TextStringBuilder(); sb30.appendln(new StringBuilder(taint()), 0, 0); sink(sb30.toString()); // $ hasTaintFlow + TextStringBuilder sb31 = new TextStringBuilder(); sb31.appendln(taint()); sink(sb31.toString()); // $ hasTaintFlow + TextStringBuilder sb32 = new TextStringBuilder(); sb32.appendln(taint(), 0, 0); sink(sb32.toString()); // $ hasTaintFlow + TextStringBuilder sb33 = new TextStringBuilder(); sb33.appendln(taint(), "format", "args"); sink(sb33.toString()); // $ hasTaintFlow + TextStringBuilder sb34 = new TextStringBuilder(); sb34.appendln("Format string", taint(), "args"); sink(sb34.toString()); // $ hasTaintFlow + TextStringBuilder sb35 = new TextStringBuilder(); sb35.appendSeparator(taint()); sink(sb35.toString()); // $ hasTaintFlow + TextStringBuilder sb36 = new TextStringBuilder(); sb36.appendSeparator(taint(), 0); sink(sb36.toString()); // $ hasTaintFlow + TextStringBuilder sb37 = new TextStringBuilder(); sb37.appendSeparator(taint(), "default"); sink(sb37.toString()); // $ hasTaintFlow + TextStringBuilder sb38 = new TextStringBuilder(); sb38.appendSeparator("", taint()); sink(sb38.toString()); // $ hasTaintFlow { TextStringBuilder auxsb = new TextStringBuilder(); auxsb.appendln(taint()); - TextStringBuilder sb39 = new TextStringBuilder(); auxsb.appendTo(sb39); sink(sb39.toString()); // $hasTaintFlow + TextStringBuilder sb39 = new TextStringBuilder(); auxsb.appendTo(sb39); sink(sb39.toString()); // $ hasTaintFlow } { List taintedList = new ArrayList<>(); taintedList.add(taint()); - TextStringBuilder sb40 = new TextStringBuilder(); sb40.appendWithSeparators(taintedList, ", "); sink(sb40.toString()); // $hasTaintFlow - TextStringBuilder sb41 = new TextStringBuilder(); sb41.appendWithSeparators(taintedList.iterator(), ", "); sink(sb41.toString()); // $hasTaintFlow + TextStringBuilder sb40 = new TextStringBuilder(); sb40.appendWithSeparators(taintedList, ", "); sink(sb40.toString()); // $ hasTaintFlow + TextStringBuilder sb41 = new TextStringBuilder(); sb41.appendWithSeparators(taintedList.iterator(), ", "); sink(sb41.toString()); // $ hasTaintFlow List untaintedList = new ArrayList<>(); - TextStringBuilder sb42 = new TextStringBuilder(); sb42.appendWithSeparators(untaintedList, taint()); sink(sb42.toString()); // $hasTaintFlow - TextStringBuilder sb43 = new TextStringBuilder(); sb43.appendWithSeparators(untaintedList.iterator(), taint()); sink(sb43.toString()); // $hasTaintFlow + TextStringBuilder sb42 = new TextStringBuilder(); sb42.appendWithSeparators(untaintedList, taint()); sink(sb42.toString()); // $ hasTaintFlow + TextStringBuilder sb43 = new TextStringBuilder(); sb43.appendWithSeparators(untaintedList.iterator(), taint()); sink(sb43.toString()); // $ hasTaintFlow String[] taintedArray = new String[] { taint() }; String[] untaintedArray = new String[] {}; - TextStringBuilder sb44 = new TextStringBuilder(); sb44.appendWithSeparators(taintedArray, ", "); sink(sb44.toString()); // $hasTaintFlow - TextStringBuilder sb45 = new TextStringBuilder(); sb45.appendWithSeparators(untaintedArray, taint()); sink(sb45.toString()); // $hasTaintFlow + TextStringBuilder sb44 = new TextStringBuilder(); sb44.appendWithSeparators(taintedArray, ", "); sink(sb44.toString()); // $ hasTaintFlow + TextStringBuilder sb45 = new TextStringBuilder(); sb45.appendWithSeparators(untaintedArray, taint()); sink(sb45.toString()); // $ hasTaintFlow } { TextStringBuilder sb46 = new TextStringBuilder(); sb46.append(taint()); char[] target = new char[100]; sb46.asReader().read(target); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } - TextStringBuilder sb47 = new TextStringBuilder(); sb47.append(taint()); sink(sb47.asTokenizer().next()); // $hasTaintFlow - TextStringBuilder sb48 = new TextStringBuilder(); sb48.append(taint()); sink(sb48.build()); // $hasTaintFlow - TextStringBuilder sb49 = new TextStringBuilder(); sb49.append(taint()); sink(sb49.getChars(null)); // $hasTaintFlow + TextStringBuilder sb47 = new TextStringBuilder(); sb47.append(taint()); sink(sb47.asTokenizer().next()); // $ hasTaintFlow + TextStringBuilder sb48 = new TextStringBuilder(); sb48.append(taint()); sink(sb48.build()); // $ hasTaintFlow + TextStringBuilder sb49 = new TextStringBuilder(); sb49.append(taint()); sink(sb49.getChars(null)); // $ hasTaintFlow { TextStringBuilder sb50 = new TextStringBuilder(); sb50.append(taint()); char[] target = new char[100]; sb50.getChars(target); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } { TextStringBuilder sb51 = new TextStringBuilder(); sb51.append(taint()); char[] target = new char[100]; sb51.getChars(0, 0, target, 0); - sink(target); // $hasTaintFlow + sink(target); // $ hasTaintFlow } - TextStringBuilder sb52 = new TextStringBuilder(); sb52.insert(0, taint().toCharArray()); sink(sb52.toString()); // $hasTaintFlow - TextStringBuilder sb53 = new TextStringBuilder(); sb53.insert(0, taint().toCharArray(), 0, 0); sink(sb53.toString()); // $hasTaintFlow - TextStringBuilder sb54 = new TextStringBuilder(); sb54.insert(0, taint()); sink(sb54.toString()); // $hasTaintFlow - TextStringBuilder sb55 = new TextStringBuilder(); sb55.insert(0, (Object)taint()); sink(sb55.toString()); // $hasTaintFlow - TextStringBuilder sb56 = new TextStringBuilder(); sb56.append(taint()); sink(sb56.leftString(0)); // $hasTaintFlow - TextStringBuilder sb57 = new TextStringBuilder(); sb57.append(taint()); sink(sb57.midString(0, 0)); // $hasTaintFlow + TextStringBuilder sb52 = new TextStringBuilder(); sb52.insert(0, taint().toCharArray()); sink(sb52.toString()); // $ hasTaintFlow + TextStringBuilder sb53 = new TextStringBuilder(); sb53.insert(0, taint().toCharArray(), 0, 0); sink(sb53.toString()); // $ hasTaintFlow + TextStringBuilder sb54 = new TextStringBuilder(); sb54.insert(0, taint()); sink(sb54.toString()); // $ hasTaintFlow + TextStringBuilder sb55 = new TextStringBuilder(); sb55.insert(0, (Object)taint()); sink(sb55.toString()); // $ hasTaintFlow + TextStringBuilder sb56 = new TextStringBuilder(); sb56.append(taint()); sink(sb56.leftString(0)); // $ hasTaintFlow + TextStringBuilder sb57 = new TextStringBuilder(); sb57.append(taint()); sink(sb57.midString(0, 0)); // $ hasTaintFlow { StringReader reader = new StringReader(taint()); - TextStringBuilder sb58 = new TextStringBuilder(); sb58.readFrom(reader); sink(sb58.toString()); // $hasTaintFlow + TextStringBuilder sb58 = new TextStringBuilder(); sb58.readFrom(reader); sink(sb58.toString()); // $ hasTaintFlow } - TextStringBuilder sb59 = new TextStringBuilder(); sb59.replace(0, 0, taint()); sink(sb59.toString()); // $hasTaintFlow - TextStringBuilder sb60 = new TextStringBuilder(); sb60.replace(null, taint(), 0, 0, 0); sink(sb60.toString()); // $hasTaintFlow - TextStringBuilder sb61 = new TextStringBuilder(); sb61.replaceAll((StringMatcher)null, taint()); sink(sb61.toString()); // $hasTaintFlow - TextStringBuilder sb62 = new TextStringBuilder(); sb62.replaceAll("search", taint()); sink(sb62.toString()); // $hasTaintFlow + TextStringBuilder sb59 = new TextStringBuilder(); sb59.replace(0, 0, taint()); sink(sb59.toString()); // $ hasTaintFlow + TextStringBuilder sb60 = new TextStringBuilder(); sb60.replace(null, taint(), 0, 0, 0); sink(sb60.toString()); // $ hasTaintFlow + TextStringBuilder sb61 = new TextStringBuilder(); sb61.replaceAll((StringMatcher)null, taint()); sink(sb61.toString()); // $ hasTaintFlow + TextStringBuilder sb62 = new TextStringBuilder(); sb62.replaceAll("search", taint()); sink(sb62.toString()); // $ hasTaintFlow TextStringBuilder sb63 = new TextStringBuilder(); sb63.replaceAll(taint(), "replace"); sink(sb63.toString()); // GOOD (search string doesn't convey taint) - TextStringBuilder sb64 = new TextStringBuilder(); sb64.replaceFirst((StringMatcher)null, taint()); sink(sb64.toString()); // $hasTaintFlow - TextStringBuilder sb65 = new TextStringBuilder(); sb65.replaceFirst("search", taint()); sink(sb65.toString()); // $hasTaintFlow + TextStringBuilder sb64 = new TextStringBuilder(); sb64.replaceFirst((StringMatcher)null, taint()); sink(sb64.toString()); // $ hasTaintFlow + TextStringBuilder sb65 = new TextStringBuilder(); sb65.replaceFirst("search", taint()); sink(sb65.toString()); // $ hasTaintFlow TextStringBuilder sb66 = new TextStringBuilder(); sb66.replaceFirst(taint(), "replace"); sink(sb66.toString()); // GOOD (search string doesn't convey taint) - TextStringBuilder sb67 = new TextStringBuilder(); sb67.append(taint()); sink(sb67.rightString(0)); // $hasTaintFlow - TextStringBuilder sb68 = new TextStringBuilder(); sb68.append(taint()); sink(sb68.subSequence(0, 0)); // $hasTaintFlow - TextStringBuilder sb69 = new TextStringBuilder(); sb69.append(taint()); sink(sb69.substring(0)); // $hasTaintFlow - TextStringBuilder sb70 = new TextStringBuilder(); sb70.append(taint()); sink(sb70.substring(0, 0)); // $hasTaintFlow - TextStringBuilder sb71 = new TextStringBuilder(); sb71.append(taint()); sink(sb71.toCharArray()); // $hasTaintFlow - TextStringBuilder sb72 = new TextStringBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $hasTaintFlow - TextStringBuilder sb73 = new TextStringBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $hasTaintFlow - TextStringBuilder sb74 = new TextStringBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $hasTaintFlow + TextStringBuilder sb67 = new TextStringBuilder(); sb67.append(taint()); sink(sb67.rightString(0)); // $ hasTaintFlow + TextStringBuilder sb68 = new TextStringBuilder(); sb68.append(taint()); sink(sb68.subSequence(0, 0)); // $ hasTaintFlow + TextStringBuilder sb69 = new TextStringBuilder(); sb69.append(taint()); sink(sb69.substring(0)); // $ hasTaintFlow + TextStringBuilder sb70 = new TextStringBuilder(); sb70.append(taint()); sink(sb70.substring(0, 0)); // $ hasTaintFlow + TextStringBuilder sb71 = new TextStringBuilder(); sb71.append(taint()); sink(sb71.toCharArray()); // $ hasTaintFlow + TextStringBuilder sb72 = new TextStringBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $ hasTaintFlow + TextStringBuilder sb73 = new TextStringBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $ hasTaintFlow + TextStringBuilder sb74 = new TextStringBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $ hasTaintFlow // Tests for fluent methods (those returning `this`): TextStringBuilder fluentTest = new TextStringBuilder(); - sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $hasTaintFlow + sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $ hasTaintFlow TextStringBuilder fluentBackflowTest = new TextStringBuilder(); fluentBackflowTest.append("Harmless").append(taint()).append("Also harmless"); - sink(fluentBackflowTest.toString()); // $hasTaintFlow + sink(fluentBackflowTest.toString()); // $ hasTaintFlow // Test the case where the fluent method contributing taint is at the end of a statement: TextStringBuilder fluentBackflowTest2 = new TextStringBuilder(); fluentBackflowTest2.append("Harmless").append(taint()); - sink(fluentBackflowTest2.toString()); // $hasTaintFlow + sink(fluentBackflowTest2.toString()); // $ hasTaintFlow // Test all fluent methods are passing taint through to their result: TextStringBuilder fluentAllMethodsTest = new TextStringBuilder(taint()); @@ -172,7 +172,7 @@ void test() throws Exception { .setLength(500) .setNewLineText("newline") .setNullText("NULL") - .trim()); // $hasTaintFlow + .trim()); // $ hasTaintFlow // Test all fluent methods are passing taint back to their qualifier: TextStringBuilder fluentAllMethodsTest2 = new TextStringBuilder(); @@ -204,7 +204,7 @@ void test() throws Exception { .setNullText("NULL") .trim() .append(taint()); - sink(fluentAllMethodsTest2); // $hasTaintFlow + sink(fluentAllMethodsTest2); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/ToStringBuilderTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/ToStringBuilderTest.java index ed2e4400dd7c..59b9206fcc71 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/ToStringBuilderTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/ToStringBuilderTest.java @@ -7,31 +7,31 @@ void sink(Object o) {} void test() throws Exception { - ToStringBuilder sb1 = new ToStringBuilder(null); sb1.append((Object)taint()); sink(sb1.toString()); // $hasTaintFlow - ToStringBuilder sb2 = new ToStringBuilder(null); sb2.append(new Object[] { taint() }); sink(sb2.toString()); // $hasTaintFlow - ToStringBuilder sb3 = new ToStringBuilder(null); sb3.append(taint(), true); sink(sb3.toString()); // $hasTaintFlow - ToStringBuilder sb4 = new ToStringBuilder(null); sb4.append("fieldname", taint()); sink(sb4.toString()); // $hasTaintFlow - ToStringBuilder sb5 = new ToStringBuilder(null); sb5.append("fieldname", new Object[] { taint() }); sink(sb5.toString()); // $hasTaintFlow - ToStringBuilder sb6 = new ToStringBuilder(null); sb6.append("fieldname", new Object[] { taint() }, true); sink(sb6.toString()); // $hasTaintFlow + ToStringBuilder sb1 = new ToStringBuilder(null); sb1.append((Object)taint()); sink(sb1.toString()); // $ hasTaintFlow + ToStringBuilder sb2 = new ToStringBuilder(null); sb2.append(new Object[] { taint() }); sink(sb2.toString()); // $ hasTaintFlow + ToStringBuilder sb3 = new ToStringBuilder(null); sb3.append(taint(), true); sink(sb3.toString()); // $ hasTaintFlow + ToStringBuilder sb4 = new ToStringBuilder(null); sb4.append("fieldname", taint()); sink(sb4.toString()); // $ hasTaintFlow + ToStringBuilder sb5 = new ToStringBuilder(null); sb5.append("fieldname", new Object[] { taint() }); sink(sb5.toString()); // $ hasTaintFlow + ToStringBuilder sb6 = new ToStringBuilder(null); sb6.append("fieldname", new Object[] { taint() }, true); sink(sb6.toString()); // $ hasTaintFlow // GOOD: this appends an Object using the Object.toString style, which does not expose fields or String content. ToStringBuilder sb7 = new ToStringBuilder(null); sb7.appendAsObjectToString(taint()); sink(sb7.toString()); - ToStringBuilder sb8 = new ToStringBuilder(null); sb8.appendSuper(taint()); sink(sb8.toString()); // $hasTaintFlow - ToStringBuilder sb9 = new ToStringBuilder(null); sb9.appendToString(taint()); sink(sb9.toString()); // $hasTaintFlow - ToStringBuilder sb10 = new ToStringBuilder(null); sb10.append((Object)taint()); sink(sb10.build()); // $hasTaintFlow - ToStringBuilder sb11 = new ToStringBuilder(null); sb11.append((Object)taint()); sink(sb11.getStringBuffer().toString()); // $hasTaintFlow + ToStringBuilder sb8 = new ToStringBuilder(null); sb8.appendSuper(taint()); sink(sb8.toString()); // $ hasTaintFlow + ToStringBuilder sb9 = new ToStringBuilder(null); sb9.appendToString(taint()); sink(sb9.toString()); // $ hasTaintFlow + ToStringBuilder sb10 = new ToStringBuilder(null); sb10.append((Object)taint()); sink(sb10.build()); // $ hasTaintFlow + ToStringBuilder sb11 = new ToStringBuilder(null); sb11.append((Object)taint()); sink(sb11.getStringBuffer().toString()); // $ hasTaintFlow // Test fluent methods: ToStringBuilder fluentTest = new ToStringBuilder(null); - sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $hasTaintFlow + sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $ hasTaintFlow ToStringBuilder fluentBackflowTest = new ToStringBuilder(null); fluentBackflowTest.append("Harmless").append(taint()).append("Also harmless"); - sink(fluentBackflowTest.toString()); // $hasTaintFlow + sink(fluentBackflowTest.toString()); // $ hasTaintFlow // Test the case where the fluent method contributing taint is at the end of a statement: ToStringBuilder fluentBackflowTest2 = new ToStringBuilder(null); fluentBackflowTest2.append("Harmless").append(taint()); - sink(fluentBackflowTest2.toString()); // $hasTaintFlow + sink(fluentBackflowTest2.toString()); // $ hasTaintFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java index b6f9c53cc7ef..bc8c72ba221e 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/TripleTest.java @@ -18,69 +18,69 @@ void test() throws Exception { ImmutableTriple taintedRight = ImmutableTriple.of("clean-left", "clean-middle", taint()); // Check flow through ImmutableTriples: - sink(taintedLeft.getLeft()); // $hasValueFlow + sink(taintedLeft.getLeft()); // $ hasValueFlow sink(taintedLeft.getMiddle()); sink(taintedLeft.getRight()); - sink(taintedLeft.left); // $hasValueFlow + sink(taintedLeft.left); // $ hasValueFlow sink(taintedLeft.middle); sink(taintedLeft.right); sink(taintedMiddle.getLeft()); - sink(taintedMiddle.getMiddle()); // $hasValueFlow + sink(taintedMiddle.getMiddle()); // $ hasValueFlow sink(taintedMiddle.getRight()); sink(taintedMiddle.left); - sink(taintedMiddle.middle); // $hasValueFlow + sink(taintedMiddle.middle); // $ hasValueFlow sink(taintedMiddle.right); sink(taintedRight.getLeft()); sink(taintedRight.getMiddle()); - sink(taintedRight.getRight()); // $hasValueFlow + sink(taintedRight.getRight()); // $ hasValueFlow sink(taintedRight.left); sink(taintedRight.middle); - sink(taintedRight.right); // $hasValueFlow + sink(taintedRight.right); // $ hasValueFlow Triple taintedLeft2 = taintedLeft; Triple taintedMiddle2 = taintedMiddle; Triple taintedRight2 = taintedRight; // Check flow also works via an alias of type Triple: - sink(taintedLeft2.getLeft()); // $hasValueFlow + sink(taintedLeft2.getLeft()); // $ hasValueFlow sink(taintedLeft2.getMiddle()); sink(taintedLeft2.getRight()); sink(taintedMiddle2.getLeft()); - sink(taintedMiddle2.getMiddle()); // $hasValueFlow + sink(taintedMiddle2.getMiddle()); // $ hasValueFlow sink(taintedMiddle2.getRight()); sink(taintedRight2.getLeft()); sink(taintedRight2.getMiddle()); - sink(taintedRight2.getRight()); // $hasValueFlow + sink(taintedRight2.getRight()); // $ hasValueFlow // Check flow via Triple.of: Triple taintedLeft3 = Triple.of(taint(), "clean-middle", "clean-right"); Triple taintedMiddle3 = Triple.of("clean-left", taint(), "clean-right"); Triple taintedRight3 = Triple.of("clean-left", "clean-middle", taint()); - sink(taintedLeft3.getLeft()); // $hasValueFlow + sink(taintedLeft3.getLeft()); // $ hasValueFlow sink(taintedLeft3.getMiddle()); sink(taintedLeft3.getRight()); sink(taintedMiddle3.getLeft()); - sink(taintedMiddle3.getMiddle()); // $hasValueFlow + sink(taintedMiddle3.getMiddle()); // $ hasValueFlow sink(taintedMiddle3.getRight()); sink(taintedRight3.getLeft()); sink(taintedRight3.getMiddle()); - sink(taintedRight3.getRight()); // $hasValueFlow + sink(taintedRight3.getRight()); // $ hasValueFlow // Check flow via constructor: ImmutableTriple taintedLeft4 = new ImmutableTriple(taint(), "clean-middle", "clean-right"); ImmutableTriple taintedMiddle4 = new ImmutableTriple("clean-left", taint(), "clean-right"); ImmutableTriple taintedRight4 = new ImmutableTriple("clean-left", "clean-middle", taint()); - sink(taintedLeft4.getLeft()); // $hasValueFlow + sink(taintedLeft4.getLeft()); // $ hasValueFlow sink(taintedLeft4.getMiddle()); sink(taintedLeft4.getRight()); sink(taintedMiddle4.getLeft()); - sink(taintedMiddle4.getMiddle()); // $hasValueFlow + sink(taintedMiddle4.getMiddle()); // $ hasValueFlow sink(taintedMiddle4.getRight()); sink(taintedRight4.getLeft()); sink(taintedRight4.getMiddle()); - sink(taintedRight4.getRight()); // $hasValueFlow + sink(taintedRight4.getRight()); // $ hasValueFlow MutableTriple mutableTaintedLeft = MutableTriple.of(taint(), "clean-middle", "clean-right"); MutableTriple mutableTaintedMiddle = MutableTriple.of("clean-left", taint(), "clean-right"); @@ -96,60 +96,60 @@ void test() throws Exception { MutableTriple mutableTaintedRightConstructed = new MutableTriple("clean-left", "clean-middle", taint()); // Check flow through MutableTriples: - sink(mutableTaintedLeft.getLeft()); // $hasValueFlow + sink(mutableTaintedLeft.getLeft()); // $ hasValueFlow sink(mutableTaintedLeft.getMiddle()); sink(mutableTaintedLeft.getRight()); - sink(mutableTaintedLeft.left); // $hasValueFlow + sink(mutableTaintedLeft.left); // $ hasValueFlow sink(mutableTaintedLeft.middle); sink(mutableTaintedLeft.right); sink(mutableTaintedMiddle.getLeft()); - sink(mutableTaintedMiddle.getMiddle()); // $hasValueFlow + sink(mutableTaintedMiddle.getMiddle()); // $ hasValueFlow sink(mutableTaintedMiddle.getRight()); sink(mutableTaintedMiddle.left); - sink(mutableTaintedMiddle.middle); // $hasValueFlow + sink(mutableTaintedMiddle.middle); // $ hasValueFlow sink(mutableTaintedMiddle.right); sink(mutableTaintedRight.getLeft()); sink(mutableTaintedRight.getMiddle()); - sink(mutableTaintedRight.getRight()); // $hasValueFlow + sink(mutableTaintedRight.getRight()); // $ hasValueFlow sink(mutableTaintedRight.left); sink(mutableTaintedRight.middle); - sink(mutableTaintedRight.right); // $hasValueFlow - sink(setTaintedLeft.getLeft()); // $hasValueFlow + sink(mutableTaintedRight.right); // $ hasValueFlow + sink(setTaintedLeft.getLeft()); // $ hasValueFlow sink(setTaintedLeft.getMiddle()); sink(setTaintedLeft.getRight()); - sink(setTaintedLeft.left); // $hasValueFlow + sink(setTaintedLeft.left); // $ hasValueFlow sink(setTaintedLeft.middle); sink(setTaintedLeft.right); sink(setTaintedMiddle.getLeft()); - sink(setTaintedMiddle.getMiddle()); // $hasValueFlow + sink(setTaintedMiddle.getMiddle()); // $ hasValueFlow sink(setTaintedMiddle.getRight()); sink(setTaintedMiddle.left); - sink(setTaintedMiddle.middle); // $hasValueFlow + sink(setTaintedMiddle.middle); // $ hasValueFlow sink(setTaintedMiddle.right); sink(setTaintedRight.getLeft()); sink(setTaintedRight.getMiddle()); - sink(setTaintedRight.getRight()); // $hasValueFlow + sink(setTaintedRight.getRight()); // $ hasValueFlow sink(setTaintedRight.left); sink(setTaintedRight.middle); - sink(setTaintedRight.right); // $hasValueFlow - sink(mutableTaintedLeftConstructed.getLeft()); // $hasValueFlow + sink(setTaintedRight.right); // $ hasValueFlow + sink(mutableTaintedLeftConstructed.getLeft()); // $ hasValueFlow sink(mutableTaintedLeftConstructed.getMiddle()); sink(mutableTaintedLeftConstructed.getRight()); - sink(mutableTaintedLeftConstructed.left); // $hasValueFlow + sink(mutableTaintedLeftConstructed.left); // $ hasValueFlow sink(mutableTaintedLeftConstructed.middle); sink(mutableTaintedLeftConstructed.right); sink(mutableTaintedMiddleConstructed.getLeft()); - sink(mutableTaintedMiddleConstructed.getMiddle()); // $hasValueFlow + sink(mutableTaintedMiddleConstructed.getMiddle()); // $ hasValueFlow sink(mutableTaintedMiddleConstructed.getRight()); sink(mutableTaintedMiddleConstructed.left); - sink(mutableTaintedMiddleConstructed.middle); // $hasValueFlow + sink(mutableTaintedMiddleConstructed.middle); // $ hasValueFlow sink(mutableTaintedMiddleConstructed.right); sink(mutableTaintedRightConstructed.getLeft()); sink(mutableTaintedRightConstructed.getMiddle()); - sink(mutableTaintedRightConstructed.getRight()); // $hasValueFlow + sink(mutableTaintedRightConstructed.getRight()); // $ hasValueFlow sink(mutableTaintedRightConstructed.left); sink(mutableTaintedRightConstructed.middle); - sink(mutableTaintedRightConstructed.right); // $hasValueFlow + sink(mutableTaintedRightConstructed.right); // $ hasValueFlow Triple mutableTaintedLeft2 = mutableTaintedLeft; Triple mutableTaintedMiddle2 = mutableTaintedMiddle; @@ -159,23 +159,23 @@ void test() throws Exception { Triple setTaintedRight2 = setTaintedRight; // Check flow also works via an alias of type Triple: - sink(mutableTaintedLeft2.getLeft()); // $hasValueFlow + sink(mutableTaintedLeft2.getLeft()); // $ hasValueFlow sink(mutableTaintedLeft2.getMiddle()); sink(mutableTaintedLeft2.getRight()); sink(mutableTaintedMiddle2.getLeft()); - sink(mutableTaintedMiddle2.getMiddle()); // $hasValueFlow + sink(mutableTaintedMiddle2.getMiddle()); // $ hasValueFlow sink(mutableTaintedMiddle2.getRight()); sink(mutableTaintedRight2.getLeft()); sink(mutableTaintedRight2.getMiddle()); - sink(mutableTaintedRight2.getRight()); // $hasValueFlow - sink(setTaintedLeft2.getLeft()); // $hasValueFlow + sink(mutableTaintedRight2.getRight()); // $ hasValueFlow + sink(setTaintedLeft2.getLeft()); // $ hasValueFlow sink(setTaintedLeft2.getMiddle()); sink(setTaintedLeft2.getRight()); sink(setTaintedMiddle2.getLeft()); - sink(setTaintedMiddle2.getMiddle()); // $hasValueFlow + sink(setTaintedMiddle2.getMiddle()); // $ hasValueFlow sink(setTaintedMiddle2.getRight()); sink(setTaintedRight2.getLeft()); sink(setTaintedRight2.getMiddle()); - sink(setTaintedRight2.getRight()); // $hasValueFlow + sink(setTaintedRight2.getRight()); // $ hasValueFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTest.java index 5b64915ffb73..60edaf669929 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTest.java @@ -6,20 +6,20 @@ public class WordUtilsTest { void sink(Object o) {} void test() throws Exception { - sink(WordUtils.capitalize(taint())); // $hasTaintFlow - sink(WordUtils.capitalize(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.capitalizeFully(taint())); // $hasTaintFlow - sink(WordUtils.capitalizeFully(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.initials(taint())); // $hasTaintFlow - sink(WordUtils.initials(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.swapCase(taint())); // $hasTaintFlow - sink(WordUtils.uncapitalize(taint())); // $hasTaintFlow - sink(WordUtils.uncapitalize(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.wrap(taint(), 0)); // $hasTaintFlow - sink(WordUtils.wrap(taint(), 0, "\n", false)); // $hasTaintFlow - sink(WordUtils.wrap("wrap me", 0, taint(), false)); // $hasTaintFlow - sink(WordUtils.wrap(taint(), 0, "\n", false, "\n")); // $hasTaintFlow - sink(WordUtils.wrap("wrap me", 0, taint(), false, "\n")); // $hasTaintFlow + sink(WordUtils.capitalize(taint())); // $ hasTaintFlow + sink(WordUtils.capitalize(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.capitalizeFully(taint())); // $ hasTaintFlow + sink(WordUtils.capitalizeFully(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.initials(taint())); // $ hasTaintFlow + sink(WordUtils.initials(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.swapCase(taint())); // $ hasTaintFlow + sink(WordUtils.uncapitalize(taint())); // $ hasTaintFlow + sink(WordUtils.uncapitalize(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.wrap(taint(), 0)); // $ hasTaintFlow + sink(WordUtils.wrap(taint(), 0, "\n", false)); // $ hasTaintFlow + sink(WordUtils.wrap("wrap me", 0, taint(), false)); // $ hasTaintFlow + sink(WordUtils.wrap(taint(), 0, "\n", false, "\n")); // $ hasTaintFlow + sink(WordUtils.wrap("wrap me", 0, taint(), false, "\n")); // $ hasTaintFlow // GOOD: the wrap-on line terminator does not propagate to the return value sink(WordUtils.wrap("wrap me", 0, "\n", false, taint())); } diff --git a/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTextTest.java b/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTextTest.java index 14318a08d56b..ef0baa1ed92b 100644 --- a/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTextTest.java +++ b/java/ql/test/library-tests/frameworks/apache-commons-lang3/WordUtilsTextTest.java @@ -6,22 +6,22 @@ public class WordUtilsTextTest { void sink(Object o) {} void test() throws Exception { - sink(WordUtils.abbreviate(taint(), 0, 0, "append me")); // $hasTaintFlow - sink(WordUtils.abbreviate("abbreviate me", 0, 0, taint())); // $hasTaintFlow - sink(WordUtils.capitalize(taint())); // $hasTaintFlow - sink(WordUtils.capitalize(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.capitalizeFully(taint())); // $hasTaintFlow - sink(WordUtils.capitalizeFully(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.initials(taint())); // $hasTaintFlow - sink(WordUtils.initials(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.swapCase(taint())); // $hasTaintFlow - sink(WordUtils.uncapitalize(taint())); // $hasTaintFlow - sink(WordUtils.uncapitalize(taint(), ' ', ',')); // $hasTaintFlow - sink(WordUtils.wrap(taint(), 0)); // $hasTaintFlow - sink(WordUtils.wrap(taint(), 0, "\n", false)); // $hasTaintFlow - sink(WordUtils.wrap("wrap me", 0, taint(), false)); // $hasTaintFlow - sink(WordUtils.wrap(taint(), 0, "\n", false, "\n")); // $hasTaintFlow - sink(WordUtils.wrap("wrap me", 0, taint(), false, "\n")); // $hasTaintFlow + sink(WordUtils.abbreviate(taint(), 0, 0, "append me")); // $ hasTaintFlow + sink(WordUtils.abbreviate("abbreviate me", 0, 0, taint())); // $ hasTaintFlow + sink(WordUtils.capitalize(taint())); // $ hasTaintFlow + sink(WordUtils.capitalize(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.capitalizeFully(taint())); // $ hasTaintFlow + sink(WordUtils.capitalizeFully(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.initials(taint())); // $ hasTaintFlow + sink(WordUtils.initials(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.swapCase(taint())); // $ hasTaintFlow + sink(WordUtils.uncapitalize(taint())); // $ hasTaintFlow + sink(WordUtils.uncapitalize(taint(), ' ', ',')); // $ hasTaintFlow + sink(WordUtils.wrap(taint(), 0)); // $ hasTaintFlow + sink(WordUtils.wrap(taint(), 0, "\n", false)); // $ hasTaintFlow + sink(WordUtils.wrap("wrap me", 0, taint(), false)); // $ hasTaintFlow + sink(WordUtils.wrap(taint(), 0, "\n", false, "\n")); // $ hasTaintFlow + sink(WordUtils.wrap("wrap me", 0, taint(), false, "\n")); // $ hasTaintFlow // GOOD: the wrap-on line terminator does not propagate to the return value sink(WordUtils.wrap("wrap me", 0, "\n", false, taint())); } diff --git a/java/ql/test/library-tests/frameworks/apache-http/A.java b/java/ql/test/library-tests/frameworks/apache-http/A.java index e33bf3915901..c9ac2bde3a21 100644 --- a/java/ql/test/library-tests/frameworks/apache-http/A.java +++ b/java/ql/test/library-tests/frameworks/apache-http/A.java @@ -12,54 +12,54 @@ static void sink(Object o) { } class Test1 implements HttpRequestHandler { public void handle(HttpRequest req, HttpResponse res, HttpContext ctx) throws IOException { - A.sink(req.getRequestLine()); //$hasTaintFlow - A.sink(req.getRequestLine().getUri()); //$hasTaintFlow - A.sink(req.getRequestLine().getMethod()); //$hasTaintFlow - A.sink(req.getAllHeaders()); //$hasTaintFlow + A.sink(req.getRequestLine()); // $ hasTaintFlow + A.sink(req.getRequestLine().getUri()); // $ hasTaintFlow + A.sink(req.getRequestLine().getMethod()); // $ hasTaintFlow + A.sink(req.getAllHeaders()); // $ hasTaintFlow HeaderIterator it = req.headerIterator(); - A.sink(it.next()); //$hasTaintFlow - A.sink(it.nextHeader()); //$hasTaintFlow + A.sink(it.next()); // $ hasTaintFlow + A.sink(it.nextHeader()); // $ hasTaintFlow Header h = req.getHeaders("abc")[3]; - A.sink(h.getName()); //$hasTaintFlow - A.sink(h.getValue()); //$hasTaintFlow + A.sink(h.getName()); // $ hasTaintFlow + A.sink(h.getValue()); // $ hasTaintFlow HeaderElement el = h.getElements()[0]; - A.sink(el.getName()); //$hasTaintFlow - A.sink(el.getValue()); //$hasTaintFlow - A.sink(el.getParameters()); //$hasTaintFlow - A.sink(el.getParameterByName("abc").getValue()); //$hasTaintFlow - A.sink(el.getParameter(0).getName()); //$hasTaintFlow + A.sink(el.getName()); // $ hasTaintFlow + A.sink(el.getValue()); // $ hasTaintFlow + A.sink(el.getParameters()); // $ hasTaintFlow + A.sink(el.getParameterByName("abc").getValue()); // $ hasTaintFlow + A.sink(el.getParameter(0).getName()); // $ hasTaintFlow HttpEntity ent = ((HttpEntityEnclosingRequest)req).getEntity(); - A.sink(ent.getContent()); //$hasTaintFlow - A.sink(ent.getContentEncoding()); //$hasTaintFlow - A.sink(ent.getContentType()); //$hasTaintFlow - A.sink(EntityUtils.toString(ent)); //$hasTaintFlow - A.sink(EntityUtils.toByteArray(ent)); //$hasTaintFlow - A.sink(EntityUtils.getContentCharSet(ent)); //$hasTaintFlow - A.sink(EntityUtils.getContentMimeType(ent)); //$hasTaintFlow - res.setEntity(new StringEntity("a")); //$hasTaintFlow - EntityUtils.updateEntity(res, new ByteArrayEntity(EntityUtils.toByteArray(ent))); //$hasTaintFlow - res.setHeader("Location", req.getRequestLine().getUri()); //$hasTaintFlow - res.setHeader(new BasicHeader("Location", req.getRequestLine().getUri())); //$hasTaintFlow + A.sink(ent.getContent()); // $ hasTaintFlow + A.sink(ent.getContentEncoding()); // $ hasTaintFlow + A.sink(ent.getContentType()); // $ hasTaintFlow + A.sink(EntityUtils.toString(ent)); // $ hasTaintFlow + A.sink(EntityUtils.toByteArray(ent)); // $ hasTaintFlow + A.sink(EntityUtils.getContentCharSet(ent)); // $ hasTaintFlow + A.sink(EntityUtils.getContentMimeType(ent)); // $ hasTaintFlow + res.setEntity(new StringEntity("a")); // $ hasTaintFlow + EntityUtils.updateEntity(res, new ByteArrayEntity(EntityUtils.toByteArray(ent))); // $ hasTaintFlow + res.setHeader("Location", req.getRequestLine().getUri()); // $ hasTaintFlow + res.setHeader(new BasicHeader("Location", req.getRequestLine().getUri())); // $ hasTaintFlow } } void test2() { ByteArrayBuffer bbuf = new ByteArrayBuffer(42); bbuf.append((byte[]) taint(), 0, 3); - sink(bbuf.buffer()); //$hasTaintFlow - sink(bbuf.toByteArray()); //$hasTaintFlow + sink(bbuf.buffer()); // $ hasTaintFlow + sink(bbuf.toByteArray()); // $ hasTaintFlow CharArrayBuffer cbuf = new CharArrayBuffer(42); cbuf.append(bbuf.toByteArray(), 0, 3); - sink(cbuf.toCharArray()); //$hasTaintFlow - sink(cbuf.toString()); //$hasTaintFlow - sink(cbuf.subSequence(0, 3)); //$hasTaintFlow - sink(cbuf.substring(0, 3)); //$hasTaintFlow - sink(cbuf.substringTrimmed(0, 3)); //$hasTaintFlow + sink(cbuf.toCharArray()); // $ hasTaintFlow + sink(cbuf.toString()); // $ hasTaintFlow + sink(cbuf.subSequence(0, 3)); // $ hasTaintFlow + sink(cbuf.substring(0, 3)); // $ hasTaintFlow + sink(cbuf.substringTrimmed(0, 3)); // $ hasTaintFlow - sink(Args.notNull(taint(), "x")); //$hasTaintFlow - sink(Args.notEmpty((String) taint(), "x")); //$hasTaintFlow - sink(Args.notBlank((String) taint(), "x")); //$hasTaintFlow + sink(Args.notNull(taint(), "x")); // $ hasTaintFlow + sink(Args.notEmpty((String) taint(), "x")); // $ hasTaintFlow + sink(Args.notBlank((String) taint(), "x")); // $ hasTaintFlow sink(Args.notNull("x", (String) taint())); // Good } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/apache-http/B.java b/java/ql/test/library-tests/frameworks/apache-http/B.java index 493aaadd8e3a..d1bca8462d39 100644 --- a/java/ql/test/library-tests/frameworks/apache-http/B.java +++ b/java/ql/test/library-tests/frameworks/apache-http/B.java @@ -14,63 +14,63 @@ static void sink(Object o) { } class Test1 implements HttpRequestHandler { public void handle(ClassicHttpRequest req, ClassicHttpResponse res, HttpContext ctx) throws IOException, ParseException { - B.sink(req.getAuthority().getHostName()); //$hasTaintFlow - B.sink(req.getAuthority().toString()); //$hasTaintFlow - B.sink(req.getMethod()); //$hasTaintFlow - B.sink(req.getPath()); //$hasTaintFlow - B.sink(req.getScheme()); - B.sink(req.getRequestUri()); //$hasTaintFlow + B.sink(req.getAuthority().getHostName()); // $ hasTaintFlow + B.sink(req.getAuthority().toString()); // $ hasTaintFlow + B.sink(req.getMethod()); // $ hasTaintFlow + B.sink(req.getPath()); // $ hasTaintFlow + B.sink(req.getScheme()); + B.sink(req.getRequestUri()); // $ hasTaintFlow RequestLine line = new RequestLine(req); - B.sink(line.getUri()); //$hasTaintFlow - B.sink(line.getMethod()); //$hasTaintFlow - B.sink(req.getHeaders()); //$hasTaintFlow - B.sink(req.headerIterator()); //$hasTaintFlow + B.sink(line.getUri()); // $ hasTaintFlow + B.sink(line.getMethod()); // $ hasTaintFlow + B.sink(req.getHeaders()); // $ hasTaintFlow + B.sink(req.headerIterator()); // $ hasTaintFlow Header h = req.getHeaders("abc")[3]; - B.sink(h.getName()); //$hasTaintFlow - B.sink(h.getValue()); //$hasTaintFlow - B.sink(req.getFirstHeader("abc")); //$hasTaintFlow - B.sink(req.getLastHeader("abc")); //$hasTaintFlow + B.sink(h.getName()); // $ hasTaintFlow + B.sink(h.getValue()); // $ hasTaintFlow + B.sink(req.getFirstHeader("abc")); // $ hasTaintFlow + B.sink(req.getLastHeader("abc")); // $ hasTaintFlow HttpEntity ent = req.getEntity(); - B.sink(ent.getContent()); //$hasTaintFlow - B.sink(ent.getContentEncoding()); //$hasTaintFlow - B.sink(ent.getContentType()); //$hasTaintFlow - B.sink(ent.getTrailerNames()); //$hasTaintFlow - B.sink(ent.getTrailers().get()); //$hasTaintFlow - B.sink(EntityUtils.toString(ent)); //$hasTaintFlow - B.sink(EntityUtils.toByteArray(ent)); //$hasTaintFlow - B.sink(EntityUtils.parse(ent)); //$hasTaintFlow - res.setEntity(new StringEntity("a")); //$hasTaintFlow - res.setEntity(new ByteArrayEntity(EntityUtils.toByteArray(ent), ContentType.TEXT_HTML)); //$hasTaintFlow - res.setEntity(HttpEntities.create("a")); //$hasTaintFlow - res.setHeader("Location", req.getRequestUri()); //$hasTaintFlow - res.setHeader(new BasicHeader("Location", req.getRequestUri())); //$hasTaintFlow + B.sink(ent.getContent()); // $ hasTaintFlow + B.sink(ent.getContentEncoding()); // $ hasTaintFlow + B.sink(ent.getContentType()); // $ hasTaintFlow + B.sink(ent.getTrailerNames()); // $ hasTaintFlow + B.sink(ent.getTrailers().get()); // $ hasTaintFlow + B.sink(EntityUtils.toString(ent)); // $ hasTaintFlow + B.sink(EntityUtils.toByteArray(ent)); // $ hasTaintFlow + B.sink(EntityUtils.parse(ent)); // $ hasTaintFlow + res.setEntity(new StringEntity("a")); // $ hasTaintFlow + res.setEntity(new ByteArrayEntity(EntityUtils.toByteArray(ent), ContentType.TEXT_HTML)); // $ hasTaintFlow + res.setEntity(HttpEntities.create("a")); // $ hasTaintFlow + res.setHeader("Location", req.getRequestUri()); // $ hasTaintFlow + res.setHeader(new BasicHeader("Location", req.getRequestUri())); // $ hasTaintFlow } } void test2() { ByteArrayBuffer bbuf = new ByteArrayBuffer(42); - bbuf.append((byte[]) taint(), 0, 3); - sink(bbuf.array()); //$hasTaintFlow - sink(bbuf.toByteArray()); //$hasTaintFlow - sink(bbuf.toString()); + bbuf.append((byte[]) taint(), 0, 3); + sink(bbuf.array()); // $ hasTaintFlow + sink(bbuf.toByteArray()); // $ hasTaintFlow + sink(bbuf.toString()); CharArrayBuffer cbuf = new CharArrayBuffer(42); - cbuf.append(bbuf.toByteArray(), 0, 3); - sink(cbuf.toCharArray()); //$hasTaintFlow - sink(cbuf.toString()); //$hasTaintFlow - sink(cbuf.subSequence(0, 3)); //$hasTaintFlow - sink(cbuf.substring(0, 3)); //$hasTaintFlow - sink(cbuf.substringTrimmed(0, 3)); //$hasTaintFlow + cbuf.append(bbuf.toByteArray(), 0, 3); + sink(cbuf.toCharArray()); // $ hasTaintFlow + sink(cbuf.toString()); // $ hasTaintFlow + sink(cbuf.subSequence(0, 3)); // $ hasTaintFlow + sink(cbuf.substring(0, 3)); // $ hasTaintFlow + sink(cbuf.substringTrimmed(0, 3)); // $ hasTaintFlow - sink(Args.notNull(taint(), "x")); //$hasTaintFlow - sink(Args.notEmpty((String) taint(), "x")); //$hasTaintFlow - sink(Args.notBlank((String) taint(), "x")); //$hasTaintFlow - sink(Args.notNull("x", (String) taint())); + sink(Args.notNull(taint(), "x")); // $ hasTaintFlow + sink(Args.notEmpty((String) taint(), "x")); // $ hasTaintFlow + sink(Args.notBlank((String) taint(), "x")); // $ hasTaintFlow + sink(Args.notNull("x", (String) taint())); } class Test3 implements HttpServerRequestHandler { public void handle(ClassicHttpRequest req, HttpServerRequestHandler.ResponseTrigger restr, HttpContext ctx) throws HttpException, IOException { - B.sink(req.getEntity()); //$hasTaintFlow + B.sink(req.getEntity()); // $ hasTaintFlow } } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/guava/handwritten/TestBase.java b/java/ql/test/library-tests/frameworks/guava/handwritten/TestBase.java index 963b971235f4..e2e4150fdfe3 100644 --- a/java/ql/test/library-tests/frameworks/guava/handwritten/TestBase.java +++ b/java/ql/test/library-tests/frameworks/guava/handwritten/TestBase.java @@ -13,13 +13,13 @@ void sink(Object o) {} void test1() { String x = taint(); - sink(Strings.padStart(x, 10, ' ')); // $numTaintFlow=1 - sink(Strings.padEnd(x, 10, ' ')); // $numTaintFlow=1 - sink(Strings.repeat(x, 3)); // $numTaintFlow=1 - sink(Strings.emptyToNull(Strings.nullToEmpty(x))); // $numValueFlow=1 - sink(Strings.lenientFormat(x, 3)); // $numTaintFlow=1 - sink(Strings.commonPrefix(x, "abc")); - sink(Strings.commonSuffix(x, "cde")); + sink(Strings.padStart(x, 10, ' ')); // $ numTaintFlow=1 + sink(Strings.padEnd(x, 10, ' ')); // $ numTaintFlow=1 + sink(Strings.repeat(x, 3)); // $ numTaintFlow=1 + sink(Strings.emptyToNull(Strings.nullToEmpty(x))); // $ numValueFlow=1 + sink(Strings.lenientFormat(x, 3)); // $ numTaintFlow=1 + sink(Strings.commonPrefix(x, "abc")); + sink(Strings.commonSuffix(x, "cde")); sink(Strings.lenientFormat("%s = %s", x, 3)); // $ numTaintFlow=1 } @@ -28,10 +28,10 @@ void test2() { Splitter s = Splitter.on(x).omitEmptyStrings(); sink(s.split("x y z")); - sink(s.split(x)); // $numTaintFlow=1 - sink(s.splitToList(x)); // $numTaintFlow=1 + sink(s.split(x)); // $ numTaintFlow=1 + sink(s.splitToList(x)); // $ numTaintFlow=1 sink(s.withKeyValueSeparator("=").split("a=b")); - sink(s.withKeyValueSeparator("=").split(x)); // $numTaintFlow=1 + sink(s.withKeyValueSeparator("=").split(x)); // $ numTaintFlow=1 } void test3() { @@ -42,68 +42,68 @@ void test3() { StringBuilder sb = new StringBuilder(); sink(safeJoiner.appendTo(sb, "a", "b", "c")); sink(sb.toString()); - sink(taintedJoiner.appendTo(sb, "a", "b", "c")); // $numTaintFlow=1 - sink(sb.toString()); // $numTaintFlow=1 - sink(safeJoiner.appendTo(sb, "a", "b", "c")); // $numTaintFlow=1 - sink(sb.toString()); // $numTaintFlow=1 + sink(taintedJoiner.appendTo(sb, "a", "b", "c")); // $ numTaintFlow=1 + sink(sb.toString()); // $ numTaintFlow=1 + sink(safeJoiner.appendTo(sb, "a", "b", "c")); // $ numTaintFlow=1 + sink(sb.toString()); // $ numTaintFlow=1 sb = new StringBuilder(); - sink(safeJoiner.appendTo(sb, x, x)); // $numTaintFlow=1 + sink(safeJoiner.appendTo(sb, x, x)); // $ numTaintFlow=1 Map m = new HashMap(); m.put("k", "v"); sink(safeJoiner.withKeyValueSeparator("=").join(m)); - sink(safeJoiner.withKeyValueSeparator(x).join(m)); // $numTaintFlow=1 - sink(taintedJoiner.useForNull("(null)").withKeyValueSeparator("=").join(m)); // $numTaintFlow=1 + sink(safeJoiner.withKeyValueSeparator(x).join(m)); // $ numTaintFlow=1 + sink(taintedJoiner.useForNull("(null)").withKeyValueSeparator("=").join(m)); // $ numTaintFlow=1 m.put("k2", x); - sink(safeJoiner.withKeyValueSeparator("=").join(m)); // $numTaintFlow=1 + sink(safeJoiner.withKeyValueSeparator("=").join(m)); // $ numTaintFlow=1 } void test4() { - sink(Preconditions.checkNotNull(taint())); // $numValueFlow=1 - sink(Verify.verifyNotNull(taint())); // $numValueFlow=1 + sink(Preconditions.checkNotNull(taint())); // $ numValueFlow=1 + sink(Verify.verifyNotNull(taint())); // $ numValueFlow=1 } void test5() { - sink(Ascii.toLowerCase(taint())); // $numTaintFlow=1 - sink(Ascii.toUpperCase(taint())); // $numTaintFlow=1 - sink(Ascii.truncate(taint(), 3, "...")); // $numTaintFlow=1 - sink(Ascii.truncate("abcabcabc", 3, taint())); // $numTaintFlow=1 - sink(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, taint())); // $numTaintFlow=1 - sink(CaseFormat.LOWER_HYPHEN.converterTo(CaseFormat.UPPER_CAMEL).convert(taint())); // $numTaintFlow=1 - sink(CaseFormat.LOWER_UNDERSCORE.converterTo(CaseFormat.LOWER_HYPHEN).reverse().convert(taint())); // $numTaintFlow=1 + sink(Ascii.toLowerCase(taint())); // $ numTaintFlow=1 + sink(Ascii.toUpperCase(taint())); // $ numTaintFlow=1 + sink(Ascii.truncate(taint(), 3, "...")); // $ numTaintFlow=1 + sink(Ascii.truncate("abcabcabc", 3, taint())); // $ numTaintFlow=1 + sink(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, taint())); // $ numTaintFlow=1 + sink(CaseFormat.LOWER_HYPHEN.converterTo(CaseFormat.UPPER_CAMEL).convert(taint())); // $ numTaintFlow=1 + sink(CaseFormat.LOWER_UNDERSCORE.converterTo(CaseFormat.LOWER_HYPHEN).reverse().convert(taint())); // $ numTaintFlow=1 } void test6() { - sink(Suppliers.memoize(Suppliers.memoizeWithExpiration(Suppliers.synchronizedSupplier(Suppliers.ofInstance(taint())), 3, TimeUnit.HOURS)).get()); // $numTaintFlow=1 + sink(Suppliers.memoize(Suppliers.memoizeWithExpiration(Suppliers.synchronizedSupplier(Suppliers.ofInstance(taint())), 3, TimeUnit.HOURS)).get()); // $ numTaintFlow=1 } void test7() { - sink(MoreObjects.firstNonNull(taint(), taint())); // $numValueFlow=2 - sink(MoreObjects.firstNonNull(null, taint())); // $numValueFlow=1 - sink(MoreObjects.firstNonNull(taint(), null)); // $numValueFlow=1 - sink(MoreObjects.toStringHelper(taint()).add("x", 3).omitNullValues().toString()); // $numTaintFlow=1 + sink(MoreObjects.firstNonNull(taint(), taint())); // $ numValueFlow=2 + sink(MoreObjects.firstNonNull(null, taint())); // $ numValueFlow=1 + sink(MoreObjects.firstNonNull(taint(), null)); // $ numValueFlow=1 + sink(MoreObjects.toStringHelper(taint()).add("x", 3).omitNullValues().toString()); // $ numTaintFlow=1 sink(MoreObjects.toStringHelper((Object) taint()).toString()); - sink(MoreObjects.toStringHelper("a").add("x", 3).add(taint(), 4).toString()); // $numTaintFlow=1 - sink(MoreObjects.toStringHelper("a").add("x", taint()).toString()); // $numTaintFlow=1 - sink(MoreObjects.toStringHelper("a").addValue(taint()).toString()); // $numTaintFlow=1 + sink(MoreObjects.toStringHelper("a").add("x", 3).add(taint(), 4).toString()); // $ numTaintFlow=1 + sink(MoreObjects.toStringHelper("a").add("x", taint()).toString()); // $ numTaintFlow=1 + sink(MoreObjects.toStringHelper("a").addValue(taint()).toString()); // $ numTaintFlow=1 MoreObjects.ToStringHelper h = MoreObjects.toStringHelper("a"); h.add("x", 3).add(taint(), 4); - sink(h.add("z",5).toString()); // $numTaintFlow=1 + sink(h.add("z",5).toString()); // $ numTaintFlow=1 } void test8() { Optional x = Optional.of(taint()); sink(x); // no flow - sink(x.get()); // $numValueFlow=1 - sink(x.or("hi")); // $numValueFlow=1 - sink(x.orNull()); // $numValueFlow=1 - sink(x.asSet().toArray()[0]); // $numValueFlow=1 - sink(Optional.fromJavaUtil(x.toJavaUtil()).get()); // $numValueFlow=1 - sink(Optional.fromJavaUtil(Optional.toJavaUtil(x)).get()); // $numValueFlow=1 - sink(Optional.fromNullable(taint()).get()); // $numValueFlow=1 - sink(Optional.absent().or(x).get()); // $numValueFlow=1 - sink(Optional.absent().or(taint())); // $numValueFlow=1 - sink(Optional.presentInstances(Set.of(x)).iterator().next()); // $numValueFlow=1 + sink(x.get()); // $ numValueFlow=1 + sink(x.or("hi")); // $ numValueFlow=1 + sink(x.orNull()); // $ numValueFlow=1 + sink(x.asSet().toArray()[0]); // $ numValueFlow=1 + sink(Optional.fromJavaUtil(x.toJavaUtil()).get()); // $ numValueFlow=1 + sink(Optional.fromJavaUtil(Optional.toJavaUtil(x)).get()); // $ numValueFlow=1 + sink(Optional.fromNullable(taint()).get()); // $ numValueFlow=1 + sink(Optional.absent().or(x).get()); // $ numValueFlow=1 + sink(Optional.absent().or(taint())); // $ numValueFlow=1 + sink(Optional.presentInstances(Set.of(x)).iterator().next()); // $ numValueFlow=1 } } diff --git a/java/ql/test/library-tests/frameworks/guava/handwritten/TestCollect.java b/java/ql/test/library-tests/frameworks/guava/handwritten/TestCollect.java index 09dd28c19bae..f12dcb485d5c 100644 --- a/java/ql/test/library-tests/frameworks/guava/handwritten/TestCollect.java +++ b/java/ql/test/library-tests/frameworks/guava/handwritten/TestCollect.java @@ -47,25 +47,25 @@ void test1() { String x = taint(); ImmutableSet xs = ImmutableSet.of(x, "y", "z"); - sink(element(xs.asList())); // $numValueFlow=1 + sink(element(xs.asList())); // $ numValueFlow=1 ImmutableSet ys = ImmutableSet.of("a", "b", "c"); - sink(element(Sets.filter(Sets.union(xs, ys), y -> true))); // $numValueFlow=1 + sink(element(Sets.filter(Sets.union(xs, ys), y -> true))); // $ numValueFlow=1 - sink(element(Sets.newHashSet("a", "b", "c", "d", x))); // $numValueFlow=1 + sink(element(Sets.newHashSet("a", "b", "c", "d", x))); // $ numValueFlow=1 } void test2() { - sink(element(ImmutableList.of(taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint()))); // $numValueFlow=16 - sink(element(ImmutableSet.of(taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint()))); // $numValueFlow=16 - sink(mapKey(ImmutableMap.of(taint(), taint(), taint(), taint()))); // $numValueFlow=2 - sink(mapValue(ImmutableMap.of(taint(), taint(), taint(), taint()))); // $numValueFlow=2 - sink(multimapKey(ImmutableMultimap.of(taint(), taint(), taint(), taint()))); // $numValueFlow=2 - sink(multimapValue(ImmutableMultimap.of(taint(), taint(), taint(), taint()))); // $numValueFlow=2 - sink(tableRow(ImmutableTable.of(taint(), taint(), taint()))); // $numValueFlow=1 - sink(tableColumn(ImmutableTable.of(taint(), taint(), taint()))); // $numValueFlow=1 - sink(tableValue(ImmutableTable.of(taint(), taint(), taint()))); // $numValueFlow=1 + sink(element(ImmutableList.of(taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint()))); // $ numValueFlow=16 + sink(element(ImmutableSet.of(taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint(),taint(), taint(), taint(), taint()))); // $ numValueFlow=16 + sink(mapKey(ImmutableMap.of(taint(), taint(), taint(), taint()))); // $ numValueFlow=2 + sink(mapValue(ImmutableMap.of(taint(), taint(), taint(), taint()))); // $ numValueFlow=2 + sink(multimapKey(ImmutableMultimap.of(taint(), taint(), taint(), taint()))); // $ numValueFlow=2 + sink(multimapValue(ImmutableMultimap.of(taint(), taint(), taint(), taint()))); // $ numValueFlow=2 + sink(tableRow(ImmutableTable.of(taint(), taint(), taint()))); // $ numValueFlow=1 + sink(tableColumn(ImmutableTable.of(taint(), taint(), taint()))); // $ numValueFlow=1 + sink(tableValue(ImmutableTable.of(taint(), taint(), taint()))); // $ numValueFlow=1 } void test3() { @@ -76,60 +76,60 @@ void test3() { b.add("a"); sink(b); b.add(x); - sink(element(b.build())); // $numValueFlow=1 + sink(element(b.build())); // $ numValueFlow=1 b = ImmutableList.builder(); b.add("a").add(x); - sink(element(b.build())); // $numValueFlow=1 + sink(element(b.build())); // $ numValueFlow=1 - sink(ImmutableList.builder().add("a").add(x).build().toArray()[0]); // $numValueFlow=1 + sink(ImmutableList.builder().add("a").add(x).build().toArray()[0]); // $ numValueFlow=1 ImmutableMap.Builder b2 = ImmutableMap.builder(); b2.put(x,"v"); - sink(mapKey(b2.build())); // $numValueFlow=1 + sink(mapKey(b2.build())); // $ numValueFlow=1 b2.put("k",x); - sink(mapValue(b2.build())); // $numValueFlow=1 + sink(mapValue(b2.build())); // $ numValueFlow=1 } void test4(Table t1, Table t2, Table t3) { String x = taint(); t1.put(x, "c", "v"); - sink(tableRow(t1)); // $numValueFlow=1 + sink(tableRow(t1)); // $ numValueFlow=1 t1.put("r", x, "v"); - sink(tableColumn(t1)); // $numValueFlow=1 + sink(tableColumn(t1)); // $ numValueFlow=1 t1.put("r", "c", x); - sink(tableValue(t1)); // $numValueFlow=1 - sink(mapKey(t1.row("r"))); // $numValueFlow=1 - sink(mapValue(t1.row("r"))); // $numValueFlow=1 - + sink(tableValue(t1)); // $ numValueFlow=1 + sink(mapKey(t1.row("r"))); // $ numValueFlow=1 + sink(mapValue(t1.row("r"))); // $ numValueFlow=1 + t2.putAll(t1); for (Table.Cell c : t2.cellSet()) { - sink(c.getValue()); // $numValueFlow=1 + sink(c.getValue()); // $ numValueFlow=1 } - sink(t1.remove("r", "c")); // $numValueFlow=1 + sink(t1.remove("r", "c")); // $ numValueFlow=1 t3.row("r").put("c", x); sink(tableValue(t3)); // $ MISSING:numValueFlow=1 // depends on aliasing } - void test5(Multimap m1, Multimap m2, Multimap m3, + void test5(Multimap m1, Multimap m2, Multimap m3, Multimap m4, Multimap m5){ String x = taint(); m1.put("k", x); - sink(multimapValue(m1)); // $numValueFlow=1 - sink(element(m1.get("k"))); // $numValueFlow=1 + sink(multimapValue(m1)); // $ numValueFlow=1 + sink(element(m1.get("k"))); // $ numValueFlow=1 m2.putAll("k", ImmutableList.of("a", x, "b")); - sink(multimapValue(m2)); // $numValueFlow=1 + sink(multimapValue(m2)); // $ numValueFlow=1 m3.putAll(m1); - sink(multimapValue(m3)); // $numValueFlow=1 + sink(multimapValue(m3)); // $ numValueFlow=1 m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a"))); for (Map.Entry e : m4.entries()) { - sink(e.getValue()); // $numValueFlow=1 + sink(e.getValue()); // $ numValueFlow=1 } m5.asMap().get("k").add(x); @@ -139,23 +139,23 @@ void test5(Multimap m1, Multimap m2, Multimap comp, SortedSet sorS, SortedMap sorM) { ImmutableSortedSet s = ImmutableSortedSet.of(taint()); - sink(element(s)); // $numValueFlow=1 - sink(element(ImmutableSortedSet.copyOf(s))); // $numValueFlow=1 - sink(element(ImmutableSortedSet.copyOf(comp, s))); // $numValueFlow=1 + sink(element(s)); // $ numValueFlow=1 + sink(element(ImmutableSortedSet.copyOf(s))); // $ numValueFlow=1 + sink(element(ImmutableSortedSet.copyOf(comp, s))); // $ numValueFlow=1 sorS.add(taint()); - sink(element(ImmutableSortedSet.copyOfSorted(sorS))); // $numValueFlow=1 + sink(element(ImmutableSortedSet.copyOfSorted(sorS))); // $ numValueFlow=1 - sink(element(ImmutableList.sortedCopyOf(s))); // $numValueFlow=1 - sink(element(ImmutableList.sortedCopyOf(comp, s))); // $numValueFlow=1 + sink(element(ImmutableList.sortedCopyOf(s))); // $ numValueFlow=1 + sink(element(ImmutableList.sortedCopyOf(comp, s))); // $ numValueFlow=1 ImmutableSortedMap m = ImmutableSortedMap.of("k", taint()); - sink(mapValue(m)); // $numValueFlow=1 - sink(mapValue(ImmutableSortedMap.copyOf(m))); // $numValueFlow=1 - sink(mapValue(ImmutableSortedMap.copyOf(m, comp))); // $numValueFlow=1 + sink(mapValue(m)); // $ numValueFlow=1 + sink(mapValue(ImmutableSortedMap.copyOf(m))); // $ numValueFlow=1 + sink(mapValue(ImmutableSortedMap.copyOf(m, comp))); // $ numValueFlow=1 sorM.put("k", taint()); - sink(mapValue(ImmutableSortedMap.copyOfSorted(sorM))); // $numValueFlow=1 + sink(mapValue(ImmutableSortedMap.copyOfSorted(sorM))); // $ numValueFlow=1 } } diff --git a/java/ql/test/library-tests/frameworks/guava/handwritten/TestIO.java b/java/ql/test/library-tests/frameworks/guava/handwritten/TestIO.java index 1135dd1c5b2d..9eeb10d1fc9f 100644 --- a/java/ql/test/library-tests/frameworks/guava/handwritten/TestIO.java +++ b/java/ql/test/library-tests/frameworks/guava/handwritten/TestIO.java @@ -28,43 +28,43 @@ void sink(Object o) {} void test1() { BaseEncoding enc = BaseEncoding.base64(); - sink(enc.decode(staint())); // $numTaintFlow=1 - sink(enc.encode(btaint())); // $numTaintFlow=1 - sink(enc.encode(btaint(), 0, 42)); // $numTaintFlow=1 - sink(enc.decodingStream(rtaint())); // $numTaintFlow=1 - sink(enc.decodingSource(CharSource.wrap(staint()))); // $numTaintFlow=1 - sink(enc.withSeparator(staint(), 10).omitPadding().lowerCase().decode("abc")); // $numTaintFlow=1 + sink(enc.decode(staint())); // $ numTaintFlow=1 + sink(enc.encode(btaint())); // $ numTaintFlow=1 + sink(enc.encode(btaint(), 0, 42)); // $ numTaintFlow=1 + sink(enc.decodingStream(rtaint())); // $ numTaintFlow=1 + sink(enc.decodingSource(CharSource.wrap(staint()))); // $ numTaintFlow=1 + sink(enc.withSeparator(staint(), 10).omitPadding().lowerCase().decode("abc")); // $ numTaintFlow=1 } void test2() throws IOException { ByteSource b = ByteSource.wrap(btaint()); - sink(b.openStream()); // $numTaintFlow=1 - sink(b.openBufferedStream()); // $numTaintFlow=1 - sink(b.asCharSource(null)); // $numTaintFlow=1 - sink(b.slice(42,1337)); // $numTaintFlow=1 - sink(b.read()); // $numTaintFlow=1 - sink(ByteSource.concat(ByteSource.empty(), ByteSource.empty(), b)); // $numTaintFlow=1 - sink(ByteSource.concat(ImmutableList.of(ByteSource.empty(), ByteSource.empty(), b))); // $numTaintFlow=1 + sink(b.openStream()); // $ numTaintFlow=1 + sink(b.openBufferedStream()); // $ numTaintFlow=1 + sink(b.asCharSource(null)); // $ numTaintFlow=1 + sink(b.slice(42,1337)); // $ numTaintFlow=1 + sink(b.read()); // $ numTaintFlow=1 + sink(ByteSource.concat(ByteSource.empty(), ByteSource.empty(), b)); // $ numTaintFlow=1 + sink(ByteSource.concat(ImmutableList.of(ByteSource.empty(), ByteSource.empty(), b))); // $ numTaintFlow=1 sink(b.read(new MyByteProcessor())); // $ MISSING:numTaintFlow=1 ByteArrayOutputStream out = new ByteArrayOutputStream(); b.copyTo(out); - sink(out.toByteArray()); // $numTaintFlow=1 + sink(out.toByteArray()); // $ numTaintFlow=1 CharSource c = CharSource.wrap(staint()); - sink(c.openStream()); // $numTaintFlow=1 - sink(c.openBufferedStream()); // $numTaintFlow=1 - sink(c.asByteSource(null)); // $numTaintFlow=1 - sink(c.readFirstLine()); // $numTaintFlow=1 - sink(c.readLines()); // $numTaintFlow=1 - sink(c.read()); // $numTaintFlow=1 - sink(c.lines()); // $numTaintFlow=1 - sink(CharSource.concat(CharSource.empty(), CharSource.empty(), c)); // $numTaintFlow=1 - sink(CharSource.concat(ImmutableList.of(CharSource.empty(), CharSource.empty(), c))); // $numTaintFlow=1 + sink(c.openStream()); // $ numTaintFlow=1 + sink(c.openBufferedStream()); // $ numTaintFlow=1 + sink(c.asByteSource(null)); // $ numTaintFlow=1 + sink(c.readFirstLine()); // $ numTaintFlow=1 + sink(c.readLines()); // $ numTaintFlow=1 + sink(c.read()); // $ numTaintFlow=1 + sink(c.lines()); // $ numTaintFlow=1 + sink(CharSource.concat(CharSource.empty(), CharSource.empty(), c)); // $ numTaintFlow=1 + sink(CharSource.concat(ImmutableList.of(CharSource.empty(), CharSource.empty(), c))); // $ numTaintFlow=1 sink(c.readLines(new MyLineProcessor())); // $ MISSING:numTaintFlow=1 c.forEachLine(l -> sink(l)); // $ MISSING:numTaintFlow=1 StringBuffer buf = new StringBuffer(); c.copyTo(buf); - sink(buf); // $numTaintFlow=1 + sink(buf); // $ numTaintFlow=1 } class MyByteProcessor implements ByteProcessor { @@ -83,59 +83,59 @@ void test3() throws IOException { { ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteStreams.copy(itaint(), out); - sink(out); // $numTaintFlow=1 + sink(out); // $ numTaintFlow=1 } { WritableByteChannel out = FileChannel.open(Paths.get("/tmp/xyz")); ByteStreams.copy(rbctaint(), out); - sink(out); // $numTaintFlow=1 + sink(out); // $ numTaintFlow=1 } - sink(ByteStreams.limit(itaint(), 1337)); // $numTaintFlow=1 - sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1 - sink(ByteStreams.newDataInput(btaint(), 0)); // $numTaintFlow=1 - sink(ByteStreams.newDataInput(btaint())); // $numTaintFlow=1 - sink(ByteStreams.newDataInput(btaint()).readLine()); // $numTaintFlow=1 - sink(ByteStreams.newDataInput(new ByteArrayInputStream(btaint()))); // $numTaintFlow=1 + sink(ByteStreams.limit(itaint(), 1337)); // $ numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint())); // $ numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint(), 0)); // $ numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint())); // $ numTaintFlow=1 + sink(ByteStreams.newDataInput(btaint()).readLine()); // $ numTaintFlow=1 + sink(ByteStreams.newDataInput(new ByteArrayInputStream(btaint()))); // $ numTaintFlow=1 ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(btaint()); - sink(ByteStreams.newDataOutput(out)); // $numTaintFlow=1 + sink(ByteStreams.newDataOutput(out)); // $ numTaintFlow=1 byte[] b1 = null, b2 = null, b3 = null; ByteStreams.read(itaint(), b1, 0, 42); - sink(b1); // $numTaintFlow=1 + sink(b1); // $ numTaintFlow=1 ByteStreams.readFully(itaint(), b2); - sink(b2); // $numTaintFlow=1 + sink(b2); // $ numTaintFlow=1 ByteStreams.readFully(itaint(), b3, 0, 42); - sink(b3); // $numTaintFlow=1 + sink(b3); // $ numTaintFlow=1 sink(ByteStreams.readBytes(itaint(), new MyByteProcessor())); // $ MISSING:numTaintFlow=1 - sink(ByteStreams.toByteArray(itaint())); // $numTaintFlow=1 + sink(ByteStreams.toByteArray(itaint())); // $ numTaintFlow=1 ByteArrayDataOutput out2 = ByteStreams.newDataOutput(); out2.writeUTF(staint()); - sink(out2.toByteArray()); // $numTaintFlow=1 + sink(out2.toByteArray()); // $ numTaintFlow=1 StringBuffer buf = new StringBuffer(); CharStreams.copy(rtaint(), buf); - sink(buf); // $numTaintFlow=1 - sink(CharStreams.readLines(rtaint())); // $numTaintFlow=1 + sink(buf); // $ numTaintFlow=1 + sink(CharStreams.readLines(rtaint())); // $ numTaintFlow=1 sink(CharStreams.readLines(rtaint(), new MyLineProcessor())); // $ MISSING:numTaintFlow=1 - sink(CharStreams.toString(rtaint())); // $numTaintFlow=1 + sink(CharStreams.toString(rtaint())); // $ numTaintFlow=1 } void test4() throws IOException { - sink(Closer.create().register((Closeable) taint())); // $numValueFlow=1 - sink(new LineReader(rtaint()).readLine()); // $numTaintFlow=1 - sink(Files.simplifyPath(staint())); // $numTaintFlow=1 - sink(Files.getFileExtension(staint())); // $numTaintFlow=1 - sink(Files.getNameWithoutExtension(staint())); // $numTaintFlow=1 - sink(MoreFiles.getFileExtension(ptaint())); // $numTaintFlow=1 - sink(MoreFiles.getNameWithoutExtension(ptaint())); // $numTaintFlow=1 + sink(Closer.create().register((Closeable) taint())); // $ numValueFlow=1 + sink(new LineReader(rtaint()).readLine()); // $ numTaintFlow=1 + sink(Files.simplifyPath(staint())); // $ numTaintFlow=1 + sink(Files.getFileExtension(staint())); // $ numTaintFlow=1 + sink(Files.getNameWithoutExtension(staint())); // $ numTaintFlow=1 + sink(MoreFiles.getFileExtension(ptaint())); // $ numTaintFlow=1 + sink(MoreFiles.getNameWithoutExtension(ptaint())); // $ numTaintFlow=1 } void test6() throws IOException { - sink(new CountingInputStream(itaint())); // $numTaintFlow=1 + sink(new CountingInputStream(itaint())); // $ numTaintFlow=1 byte[] buf = null; - new CountingInputStream(itaint()).read(buf, 0, 42); - sink(buf); // $numTaintFlow=1 - sink(new LittleEndianDataInputStream(itaint())); // $numTaintFlow=1 - sink(new LittleEndianDataInputStream(itaint()).readUTF()); // $numTaintFlow=1 + new CountingInputStream(itaint()).read(buf, 0, 42); + sink(buf); // $ numTaintFlow=1 + sink(new LittleEndianDataInputStream(itaint())); // $ numTaintFlow=1 + sink(new LittleEndianDataInputStream(itaint()).readUTF()); // $ numTaintFlow=1 } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/javax-json/Test.java b/java/ql/test/library-tests/frameworks/javax-json/Test.java index 979bfe9a5683..8465dbd80b52 100644 --- a/java/ql/test/library-tests/frameworks/javax-json/Test.java +++ b/java/ql/test/library-tests/frameworks/javax-json/Test.java @@ -28,7 +28,7 @@ public void test() { jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); jakarta.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -36,7 +36,7 @@ public void test() { jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); jakarta.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -44,7 +44,7 @@ public void test() { Reader in = (Reader)source(); jakarta.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -52,7 +52,7 @@ public void test() { InputStream in = (InputStream)source(); jakarta.json.stream.JsonParserFactory instance = null; out = instance.createParser(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -60,196 +60,196 @@ public void test() { InputStream in = (InputStream)source(); jakarta.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createArrayBuilder;(Collection);;Element of Argument[0];ReturnValue;taint;manual" jakarta.json.JsonArrayBuilder out = null; Collection in = (Collection)newWithElement(source()); out = jakarta.json.Json.createArrayBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createArrayBuilder;(JsonArray);;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = jakarta.json.Json.createArrayBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createDiff;;;Argument[0..1];ReturnValue;taint;manual" jakarta.json.JsonPatch out = null; jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); out = jakarta.json.Json.createDiff(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createDiff;;;Argument[0..1];ReturnValue;taint;manual" jakarta.json.JsonPatch out = null; jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); out = jakarta.json.Json.createDiff(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createMergeDiff;;;Argument[0..1];ReturnValue;taint;manual" jakarta.json.JsonMergePatch out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out = jakarta.json.Json.createMergeDiff(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createMergeDiff;;;Argument[0..1];ReturnValue;taint;manual" jakarta.json.JsonMergePatch out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out = jakarta.json.Json.createMergeDiff(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createMergePatch;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonMergePatch out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out = jakarta.json.Json.createMergePatch(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createObjectBuilder;(JsonObject);;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = jakarta.json.Json.createObjectBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createObjectBuilder;(Map);;MapKey of Argument[0];ReturnValue;taint;manual" jakarta.json.JsonObjectBuilder out = null; Map in = (Map)newWithMapKey(source()); out = jakarta.json.Json.createObjectBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createObjectBuilder;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" jakarta.json.JsonObjectBuilder out = null; Map in = (Map)newWithMapValue(source()); out = jakarta.json.Json.createObjectBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createPatch;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonPatch out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = jakarta.json.Json.createPatch(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createPatchBuilder;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = jakarta.json.Json.createPatchBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createPointer;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonPointer out = null; String in = (String)source(); out = jakarta.json.Json.createPointer(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createReader;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonReader out = null; Reader in = (Reader)source(); out = jakarta.json.Json.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createReader;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonReader out = null; InputStream in = (InputStream)source(); out = jakarta.json.Json.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonString out = null; String in = (String)source(); out = jakarta.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; long in = (long)source(); out = jakarta.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; int in = (int)source(); out = jakarta.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; double in = (double)source(); out = jakarta.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; BigInteger in = (BigInteger)source(); out = jakarta.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; BigDecimal in = (BigDecimal)source(); out = jakarta.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createWriter;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonWriter out = null; Writer in = (Writer)source(); out = jakarta.json.Json.createWriter(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;createWriter;;;Argument[0];ReturnValue;taint;manual" jakarta.json.JsonWriter out = null; OutputStream in = (OutputStream)source(); out = jakarta.json.Json.createWriter(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;decodePointer;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = jakarta.json.Json.decodePointer(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;Json;false;encodePointer;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = jakarta.json.Json.encodePointer(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getBoolean(0, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getBoolean(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getBoolean;;;Argument[1];ReturnValue;value;manual" @@ -257,21 +257,21 @@ public void test() { boolean in = (boolean)source(); jakarta.json.JsonArray instance = null; out = instance.getBoolean(0, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArray;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getInt(0, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getInt(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getInt;;;Argument[1];ReturnValue;value;manual" @@ -279,49 +279,49 @@ public void test() { int in = (int)source(); jakarta.json.JsonArray instance = null; out = instance.getInt(0, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArray;false;getJsonArray;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonArray out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getJsonArray(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getJsonNumber;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getJsonNumber(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getJsonObject;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonObject out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getJsonObject(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getJsonString;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonString out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getJsonString(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getString(0, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getString(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getString;;;Argument[1];ReturnValue;value;manual" @@ -329,497 +329,497 @@ public void test() { String in = (String)source(); jakarta.json.JsonArray instance = null; out = instance.getString(0, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArray;false;getValuesAs;;;Argument[this];ReturnValue;taint;manual" List out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getValuesAs((Function)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArray;false;getValuesAs;;;Argument[this];ReturnValue;taint;manual" List out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out = in.getValuesAs((Class)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(BigDecimal);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; BigDecimal in = (BigDecimal)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(BigInteger);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; BigInteger in = (BigInteger)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(JsonArrayBuilder);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(JsonObjectBuilder);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(JsonValue);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(String);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; String in = (String)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(boolean);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; boolean in = (boolean)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(double);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; double in = (double)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; int in = (int)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,BigDecimal);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; BigDecimal in = (BigDecimal)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,BigInteger);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; BigInteger in = (BigInteger)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,JsonArrayBuilder);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,JsonObjectBuilder);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,JsonValue);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,String);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; String in = (String)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,boolean);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; boolean in = (boolean)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,double);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; double in = (double)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,int);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; int in = (int)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(int,long);;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; long in = (long)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;(long);;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; long in = (long)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, 0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, 0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, (jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, (jakarta.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, (jakarta.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, (BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0, (BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add((jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add((jakarta.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add((jakarta.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add((String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add((BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.add((BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;addAll;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.addAll(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;addAll;;;Argument[0];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out.addAll(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;addNull;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.addNull(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;addNull;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.addNull(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonArray out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;remove;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.remove(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, 0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, 0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, (jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, (jakarta.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, (jakarta.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, (BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.set(0, (BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; long in = (long)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; int in = (int)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; double in = (double)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; boolean in = (boolean)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; String in = (String)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; BigInteger in = (BigInteger)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonArrayBuilder out = null; BigDecimal in = (BigDecimal)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonArrayBuilder;false;setNull;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonArrayBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out = in.setNull(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonMergePatch;false;apply;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonValue out = null; jakarta.json.JsonMergePatch in = (jakarta.json.JsonMergePatch)source(); out = in.apply(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonMergePatch;false;apply;;;Argument[0];ReturnValue;taint;manual" @@ -827,91 +827,91 @@ public void test() { jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); jakarta.json.JsonMergePatch instance = null; out = instance.apply(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonMergePatch;false;toJsonValue;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonValue out = null; jakarta.json.JsonMergePatch in = (jakarta.json.JsonMergePatch)source(); out = in.toJsonValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;bigDecimalValue;;;Argument[this];ReturnValue;taint;manual" BigDecimal out = null; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.bigDecimalValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;bigIntegerValue;;;Argument[this];ReturnValue;taint;manual" BigInteger out = null; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.bigIntegerValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;bigIntegerValueExact;;;Argument[this];ReturnValue;taint;manual" BigInteger out = null; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.bigIntegerValueExact(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;doubleValue;;;Argument[this];ReturnValue;taint;manual" double out = 0.0; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.doubleValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;intValue;;;Argument[this];ReturnValue;taint;manual" int out = 0; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.intValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;intValueExact;;;Argument[this];ReturnValue;taint;manual" int out = 0; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.intValueExact(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;longValue;;;Argument[this];ReturnValue;taint;manual" long out = 0L; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.longValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;longValueExact;;;Argument[this];ReturnValue;taint;manual" long out = 0L; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.longValueExact(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonNumber;false;numberValue;;;Argument[this];ReturnValue;taint;manual" Number out = null; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.numberValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getBoolean(null, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getBoolean(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getBoolean;;;Argument[1];ReturnValue;value;manual" @@ -919,21 +919,21 @@ public void test() { boolean in = (boolean)source(); jakarta.json.JsonObject instance = null; out = instance.getBoolean(null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObject;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getInt(null, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getInt(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getInt;;;Argument[1];ReturnValue;value;manual" @@ -941,49 +941,49 @@ public void test() { int in = (int)source(); jakarta.json.JsonObject instance = null; out = instance.getInt(null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObject;false;getJsonArray;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonArray out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getJsonArray(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getJsonNumber;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonNumber out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getJsonNumber(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getJsonObject;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonObject out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getJsonObject(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getJsonString;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonString out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getJsonString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getString(null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out = in.getString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObject;false;getString;;;Argument[1];ReturnValue;value;manual" @@ -991,154 +991,154 @@ public void test() { String in = (String)source(); jakarta.json.JsonObject instance = null; out = instance.getString(null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, 0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, 0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, (jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, (jakarta.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, (jakarta.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, (BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.add((String)null, (BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; long in = (long)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonArrayBuilder in = (jakarta.json.JsonArrayBuilder)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; int in = (int)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; double in = (double)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; boolean in = (boolean)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; String in = (String)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; BigInteger in = (BigInteger)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" jakarta.json.JsonObjectBuilder out = null; BigDecimal in = (BigDecimal)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;addAll;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.addAll(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;addAll;;;Argument[0];ReturnValue;value;manual" @@ -1146,35 +1146,35 @@ public void test() { jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); jakarta.json.JsonObjectBuilder instance = null; out = instance.addAll(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;addNull;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.addNull(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonObjectBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonObject out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonObjectBuilder;false;remove;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonObjectBuilder out = null; jakarta.json.JsonObjectBuilder in = (jakarta.json.JsonObjectBuilder)source(); out = in.remove(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatch;false;apply;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonStructure out = null; jakarta.json.JsonPatch in = (jakarta.json.JsonPatch)source(); out = in.apply(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatch;false;apply;;;Argument[0];ReturnValue;taint;manual" @@ -1182,42 +1182,42 @@ public void test() { jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); jakarta.json.JsonPatch instance = null; out = instance.apply(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatch;false;toJsonArray;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonArray out = null; jakarta.json.JsonPatch in = (jakarta.json.JsonPatch)source(); out = in.toJsonArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.add((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.add((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.add((String)null, (jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.add((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1225,7 +1225,7 @@ public void test() { jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1233,7 +1233,7 @@ public void test() { int in = (int)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1241,7 +1241,7 @@ public void test() { boolean in = (boolean)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1249,7 +1249,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1257,7 +1257,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1265,7 +1265,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add(in, (jakarta.json.JsonValue)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1273,7 +1273,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1281,21 +1281,21 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonPatch out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;copy;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.copy(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;copy;;;Argument[0..1];ReturnValue;taint;manual" @@ -1303,7 +1303,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.copy(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;copy;;;Argument[0..1];ReturnValue;taint;manual" @@ -1311,14 +1311,14 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.copy(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;move;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.move(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;move;;;Argument[0..1];ReturnValue;taint;manual" @@ -1326,7 +1326,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.move(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;move;;;Argument[0..1];ReturnValue;taint;manual" @@ -1334,14 +1334,14 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.move(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;remove;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.remove(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;remove;;;Argument[0];ReturnValue;taint;manual" @@ -1349,35 +1349,35 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.remove(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.replace((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.replace((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.replace((String)null, (jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.replace((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1385,7 +1385,7 @@ public void test() { jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1393,7 +1393,7 @@ public void test() { int in = (int)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1401,7 +1401,7 @@ public void test() { boolean in = (boolean)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1409,7 +1409,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1417,7 +1417,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1425,7 +1425,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace(in, (jakarta.json.JsonValue)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1433,7 +1433,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1441,35 +1441,35 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.test((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.test((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.test((String)null, (jakarta.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" jakarta.json.JsonPatchBuilder out = null; jakarta.json.JsonPatchBuilder in = (jakarta.json.JsonPatchBuilder)source(); out = in.test((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1477,7 +1477,7 @@ public void test() { jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1485,7 +1485,7 @@ public void test() { int in = (int)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1493,7 +1493,7 @@ public void test() { boolean in = (boolean)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1501,7 +1501,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1509,7 +1509,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1517,7 +1517,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test(in, (jakarta.json.JsonValue)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1525,7 +1525,7 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -1533,14 +1533,14 @@ public void test() { String in = (String)source(); jakarta.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;add;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonStructure out = null; jakarta.json.JsonPointer in = (jakarta.json.JsonPointer)source(); out = in.add(null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1548,7 +1548,7 @@ public void test() { jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); jakarta.json.JsonPointer instance = null; out = instance.add(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -1556,7 +1556,7 @@ public void test() { jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); jakarta.json.JsonPointer instance = null; out = instance.add(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;getValue;;;Argument[0];ReturnValue;taint;manual" @@ -1564,7 +1564,7 @@ public void test() { jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); jakarta.json.JsonPointer instance = null; out = instance.getValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;remove;;;Argument[0];ReturnValue;taint;manual" @@ -1572,7 +1572,7 @@ public void test() { jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); jakarta.json.JsonPointer instance = null; out = instance.remove(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1580,7 +1580,7 @@ public void test() { jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); jakarta.json.JsonPointer instance = null; out = instance.replace(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -1588,42 +1588,42 @@ public void test() { jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); jakarta.json.JsonPointer instance = null; out = instance.replace(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonPointer;false;toString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonPointer in = (jakarta.json.JsonPointer)source(); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReader;false;read;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonStructure out = null; jakarta.json.JsonReader in = (jakarta.json.JsonReader)source(); out = in.read(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReader;false;readArray;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonArray out = null; jakarta.json.JsonReader in = (jakarta.json.JsonReader)source(); out = in.readArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReader;false;readObject;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonObject out = null; jakarta.json.JsonReader in = (jakarta.json.JsonReader)source(); out = in.readObject(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReader;false;readValue;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonValue out = null; jakarta.json.JsonReader in = (jakarta.json.JsonReader)source(); out = in.readValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReaderFactory;false;createReader;;;Argument[0];ReturnValue;taint;manual" @@ -1631,7 +1631,7 @@ public void test() { Reader in = (Reader)source(); jakarta.json.JsonReaderFactory instance = null; out = instance.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReaderFactory;false;createReader;;;Argument[0];ReturnValue;taint;manual" @@ -1639,7 +1639,7 @@ public void test() { InputStream in = (InputStream)source(); jakarta.json.JsonReaderFactory instance = null; out = instance.createReader(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonReaderFactory;false;createReader;;;Argument[0];ReturnValue;taint;manual" @@ -1647,105 +1647,105 @@ public void test() { InputStream in = (InputStream)source(); jakarta.json.JsonReaderFactory instance = null; out = instance.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonString;false;getChars;;;Argument[this];ReturnValue;taint;manual" CharSequence out = null; jakarta.json.JsonString in = (jakarta.json.JsonString)source(); out = in.getChars(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonString;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonString in = (jakarta.json.JsonString)source(); out = in.getString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonStructure;true;getValue;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonValue out = null; jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); out = in.getValue(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonValue;true;asJsonArray;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonArray out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out = in.asJsonArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonValue;true;asJsonObject;;;Argument[this];ReturnValue;taint;manual" jakarta.json.JsonObject out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out = in.asJsonObject(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonValue;true;toString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonValue;true;toString;;;Argument[this];ReturnValue;taint;manual" String out = null; jakarta.json.JsonNumber in = (jakarta.json.JsonNumber)source(); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriter;false;write;;;Argument[0];Argument[this];taint;manual" jakarta.json.JsonWriter out = null; jakarta.json.JsonValue in = (jakarta.json.JsonValue)source(); out.write(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriter;false;write;;;Argument[0];Argument[this];taint;manual" jakarta.json.JsonWriter out = null; jakarta.json.JsonStructure in = (jakarta.json.JsonStructure)source(); out.write(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriter;false;writeArray;;;Argument[0];Argument[this];taint;manual" jakarta.json.JsonWriter out = null; jakarta.json.JsonArray in = (jakarta.json.JsonArray)source(); out.writeArray(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriter;false;writeObject;;;Argument[0];Argument[this];taint;manual" jakarta.json.JsonWriter out = null; jakarta.json.JsonObject in = (jakarta.json.JsonObject)source(); out.writeObject(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriterFactory;false;createWriter;;;Argument[this];Argument[0];taint;manual" Writer out = null; jakarta.json.JsonWriterFactory in = (jakarta.json.JsonWriterFactory)source(); in.createWriter(out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriterFactory;false;createWriter;;;Argument[this];Argument[0];taint;manual" OutputStream out = null; jakarta.json.JsonWriterFactory in = (jakarta.json.JsonWriterFactory)source(); in.createWriter(out, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "jakarta.json;JsonWriterFactory;false;createWriter;;;Argument[this];Argument[0];taint;manual" OutputStream out = null; jakarta.json.JsonWriterFactory in = (jakarta.json.JsonWriterFactory)source(); in.createWriter(out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -1753,7 +1753,7 @@ public void test() { javax.json.JsonObject in = (javax.json.JsonObject)source(); javax.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -1761,7 +1761,7 @@ public void test() { javax.json.JsonArray in = (javax.json.JsonArray)source(); javax.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -1769,7 +1769,7 @@ public void test() { Reader in = (Reader)source(); javax.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -1777,7 +1777,7 @@ public void test() { InputStream in = (InputStream)source(); javax.json.stream.JsonParserFactory instance = null; out = instance.createParser(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json.stream;JsonParserFactory;false;createParser;;;Argument[0];ReturnValue;taint;manual" @@ -1785,196 +1785,196 @@ public void test() { InputStream in = (InputStream)source(); javax.json.stream.JsonParserFactory instance = null; out = instance.createParser(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createArrayBuilder;(Collection);;Element of Argument[0];ReturnValue;taint;manual" javax.json.JsonArrayBuilder out = null; Collection in = (Collection)newWithElement(source()); out = javax.json.Json.createArrayBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createArrayBuilder;(JsonArray);;Argument[0];ReturnValue;taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = javax.json.Json.createArrayBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createDiff;;;Argument[0..1];ReturnValue;taint;manual" javax.json.JsonPatch out = null; javax.json.JsonStructure in = (javax.json.JsonStructure)source(); out = javax.json.Json.createDiff(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createDiff;;;Argument[0..1];ReturnValue;taint;manual" javax.json.JsonPatch out = null; javax.json.JsonStructure in = (javax.json.JsonStructure)source(); out = javax.json.Json.createDiff(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createMergeDiff;;;Argument[0..1];ReturnValue;taint;manual" javax.json.JsonMergePatch out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out = javax.json.Json.createMergeDiff(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createMergeDiff;;;Argument[0..1];ReturnValue;taint;manual" javax.json.JsonMergePatch out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out = javax.json.Json.createMergeDiff(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createMergePatch;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonMergePatch out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out = javax.json.Json.createMergePatch(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createObjectBuilder;(JsonObject);;Argument[0];ReturnValue;taint;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = javax.json.Json.createObjectBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createObjectBuilder;(Map);;MapKey of Argument[0];ReturnValue;taint;manual" javax.json.JsonObjectBuilder out = null; Map in = (Map)newWithMapKey(source()); out = javax.json.Json.createObjectBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createObjectBuilder;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" javax.json.JsonObjectBuilder out = null; Map in = (Map)newWithMapValue(source()); out = javax.json.Json.createObjectBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createPatch;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonPatch out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = javax.json.Json.createPatch(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createPatchBuilder;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = javax.json.Json.createPatchBuilder(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createPointer;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonPointer out = null; String in = (String)source(); out = javax.json.Json.createPointer(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createReader;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonReader out = null; Reader in = (Reader)source(); out = javax.json.Json.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createReader;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonReader out = null; InputStream in = (InputStream)source(); out = javax.json.Json.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonString out = null; String in = (String)source(); out = javax.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonNumber out = null; long in = (long)source(); out = javax.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonNumber out = null; int in = (int)source(); out = javax.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonNumber out = null; double in = (double)source(); out = javax.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonNumber out = null; BigInteger in = (BigInteger)source(); out = javax.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createValue;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonNumber out = null; BigDecimal in = (BigDecimal)source(); out = javax.json.Json.createValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createWriter;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonWriter out = null; Writer in = (Writer)source(); out = javax.json.Json.createWriter(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;createWriter;;;Argument[0];ReturnValue;taint;manual" javax.json.JsonWriter out = null; OutputStream in = (OutputStream)source(); out = javax.json.Json.createWriter(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;decodePointer;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = javax.json.Json.decodePointer(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;Json;false;encodePointer;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = javax.json.Json.encodePointer(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getBoolean(0, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getBoolean(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getBoolean;;;Argument[1];ReturnValue;value;manual" @@ -1982,21 +1982,21 @@ public void test() { boolean in = (boolean)source(); javax.json.JsonArray instance = null; out = instance.getBoolean(0, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArray;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getInt(0, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getInt(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getInt;;;Argument[1];ReturnValue;value;manual" @@ -2004,49 +2004,49 @@ public void test() { int in = (int)source(); javax.json.JsonArray instance = null; out = instance.getInt(0, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArray;false;getJsonArray;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonArray out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getJsonArray(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getJsonNumber;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonNumber out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getJsonNumber(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getJsonObject;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonObject out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getJsonObject(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getJsonString;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonString out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getJsonString(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getString(0, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getString(0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getString;;;Argument[1];ReturnValue;value;manual" @@ -2054,497 +2054,497 @@ public void test() { String in = (String)source(); javax.json.JsonArray instance = null; out = instance.getString(0, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArray;false;getValuesAs;;;Argument[this];ReturnValue;taint;manual" List out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getValuesAs((Function)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArray;false;getValuesAs;;;Argument[this];ReturnValue;taint;manual" List out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out = in.getValuesAs((Class)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(BigDecimal);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; BigDecimal in = (BigDecimal)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(BigInteger);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; BigInteger in = (BigInteger)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(JsonArrayBuilder);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(JsonObjectBuilder);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(JsonValue);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(String);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; String in = (String)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(boolean);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; boolean in = (boolean)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(double);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; double in = (double)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; int in = (int)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,BigDecimal);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; BigDecimal in = (BigDecimal)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,BigInteger);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; BigInteger in = (BigInteger)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,JsonArrayBuilder);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,JsonObjectBuilder);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,JsonValue);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,String);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; String in = (String)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,boolean);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; boolean in = (boolean)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,double);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; double in = (double)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,int);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; int in = (int)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(int,long);;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; long in = (long)source(); out.add(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;(long);;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; long in = (long)source(); out.add(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, 0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, 0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, (javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, (javax.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, (javax.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, (BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0, (BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add((javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add((javax.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add((javax.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add((String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add((BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.add((BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;addAll;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.addAll(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;addAll;;;Argument[0];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out.addAll(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;addNull;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.addNull(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;addNull;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.addNull(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonArray out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;remove;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.remove(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, 0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, 0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, (javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, (javax.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, (javax.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, (BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.set(0, (BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; long in = (long)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; int in = (int)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; double in = (double)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; boolean in = (boolean)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; String in = (String)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; BigInteger in = (BigInteger)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;set;;;Argument[1];Argument[this];taint;manual" javax.json.JsonArrayBuilder out = null; BigDecimal in = (BigDecimal)source(); out.set(0, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonArrayBuilder;false;setNull;;;Argument[this];ReturnValue;value;manual" javax.json.JsonArrayBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out = in.setNull(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonMergePatch;false;apply;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonValue out = null; javax.json.JsonMergePatch in = (javax.json.JsonMergePatch)source(); out = in.apply(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonMergePatch;false;apply;;;Argument[0];ReturnValue;taint;manual" @@ -2552,91 +2552,91 @@ public void test() { javax.json.JsonValue in = (javax.json.JsonValue)source(); javax.json.JsonMergePatch instance = null; out = instance.apply(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonMergePatch;false;toJsonValue;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonValue out = null; javax.json.JsonMergePatch in = (javax.json.JsonMergePatch)source(); out = in.toJsonValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;bigDecimalValue;;;Argument[this];ReturnValue;taint;manual" BigDecimal out = null; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.bigDecimalValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;bigIntegerValue;;;Argument[this];ReturnValue;taint;manual" BigInteger out = null; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.bigIntegerValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;bigIntegerValueExact;;;Argument[this];ReturnValue;taint;manual" BigInteger out = null; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.bigIntegerValueExact(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;doubleValue;;;Argument[this];ReturnValue;taint;manual" double out = 0.0; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.doubleValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;intValue;;;Argument[this];ReturnValue;taint;manual" int out = 0; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.intValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;intValueExact;;;Argument[this];ReturnValue;taint;manual" int out = 0; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.intValueExact(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;longValue;;;Argument[this];ReturnValue;taint;manual" long out = 0L; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.longValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;longValueExact;;;Argument[this];ReturnValue;taint;manual" long out = 0L; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.longValueExact(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonNumber;false;numberValue;;;Argument[this];ReturnValue;taint;manual" Number out = null; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.numberValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getBoolean(null, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getBoolean;;;Argument[this];ReturnValue;taint;manual" boolean out = false; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getBoolean(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getBoolean;;;Argument[1];ReturnValue;value;manual" @@ -2644,21 +2644,21 @@ public void test() { boolean in = (boolean)source(); javax.json.JsonObject instance = null; out = instance.getBoolean(null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObject;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getInt(null, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getInt;;;Argument[this];ReturnValue;taint;manual" int out = 0; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getInt(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getInt;;;Argument[1];ReturnValue;value;manual" @@ -2666,49 +2666,49 @@ public void test() { int in = (int)source(); javax.json.JsonObject instance = null; out = instance.getInt(null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObject;false;getJsonArray;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonArray out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getJsonArray(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getJsonNumber;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonNumber out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getJsonNumber(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getJsonObject;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonObject out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getJsonObject(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getJsonString;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonString out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getJsonString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getString(null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out = in.getString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObject;false;getString;;;Argument[1];ReturnValue;value;manual" @@ -2716,154 +2716,154 @@ public void test() { String in = (String)source(); javax.json.JsonObject instance = null; out = instance.getString(null, in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, 0L); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, 0.0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, (javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, (javax.json.JsonObjectBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, (javax.json.JsonArrayBuilder)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, (BigInteger)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.add((String)null, (BigDecimal)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; long in = (long)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonArrayBuilder in = (javax.json.JsonArrayBuilder)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; int in = (int)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; double in = (double)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; boolean in = (boolean)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; String in = (String)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; BigInteger in = (BigInteger)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;add;;;Argument[1];Argument[this];taint;manual" javax.json.JsonObjectBuilder out = null; BigDecimal in = (BigDecimal)source(); out.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;addAll;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.addAll(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;addAll;;;Argument[0];ReturnValue;value;manual" @@ -2871,35 +2871,35 @@ public void test() { javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); javax.json.JsonObjectBuilder instance = null; out = instance.addAll(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;addNull;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.addNull(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonObjectBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonObject out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonObjectBuilder;false;remove;;;Argument[this];ReturnValue;value;manual" javax.json.JsonObjectBuilder out = null; javax.json.JsonObjectBuilder in = (javax.json.JsonObjectBuilder)source(); out = in.remove(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatch;false;apply;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonStructure out = null; javax.json.JsonPatch in = (javax.json.JsonPatch)source(); out = in.apply(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatch;false;apply;;;Argument[0];ReturnValue;taint;manual" @@ -2907,42 +2907,42 @@ public void test() { javax.json.JsonStructure in = (javax.json.JsonStructure)source(); javax.json.JsonPatch instance = null; out = instance.apply(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatch;false;toJsonArray;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonArray out = null; javax.json.JsonPatch in = (javax.json.JsonPatch)source(); out = in.toJsonArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.add((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.add((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.add((String)null, (javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.add((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2950,7 +2950,7 @@ public void test() { javax.json.JsonValue in = (javax.json.JsonValue)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2958,7 +2958,7 @@ public void test() { int in = (int)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2966,7 +2966,7 @@ public void test() { boolean in = (boolean)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2974,7 +2974,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2982,7 +2982,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2990,7 +2990,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add(in, (javax.json.JsonValue)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -2998,7 +2998,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -3006,21 +3006,21 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.add((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonPatch out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;copy;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.copy(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;copy;;;Argument[0..1];ReturnValue;taint;manual" @@ -3028,7 +3028,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.copy(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;copy;;;Argument[0..1];ReturnValue;taint;manual" @@ -3036,14 +3036,14 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.copy(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;move;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.move(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;move;;;Argument[0..1];ReturnValue;taint;manual" @@ -3051,7 +3051,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.move(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;move;;;Argument[0..1];ReturnValue;taint;manual" @@ -3059,14 +3059,14 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.move(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;remove;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.remove(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;remove;;;Argument[0];ReturnValue;taint;manual" @@ -3074,35 +3074,35 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.remove(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.replace((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.replace((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.replace((String)null, (javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.replace((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3110,7 +3110,7 @@ public void test() { javax.json.JsonValue in = (javax.json.JsonValue)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3118,7 +3118,7 @@ public void test() { int in = (int)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3126,7 +3126,7 @@ public void test() { boolean in = (boolean)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3134,7 +3134,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3142,7 +3142,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3150,7 +3150,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace(in, (javax.json.JsonValue)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3158,7 +3158,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3166,35 +3166,35 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.replace((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.test((String)null, false); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.test((String)null, 0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.test((String)null, (javax.json.JsonValue)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[this];ReturnValue;value;manual" javax.json.JsonPatchBuilder out = null; javax.json.JsonPatchBuilder in = (javax.json.JsonPatchBuilder)source(); out = in.test((String)null, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3202,7 +3202,7 @@ public void test() { javax.json.JsonValue in = (javax.json.JsonValue)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3210,7 +3210,7 @@ public void test() { int in = (int)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3218,7 +3218,7 @@ public void test() { boolean in = (boolean)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3226,7 +3226,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3234,7 +3234,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3242,7 +3242,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test(in, (javax.json.JsonValue)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3250,7 +3250,7 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPatchBuilder;false;test;;;Argument[0..1];ReturnValue;taint;manual" @@ -3258,14 +3258,14 @@ public void test() { String in = (String)source(); javax.json.JsonPatchBuilder instance = null; out = instance.test((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;add;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonStructure out = null; javax.json.JsonPointer in = (javax.json.JsonPointer)source(); out = in.add(null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -3273,7 +3273,7 @@ public void test() { javax.json.JsonValue in = (javax.json.JsonValue)source(); javax.json.JsonPointer instance = null; out = instance.add(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;add;;;Argument[0..1];ReturnValue;taint;manual" @@ -3281,7 +3281,7 @@ public void test() { javax.json.JsonStructure in = (javax.json.JsonStructure)source(); javax.json.JsonPointer instance = null; out = instance.add(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;getValue;;;Argument[0];ReturnValue;taint;manual" @@ -3289,7 +3289,7 @@ public void test() { javax.json.JsonStructure in = (javax.json.JsonStructure)source(); javax.json.JsonPointer instance = null; out = instance.getValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;remove;;;Argument[0];ReturnValue;taint;manual" @@ -3297,7 +3297,7 @@ public void test() { javax.json.JsonStructure in = (javax.json.JsonStructure)source(); javax.json.JsonPointer instance = null; out = instance.remove(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3305,7 +3305,7 @@ public void test() { javax.json.JsonValue in = (javax.json.JsonValue)source(); javax.json.JsonPointer instance = null; out = instance.replace(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonPointer;false;replace;;;Argument[0..1];ReturnValue;taint;manual" @@ -3313,35 +3313,35 @@ public void test() { javax.json.JsonStructure in = (javax.json.JsonStructure)source(); javax.json.JsonPointer instance = null; out = instance.replace(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReader;false;read;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonStructure out = null; javax.json.JsonReader in = (javax.json.JsonReader)source(); out = in.read(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReader;false;readArray;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonArray out = null; javax.json.JsonReader in = (javax.json.JsonReader)source(); out = in.readArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReader;false;readObject;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonObject out = null; javax.json.JsonReader in = (javax.json.JsonReader)source(); out = in.readObject(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReader;false;readValue;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonValue out = null; javax.json.JsonReader in = (javax.json.JsonReader)source(); out = in.readValue(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReaderFactory;false;createReader;;;Argument[0];ReturnValue;taint;manual" @@ -3349,7 +3349,7 @@ public void test() { Reader in = (Reader)source(); javax.json.JsonReaderFactory instance = null; out = instance.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReaderFactory;false;createReader;;;Argument[0];ReturnValue;taint;manual" @@ -3357,7 +3357,7 @@ public void test() { InputStream in = (InputStream)source(); javax.json.JsonReaderFactory instance = null; out = instance.createReader(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonReaderFactory;false;createReader;;;Argument[0];ReturnValue;taint;manual" @@ -3365,107 +3365,107 @@ public void test() { InputStream in = (InputStream)source(); javax.json.JsonReaderFactory instance = null; out = instance.createReader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonString;false;getChars;;;Argument[this];ReturnValue;taint;manual" CharSequence out = null; javax.json.JsonString in = (javax.json.JsonString)source(); out = in.getChars(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonString;false;getString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonString in = (javax.json.JsonString)source(); out = in.getString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonStructure;true;getValue;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonValue out = null; javax.json.JsonStructure in = (javax.json.JsonStructure)source(); out = in.getValue(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonValue;true;asJsonArray;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonArray out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out = in.asJsonArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonValue;true;asJsonObject;;;Argument[this];ReturnValue;taint;manual" javax.json.JsonObject out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out = in.asJsonObject(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonValue;true;toString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonValue;true;toString;;;Argument[this];ReturnValue;taint;manual" String out = null; javax.json.JsonNumber in = (javax.json.JsonNumber)source(); out = in.toString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriter;false;write;;;Argument[0];Argument[this];taint;manual" javax.json.JsonWriter out = null; javax.json.JsonValue in = (javax.json.JsonValue)source(); out.write(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriter;false;write;;;Argument[0];Argument[this];taint;manual" javax.json.JsonWriter out = null; javax.json.JsonStructure in = (javax.json.JsonStructure)source(); out.write(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriter;false;writeArray;;;Argument[0];Argument[this];taint;manual" javax.json.JsonWriter out = null; javax.json.JsonArray in = (javax.json.JsonArray)source(); out.writeArray(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriter;false;writeObject;;;Argument[0];Argument[this];taint;manual" javax.json.JsonWriter out = null; javax.json.JsonObject in = (javax.json.JsonObject)source(); out.writeObject(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriterFactory;false;createWriter;;;Argument[this];Argument[0];taint;manual" Writer out = null; javax.json.JsonWriterFactory in = (javax.json.JsonWriterFactory)source(); in.createWriter(out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriterFactory;false;createWriter;;;Argument[this];Argument[0];taint;manual" OutputStream out = null; javax.json.JsonWriterFactory in = (javax.json.JsonWriterFactory)source(); in.createWriter(out, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "javax.json;JsonWriterFactory;false;createWriter;;;Argument[this];Argument[0];taint;manual" OutputStream out = null; javax.json.JsonWriterFactory in = (javax.json.JsonWriterFactory)source(); in.createWriter(out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/jms/MessageListenerImpl.java b/java/ql/test/library-tests/frameworks/jms/MessageListenerImpl.java index 29591bfcd4b2..256d564eefe9 100644 --- a/java/ql/test/library-tests/frameworks/jms/MessageListenerImpl.java +++ b/java/ql/test/library-tests/frameworks/jms/MessageListenerImpl.java @@ -13,59 +13,59 @@ public class MessageListenerImpl implements MessageListener { @Override - public void onMessage(Message message) { // $source + public void onMessage(Message message) { // $ source try { if (message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; String text = textMessage.getText(); - sink(text); // $tainted + sink(text); // $ tainted } else if (message instanceof BytesMessage) { BytesMessage bytesMessage = (BytesMessage) message; byte[] data = new byte[1024]; bytesMessage.readBytes(data, 42); - sink(new String(data)); // $tainted - sink(bytesMessage.readUTF()); // $tainted + sink(new String(data)); // $ tainted + sink(bytesMessage.readUTF()); // $ tainted } else if (message instanceof MapMessage) { MapMessage mapMessage = (MapMessage) message; - sink(mapMessage.getString("data")); // $tainted - sink(new String(mapMessage.getBytes("bytes"))); // $tainted + sink(mapMessage.getString("data")); // $ tainted + sink(new String(mapMessage.getBytes("bytes"))); // $ tainted } else if (message instanceof ObjectMessage) { ObjectMessage objectMessage = (ObjectMessage) message; - sink((String) objectMessage.getObject()); // $tainted + sink((String) objectMessage.getObject()); // $ tainted } else if (message instanceof StreamMessage) { StreamMessage streamMessage = (StreamMessage) message; byte[] data = new byte[1024]; streamMessage.readBytes(data); - sink(new String(data)); // $tainted - sink(streamMessage.readString()); // $tainted - sink((String) streamMessage.readObject()); // $tainted + sink(new String(data)); // $ tainted + sink(streamMessage.readString()); // $ tainted + sink((String) streamMessage.readObject()); // $ tainted } } catch (Exception e) { } } public void readFromCounsumer(MessageConsumer consumer) throws Exception { - TextMessage message = (TextMessage) consumer.receive(5000); // $source + TextMessage message = (TextMessage) consumer.receive(5000); // $ source String text = message.getText(); - sink(text); // $tainted - message = (TextMessage) consumer.receive(); // $source + sink(text); // $ tainted + message = (TextMessage) consumer.receive(); // $ source text = message.getText(); - sink(text); // $tainted - message = (TextMessage) consumer.receiveNoWait(); // $source + sink(text); // $ tainted + message = (TextMessage) consumer.receiveNoWait(); // $ source text = message.getText(); - sink(text); // $tainted + sink(text); // $ tainted } public void readFromQueueRequestor(QueueRequestor requestor, Message message) throws Exception { - TextMessage reply = (TextMessage) requestor.request(message); // $source + TextMessage reply = (TextMessage) requestor.request(message); // $ source String text = reply.getText(); - sink(text); // $tainted + sink(text); // $ tainted } public void readFromTopicRequestor(TopicRequestor requestor, Message message) throws Exception { - TextMessage reply = (TextMessage) requestor.request(message); // $source + TextMessage reply = (TextMessage) requestor.request(message); // $ source String text = reply.getText(); - sink(text); // $tainted + sink(text); // $ tainted } private void sink(String data) { diff --git a/java/ql/test/library-tests/frameworks/lastaflute/Test.java b/java/ql/test/library-tests/frameworks/lastaflute/Test.java index a10f4ebbdaaa..d230da8c6e3e 100644 --- a/java/ql/test/library-tests/frameworks/lastaflute/Test.java +++ b/java/ql/test/library-tests/frameworks/lastaflute/Test.java @@ -16,12 +16,10 @@ public class TestForm { public String index(TestForm form) throws IOException { MultipartFormFile file = form.file; - sink(file.getFileData()); // $hasTaintFlow - sink(file.getInputStream()); // $hasTaintFlow + sink(file.getFileData()); // $ hasTaintFlow + sink(file.getInputStream()); // $ hasTaintFlow return "index.jsp"; } } - - diff --git a/java/ql/test/library-tests/frameworks/netty/manual/Test.java b/java/ql/test/library-tests/frameworks/netty/manual/Test.java index 581506597120..090734e52513 100644 --- a/java/ql/test/library-tests/frameworks/netty/manual/Test.java +++ b/java/ql/test/library-tests/frameworks/netty/manual/Test.java @@ -12,7 +12,7 @@ static void sink(Object s) {} class A extends ChannelInboundHandlerAdapter { public void channelRead(ChannelHandlerContext ctx, Object msg) { - sink(msg); // $hasTaintFlow + sink(msg); // $ hasTaintFlow } } @@ -21,7 +21,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf bb = (ByteBuf) msg; byte[] data = new byte[1024]; bb.readBytes(data); - sink(data); // $hasTaintFlow + sink(data); // $ hasTaintFlow } } @@ -73,4 +73,4 @@ public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int stream sink(payload); // $ hasTaintFlow } } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/rabbitmq/Test.java b/java/ql/test/library-tests/frameworks/rabbitmq/Test.java index 66a7fc8560af..b2aad6e84a6e 100644 --- a/java/ql/test/library-tests/frameworks/rabbitmq/Test.java +++ b/java/ql/test/library-tests/frameworks/rabbitmq/Test.java @@ -11,20 +11,20 @@ public void defaultConsumerTest(Channel channel) { @Override public void handleDelivery( - String consumerTag, Envelope envelope, AMQP.BasicProperties properties, - byte[] body) { // $source + String consumerTag, Envelope envelope, AMQP.BasicProperties properties, + byte[] body) { // $ source - sink(body); // $hasTaintFlow + sink(body); // $ hasTaintFlow } }; } public void queueingConsumerTest(QueueingConsumer consumer) { while (true) { - QueueingConsumer.Delivery delivery = consumer.nextDelivery(); // $source - sink(delivery.getBody()); // $hasTaintFlow - delivery = consumer.nextDelivery(42); // $source - sink(delivery.getBody()); // $hasTaintFlow + QueueingConsumer.Delivery delivery = consumer.nextDelivery(); // $ source + sink(delivery.getBody()); // $ hasTaintFlow + delivery = consumer.nextDelivery(42); // $ source + sink(delivery.getBody()); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/ratpack/resources/CollectionPassingTest.java b/java/ql/test/library-tests/frameworks/ratpack/resources/CollectionPassingTest.java index eb0ca9cad92e..667cf56aa3a2 100644 --- a/java/ql/test/library-tests/frameworks/ratpack/resources/CollectionPassingTest.java +++ b/java/ql/test/library-tests/frameworks/ratpack/resources/CollectionPassingTest.java @@ -29,11 +29,11 @@ void test_1(Context ctx) { Map pojoMap = new HashMap<>(); merge(form.asMultimap().asMap(), pojoMap); // Then - sink(pojoMap.get("value")); //$hasTaintFlow + sink(pojoMap.get("value")); // $ hasTaintFlow pojoMap.forEach((key, value) -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow List values = (List) value; - sink(values.get(0)); //$hasTaintFlow + sink(values.get(0)); // $ hasTaintFlow }); }); } @@ -46,11 +46,11 @@ void test_2() { // When merge(taintedMap, pojoMap); // Then - sink(pojoMap.get("value")); //$hasTaintFlow + sink(pojoMap.get("value")); // $ hasTaintFlow pojoMap.forEach((key, value) -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow List values = (List) value; - sink(values.get(0)); //$hasTaintFlow + sink(values.get(0)); // $ hasTaintFlow }); } @@ -66,5 +66,5 @@ private static void merge(Map> params, Map values) { return values.size() == 1 ? values.iterator().next() : ImmutableList.copyOf(values); } - + } diff --git a/java/ql/test/library-tests/frameworks/ratpack/resources/IntegrationTest.java b/java/ql/test/library-tests/frameworks/ratpack/resources/IntegrationTest.java index da87794eb56c..85adece96c03 100644 --- a/java/ql/test/library-tests/frameworks/ratpack/resources/IntegrationTest.java +++ b/java/ql/test/library-tests/frameworks/ratpack/resources/IntegrationTest.java @@ -53,32 +53,32 @@ String taint() { void test1(Context ctx) { bindJson(ctx, Pojo.class) .then(pojo ->{ - sink(pojo); //$hasTaintFlow - sink(pojo.value); //$hasTaintFlow - sink(pojo.getValue()); //$hasTaintFlow + sink(pojo); // $ hasTaintFlow + sink(pojo.value); // $ hasTaintFlow + sink(pojo.getValue()); // $ hasTaintFlow }); } void test2(Context ctx) { bindForm(ctx, Pojo.class, defaults -> defaults.put("another", "potato")) .then(pojo ->{ - sink(pojo); //$hasTaintFlow - sink(pojo.value); //$hasTaintFlow - sink(pojo.getValue()); //$hasTaintFlow + sink(pojo); // $ hasTaintFlow + sink(pojo.value); // $ hasTaintFlow + sink(pojo.getValue()); // $ hasTaintFlow }); } void test3() { Object value = extractSingleValueIfPossible(ImmutableList.of("a", taint())); - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow List values = (List) value; - sink(values.get(1)); //$hasTaintFlow + sink(values.get(1)); // $ hasTaintFlow Map weirdMap = new HashMap<>(); weirdMap.put("a", value); weirdMap.forEach((key, mapValue) -> { - sink(mapValue); //$hasTaintFlow + sink(mapValue); // $ hasTaintFlow List values2 = (List) mapValue; - sink(values2.get(0)); //$hasTaintFlow + sink(values2.get(0)); // $ hasTaintFlow }); } @@ -89,13 +89,13 @@ void test4(Context ctx) { filterAndMerge(pojoForm, mergedParams, name -> false); return mergedParams; }).then(pojoMap -> { - sink(pojoMap.keySet().iterator().next()); //$hasTaintFlow - sink(pojoMap.get("value")); //$hasTaintFlow + sink(pojoMap.keySet().iterator().next()); // $ hasTaintFlow + sink(pojoMap.get("value")); // $ hasTaintFlow pojoMap.forEach((key, value) -> { - sink(key); //$hasTaintFlow - sink(value); //$hasTaintFlow + sink(key); // $ hasTaintFlow + sink(value); // $ hasTaintFlow List values = (List) value; - sink(values.get(0)); //$hasTaintFlow + sink(values.get(0)); // $ hasTaintFlow }); }); } @@ -107,13 +107,13 @@ void test5(Context ctx) { filterAndMerge_2(pojoForm, mergedParams, name -> false); return mergedParams; }).then(pojoMap -> { - sink(pojoMap.keySet().iterator().next()); //$hasTaintFlow - sink(pojoMap.get("value")); //$hasTaintFlow + sink(pojoMap.keySet().iterator().next()); // $ hasTaintFlow + sink(pojoMap.get("value")); // $ hasTaintFlow pojoMap.forEach((key, value) -> { - sink(key); //$hasTaintFlow - sink(value); //$hasTaintFlow + sink(key); // $ hasTaintFlow + sink(value); // $ hasTaintFlow List values = (List) value; - sink(values.get(0)); //$hasTaintFlow + sink(values.get(0)); // $ hasTaintFlow }); }); } @@ -121,8 +121,8 @@ void test5(Context ctx) { void test6(Context ctx) { bindQuery(ctx, Pojo.class) .then(pojo -> { - sink(pojo.getValue()); //$hasTaintFlow - sink(pojo.getValues()); //$hasTaintFlow + sink(pojo.getValue()); // $ hasTaintFlow + sink(pojo.getValues()); // $ hasTaintFlow }); } diff --git a/java/ql/test/library-tests/frameworks/ratpack/resources/PairTest.java b/java/ql/test/library-tests/frameworks/ratpack/resources/PairTest.java index efde2aaf921c..6cee6068733e 100644 --- a/java/ql/test/library-tests/frameworks/ratpack/resources/PairTest.java +++ b/java/ql/test/library-tests/frameworks/ratpack/resources/PairTest.java @@ -5,7 +5,7 @@ public class PairTest { - + void sink(Object o) {} String taint() { @@ -21,9 +21,9 @@ void test1() { sink(pair.right()); // no taint flow sink(pair.getRight()); // no taint flow Pair updatedLeftPair = pair.left(taint()); - sink(updatedLeftPair.left); //$hasTaintFlow - sink(updatedLeftPair.left()); //$hasTaintFlow - sink(updatedLeftPair.getLeft()); //$hasTaintFlow + sink(updatedLeftPair.left); // $ hasTaintFlow + sink(updatedLeftPair.left()); // $ hasTaintFlow + sink(updatedLeftPair.getLeft()); // $ hasTaintFlow sink(updatedLeftPair.right); // no taint flow sink(updatedLeftPair.right()); // no taint flow sink(updatedLeftPair.getRight()); // no taint flow @@ -31,33 +31,33 @@ void test1() { sink(updatedRightPair.left); // no taint flow sink(updatedRightPair.left()); // no taint flow sink(updatedRightPair.getLeft()); // no taint flow - sink(updatedRightPair.right); //$hasTaintFlow - sink(updatedRightPair.right()); //$hasTaintFlow - sink(updatedRightPair.getRight()); //$hasTaintFlow + sink(updatedRightPair.right); // $ hasTaintFlow + sink(updatedRightPair.right()); // $ hasTaintFlow + sink(updatedRightPair.getRight()); // $ hasTaintFlow Pair updatedBothPair = pair.left(taint()).right(taint()); - sink(updatedBothPair.left); //$hasTaintFlow - sink(updatedBothPair.left()); //$hasTaintFlow - sink(updatedBothPair.getLeft()); //$hasTaintFlow - sink(updatedBothPair.right); //$hasTaintFlow - sink(updatedBothPair.right()); //$hasTaintFlow - sink(updatedBothPair.getRight()); //$hasTaintFlow + sink(updatedBothPair.left); // $ hasTaintFlow + sink(updatedBothPair.left()); // $ hasTaintFlow + sink(updatedBothPair.getLeft()); // $ hasTaintFlow + sink(updatedBothPair.right); // $ hasTaintFlow + sink(updatedBothPair.right()); // $ hasTaintFlow + sink(updatedBothPair.getRight()); // $ hasTaintFlow } void test2() { Pair pair = Pair.of(taint(), taint()); - sink(pair.left); //$hasTaintFlow - sink(pair.left()); //$hasTaintFlow - sink(pair.getLeft()); //$hasTaintFlow - sink(pair.right); //$hasTaintFlow - sink(pair.right()); //$hasTaintFlow - sink(pair.getRight()); //$hasTaintFlow + sink(pair.left); // $ hasTaintFlow + sink(pair.left()); // $ hasTaintFlow + sink(pair.getLeft()); // $ hasTaintFlow + sink(pair.right); // $ hasTaintFlow + sink(pair.right()); // $ hasTaintFlow + sink(pair.getRight()); // $ hasTaintFlow Pair> pushedLeftPair = pair.pushLeft("safe"); sink(pushedLeftPair.left()); // no taint flow - sink(pushedLeftPair.right().left()); //$hasTaintFlow - sink(pushedLeftPair.right().right()); //$hasTaintFlow + sink(pushedLeftPair.right().left()); // $ hasTaintFlow + sink(pushedLeftPair.right().right()); // $ hasTaintFlow Pair, String> pushedRightPair = pair.pushRight("safe"); - sink(pushedRightPair.left().left()); //$hasTaintFlow - sink(pushedRightPair.left().right()); //$hasTaintFlow + sink(pushedRightPair.left().left()); // $ hasTaintFlow + sink(pushedRightPair.left().right()); // $ hasTaintFlow sink(pushedRightPair.right()); // no taint flow } @@ -70,39 +70,39 @@ void test3() { sink(pair.right()); // no taint flow sink(pair.getRight()); // no taint flow Pair> pushedLeftPair = pair.pushLeft(taint()); - sink(pushedLeftPair.left()); //$hasTaintFlow + sink(pushedLeftPair.left()); // $ hasTaintFlow sink(pushedLeftPair.right().left()); // no taint flow sink(pushedLeftPair.right().right()); // no taint flow Pair, String> pushedRightPair = pair.pushRight(taint()); sink(pushedRightPair.left().left()); // no taint flow sink(pushedRightPair.left().right()); // no taint flow - sink(pushedRightPair.right()); //$hasTaintFlow + sink(pushedRightPair.right()); // $ hasTaintFlow } void test4() { Pair pair = Pair.of(taint(), taint()); - sink(pair.left()); //$hasTaintFlow - sink(pair.right()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow + sink(pair.right()); // $ hasTaintFlow Pair, String> nestLeftPair = pair.nestLeft("safe"); sink(nestLeftPair.left().left()); // no taint flow - sink(nestLeftPair.left().right()); //$hasTaintFlow - sink(nestLeftPair.right()); //$hasTaintFlow + sink(nestLeftPair.left().right()); // $ hasTaintFlow + sink(nestLeftPair.right()); // $ hasTaintFlow Pair> nestRightPair = pair.nestRight("safe"); - sink(nestRightPair.left()); //$hasTaintFlow + sink(nestRightPair.left()); // $ hasTaintFlow sink(nestRightPair.right().left()); // no taint flow - sink(nestRightPair.right().right()); //$hasTaintFlow + sink(nestRightPair.right().right()); // $ hasTaintFlow } void test5() { Pair pair = Pair.of(taint(), "safe"); - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow Pair, String> nestLeftPair = pair.nestLeft("safe"); sink(nestLeftPair.left().left()); // no taint flow - sink(nestLeftPair.left().right()); //$hasTaintFlow + sink(nestLeftPair.left().right()); // $ hasTaintFlow sink(nestLeftPair.right()); // no taint flow Pair> nestRightPair = pair.nestRight("safe"); - sink(nestRightPair.left()); //$hasTaintFlow + sink(nestRightPair.left()); // $ hasTaintFlow sink(nestRightPair.right().left()); // no taint flow sink(nestRightPair.right().right()); // no taint flow } @@ -110,15 +110,15 @@ void test5() { void test6() { Pair pair = Pair.of("safe", taint()); sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow Pair, String> nestLeftPair = pair.nestLeft("safe"); sink(nestLeftPair.left().left()); // no taint flow sink(nestLeftPair.left().right()); // no taint flow - sink(nestLeftPair.right()); //$hasTaintFlow + sink(nestLeftPair.right()); // $ hasTaintFlow Pair> nestRightPair = pair.nestRight("safe"); sink(nestRightPair.left()); // no taint flow sink(nestRightPair.right().left()); // no taint flow - sink(nestRightPair.right().right()); //$hasTaintFlow + sink(nestRightPair.right().right()); // $ hasTaintFlow } void test7() { @@ -126,12 +126,12 @@ void test7() { sink(pair.left()); // no taint flow sink(pair.right()); // no taint flow Pair, String> nestLeftPair = pair.nestLeft(taint()); - sink(nestLeftPair.left().left()); // $hasTaintFlow + sink(nestLeftPair.left().left()); // $ hasTaintFlow sink(nestLeftPair.left().right()); // no taint flow sink(nestLeftPair.right()); // no taint flow Pair> nestRightPair = pair.nestRight(taint()); sink(nestRightPair.left()); // no taint flow - sink(nestRightPair.right().left()); // $hasTaintFlow + sink(nestRightPair.right().left()); // $ hasTaintFlow sink(nestRightPair.right().right()); // no taint flow } @@ -141,7 +141,7 @@ void test8() throws Exception { sink(left); // no taint flow return taint(); }); - sink(taintLeft.left()); //$hasTaintFlow + sink(taintLeft.left()); // $ hasTaintFlow sink(taintLeft.right()); // no taint flow } @@ -152,43 +152,43 @@ void test9() throws Exception { return taint(); }); sink(taintRight.left()); // no taint flow - sink(taintRight.right()); //$hasTaintFlow + sink(taintRight.right()); // $ hasTaintFlow } void test10() throws Exception { Pair pair = Pair.of(taint(), taint()); Pair taintLeft = pair.mapLeft(left -> { - sink(left); //$hasTaintFlow + sink(left); // $ hasTaintFlow return "safe"; }); sink(taintLeft.left()); // no taint flow - sink(taintLeft.right()); //$hasTaintFlow + sink(taintLeft.right()); // $ hasTaintFlow } void test11() throws Exception { Pair pair = Pair.of(taint(), taint()); Pair taintRight = pair.mapRight(right -> { - sink(right); //$hasTaintFlow + sink(right); // $ hasTaintFlow return "safe"; }); - sink(taintRight.left()); //$hasTaintFlow + sink(taintRight.left()); // $ hasTaintFlow sink(taintRight.right()); // no taint flow } void test12() throws Exception { Pair pair = Pair.of(taint(), taint()); String safe = pair.map(p -> { - sink(p.left()); //$hasTaintFlow - sink(p.right()); //$hasTaintFlow + sink(p.left()); // $ hasTaintFlow + sink(p.right()); // $ hasTaintFlow return "safe"; }); sink(safe); // no taint flow String unsafe = pair.map(p -> { - sink(p.left()); //$hasTaintFlow - sink(p.right()); //$hasTaintFlow + sink(p.left()); // $ hasTaintFlow + sink(p.right()); // $ hasTaintFlow return taint(); }); - sink(unsafe); //$hasTaintFlow + sink(unsafe); // $ hasTaintFlow } void test13() { @@ -197,20 +197,20 @@ void test13() { .left(Promise.value("safe")) .then(pair -> { sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow }); Promise .value(taint()) .right(Promise.value("safe")) .then(pair -> { - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow }); Promise .value("safe") .left(Promise.value(taint())) .then(pair -> { - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow }); Promise @@ -218,7 +218,7 @@ void test13() { .right(Promise.value(taint())) .then(pair -> { sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow }); } @@ -226,21 +226,21 @@ void test14() { Promise .value(taint()) .left(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return "safe"; }) .then(pair -> { sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow }); Promise .value(taint()) .right(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return "safe"; }) .then(pair -> { - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow }); Promise @@ -250,7 +250,7 @@ void test14() { return taint(); }) .then(pair -> { - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow }); Promise @@ -261,7 +261,7 @@ void test14() { }) .then(pair -> { sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow }); } @@ -269,21 +269,21 @@ void test15() { Promise .value(taint()) .flatLeft(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return Promise.value("safe"); }) .then(pair -> { sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow }); Promise .value(taint()) .flatRight(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return Promise.value("safe"); }) .then(pair -> { - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow }); Promise @@ -292,7 +292,7 @@ void test15() { return Promise.value(taint()); }) .then(pair -> { - sink(pair.left()); //$hasTaintFlow + sink(pair.left()); // $ hasTaintFlow sink(pair.right()); // no taint flow }); Promise @@ -302,7 +302,7 @@ void test15() { }) .then(pair -> { sink(pair.left()); // no taint flow - sink(pair.right()); //$hasTaintFlow + sink(pair.right()); // $ hasTaintFlow }); } } diff --git a/java/ql/test/library-tests/frameworks/ratpack/resources/Resource.java b/java/ql/test/library-tests/frameworks/ratpack/resources/Resource.java index 695ad907d1f0..19ec14fd236e 100644 --- a/java/ql/test/library-tests/frameworks/ratpack/resources/Resource.java +++ b/java/ql/test/library-tests/frameworks/ratpack/resources/Resource.java @@ -19,59 +19,59 @@ String taint() { } void test1(Context ctx) { - sink(ctx.getRequest().getContentLength()); //$hasTaintFlow - sink(ctx.getRequest().getCookies()); //$hasTaintFlow - sink(ctx.getRequest().oneCookie("Magic-Cookie")); //$hasTaintFlow - sink(ctx.getRequest().getHeaders()); //$hasTaintFlow - sink(ctx.getRequest().getHeaders().get("questionable_header")); //$hasTaintFlow - sink(ctx.getRequest().getHeaders().getAll("questionable_header")); //$hasTaintFlow - sink(ctx.getRequest().getHeaders().getNames()); //$hasTaintFlow - sink(ctx.getRequest().getHeaders().asMultiValueMap()); //$hasTaintFlow - sink(ctx.getRequest().getHeaders().asMultiValueMap().get("questionable_header")); //$hasTaintFlow - sink(ctx.getRequest().getPath()); //$hasTaintFlow - sink(ctx.getRequest().getQuery()); //$hasTaintFlow - sink(ctx.getRequest().getQueryParams()); //$hasTaintFlow - sink(ctx.getRequest().getQueryParams().get("questionable_parameter")); //$hasTaintFlow - sink(ctx.getRequest().getRawUri()); //$hasTaintFlow - sink(ctx.getRequest().getUri()); //$hasTaintFlow + sink(ctx.getRequest().getContentLength()); // $ hasTaintFlow + sink(ctx.getRequest().getCookies()); // $ hasTaintFlow + sink(ctx.getRequest().oneCookie("Magic-Cookie")); // $ hasTaintFlow + sink(ctx.getRequest().getHeaders()); // $ hasTaintFlow + sink(ctx.getRequest().getHeaders().get("questionable_header")); // $ hasTaintFlow + sink(ctx.getRequest().getHeaders().getAll("questionable_header")); // $ hasTaintFlow + sink(ctx.getRequest().getHeaders().getNames()); // $ hasTaintFlow + sink(ctx.getRequest().getHeaders().asMultiValueMap()); // $ hasTaintFlow + sink(ctx.getRequest().getHeaders().asMultiValueMap().get("questionable_header")); // $ hasTaintFlow + sink(ctx.getRequest().getPath()); // $ hasTaintFlow + sink(ctx.getRequest().getQuery()); // $ hasTaintFlow + sink(ctx.getRequest().getQueryParams()); // $ hasTaintFlow + sink(ctx.getRequest().getQueryParams().get("questionable_parameter")); // $ hasTaintFlow + sink(ctx.getRequest().getRawUri()); // $ hasTaintFlow + sink(ctx.getRequest().getUri()); // $ hasTaintFlow } void test2(Context ctx, OutputStream os) { ctx.getRequest().getBody().then(td -> { - sink(td); //$hasTaintFlow - sink(td.getText()); //$hasTaintFlow - sink(td.getBuffer()); //$hasTaintFlow - sink(td.getBytes()); //$hasTaintFlow - sink(td.getContentType()); //$hasTaintFlow - sink(td.getInputStream()); //$hasTaintFlow + sink(td); // $ hasTaintFlow + sink(td.getText()); // $ hasTaintFlow + sink(td.getBuffer()); // $ hasTaintFlow + sink(td.getBytes()); // $ hasTaintFlow + sink(td.getContentType()); // $ hasTaintFlow + sink(td.getInputStream()); // $ hasTaintFlow sink(os); td.writeTo(os); - sink(os); //$hasTaintFlow + sink(os); // $ hasTaintFlow if (td instanceof UploadedFile) { UploadedFile uf = (UploadedFile) td; - sink(uf.getFileName()); //$hasTaintFlow + sink(uf.getFileName()); // $ hasTaintFlow } }); } void test3(Context ctx) { ctx.getRequest().getBody().map(TypedData::getText).then(s -> { - sink(s); //$hasTaintFlow + sink(s); // $ hasTaintFlow }); ctx.getRequest().getBody().map(b -> { - sink(b); //$hasTaintFlow - sink(b.getText()); //$hasTaintFlow + sink(b); // $ hasTaintFlow + sink(b.getText()); // $ hasTaintFlow return b.getText(); }).then(t -> { - sink(t); //$hasTaintFlow + sink(t); // $ hasTaintFlow }); - ctx.getRequest().getBody().map(TypedData::getText).then(this::sink); //$hasTaintFlow + ctx.getRequest().getBody().map(TypedData::getText).then(this::sink); // $ hasTaintFlow ctx .getRequest() .getBody() .map(TypedData::getText) - .next(this::sink) //$hasTaintFlow - .then(this::sink); //$hasTaintFlow + .next(this::sink) // $ hasTaintFlow + .then(this::sink); // $ hasTaintFlow } void test4() { @@ -79,11 +79,11 @@ void test4() { Promise.value(tainted); Promise .value(tainted) - .then(this::sink); //$hasTaintFlow + .then(this::sink); // $ hasTaintFlow Promise .value(tainted) .map(a -> a) - .then(this::sink); //$hasTaintFlow + .then(this::sink); // $ hasTaintFlow } void test5(Context ctx) { @@ -92,22 +92,22 @@ void test5(Context ctx) { .getBody() .map(data -> { Form form = ctx.parse(data, Form.form()); - sink(form); //$hasTaintFlow + sink(form); // $ hasTaintFlow return form; }) .then(form -> { - sink(form.file("questionable_file")); //$hasTaintFlow - sink(form.file("questionable_file").getFileName()); //$hasTaintFlow - sink(form.files("questionable_files")); //$hasTaintFlow - sink(form.files()); //$hasTaintFlow - sink(form.get("questionable_parameter")); //$hasTaintFlow - sink(form.getAll().get("questionable_parameter").get(0)); //$hasTaintFlow - sink(form.getAll("questionable_parameter").get(0)); //$hasTaintFlow - sink(form.asMultimap().get("questionable_parameter")); //$hasTaintFlow - sink(form.asMultimap().asMap()); //$hasTaintFlow + sink(form.file("questionable_file")); // $ hasTaintFlow + sink(form.file("questionable_file").getFileName()); // $ hasTaintFlow + sink(form.files("questionable_files")); // $ hasTaintFlow + sink(form.files()); // $ hasTaintFlow + sink(form.get("questionable_parameter")); // $ hasTaintFlow + sink(form.getAll().get("questionable_parameter").get(0)); // $ hasTaintFlow + sink(form.getAll("questionable_parameter").get(0)); // $ hasTaintFlow + sink(form.asMultimap().get("questionable_parameter")); // $ hasTaintFlow + sink(form.asMultimap().asMap()); // $ hasTaintFlow form.asMultimap().asMap().forEach((name, values) -> { - sink(name); //$hasTaintFlow - sink(values); //$hasTaintFlow + sink(name); // $ hasTaintFlow + sink(values); // $ hasTaintFlow }); }); } @@ -116,17 +116,17 @@ void test6(Context ctx) { ctx .parse(Parse.of(Form.class)) .then(form -> { - sink(form); //$hasTaintFlow + sink(form); // $ hasTaintFlow }); ctx .parse(Form.class) .then(form -> { - sink(form); //$hasTaintFlow + sink(form); // $ hasTaintFlow }); ctx .parse(Form.class, "Some Object") .then(form -> { - sink(form); //$hasTaintFlow + sink(form); // $ hasTaintFlow }); } @@ -135,50 +135,50 @@ void test7() { Promise .flatten(() -> Promise.value(tainted)) .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .onError(Action.noop()) .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .cache() .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .fork() .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .route(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return false; }, value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .cacheIf(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return true; }) .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .onError(RuntimeException.class, Action.noop()) .next(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .map(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return value; }) .blockingMap(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return value; }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } @@ -191,7 +191,7 @@ void test8() { return "potato"; }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .value("potato") @@ -199,7 +199,7 @@ void test8() { return taint(); }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .value(tainted) @@ -208,7 +208,7 @@ void test8() { return Promise.value("potato"); }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .value("potato") @@ -216,7 +216,7 @@ void test8() { return Promise.value(taint()); }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } @@ -226,7 +226,7 @@ void test9() { .value(tainted) .map(Resource::identity) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .value("potato") @@ -238,7 +238,7 @@ void test9() { .value(tainted) .flatMap(v -> Promise.value(v)) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } @@ -252,7 +252,7 @@ void test10() { .value(tainted) .apply(Resource::promiseIdentity) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .value("potato") @@ -261,7 +261,7 @@ void test10() { sink(value); // no taints flow }); } - + public static Promise promiseIdentity(Promise input) { return input.map(i -> i); } @@ -272,7 +272,7 @@ void test11() { .value(tainted) .map(a -> a) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .value("potato") @@ -287,40 +287,40 @@ void test12() { Promise .sync(() -> tainted) .mapIf(v -> { - sink(v); //$hasTaintFlow + sink(v); // $ hasTaintFlow return true; }, v -> { - sink(v); //$hasTaintFlow + sink(v); // $ hasTaintFlow return v; }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .sync(() -> tainted) .mapIf(v -> { - sink(v); //$hasTaintFlow + sink(v); // $ hasTaintFlow return true; }, vTrue -> { - sink(vTrue); //$hasTaintFlow + sink(vTrue); // $ hasTaintFlow return vTrue; }, vFalse -> { - sink(vFalse); //$hasTaintFlow + sink(vFalse); // $ hasTaintFlow return vFalse; }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); Promise .sync(() -> tainted) .mapIf(v -> { - sink(v); //$hasTaintFlow + sink(v); // $ hasTaintFlow return true; }, vTrue -> { - sink(vTrue); //$hasTaintFlow + sink(vTrue); // $ hasTaintFlow return "potato"; }, vFalse -> { - sink(vFalse); //$hasTaintFlow + sink(vFalse); // $ hasTaintFlow return "potato"; }) .then(value -> { @@ -340,7 +340,7 @@ void test13() { .value("safe") .replace(Promise.value(tainted)) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } @@ -349,10 +349,10 @@ void test14() { Promise .value(tainted) .blockingOp(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } @@ -361,16 +361,16 @@ void test15() { Promise .value(tainted) .nextOp(value -> Operation.of(() -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow })) .nextOpIf(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow return true; }, value -> Operation.of(() -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow })) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } @@ -379,23 +379,23 @@ void test16() { Promise .value(tainted) .flatOp(value -> Operation.of(() -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow })); } void test17() throws Exception { String tainted = taint(); Result result = Result.success(tainted); - sink(result.getValue()); //$hasTaintFlow - sink(result.getValueOrThrow()); //$hasTaintFlow + sink(result.getValue()); // $ hasTaintFlow + sink(result.getValueOrThrow()); // $ hasTaintFlow Promise .value(tainted) .wiretap(r -> { - sink(r.getValue()); //$hasTaintFlow - sink(r.getValueOrThrow()); //$hasTaintFlow + sink(r.getValue()); // $ hasTaintFlow + sink(r.getValueOrThrow()); // $ hasTaintFlow }) .then(value -> { - sink(value); //$hasTaintFlow + sink(value); // $ hasTaintFlow }); } diff --git a/java/ql/test/library-tests/frameworks/spring/cache/Test.java b/java/ql/test/library-tests/frameworks/spring/cache/Test.java index 1f2473d00048..92b24a7fc585 100644 --- a/java/ql/test/library-tests/frameworks/spring/cache/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/cache/Test.java @@ -50,91 +50,91 @@ public void test() { Cache.ValueRetrievalException out = null; Object in = source(); out = new Cache.ValueRetrievalException(in, null, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.cache;Cache$ValueRetrievalException;false;getKey;;;MapKey of Argument[this];ReturnValue;value;manual" Object out = null; Cache.ValueRetrievalException in = new Cache.ValueRetrievalException(source(), null, null); out = in.getKey(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.cache;Cache$ValueWrapper;true;get;;;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; Cache.ValueWrapper in = new ValueWrapper(source()); out = in.get(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;get;(Object);;MapValue of Argument[this];MapValue of ReturnValue;value;manual" Cache.ValueWrapper out = null; Cache in = new DummyCache(null, source()); out = in.get(null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; Cache in = new DummyCache(null, source()); out = in.get(null, (Callable)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;get;(Object,Class);;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; Cache in = new DummyCache(null, source()); out = in.get(null, (Class)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;getNativeCache;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" Object out = null; Cache in = new DummyCache(source(), null); out = in.getNativeCache(); - sink(getMapKey((Cache)out)); // $hasValueFlow + sink(getMapKey((Cache)out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;getNativeCache;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" Object out = null; Cache in = new DummyCache(null, source()); out = in.getNativeCache(); - sink(getMapValue((Cache)out)); // $hasValueFlow + sink(getMapValue((Cache)out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;put;;;Argument[0];MapKey of Argument[this];value;manual" Cache out = null; Object in = source(); out.put(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;put;;;Argument[1];MapValue of Argument[this];value;manual" Cache out = null; Object in = source(); out.put(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;putIfAbsent;;;Argument[0];MapKey of Argument[this];value;manual" Cache out = null; Object in = source(); out.putIfAbsent(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;putIfAbsent;;;Argument[1];MapValue of Argument[this];value;manual" Cache out = null; Object in = source(); out.putIfAbsent(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.cache;Cache;true;putIfAbsent;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" Cache.ValueWrapper out = null; Cache in = new DummyCache(null, source()); out = in.putIfAbsent(null, null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/context/Test.java b/java/ql/test/library-tests/frameworks/spring/context/Test.java index 24680b98750f..329af10f5a35 100644 --- a/java/ql/test/library-tests/frameworks/spring/context/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/context/Test.java @@ -13,8 +13,8 @@ void sink(Object o) {} public void test() { StaticMessageSource sms = new StaticMessageSource(); sms.addMessage(code, locale, "hello {0}"); - sink(sms.getMessage(code, new String[]{ taint() }, locale)); // $hasTaintFlow - sink(sms.getMessage(code, new String[]{ taint() }, "", locale)); // $hasTaintFlow - sink(sms.getMessage(code, null, taint(), locale)); // $hasTaintFlow + sink(sms.getMessage(code, new String[]{ taint() }, locale)); // $ hasTaintFlow + sink(sms.getMessage(code, new String[]{ taint() }, "", locale)); // $ hasTaintFlow + sink(sms.getMessage(code, null, taint(), locale)); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/controller/Test.java b/java/ql/test/library-tests/frameworks/spring/controller/Test.java index ad4fbc89f44f..f7af203e8bac 100644 --- a/java/ql/test/library-tests/frameworks/spring/controller/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/controller/Test.java @@ -127,62 +127,62 @@ public void get(Pageable src) { // $ RequestMappingURL="/" static class ExplicitlyTaintedTest { @RequestMapping("/") public void get(InputStream src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void get(Reader src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void matrixVariable(@MatrixVariable Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void requestParam(@RequestParam Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void requestHeader(@RequestHeader Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void cookieValue(@CookieValue Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void requestPart(@RequestPart Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void pathVariable(@PathVariable Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void requestBody(@RequestBody Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void get(HttpEntity src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void requestAttribute(@RequestAttribute Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void sessionAttribute(@SessionAttribute Object src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } } @@ -193,12 +193,12 @@ static class Pojo { @RequestMapping("/") public void get(String src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } @RequestMapping("/") public void get1(Pojo src) { // $ RequestMappingURL="/" - sink(src); // $hasValueFlow + sink(src); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/data/Test.java b/java/ql/test/library-tests/frameworks/spring/data/Test.java index e23fc6526928..977fec5f983a 100644 --- a/java/ql/test/library-tests/frameworks/spring/data/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/data/Test.java @@ -14,6 +14,6 @@ void sink(Object o) {} void testCrudRepository(CrudRepository cr) { Struct s = new Struct(source()); s = cr.save(s); - sink(s.field); //$hasValueFlow + sink(s.field); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/http/TestHttp.java b/java/ql/test/library-tests/frameworks/spring/http/TestHttp.java index d148a6be93a7..e05d129c2e5d 100644 --- a/java/ql/test/library-tests/frameworks/spring/http/TestHttp.java +++ b/java/ql/test/library-tests/frameworks/spring/http/TestHttp.java @@ -14,149 +14,149 @@ static void sink(Object o) {} void test1() { String x = taint(); - sink(new HttpEntity(x)); // $hasTaintFlow + sink(new HttpEntity(x)); // $ hasTaintFlow MultiValueMap m1 = new LinkedMultiValueMap(); - sink(new HttpEntity(x, m1)); // $hasTaintFlow + sink(new HttpEntity(x, m1)); // $ hasTaintFlow m1.add("a", taint()); - sink(new HttpEntity("a", m1)); // $hasTaintFlow - sink(new HttpEntity(m1)); // $hasTaintFlow + sink(new HttpEntity("a", m1)); // $ hasTaintFlow + sink(new HttpEntity(m1)); // $ hasTaintFlow MultiValueMap m2 = new LinkedMultiValueMap(); m2.add(taint(), "a"); - sink(new HttpEntity(m2)); // $hasTaintFlow + sink(new HttpEntity(m2)); // $ hasTaintFlow HttpEntity ent = taint(); - sink(ent.getBody()); // $hasTaintFlow - sink(ent.getHeaders()); // $hasTaintFlow + sink(ent.getBody()); // $ hasTaintFlow + sink(ent.getHeaders()); // $ hasTaintFlow RequestEntity req = taint(); - sink(req.getUrl()); // $hasTaintFlow + sink(req.getUrl()); // $ hasTaintFlow } void test2() { String x = taint(); - sink(ResponseEntity.ok(x)); // $hasTaintFlow - sink(ResponseEntity.of(Optional.of(x))); // $hasTaintFlow + sink(ResponseEntity.ok(x)); // $ hasTaintFlow + sink(ResponseEntity.of(Optional.of(x))); // $ hasTaintFlow - sink(ResponseEntity.status(200).contentLength(2048).body(x)); // $hasTaintFlow - sink(ResponseEntity.created(taint()).contentType(null).body("a")); // $hasTaintFlow - sink(ResponseEntity.status(200).header(x, "a", "b", "c").build()); // $hasTaintFlow - sink(ResponseEntity.status(200).header("h", "a", "b", x).build()); // $hasTaintFlow + sink(ResponseEntity.status(200).contentLength(2048).body(x)); // $ hasTaintFlow + sink(ResponseEntity.created(taint()).contentType(null).body("a")); // $ hasTaintFlow + sink(ResponseEntity.status(200).header(x, "a", "b", "c").build()); // $ hasTaintFlow + sink(ResponseEntity.status(200).header("h", "a", "b", x).build()); // $ hasTaintFlow HttpHeaders h = new HttpHeaders(); h.add("h", taint()); - sink(ResponseEntity.status(200).headers(h).allow().build()); // $hasTaintFlow - sink(ResponseEntity.status(200).eTag(x).allow().build()); // $hasTaintFlow - sink(ResponseEntity.status(200).location(taint()).lastModified(10000000).build()); // $hasTaintFlow - sink(ResponseEntity.status(200).varyBy(x).build()); + sink(ResponseEntity.status(200).headers(h).allow().build()); // $ hasTaintFlow + sink(ResponseEntity.status(200).eTag(x).allow().build()); // $ hasTaintFlow + sink(ResponseEntity.status(200).location(taint()).lastModified(10000000).build()); // $ hasTaintFlow + sink(ResponseEntity.status(200).varyBy(x).build()); } void test3() { String x = taint(); MultiValueMap m1 = new LinkedMultiValueMap(); - sink(new ResponseEntity(x, HttpStatus.ACCEPTED)); // $hasTaintFlow - sink(new ResponseEntity(x, m1, HttpStatus.ACCEPTED)); // $hasTaintFlow - sink(new ResponseEntity(x, m1, 200)); // $hasTaintFlow + sink(new ResponseEntity(x, HttpStatus.ACCEPTED)); // $ hasTaintFlow + sink(new ResponseEntity(x, m1, HttpStatus.ACCEPTED)); // $ hasTaintFlow + sink(new ResponseEntity(x, m1, 200)); // $ hasTaintFlow m1.add("a", taint()); - sink(new ResponseEntity("a", m1, HttpStatus.ACCEPTED)); // $hasTaintFlow - sink(new ResponseEntity(m1, HttpStatus.ACCEPTED)); // $hasTaintFlow - sink(new ResponseEntity("a", m1, 200)); // $hasTaintFlow + sink(new ResponseEntity("a", m1, HttpStatus.ACCEPTED)); // $ hasTaintFlow + sink(new ResponseEntity(m1, HttpStatus.ACCEPTED)); // $ hasTaintFlow + sink(new ResponseEntity("a", m1, 200)); // $ hasTaintFlow MultiValueMap m2 = new LinkedMultiValueMap(); m2.add(taint(), "a"); - sink(new ResponseEntity("a", m2, HttpStatus.ACCEPTED)); // $hasTaintFlow - sink(new ResponseEntity(m2, HttpStatus.ACCEPTED)); // $hasTaintFlow - sink(new ResponseEntity("a", m2, 200)); // $hasTaintFlow + sink(new ResponseEntity("a", m2, HttpStatus.ACCEPTED)); // $ hasTaintFlow + sink(new ResponseEntity(m2, HttpStatus.ACCEPTED)); // $ hasTaintFlow + sink(new ResponseEntity("a", m2, 200)); // $ hasTaintFlow ResponseEntity ent = taint(); - sink(ent.getBody()); // $hasTaintFlow - sink(ent.getHeaders()); // $hasTaintFlow + sink(ent.getBody()); // $ hasTaintFlow + sink(ent.getHeaders()); // $ hasTaintFlow } void test4() { MultiValueMap m1 = new LinkedMultiValueMap(); m1.add("a", taint()); - sink(new HttpHeaders(m1)); // $hasTaintFlow + sink(new HttpHeaders(m1)); // $ hasTaintFlow MultiValueMap m2 = new LinkedMultiValueMap(); m2.add(taint(), "a"); - sink(new HttpHeaders(m2)); // $hasTaintFlow + sink(new HttpHeaders(m2)); // $ hasTaintFlow HttpHeaders h1 = new HttpHeaders(); - h1.add(taint(), "a"); - sink(h1); // $hasTaintFlow + h1.add(taint(), "a"); + sink(h1); // $ hasTaintFlow HttpHeaders h2 = new HttpHeaders(); - h2.add("a", taint()); - sink(h2); // $hasTaintFlow + h2.add("a", taint()); + sink(h2); // $ hasTaintFlow HttpHeaders h3 = new HttpHeaders(); - h3.addAll(m1); - sink(h3); // $hasTaintFlow + h3.addAll(m1); + sink(h3); // $ hasTaintFlow HttpHeaders h4 = new HttpHeaders(); - h4.addAll(m2); - sink(h4); // $hasTaintFlow + h4.addAll(m2); + sink(h4); // $ hasTaintFlow HttpHeaders h5 = new HttpHeaders(); - h5.addAll(taint(), List.of()); - sink(h5); // $hasTaintFlow + h5.addAll(taint(), List.of()); + sink(h5); // $ hasTaintFlow HttpHeaders h6 = new HttpHeaders(); - h6.addAll("a", List.of(taint())); - sink(h6); // $hasTaintFlow + h6.addAll("a", List.of(taint())); + sink(h6); // $ hasTaintFlow - sink(HttpHeaders.formatHeaders(m1)); // $hasTaintFlow - sink(HttpHeaders.formatHeaders(m2)); // $hasTaintFlow + sink(HttpHeaders.formatHeaders(m1)); // $ hasTaintFlow + sink(HttpHeaders.formatHeaders(m2)); // $ hasTaintFlow - sink(HttpHeaders.encodeBasicAuth(taint(), "a", null)); // $hasTaintFlow - sink(HttpHeaders.encodeBasicAuth("a", taint(), null)); // $hasTaintFlow + sink(HttpHeaders.encodeBasicAuth(taint(), "a", null)); // $ hasTaintFlow + sink(HttpHeaders.encodeBasicAuth("a", taint(), null)); // $ hasTaintFlow } void test5() { HttpHeaders h = taint(); - - sink(h.get(null).get(0)); // $hasTaintFlow + + sink(h.get(null).get(0)); // $ hasTaintFlow sink(h.getAccept().get(0)); sink(h.getAcceptCharset().get(0)); sink(h.getAcceptLanguage().get(0)); sink(h.getAcceptLanguageAsLocales().get(0)); sink(h.getAccessControlAllowCredentials()); - sink(h.getAccessControlAllowHeaders().get(0)); // $hasTaintFlow + sink(h.getAccessControlAllowHeaders().get(0)); // $ hasTaintFlow sink(h.getAccessControlAllowMethods().get(0)); - sink(h.getAccessControlAllowOrigin()); // $hasTaintFlow - sink(h.getAccessControlExposeHeaders().get(0)); // $hasTaintFlow + sink(h.getAccessControlAllowOrigin()); // $ hasTaintFlow + sink(h.getAccessControlExposeHeaders().get(0)); // $ hasTaintFlow sink(h.getAccessControlMaxAge()); - sink(h.getAccessControlRequestHeaders().get(0)); // $hasTaintFlow - sink(h.getAccessControlRequestMethod()); + sink(h.getAccessControlRequestHeaders().get(0)); // $ hasTaintFlow + sink(h.getAccessControlRequestMethod()); sink(h.getAllow().toArray()[0]); - sink(h.getCacheControl()); // $hasTaintFlow - sink(h.getConnection().get(0)); // $hasTaintFlow + sink(h.getCacheControl()); // $ hasTaintFlow + sink(h.getConnection().get(0)); // $ hasTaintFlow sink(h.getContentDisposition()); sink(h.getContentLanguage()); sink(h.getContentLength()); sink(h.getContentType()); sink(h.getDate()); - sink(h.getETag()); // $hasTaintFlow + sink(h.getETag()); // $ hasTaintFlow sink(h.getExpires()); - sink(h.getFirst("a")); // $hasTaintFlow - sink(h.getFirstDate("a")); - sink(h.getFirstZonedDateTime("a")); - sink(h.getHost()); // $hasTaintFlow - sink(h.getIfMatch().get(0)); // $hasTaintFlow - sink(h.getIfModifiedSince()); - sink(h.getIfNoneMatch().get(0)); // $hasTaintFlow - sink(h.getIfUnmodifiedSince()); - sink(h.getLastModified()); - sink(h.getLocation()); // $hasTaintFlow - sink(h.getOrEmpty("a").get(0)); // $hasTaintFlow - sink(h.getOrigin()); // $hasTaintFlow - sink(h.getPragma()); // $hasTaintFlow - sink(h.getUpgrade()); // $hasTaintFlow - sink(h.getValuesAsList("a").get(0)); // $hasTaintFlow - sink(h.getVary().get(0)); // $hasTaintFlow + sink(h.getFirst("a")); // $ hasTaintFlow + sink(h.getFirstDate("a")); + sink(h.getFirstZonedDateTime("a")); + sink(h.getHost()); // $ hasTaintFlow + sink(h.getIfMatch().get(0)); // $ hasTaintFlow + sink(h.getIfModifiedSince()); + sink(h.getIfNoneMatch().get(0)); // $ hasTaintFlow + sink(h.getIfUnmodifiedSince()); + sink(h.getLastModified()); + sink(h.getLocation()); // $ hasTaintFlow + sink(h.getOrEmpty("a").get(0)); // $ hasTaintFlow + sink(h.getOrigin()); // $ hasTaintFlow + sink(h.getPragma()); // $ hasTaintFlow + sink(h.getUpgrade()); // $ hasTaintFlow + sink(h.getValuesAsList("a").get(0)); // $ hasTaintFlow + sink(h.getVary().get(0)); // $ hasTaintFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/spring/ui/Test.java b/java/ql/test/library-tests/frameworks/spring/ui/Test.java index 9512cf391aa8..e0112529be01 100644 --- a/java/ql/test/library-tests/frameworks/spring/ui/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/ui/Test.java @@ -28,35 +28,35 @@ public void test() { ConcurrentModel out = null; Object in = source(); out = new ConcurrentModel(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ConcurrentModel;false;ConcurrentModel;(String,Object);;Argument[0];MapKey of Argument[this];value;manual" ConcurrentModel out = null; String in = (String)source(); out = new ConcurrentModel(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ConcurrentModel;false;ConcurrentModel;(String,Object);;Argument[1];MapValue of Argument[this];value;manual" ConcurrentModel out = null; Object in = source(); out = new ConcurrentModel(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Collection);;Element of Argument[0];MapValue of Argument[this];value;manual" Model out = null; Collection in = List.of(source()); out.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Collection);;Element of Argument[0];MapValue of Argument[this];value;manual" ConcurrentModel out = null; Collection in = List.of(source()); out.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Collection);;Element of Argument[0];MapValue of ReturnValue;value;manual" @@ -64,7 +64,7 @@ public void test() { Collection in = List.of(source()); Model instance = null; out = instance.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Collection);;Element of Argument[0];MapValue of ReturnValue;value;manual" @@ -72,21 +72,21 @@ public void test() { Collection in = List.of(source()); ConcurrentModel instance = null; out = instance.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of Argument[this];value;manual" Model out = null; Map in = Map.of(source(), null); out.addAllAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of Argument[this];value;manual" ConcurrentModel out = null; Map in = Map.of(source(), null); out.addAllAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of ReturnValue;value;manual" @@ -94,7 +94,7 @@ public void test() { Map in = Map.of(source(), null); Model instance = null; out = instance.addAllAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of ReturnValue;value;manual" @@ -102,21 +102,21 @@ public void test() { Map in = Map.of(source(), null); ConcurrentModel instance = null; out = instance.addAllAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of Argument[this];value;manual" Model out = null; Map in = Map.of(null, source()); out.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of Argument[this];value;manual" ConcurrentModel out = null; Map in = Map.of(null, source()); out.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of ReturnValue;value;manual" @@ -124,7 +124,7 @@ public void test() { Map in = Map.of(null, source()); Model instance = null; out = instance.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of ReturnValue;value;manual" @@ -132,49 +132,49 @@ public void test() { Map in = Map.of(null, source()); ConcurrentModel instance = null; out = instance.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;;;Argument[this];ReturnValue;value;manual" Model out = null; Model in = (Model)source(); out = in.addAllAttributes((Map)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;;;Argument[this];ReturnValue;value;manual" Model out = null; Model in = (Model)source(); out = in.addAllAttributes((Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;;;Argument[this];ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = (ConcurrentModel)source(); out = in.addAllAttributes((Map)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAllAttributes;;;Argument[this];ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = (ConcurrentModel)source(); out = in.addAllAttributes((Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(Object);;Argument[0];MapValue of Argument[this];value;manual" Model out = null; Object in = source(); out.addAttribute(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(Object);;Argument[0];MapValue of Argument[this];value;manual" ConcurrentModel out = null; Object in = source(); out.addAttribute(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(Object);;Argument[0];MapValue of ReturnValue;value;manual" @@ -182,7 +182,7 @@ public void test() { Object in = source(); Model instance = null; out = instance.addAttribute(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(Object);;Argument[0];MapValue of ReturnValue;value;manual" @@ -190,21 +190,21 @@ public void test() { Object in = source(); ConcurrentModel instance = null; out = instance.addAttribute(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[0];MapKey of Argument[this];value;manual" Model out = null; String in = (String)source(); out.addAttribute(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[0];MapKey of Argument[this];value;manual" ConcurrentModel out = null; String in = (String)source(); out.addAttribute(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[0];MapKey of ReturnValue;value;manual" @@ -212,7 +212,7 @@ public void test() { String in = (String)source(); Model instance = null; out = instance.addAttribute(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[0];MapKey of ReturnValue;value;manual" @@ -220,21 +220,21 @@ public void test() { String in = (String)source(); ConcurrentModel instance = null; out = instance.addAttribute(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[1];MapValue of Argument[this];value;manual" Model out = null; Object in = source(); out.addAttribute(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[1];MapValue of Argument[this];value;manual" ConcurrentModel out = null; Object in = source(); out.addAttribute(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[1];MapValue of ReturnValue;value;manual" @@ -242,7 +242,7 @@ public void test() { Object in = source(); Model instance = null; out = instance.addAttribute(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[1];MapValue of ReturnValue;value;manual" @@ -250,175 +250,175 @@ public void test() { Object in = source(); ConcurrentModel instance = null; out = instance.addAttribute(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;;;Argument[this];ReturnValue;value;manual" Model out = null; Model in = (Model)source(); out = in.addAttribute(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;;;Argument[this];ReturnValue;value;manual" Model out = null; Model in = (Model)source(); out = in.addAttribute(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;;;Argument[this];ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = (ConcurrentModel)source(); out = in.addAttribute(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;addAttribute;;;Argument[this];ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = (ConcurrentModel)source(); out = in.addAttribute(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;asMap;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" Map out = null; Model in = new ConcurrentModel((String)source(), null); out = in.asMap(); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;asMap;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" Map out = null; ConcurrentModel in = new ConcurrentModel((String)source(), null); out = in.asMap(); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;asMap;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" Map out = null; Model in = (Model)Map.of(null, source()); out = in.asMap(); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;asMap;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" Map out = null; ConcurrentModel in = new ConcurrentModel(null, source()); out = in.asMap(); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;getAttribute;;;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; Model in = (Model)Map.of(null, source()); out = in.getAttribute(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;getAttribute;;;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; ConcurrentModel in = new ConcurrentModel(null, source()); out = in.getAttribute(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;Argument[this];ReturnValue;value;manual" Model out = null; Model in = (Model)source(); out = in.mergeAttributes(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;Argument[this];ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = (ConcurrentModel)source(); out = in.mergeAttributes(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" Model out = null; Model in = new ConcurrentModel((String)source(), null); out = in.mergeAttributes(null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = new ConcurrentModel((String)source(), null); out = in.mergeAttributes(null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapKey of Argument[0];MapKey of Argument[this];value;manual" Model out = null; Map in = Map.of(source(), null); out.mergeAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapKey of Argument[0];MapKey of Argument[this];value;manual" ConcurrentModel out = null; Map in = Map.of(source(), null); out.mergeAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" Model out = null; Model in = (Model)Map.of(null, source()); out = in.mergeAttributes(null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" ConcurrentModel out = null; ConcurrentModel in = new ConcurrentModel(null, source()); out = in.mergeAttributes(null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapValue of Argument[0];MapValue of Argument[this];value;manual" Model out = null; Map in = Map.of(null, source()); out.mergeAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;Model;true;mergeAttributes;;;MapValue of Argument[0];MapValue of Argument[this];value;manual" ConcurrentModel out = null; Map in = Map.of(null, source()); out.mergeAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;ModelMap;(Object);;Argument[0];MapValue of Argument[this];value;manual" ModelMap out = null; Object in = source(); out = new ModelMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;ModelMap;(String,Object);;Argument[0];MapKey of Argument[this];value;manual" ModelMap out = null; String in = (String)source(); out = new ModelMap(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;ModelMap;(String,Object);;Argument[1];MapValue of Argument[this];value;manual" ModelMap out = null; Object in = source(); out = new ModelMap(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;(Collection);;Element of Argument[0];MapValue of Argument[this];value;manual" ModelMap out = null; Collection in = List.of(source()); out.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;(Collection);;Element of Argument[0];MapValue of ReturnValue;value;manual" @@ -426,14 +426,14 @@ public void test() { Collection in = List.of(source()); ModelMap instance = null; out = instance.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of Argument[this];value;manual" ModelMap out = null; Map in = Map.of(source(), null); out.addAllAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of ReturnValue;value;manual" @@ -441,14 +441,14 @@ public void test() { Map in = Map.of(source(), null); ModelMap instance = null; out = instance.addAllAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of Argument[this];value;manual" ModelMap out = null; Map in = Map.of(null, source()); out.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of ReturnValue;value;manual" @@ -456,28 +456,28 @@ public void test() { Map in = Map.of(null, source()); ModelMap instance = null; out = instance.addAllAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;;;Argument[this];ReturnValue;value;manual" ModelMap out = null; ModelMap in = (ModelMap)source(); out = in.addAllAttributes((Map)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAllAttributes;;;Argument[this];ReturnValue;value;manual" ModelMap out = null; ModelMap in = (ModelMap)source(); out = in.addAllAttributes((Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;(Object);;Argument[0];MapValue of Argument[this];value;manual" ModelMap out = null; Object in = source(); out.addAttribute(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;(Object);;Argument[0];MapValue of ReturnValue;value;manual" @@ -485,14 +485,14 @@ public void test() { Object in = source(); ModelMap instance = null; out = instance.addAttribute(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;(String,Object);;Argument[0];MapKey of Argument[this];value;manual" ModelMap out = null; String in = (String)source(); out.addAttribute(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;(String,Object);;Argument[0];MapKey of ReturnValue;value;manual" @@ -500,14 +500,14 @@ public void test() { String in = (String)source(); ModelMap instance = null; out = instance.addAttribute(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;(String,Object);;Argument[1];MapValue of Argument[this];value;manual" ModelMap out = null; Object in = source(); out.addAttribute(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;(String,Object);;Argument[1];MapValue of ReturnValue;value;manual" @@ -515,63 +515,63 @@ public void test() { Object in = source(); ModelMap instance = null; out = instance.addAttribute(null, in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;;;Argument[this];ReturnValue;value;manual" ModelMap out = null; ModelMap in = (ModelMap)source(); out = in.addAttribute(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;addAttribute;;;Argument[this];ReturnValue;value;manual" ModelMap out = null; ModelMap in = (ModelMap)source(); out = in.addAttribute(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;getAttribute;;;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; ModelMap in = new ModelMap(null, source()); out = in.getAttribute(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;mergeAttributes;;;Argument[this];ReturnValue;value;manual" ModelMap out = null; ModelMap in = (ModelMap)source(); out = in.mergeAttributes(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;mergeAttributes;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" ModelMap out = null; ModelMap in = new ModelMap((String)source(), null); out = in.mergeAttributes(null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;mergeAttributes;;;MapKey of Argument[0];MapKey of Argument[this];value;manual" ModelMap out = null; Map in = Map.of(source(), null); out.mergeAttributes(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;mergeAttributes;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" ModelMap out = null; ModelMap in = new ModelMap(null, source()); out = in.mergeAttributes(null); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.ui;ModelMap;false;mergeAttributes;;;MapValue of Argument[0];MapValue of Argument[this];value;manual" ModelMap out = null; Map in = Map.of(null, source()); out.mergeAttributes(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/util/Test.java b/java/ql/test/library-tests/frameworks/spring/util/Test.java index ac59cd33f3eb..9153021e2e5a 100644 --- a/java/ql/test/library-tests/frameworks/spring/util/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/util/Test.java @@ -65,21 +65,21 @@ public void test() throws Exception { Map out = new HashMap<>(); String in = (String)source(); this.doMatch("somePattern", in, true, out); - sink(out.get("someKey")); // $hasTaintFlow + sink(out.get("someKey")); // $ hasTaintFlow } { // "org.springframework.util;AntPathMatcher;false;tokenizePath;;;Argument[0];ArrayValue of ReturnValue;taint;manual", String[] out = null; String in = (String)source(); out = this.tokenizePath(in); - sink(out[0]); // $hasTaintFlow + sink(out[0]); // $ hasTaintFlow } { // "org.springframework.util;AntPathMatcher;false;tokenizePattern;;;Argument[0];ArrayValue of ReturnValue;taint;manual", String[] out = null; String in = (String)source(); out = this.tokenizePattern(in); - sink(out[0]); // $hasTaintFlow + sink(out[0]); // $ hasTaintFlow } } @@ -93,7 +93,7 @@ public void test() throws Exception { String in = (String)source(); AntPathMatcher instance = null; out = instance.combine(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;AntPathMatcher;false;combine;;;Argument[0..1];ReturnValue;taint;manual" @@ -101,7 +101,7 @@ public void test() throws Exception { String in = (String)source(); AntPathMatcher instance = null; out = instance.combine(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;AntPathMatcher;false;extractPathWithinPattern;;;Argument[1];ReturnValue;taint;manual" @@ -109,7 +109,7 @@ public void test() throws Exception { String in = (String)source(); AntPathMatcher instance = null; out = instance.extractPathWithinPattern(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;AntPathMatcher;false;extractUriTemplateVariables;;;Argument[1];MapValue of ReturnValue;taint;manual" @@ -117,182 +117,182 @@ public void test() throws Exception { String in = (String)source(); AntPathMatcher instance = null; out = instance.extractUriTemplateVariables(null, in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.util;AutoPopulatingList;false;AutoPopulatingList;(java.util.List,java.lang.Class);;Element of Argument[0];Element of Argument[this];value;manual" AutoPopulatingList out = null; List in = List.of(source()); out = new AutoPopulatingList(in, (Class)null); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.springframework.util;AutoPopulatingList;false;AutoPopulatingList;(java.util.List,org.springframework.util.AutoPopulatingList.ElementFactory);;Element of Argument[0];Element of Argument[this];value;manual" AutoPopulatingList out = null; List in = List.of(source()); out = new AutoPopulatingList(in, (AutoPopulatingList.ElementFactory)null); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.springframework.util;Base64Utils;false;decode;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; byte[] in = (byte[])source(); out = Base64Utils.decode(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;decodeFromString;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; String in = (String)source(); out = Base64Utils.decodeFromString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;decodeFromUrlSafeString;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; String in = (String)source(); out = Base64Utils.decodeFromUrlSafeString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;decodeUrlSafe;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; byte[] in = (byte[])source(); out = Base64Utils.decodeUrlSafe(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;encode;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; byte[] in = (byte[])source(); out = Base64Utils.encode(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;encodeToString;;;Argument[0];ReturnValue;taint;manual" String out = null; byte[] in = (byte[])source(); out = Base64Utils.encodeToString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;encodeToUrlSafeString;;;Argument[0];ReturnValue;taint;manual" String out = null; byte[] in = (byte[])source(); out = Base64Utils.encodeToUrlSafeString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;Base64Utils;false;encodeUrlSafe;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; byte[] in = (byte[])source(); out = Base64Utils.encodeUrlSafe(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;CollectionUtils;false;arrayToList;;;ArrayElement of Argument[0];Element of ReturnValue;value;manual" List out = null; Object[] in = newWithArrayElement(source()); out = CollectionUtils.arrayToList(in); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;findFirstMatch;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; Collection in = List.of(source()); out = CollectionUtils.findFirstMatch(in, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;findValueOfType;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; Collection in = List.of(source()); out = CollectionUtils.findValueOfType(in, (Class[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;findValueOfType;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; Collection in = List.of(source()); out = CollectionUtils.findValueOfType(in, (Class)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;firstElement;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; Set in = Set.of(source()); out = CollectionUtils.firstElement(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;firstElement;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; List in = List.of(source()); out = CollectionUtils.firstElement(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;lastElement;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; Set in = Set.of(source()); out = CollectionUtils.lastElement(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;lastElement;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; List in = List.of(source()); out = CollectionUtils.lastElement(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;mergeArrayIntoCollection;;;ArrayElement of Argument[0];Element of Argument[1];value;manual" Collection out = null; Object[] in = newWithArrayElement(source()); CollectionUtils.mergeArrayIntoCollection(in, out); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;mergePropertiesIntoMap;;;MapKey of Argument[0];MapKey of Argument[1];value;manual" Map out = null; Properties in = newPropertiesWithMapKey(source()); CollectionUtils.mergePropertiesIntoMap(in, out); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;mergePropertiesIntoMap;;;MapValue of Argument[0];MapValue of Argument[1];value;manual" Map out = null; Properties in = newPropertiesWithMapValue(source()); CollectionUtils.mergePropertiesIntoMap(in, out); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;toIterator;;;Element of Argument[0];Element of ReturnValue;value;manual" Iterator out = null; Enumeration in = Collections.enumeration(List.of(source())); out = CollectionUtils.toIterator(in); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;toMultiValueMap;;;Element of MapValue of Argument[0];Element of MapValue of ReturnValue;value;manual" MultiValueMap out = null; Map in = Map.of(null, List.of(source())); out = CollectionUtils.toMultiValueMap(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;toMultiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value;manual" MultiValueMap out = null; Map in = Map.of(source(), null); out = CollectionUtils.toMultiValueMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;unmodifiableMultiValueMap;;;MapKey of Argument[0];MapKey of ReturnValue;value;manual" MultiValueMap out = null; MultiValueMap in = new LinkedMultiValueMap(Map.of(source(), null)); out = CollectionUtils.unmodifiableMultiValueMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;CollectionUtils;false;unmodifiableMultiValueMap;;;MapValue of Argument[0];MapValue of ReturnValue;value;manual" @@ -300,14 +300,14 @@ public void test() throws Exception { MultiValueMap in = new LinkedMultiValueMap(); in.put(null, source()); out = CollectionUtils.unmodifiableMultiValueMap(in); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.util;CompositeIterator;false;add;;;Element of Argument[0];Element of Argument[this];value;manual" CompositeIterator out = null; Iterator in = List.of(source()).iterator(); out.add(in); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "org.springframework.util;CompositeIterator;false;next;;;Element of Argument[this];ReturnValue;value;manual" @@ -315,112 +315,112 @@ public void test() throws Exception { CompositeIterator in = new CompositeIterator(); in.add(List.of(source()).iterator()); out = in.next(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;FastByteArrayOutputStream;false;getInputStream;;;Argument[this];ReturnValue;taint;manual" InputStream out = null; FastByteArrayOutputStream in = (FastByteArrayOutputStream)source(); out = in.getInputStream(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FastByteArrayOutputStream;false;toByteArray;;;Argument[this];ReturnValue;taint;manual" byte[] out = null; FastByteArrayOutputStream in = (FastByteArrayOutputStream)source(); out = in.toByteArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FastByteArrayOutputStream;false;write;;;Argument[0];Argument[this];taint;manual" FastByteArrayOutputStream out = null; int in = (int)source(); out.write(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FastByteArrayOutputStream;false;write;;;Argument[0];Argument[this];taint;manual" FastByteArrayOutputStream out = null; byte[] in = (byte[])source(); out.write(in, 0, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FastByteArrayOutputStream;false;writeTo;;;Argument[this];Argument[0];taint;manual" OutputStream out = null; FastByteArrayOutputStream in = (FastByteArrayOutputStream)source(); in.writeTo(out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual" Writer out = null; String in = (String)source(); FileCopyUtils.copy(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual" Writer out = null; Reader in = (Reader)source(); FileCopyUtils.copy(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual" OutputStream out = null; byte[] in = (byte[])source(); FileCopyUtils.copy(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copy;;;Argument[0];Argument[1];taint;manual" OutputStream out = null; InputStream in = (InputStream)source(); FileCopyUtils.copy(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copyToByteArray;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; InputStream in = (InputStream)source(); out = FileCopyUtils.copyToByteArray(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copyToByteArray;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; File in = (File)source(); out = FileCopyUtils.copyToByteArray(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileCopyUtils;false;copyToString;;;Argument[0];ReturnValue;taint;manual" String out = null; Reader in = (Reader)source(); out = FileCopyUtils.copyToString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;FileSystemUtils;false;copyRecursively;(java.io.File,java.io.File);;Argument[0];Argument[1];taint;manual" File out = null; File in = (File)source(); FileSystemUtils.copyRecursively(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;LinkedMultiValueMap;false;LinkedMultiValueMap;(java.util.Map);;Element of MapValue of Argument[0];Element of MapValue of Argument[this];value;manual" LinkedMultiValueMap out = null; Map in = Map.of(null, List.of(source())); out = new LinkedMultiValueMap(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;LinkedMultiValueMap;false;LinkedMultiValueMap;(java.util.Map);;MapKey of Argument[0];MapKey of Argument[this];value;manual" LinkedMultiValueMap out = null; Map in = Map.of(source(), null); out = new LinkedMultiValueMap(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;LinkedMultiValueMap;false;deepCopy;;;MapKey of Argument[this];MapValue of ReturnValue;value;manual" @@ -428,7 +428,7 @@ public void test() throws Exception { LinkedMultiValueMap in = new LinkedMultiValueMap(); in.set(source(), null); out = in.deepCopy(); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;LinkedMultiValueMap;false;deepCopy;;;MapValue of Argument[this];MapValue of ReturnValue;value;manual" @@ -436,98 +436,98 @@ public void test() throws Exception { LinkedMultiValueMap in = new LinkedMultiValueMap(); in.set(null, source()); out = in.deepCopy(); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;add;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMapAdapter out = null; Object in = source(); out.add(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;add;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.add(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;add;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.add(in, (Object)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;add;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMapAdapter out = null; Object in = source(); out.add(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;add;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.add(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;add;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.add((Object)null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;(java.lang.Object,java.util.List);;Element of Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMapAdapter out = null; List in = List.of(source()); out.addAll(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;(java.lang.Object,java.util.List);;Element of Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; List in = List.of(source()); out.addAll(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;(java.lang.Object,java.util.List);;Element of Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; List in = List.of(source()); out.addAll((Object)null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;(org.springframework.util.MultiValueMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[this];value;manual" MultiValueMapAdapter out = null; MultiValueMap in = (MultiValueMap)Map.of(null, List.of(source())); out.addAll(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;(org.springframework.util.MultiValueMap);;Element of MapValue of Argument[0];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; MultiValueMap in = (MultiValueMap)Map.of(null, List.of(source())); out.addAll(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMapAdapter out = null; Object in = source(); out.addAll(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.addAll(in, (List)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;;;Argument[0];MapKey of Argument[this];value;manual" @@ -535,7 +535,7 @@ public void test() throws Exception { MultiValueMap mvm = null; mvm.set(source(), "someValue"); out.addAll(mvm); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addAll;;;Argument[0];MapKey of Argument[this];value;manual" @@ -543,175 +543,175 @@ public void test() throws Exception { MultiValueMap mvm = null; mvm.set(source(), "someValue"); out.addAll(mvm); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addIfAbsent;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.addIfAbsent(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addIfAbsent;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.addIfAbsent(in, (Object)null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addIfAbsent;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.addIfAbsent(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;addIfAbsent;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.addIfAbsent((Object)null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;getFirst;;;Element of MapValue of Argument[this];ReturnValue;value;manual" Object out = null; MultiValueMapAdapter in = new MultiValueMapAdapter(Map.of(null, List.of(source()))); out = in.getFirst(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;getFirst;;;Element of MapValue of Argument[this];ReturnValue;value;manual" Object out = null; MultiValueMap in = (MultiValueMap)Map.of(null, List.of(source())); out = in.getFirst(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;getFirst;;;Element of MapValue of Argument[this];ReturnValue;value;manual" Object out = null; MultiValueMap in = (MultiValueMap)Map.of(null, List.of(source())); out = in.getFirst((Object)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;set;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMapAdapter out = null; Object in = source(); out.set(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;set;;;Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.set(in, null); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;set;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMapAdapter out = null; Object in = source(); out.set(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;set;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.set(null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;set;;;Argument[1];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Object in = source(); out.set((Object)null, in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;setAll;;;MapKey of Argument[0];MapKey of Argument[this];value;manual" MultiValueMapAdapter out = null; Map in = Map.of(source(), null); out.setAll(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;setAll;;;MapKey of Argument[0];MapKey of Argument[this];value;manual" MultiValueMap out = null; Map in = Map.of(source(), null); out.setAll(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;setAll;;;MapValue of Argument[0];Element of MapValue of Argument[this];value;manual" MultiValueMapAdapter out = null; Map in = Map.of(null, source()); out.setAll(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;setAll;;;MapValue of Argument[0];Element of MapValue of Argument[this];value;manual" MultiValueMap out = null; Map in = Map.of(null, source()); out.setAll(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;toSingleValueMap;;;Element of MapValue of Argument[this];MapValue of ReturnValue;value;manual" Map out = null; MultiValueMapAdapter in = new MultiValueMapAdapter(Map.of(null, List.of(source()))); out = in.toSingleValueMap(); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;toSingleValueMap;;;Element of MapValue of Argument[this];MapValue of ReturnValue;value;manual" Map out = null; MultiValueMap in = (MultiValueMap)Map.of(null, List.of(source())); out = in.toSingleValueMap(); - sink(getMapValue(out)); // $hasValueFlow + sink(getMapValue(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;toSingleValueMap;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" Map out = null; MultiValueMapAdapter in = new MultiValueMapAdapter(Map.of(source(), null)); out = in.toSingleValueMap(); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMap;true;toSingleValueMap;;;MapKey of Argument[this];MapKey of ReturnValue;value;manual" Map out = null; MultiValueMap in = new MultiValueMapAdapter(Map.of(source(), null)); out = in.toSingleValueMap(); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;MultiValueMapAdapter;false;MultiValueMapAdapter;;;Element of MapValue of Argument[0];Element of MapValue of Argument[this];value;manual" MultiValueMapAdapter out = null; Map in = Map.of(null, List.of(source())); out = new MultiValueMapAdapter(in); - sink(getElement(getMapValue(out))); // $hasValueFlow + sink(getElement(getMapValue(out))); // $ hasValueFlow } { // "org.springframework.util;MultiValueMapAdapter;false;MultiValueMapAdapter;;;MapKey of Argument[0];MapKey of Argument[this];value;manual" MultiValueMapAdapter out = null; Map in = Map.of(source(), null); out = new MultiValueMapAdapter(in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.util;ObjectUtils;false;toObjectArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value;manual" Object[] out = null; Object[] in = newWithArrayElement(source()); out = ObjectUtils.toObjectArray(in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;ObjectUtils;false;unwrapOptional;;;Element of Argument[0];ReturnValue;value;manual" Object out = null; Object in = Optional.of(source()); out = ObjectUtils.unwrapOptional(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.util;PropertiesPersister;true;load;;;Argument[1];Argument[0];taint;manual" @@ -719,7 +719,7 @@ public void test() throws Exception { Reader in = (Reader)source(); PropertiesPersister instance = null; instance.load(out, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;load;;;Argument[1];Argument[0];taint;manual" @@ -727,7 +727,7 @@ public void test() throws Exception { InputStream in = (InputStream)source(); PropertiesPersister instance = null; instance.load(out, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;loadFromXml;;;Argument[1];Argument[0];taint;manual" @@ -735,7 +735,7 @@ public void test() throws Exception { InputStream in = (InputStream)source(); PropertiesPersister instance = null; instance.loadFromXml(out, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;store;;;Argument[0];Argument[1];taint;manual" @@ -743,7 +743,7 @@ public void test() throws Exception { Properties in = (Properties)source(); PropertiesPersister instance = null; instance.store(in, out, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;store;;;Argument[0];Argument[1];taint;manual" @@ -751,7 +751,7 @@ public void test() throws Exception { Properties in = (Properties)source(); PropertiesPersister instance = null; instance.store(in, out, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;store;;;Argument[2];Argument[1];taint;manual" @@ -759,7 +759,7 @@ public void test() throws Exception { String in = (String)source(); PropertiesPersister instance = null; instance.store((Properties)null, out, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;store;;;Argument[2];Argument[1];taint;manual" @@ -767,7 +767,7 @@ public void test() throws Exception { String in = (String)source(); PropertiesPersister instance = null; instance.store((Properties)null, out, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;storeToXml;;;Argument[0];Argument[1];taint;manual" @@ -775,7 +775,7 @@ public void test() throws Exception { Properties in = (Properties)source(); PropertiesPersister instance = null; instance.storeToXml(in, out, null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;storeToXml;;;Argument[0];Argument[1];taint;manual" @@ -783,7 +783,7 @@ public void test() throws Exception { Properties in = (Properties)source(); PropertiesPersister instance = null; instance.storeToXml(in, out, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;storeToXml;;;Argument[2];Argument[1];taint;manual" @@ -791,7 +791,7 @@ public void test() throws Exception { String in = (String)source(); PropertiesPersister instance = null; instance.storeToXml(null, out, in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertiesPersister;true;storeToXml;;;Argument[2];Argument[1];taint;manual" @@ -799,35 +799,35 @@ public void test() throws Exception { String in = (String)source(); PropertiesPersister instance = null; instance.storeToXml(null, out, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertyPlaceholderHelper;false;PropertyPlaceholderHelper;;;Argument[0..1];Argument[this];taint;manual" PropertyPlaceholderHelper out = null; String in = (String)source(); out = new PropertyPlaceholderHelper(null, in, null, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertyPlaceholderHelper;false;PropertyPlaceholderHelper;;;Argument[0..1];Argument[this];taint;manual" PropertyPlaceholderHelper out = null; String in = (String)source(); out = new PropertyPlaceholderHelper(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertyPlaceholderHelper;false;PropertyPlaceholderHelper;;;Argument[0..1];Argument[this];taint;manual" PropertyPlaceholderHelper out = null; String in = (String)source(); out = new PropertyPlaceholderHelper(in, null, null, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertyPlaceholderHelper;false;PropertyPlaceholderHelper;;;Argument[0..1];Argument[this];taint;manual" PropertyPlaceholderHelper out = null; String in = (String)source(); out = new PropertyPlaceholderHelper(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertyPlaceholderHelper;false;replacePlaceholders;;;Argument[0];ReturnValue;taint;manual" @@ -835,7 +835,7 @@ public void test() throws Exception { String in = (String)source(); PropertyPlaceholderHelper instance = null; out = instance.replacePlaceholders(in, (PropertyPlaceholderHelper.PlaceholderResolver)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;PropertyPlaceholderHelper;false;replacePlaceholders;;;Argument[0];ReturnValue;taint;manual" @@ -843,77 +843,77 @@ public void test() throws Exception { String in = (String)source(); PropertyPlaceholderHelper instance = null; out = instance.replacePlaceholders(in, (Properties)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;extractArchiveURL;;;Argument[0];ReturnValue;taint;manual" URL out = null; URL in = (URL)source(); out = ResourceUtils.extractArchiveURL(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;extractJarFileURL;;;Argument[0];ReturnValue;taint;manual" URL out = null; URL in = (URL)source(); out = ResourceUtils.extractJarFileURL(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;getFile;;;Argument[0];ReturnValue;taint;manual" File out = null; URL in = (URL)source(); out = ResourceUtils.getFile(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;getFile;;;Argument[0];ReturnValue;taint;manual" File out = null; URL in = (URL)source(); out = ResourceUtils.getFile(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;getFile;;;Argument[0];ReturnValue;taint;manual" File out = null; URI in = (URI)source(); out = ResourceUtils.getFile(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;getFile;;;Argument[0];ReturnValue;taint;manual" File out = null; URI in = (URI)source(); out = ResourceUtils.getFile(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;getFile;;;Argument[0];ReturnValue;taint;manual" File out = null; String in = (String)source(); out = ResourceUtils.getFile(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;getURL;;;Argument[0];ReturnValue;taint;manual" URL out = null; String in = (String)source(); out = ResourceUtils.getURL(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;toURI;;;Argument[0];ReturnValue;taint;manual" URI out = null; URL in = (URL)source(); out = ResourceUtils.toURI(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;ResourceUtils;false;toURI;;;Argument[0];ReturnValue;taint;manual" URI out = null; String in = (String)source(); out = ResourceUtils.toURI(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;RouteMatcher;true;combine;;;Argument[0..1];ReturnValue;taint;manual" @@ -921,7 +921,7 @@ public void test() throws Exception { String in = (String)source(); RouteMatcher instance = null; out = instance.combine(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;RouteMatcher;true;combine;;;Argument[0..1];ReturnValue;taint;manual" @@ -929,7 +929,7 @@ public void test() throws Exception { String in = (String)source(); RouteMatcher instance = null; out = instance.combine(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;RouteMatcher;true;matchAndExtract;;;Argument[0];MapKey of ReturnValue;taint;manual" @@ -937,7 +937,7 @@ public void test() throws Exception { String in = (String)source(); RouteMatcher instance = null; out = instance.matchAndExtract(in, null); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.util;RouteMatcher;true;matchAndExtract;;;Argument[1];MapValue of ReturnValue;taint;manual" @@ -945,7 +945,7 @@ public void test() throws Exception { RouteMatcher.Route in = (RouteMatcher.Route)source(); RouteMatcher instance = null; out = instance.matchAndExtract(null, in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.util;RouteMatcher;true;parseRoute;;;Argument[0];ReturnValue;taint;manual" @@ -953,448 +953,448 @@ public void test() throws Exception { String in = (String)source(); RouteMatcher instance = null; out = instance.parseRoute(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;SerializationUtils;false;deserialize;;;Argument[0];ReturnValue;taint;manual" Object out = null; byte[] in = (byte[])source(); out = SerializationUtils.deserialize(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;SerializationUtils;false;serialize;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; Object in = source(); out = SerializationUtils.serialize(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copy;(byte[],java.io.OutputStream);;Argument[0];Argument[1];taint;manual" OutputStream out = null; byte[] in = (byte[])source(); StreamUtils.copy(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copy;(java.io.InputStream,java.io.OutputStream);;Argument[0];Argument[1];taint;manual" OutputStream out = null; InputStream in = (InputStream)source(); StreamUtils.copy(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copy;(java.lang.String,java.nio.charset.Charset,java.io.OutputStream);;Argument[0];Argument[2];taint;manual" OutputStream out = null; String in = (String)source(); StreamUtils.copy(in, null, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copyRange;;;Argument[0];Argument[1];taint;manual" OutputStream out = null; InputStream in = (InputStream)source(); StreamUtils.copyRange(in, out, 0L, 0L); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copyToByteArray;;;Argument[0];ReturnValue;taint;manual" byte[] out = null; InputStream in = (InputStream)source(); out = StreamUtils.copyToByteArray(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copyToString;;;Argument[0];ReturnValue;taint;manual" String out = null; InputStream in = (InputStream)source(); out = StreamUtils.copyToString(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StreamUtils;false;copyToString;;;Argument[0];ReturnValue;taint;manual" String out = null; ByteArrayOutputStream in = (ByteArrayOutputStream)source(); out = StreamUtils.copyToString(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;addStringToArray;;;Argument[1];ArrayElement of ReturnValue;value;manual" String[] out = null; String in = (String)source(); out = StringUtils.addStringToArray(null, in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;addStringToArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value;manual" String[] out = null; String[] in = (String[])newWithArrayElement(source()); out = StringUtils.addStringToArray(in, null); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;applyRelativePath;;;Argument[0..1];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.applyRelativePath(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;applyRelativePath;;;Argument[0..1];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.applyRelativePath(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;arrayToCommaDelimitedString;;;ArrayElement of Argument[0];ReturnValue;taint;manual", String out = null; Object[] in = { source() }; out = StringUtils.arrayToCommaDelimitedString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;arrayToDelimitedString;;;Argument[1];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.arrayToDelimitedString(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;arrayToDelimitedString;;;ArrayElement of Argument[0];ReturnValue;taint;manual", String out = null; Object[] in = { source() }; out = StringUtils.arrayToDelimitedString(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.capitalize(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;cleanPath;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.cleanPath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToCommaDelimitedString;;;Element of Argument[0];ReturnValue;taint;manual" String out = null; Collection in = List.of(source()); out = StringUtils.collectionToCommaDelimitedString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToDelimitedString;;;Argument[1..3];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.collectionToDelimitedString(null, null, null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToDelimitedString;;;Argument[1..3];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.collectionToDelimitedString(null, null, in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToDelimitedString;;;Argument[1..3];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.collectionToDelimitedString(null, in, null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToDelimitedString;;;Argument[1..3];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.collectionToDelimitedString(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToDelimitedString;;;Element of Argument[0];ReturnValue;taint;manual" String out = null; Collection in = List.of(source()); out = StringUtils.collectionToDelimitedString(in, null, null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;collectionToDelimitedString;;;Element of Argument[0];ReturnValue;taint;manual" String out = null; Collection in = List.of(source()); out = StringUtils.collectionToDelimitedString(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;commaDelimitedListToSet;;;Argument[0];Element of ReturnValue;taint;manual" Set out = null; String in = (String)source(); out = StringUtils.commaDelimitedListToSet(in); - sink(getElement(out)); // $hasTaintFlow + sink(getElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;commaDelimitedListToStringArray;;;Argument[0];ArrayElement of ReturnValue;taint;manual" String[] out = null; String in = (String)source(); out = StringUtils.commaDelimitedListToStringArray(in); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;concatenateStringArrays;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;taint;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.concatenateStringArrays(null, in); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;concatenateStringArrays;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;taint;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.concatenateStringArrays(in, null); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;delete;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.delete(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;deleteAny;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.deleteAny(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;delimitedListToStringArray;;;Argument[0];ReturnValue;taint;manual" String[] out = null; String in = (String)source(); out = StringUtils.delimitedListToStringArray(in, null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;delimitedListToStringArray;;;Argument[0];ReturnValue;taint;manual" String[] out = null; String in = (String)source(); out = StringUtils.delimitedListToStringArray(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;getFilename;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.getFilename(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;getFilenameExtension;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.getFilenameExtension(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;mergeStringArrays;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.mergeStringArrays(null, in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;mergeStringArrays;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.mergeStringArrays(in, null); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;quote;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.quote(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;quoteIfString;;;Argument[0];ReturnValue;taint;manual" Object out = null; Object in = source(); out = StringUtils.quoteIfString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;removeDuplicateStrings;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.removeDuplicateStrings(in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;replace;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.replace(in, null, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;replace;;;Argument[2];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.replace(null, null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;sortStringArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.sortStringArray(in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;split;;;Argument[0];ArrayElement of ReturnValue;taint;manual" String[] out = null; String in = (String)source(); out = StringUtils.split(in, null); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;splitArrayElementsIntoProperties;;;ArrayElement of Argument[0];MapKey of ReturnValue;taint;manual", Properties out = null; String[] in = { (String)source() }; out = StringUtils.splitArrayElementsIntoProperties(in, null, null); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;splitArrayElementsIntoProperties;;;ArrayElement of Argument[0];MapValue of ReturnValue;taint;manual", Properties out = null; String[] in = { (String)source() }; out = StringUtils.splitArrayElementsIntoProperties(in, null, null); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;splitArrayElementsIntoProperties;;;Argument[0];ReturnValue;taint;manual" Properties out = null; String[] in = (String[])source(); out = StringUtils.splitArrayElementsIntoProperties(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;stripFilenameExtension;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.stripFilenameExtension(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;toStringArray;;;Element of Argument[0];ArrayElement of ReturnValue;value;manual", String[] out = null; Enumeration in = Collections.enumeration(List.of(source()));; out = StringUtils.toStringArray(in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;toStringArray;;;Element of Argument[0];ArrayElement of ReturnValue;value;manual", String[] out = null; Collection in = List.of(source()); out = StringUtils.toStringArray(in); - sink(getArrayElement(out)); // $hasValueFlow + sink(getArrayElement(out)); // $ hasValueFlow } { // "org.springframework.util;StringUtils;false;tokenizeToStringArray;;;Argument[0];ArrayElement of ReturnValue;taint;manual" String[] out = null; String in = (String)source(); out = StringUtils.tokenizeToStringArray(in, null, false, false); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;tokenizeToStringArray;;;Argument[0];ArrayElement of ReturnValue;taint;manual" String[] out = null; String in = (String)source(); out = StringUtils.tokenizeToStringArray(in, null); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimAllWhitespace;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.trimAllWhitespace(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimArrayElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint;manual" String[] out = null; String[] in = { (String)source() }; out = StringUtils.trimArrayElements(in); - sink(getArrayElement(out)); // $hasTaintFlow + sink(getArrayElement(out)); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimLeadingCharacter;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.trimLeadingCharacter(in, 'a'); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimLeadingWhitespace;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.trimLeadingWhitespace(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimTrailingCharacter;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.trimTrailingCharacter(in, 'a'); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimTrailingWhitespace;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.trimTrailingWhitespace(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;trimWhitespace;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.trimWhitespace(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.uncapitalize(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;unqualify;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.unqualify(in, 'a'); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;unqualify;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.unqualify(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringUtils;false;uriDecode;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = StringUtils.uriDecode(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;StringValueResolver;false;resolveStringValue;;;Argument[0];ReturnValue;taint;manual" @@ -1402,21 +1402,21 @@ public void test() throws Exception { String in = (String)source(); StringValueResolver instance = null; out = instance.resolveStringValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;SystemPropertyUtils;false;resolvePlaceholders;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = SystemPropertyUtils.resolvePlaceholders(in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.util;SystemPropertyUtils;false;resolvePlaceholders;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = SystemPropertyUtils.resolvePlaceholders(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/validation/Test.java b/java/ql/test/library-tests/frameworks/spring/validation/Test.java index 4f8aac5a3356..d081b860297e 100644 --- a/java/ql/test/library-tests/frameworks/spring/validation/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/validation/Test.java @@ -11,68 +11,68 @@ void sink(Object o) {} void test() { Errors es0 = errors(); es0.addAllErrors(sourceErrs()); - sink(es0); // $hasTaintFlow + sink(es0); // $ hasTaintFlow - sink(sourceErrs().getAllErrors()); // $hasTaintFlow + sink(sourceErrs().getAllErrors()); // $ hasTaintFlow - sink(sourceErrs().getFieldError()); // $hasTaintFlow - sink(sourceErrs().getFieldError("field")); // $hasTaintFlow + sink(sourceErrs().getFieldError()); // $ hasTaintFlow + sink(sourceErrs().getFieldError("field")); // $ hasTaintFlow - sink(sourceErrs().getGlobalError()); // $hasTaintFlow - sink(sourceErrs().getGlobalErrors()); // $hasTaintFlow + sink(sourceErrs().getGlobalError()); // $ hasTaintFlow + sink(sourceErrs().getGlobalErrors()); // $ hasTaintFlow Errors es1 = errors(); es1.reject((String)source()); - sink(es1); // $hasTaintFlow + sink(es1); // $ hasTaintFlow Errors es2 = errors(); es2.reject((String)source(), null, ""); - sink(es2); // $hasTaintFlow + sink(es2); // $ hasTaintFlow Errors es3 = errors(); es3.reject((String)source(), null, ""); - sink(es3); // $hasTaintFlow + sink(es3); // $ hasTaintFlow { Errors es4 = errors(); Object[] in = { (String)source() }; es4.reject("", in, ""); - sink(in); // $hasTaintFlow + sink(in); // $ hasTaintFlow } { Errors es5 = errors(); es5.reject("", null, (String)source()); - sink(es5); // $hasTaintFlow + sink(es5); // $ hasTaintFlow } Errors es6 = errors(); es6.reject((String)source(), ""); - sink(es6); // $hasTaintFlow + sink(es6); // $ hasTaintFlow Errors es7 = errors(); es7.reject("", (String)source()); - sink(es7); // $hasTaintFlow + sink(es7); // $ hasTaintFlow Errors es8 = errors(); es8.rejectValue("", (String)source(), null, ""); - sink(es8); // $hasTaintFlow + sink(es8); // $ hasTaintFlow Errors es9 = errors(); Object[] in = {source()}; es9.rejectValue("", "", in, ""); - sink(es9); // $hasTaintFlow + sink(es9); // $ hasTaintFlow Errors es10 = errors(); es10.rejectValue("", "", null, (String)source()); - sink(es10); // $hasTaintFlow + sink(es10); // $ hasTaintFlow Errors es11 = errors(); es11.rejectValue("", (String)source(), ""); - sink(es11); // $hasTaintFlow + sink(es11); // $ hasTaintFlow Errors es12 = errors(); es12.rejectValue("", "", (String)source()); - sink(es12); // $hasTaintFlow + sink(es12); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/webmultipart/Test.java b/java/ql/test/library-tests/frameworks/spring/webmultipart/Test.java index 5d7387c20e07..62129a6d4345 100644 --- a/java/ql/test/library-tests/frameworks/spring/webmultipart/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/webmultipart/Test.java @@ -30,84 +30,84 @@ public void test() throws Exception { byte[] out = null; MultipartFile in = (MultipartFile)source(); out = in.getBytes(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartFile;true;getInputStream;;;Argument[this];ReturnValue;taint;manual" InputStream out = null; MultipartFile in = (MultipartFile)source(); out = in.getInputStream(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartFile;true;getName;;;Argument[this];ReturnValue;taint;manual" String out = null; MultipartFile in = (MultipartFile)source(); out = in.getName(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartFile;true;getOriginalFilename;;;Argument[this];ReturnValue;taint;manual" String out = null; MultipartFile in = (MultipartFile)source(); out = in.getOriginalFilename(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartFile;true;getResource;;;Argument[this];ReturnValue;taint;manual" Resource out = null; MultipartFile in = (MultipartFile)source(); out = in.getResource(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartHttpServletRequest;true;getMultipartHeaders;;;Argument[this];ReturnValue;taint;manual" HttpHeaders out = null; MultipartHttpServletRequest in = (MultipartHttpServletRequest)source(); out = in.getMultipartHeaders(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartHttpServletRequest;true;getRequestHeaders;;;Argument[this];ReturnValue;taint;manual" HttpHeaders out = null; MultipartHttpServletRequest in = (MultipartHttpServletRequest)source(); out = in.getRequestHeaders(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartRequest;true;getFile;;;Argument[this];ReturnValue;taint;manual" MultipartFile out = null; MultipartRequest in = (MultipartRequest)source(); out = in.getFile(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartRequest;true;getFileMap;;;Argument[this];MapValue of ReturnValue;taint;manual" Map out = null; MultipartRequest in = (MultipartRequest)source(); out = in.getFileMap(); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartRequest;true;getFileNames;;;Argument[this];Element of ReturnValue;taint;manual" Iterator out = null; MultipartRequest in = (MultipartRequest)source(); out = in.getFileNames(); - sink(getElement(out)); // $hasTaintFlow + sink(getElement(out)); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartRequest;true;getFiles;;;Argument[this];Element of ReturnValue;taint;manual" List out = null; MultipartRequest in = (MultipartRequest)source(); out = in.getFiles(null); - sink(getElement(out)); // $hasTaintFlow + sink(getElement(out)); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartRequest;true;getMultiFileMap;;;Argument[this];MapValue of ReturnValue;taint;manual" MultiValueMap out = null; MultipartRequest in = (MultipartRequest)source(); out = in.getMultiFileMap(); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.multipart;MultipartResolver;true;resolveMultipart;;;Argument[0];ReturnValue;taint;manual" @@ -115,7 +115,7 @@ public void test() throws Exception { HttpServletRequest in = (HttpServletRequest)source(); MultipartResolver instance = null; out = instance.resolveMultipart(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } } diff --git a/java/ql/test/library-tests/frameworks/spring/websocket/Test.java b/java/ql/test/library-tests/frameworks/spring/websocket/Test.java index ceaab98344e6..4c16529db462 100644 --- a/java/ql/test/library-tests/frameworks/spring/websocket/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/websocket/Test.java @@ -14,51 +14,51 @@ void sink(Object o) {} public class A extends TextWebSocketHandler { @Override public void handleMessage(WebSocketSession s, WebSocketMessage m) { - sink(s); // $hasTaintFlow - sink(s.getAcceptedProtocol()); // $hasTaintFlow - sink(s.getHandshakeHeaders()); // $hasTaintFlow - sink(s.getPrincipal()); // $hasTaintFlow - sink(s.getUri()); // $hasTaintFlow + sink(s); // $ hasTaintFlow + sink(s.getAcceptedProtocol()); // $ hasTaintFlow + sink(s.getHandshakeHeaders()); // $ hasTaintFlow + sink(s.getPrincipal()); // $ hasTaintFlow + sink(s.getUri()); // $ hasTaintFlow - sink(m); // $hasTaintFlow - sink(m.getPayload()); // $hasTaintFlow + sink(m); // $ hasTaintFlow + sink(m.getPayload()); // $ hasTaintFlow } - @Override + @Override protected void handleTextMessage(WebSocketSession s, TextMessage m) { - sink(s); // $hasTaintFlow - sink(m); // $hasTaintFlow - sink(m.asBytes()); // $hasTaintFlow + sink(s); // $ hasTaintFlow + sink(m); // $ hasTaintFlow + sink(m.asBytes()); // $ hasTaintFlow } - @Override + @Override protected void handleBinaryMessage(WebSocketSession s, BinaryMessage m) { - sink(s); // $hasTaintFlow - sink(m); // $hasTaintFlow + sink(s); // $ hasTaintFlow + sink(m); // $ hasTaintFlow } @Override protected void handlePongMessage(WebSocketSession s, PongMessage m) { - sink(s); // $hasTaintFlow - sink(m); // $hasTaintFlow + sink(s); // $ hasTaintFlow + sink(m); // $ hasTaintFlow } @Override public void afterConnectionEstablished(WebSocketSession s) { - sink(s); // $hasTaintFlow + sink(s); // $ hasTaintFlow } - @Override + @Override public void afterConnectionClosed(WebSocketSession s, CloseStatus c) { - sink(s); // $hasTaintFlow + sink(s); // $ hasTaintFlow } - @Override - public void handleTransportError(WebSocketSession s, Throwable exc) { - sink(s); // $hasTaintFlow + @Override + public void handleTransportError(WebSocketSession s, Throwable exc) { + sink(s); // $ hasTaintFlow } } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/frameworks/spring/webutil/Test.java b/java/ql/test/library-tests/frameworks/spring/webutil/Test.java index 11ab7a48d87e..3f79f17a388b 100644 --- a/java/ql/test/library-tests/frameworks/spring/webutil/Test.java +++ b/java/ql/test/library-tests/frameworks/spring/webutil/Test.java @@ -63,84 +63,84 @@ public void test() throws Exception { String out = null; AbstractUriTemplateHandler in = (AbstractUriTemplateHandler)source(); out = in.getBaseUrl(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;AbstractUriTemplateHandler;true;setBaseUrl;;;Argument[0];Argument[this];taint;manual" AbstractUriTemplateHandler out = null; String in = (String)source(); out.setBaseUrl(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;AbstractUriTemplateHandler;true;setDefaultUriVariables;;;Argument[0];Argument[this];taint;manual" AbstractUriTemplateHandler out = null; Map in = (Map)source(); out.setDefaultUriVariables(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ContentCachingRequestWrapper;false;ContentCachingRequestWrapper;;;Argument[0];Argument[this];taint;manual" ContentCachingRequestWrapper out = null; HttpServletRequest in = (HttpServletRequest)source(); out = new ContentCachingRequestWrapper(in, 0); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ContentCachingRequestWrapper;false;ContentCachingRequestWrapper;;;Argument[0];Argument[this];taint;manual" ContentCachingRequestWrapper out = null; HttpServletRequest in = (HttpServletRequest)source(); out = new ContentCachingRequestWrapper(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ContentCachingRequestWrapper;false;getContentAsByteArray;;;Argument[this];ReturnValue;taint;manual" byte[] out = null; ContentCachingRequestWrapper in = (ContentCachingRequestWrapper)source(); out = in.getContentAsByteArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ContentCachingResponseWrapper;false;ContentCachingResponseWrapper;;;Argument[0];Argument[this];taint;manual" ContentCachingResponseWrapper out = null; HttpServletResponse in = (HttpServletResponse)source(); out = new ContentCachingResponseWrapper(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentAsByteArray;;;Argument[this];ReturnValue;taint;manual" byte[] out = null; ContentCachingResponseWrapper in = (ContentCachingResponseWrapper)source(); out = in.getContentAsByteArray(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ContentCachingResponseWrapper;false;getContentInputStream;;;Argument[this];ReturnValue;taint;manual" InputStream out = null; ContentCachingResponseWrapper in = (ContentCachingResponseWrapper)source(); out = in.getContentInputStream(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;DefaultUriBuilderFactory;;;Argument[0];Argument[this];taint;manual" DefaultUriBuilderFactory out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = new DefaultUriBuilderFactory(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;DefaultUriBuilderFactory;;;Argument[0];Argument[this];taint;manual" DefaultUriBuilderFactory out = null; String in = (String)source(); out = new DefaultUriBuilderFactory(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;builder;;;Argument[this];ReturnValue;taint;manual" UriBuilder out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.builder(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint;manual" @@ -148,7 +148,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); DefaultUriBuilderFactory instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -156,7 +156,7 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; DefaultUriBuilderFactory instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[0];ReturnValue;taint;manual" @@ -164,7 +164,7 @@ public void test() throws Exception { String in = (String)source(); DefaultUriBuilderFactory instance = null; out = instance.expand(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[0];ReturnValue;taint;manual" @@ -172,28 +172,28 @@ public void test() throws Exception { String in = (String)source(); DefaultUriBuilderFactory instance = null; out = instance.expand(in, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.expand((String)null, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.expand((String)null, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;getDefaultUriVariables;;;Argument[this];MapValue of ReturnValue;taint;manual" Map out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.getDefaultUriVariables(); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;DefaultUriBuilderFactory;false;setDefaultUriVariables;;;MapValue of Argument[0];Argument[this];taint;manual" @@ -207,84 +207,84 @@ public void test() throws Exception { UriBuilder out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.uriString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;HtmlUtils;false;htmlUnescape;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = HtmlUtils.htmlUnescape(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = ServletContextPropertyUtils.resolvePlaceholders(in, null, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = ServletContextPropertyUtils.resolvePlaceholders(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint;manual" String out = null; ServletContext in = (ServletContext)source(); out = ServletContextPropertyUtils.resolvePlaceholders(null, in, false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletContextPropertyUtils;false;resolvePlaceholders;;;Argument[0..1];ReturnValue;taint;manual" String out = null; ServletContext in = (ServletContext)source(); out = ServletContextPropertyUtils.resolvePlaceholders(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletRequestPathUtils;false;getCachedPath;;;Argument[0];ReturnValue;taint;manual" Object out = null; ServletRequest in = (ServletRequest)source(); out = ServletRequestPathUtils.getCachedPath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletRequestPathUtils;false;getCachedPathValue;;;Argument[0];ReturnValue;taint;manual" String out = null; ServletRequest in = (ServletRequest)source(); out = ServletRequestPathUtils.getCachedPathValue(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletRequestPathUtils;false;getParsedRequestPath;;;Argument[0];ReturnValue;taint;manual" RequestPath out = null; ServletRequest in = (ServletRequest)source(); out = ServletRequestPathUtils.getParsedRequestPath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletRequestPathUtils;false;parseAndCache;;;Argument[0];ReturnValue;taint;manual" RequestPath out = null; HttpServletRequest in = (HttpServletRequest)source(); out = ServletRequestPathUtils.parseAndCache(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;ServletRequestPathUtils;false;setParsedRequestPath;;;Argument[0];Argument[1];taint;manual" ServletRequest out = null; RequestPath in = (RequestPath)source(); ServletRequestPathUtils.setParsedRequestPath(in, out); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];Argument[this];taint;manual" UriBuilder out = null; Map in = newMapWithValue(source()); out.build(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;build;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" @@ -292,63 +292,63 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriBuilder instance = null; out = instance.build(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;build;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriBuilder in = (UriBuilder)source(); out = in.build(false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;build;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriBuilder in = (UriBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;build;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriBuilder in = (UriBuilder)source(); out = in.build((Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;build;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriBuilder in = (UriBuilder)source(); out = in.build((Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.fragment(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.fragment(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.fragment(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.fragment(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];ReturnValue;taint;manual" @@ -356,7 +356,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.fragment(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;fragment;;;Argument[0];ReturnValue;taint;manual" @@ -364,21 +364,21 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.fragment(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;host;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.host(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;host;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.host(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;host;;;Argument[0];ReturnValue;taint;manual" @@ -386,7 +386,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.host(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;host;;;Argument[0];ReturnValue;taint;manual" @@ -394,35 +394,35 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.host(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;path;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.path(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;path;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.path(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.path(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.path(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];ReturnValue;taint;manual" @@ -430,7 +430,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.path(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;path;;;Argument[0];ReturnValue;taint;manual" @@ -438,35 +438,35 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.path(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;pathSegment;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.pathSegment((String[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;pathSegment;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.pathSegment((String[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];Argument[this];taint;manual" UriBuilder out = null; String[] in = new String[]{(String)source()}; out.pathSegment((String[])in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];Argument[this];taint;manual" UriBuilder out = null; String[] in = new String[]{(String)source()}; out.pathSegment((String[])in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -474,7 +474,7 @@ public void test() throws Exception { String[] in = new String[]{(String)source()}; UriBuilder instance = null; out = instance.pathSegment((String[])in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;pathSegment;;;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -482,21 +482,21 @@ public void test() throws Exception { String[] in = new String[]{(String)source()}; UriBuilder instance = null; out = instance.pathSegment((String[])in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.port(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.port(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];ReturnValue;taint;manual" @@ -504,7 +504,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.port(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;port;(java.lang.String);;Argument[0];ReturnValue;taint;manual" @@ -512,63 +512,63 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.port(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;port;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.port(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;port;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.port((String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;port;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.port(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;port;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.port((String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;query;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.query(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;query;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.query(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.query(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.query(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];ReturnValue;taint;manual" @@ -576,7 +576,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.query(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;query;;;Argument[0];ReturnValue;taint;manual" @@ -584,21 +584,21 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.query(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Collection in = List.of(source()); out.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Collection in = List.of(source()); out.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint;manual" @@ -606,7 +606,7 @@ public void test() throws Exception { Collection in = List.of(source()); UriBuilder instance = null; out = instance.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint;manual" @@ -614,21 +614,21 @@ public void test() throws Exception { Collection in = List.of(source()); UriBuilder instance = null; out = instance.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Object[] in = new Object[]{source()}; out.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Object[] in = new Object[]{source()}; out.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -636,7 +636,7 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriBuilder instance = null; out = instance.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -644,63 +644,63 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriBuilder instance = null; out = instance.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParam((String)null, (Object[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParam((String)null, (Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParam((String)null, (Object[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParam((String)null, (Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.queryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.queryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.queryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.queryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint;manual" @@ -708,7 +708,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.queryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint;manual" @@ -716,7 +716,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.queryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint;manual" @@ -724,7 +724,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.queryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParam;;;Argument[0];ReturnValue;taint;manual" @@ -732,35 +732,35 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.queryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParamIfPresent(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParamIfPresent(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.queryParamIfPresent(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.queryParamIfPresent(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];ReturnValue;taint;manual" @@ -768,7 +768,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.queryParamIfPresent(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Argument[0];ReturnValue;taint;manual" @@ -776,21 +776,21 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.queryParamIfPresent(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Optional in = Optional.of(source()); out.queryParamIfPresent(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Optional in = Optional.of(source()); out.queryParamIfPresent(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];ReturnValue;taint;manual" @@ -798,7 +798,7 @@ public void test() throws Exception { Optional in = Optional.of(source()); UriBuilder instance = null; out = instance.queryParamIfPresent(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParamIfPresent;;;Element of Argument[1];ReturnValue;taint;manual" @@ -806,35 +806,35 @@ public void test() throws Exception { Optional in = Optional.of(source()); UriBuilder instance = null; out = instance.queryParamIfPresent(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParams(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.queryParams(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];Argument[this];taint;manual" UriBuilder out = null; MultiValueMap in = newMultiValueMapWithKey(source()); out.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];Argument[this];taint;manual" UriBuilder out = null; MultiValueMap in = newMultiValueMapWithKey(source()); out.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];ReturnValue;taint;manual" @@ -842,7 +842,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UriBuilder instance = null; out = instance.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;MapKey of Argument[0];ReturnValue;taint;manual" @@ -850,21 +850,21 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UriBuilder instance = null; out = instance.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];Argument[this];taint;manual" UriBuilder out = null; MultiValueMap in = newMultiValueMapWithValue(source()); out.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];Argument[this];taint;manual" UriBuilder out = null; MultiValueMap in = newMultiValueMapWithValue(source()); out.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];ReturnValue;taint;manual" @@ -872,7 +872,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UriBuilder instance = null; out = instance.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;queryParams;;;Element of MapValue of Argument[0];ReturnValue;taint;manual" @@ -880,35 +880,35 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UriBuilder instance = null; out = instance.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replacePath(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replacePath(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replacePath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replacePath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];ReturnValue;taint;manual" @@ -916,7 +916,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replacePath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replacePath;;;Argument[0];ReturnValue;taint;manual" @@ -924,35 +924,35 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replacePath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQuery(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQuery(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replaceQuery(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replaceQuery(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];ReturnValue;taint;manual" @@ -960,7 +960,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replaceQuery(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQuery;;;Argument[0];ReturnValue;taint;manual" @@ -968,21 +968,21 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replaceQuery(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Collection in = List.of(source()); out.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Collection in = List.of(source()); out.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint;manual" @@ -990,7 +990,7 @@ public void test() throws Exception { Collection in = List.of(source()); UriBuilder instance = null; out = instance.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint;manual" @@ -998,21 +998,21 @@ public void test() throws Exception { Collection in = List.of(source()); UriBuilder instance = null; out = instance.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Object[] in = new Object[]{source()}; out.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];Argument[this];taint;manual" UriBuilder out = null; Object[] in = new Object[]{source()}; out.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -1020,7 +1020,7 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriBuilder instance = null; out = instance.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -1028,63 +1028,63 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriBuilder instance = null; out = instance.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQueryParam((String)null, (Object[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQueryParam((String)null, (Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQueryParam((String)null, (Object[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQueryParam((String)null, (Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replaceQueryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replaceQueryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replaceQueryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.replaceQueryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1092,7 +1092,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replaceQueryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1100,7 +1100,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replaceQueryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1108,7 +1108,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replaceQueryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1116,21 +1116,21 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.replaceQueryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQueryParams(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.replaceQueryParams(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;MapKey of Argument[0];ReturnValue;taint;manual" @@ -1138,7 +1138,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UriBuilder instance = null; out = instance.replaceQueryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;MapKey of Argument[0];ReturnValue;taint;manual" @@ -1146,7 +1146,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UriBuilder instance = null; out = instance.replaceQueryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Element of MapValue of Argument[0];ReturnValue;taint;manual" @@ -1154,7 +1154,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UriBuilder instance = null; out = instance.replaceQueryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;replaceQueryParams;;;Element of MapValue of Argument[0];ReturnValue;taint;manual" @@ -1162,35 +1162,35 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UriBuilder instance = null; out = instance.replaceQueryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.scheme(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.scheme(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.scheme(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.scheme(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];ReturnValue;taint;manual" @@ -1198,7 +1198,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.scheme(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;scheme;;;Argument[0];ReturnValue;taint;manual" @@ -1206,35 +1206,35 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.scheme(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.userInfo(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[this];ReturnValue;value;manual" UriBuilder out = null; UriBuilder in = (UriBuilder)source(); out = in.userInfo(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.userInfo(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];Argument[this];taint;manual" UriBuilder out = null; String in = (String)source(); out.userInfo(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];ReturnValue;taint;manual" @@ -1242,7 +1242,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.userInfo(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilder;true;userInfo;;;Argument[0];ReturnValue;taint;manual" @@ -1250,28 +1250,28 @@ public void test() throws Exception { String in = (String)source(); UriBuilder instance = null; out = instance.userInfo(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilderFactory;true;builder;;;Argument[this];ReturnValue;taint;manual" UriBuilder out = null; UriBuilderFactory in = (UriBuilderFactory)source(); out = in.builder(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilderFactory;true;builder;;;Argument[this];ReturnValue;taint;manual" UriBuilder out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.builder(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[this];ReturnValue;taint;manual" UriBuilder out = null; UriBuilderFactory in = (UriBuilderFactory)source(); out = in.uriString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[0];ReturnValue;taint;manual" @@ -1279,7 +1279,7 @@ public void test() throws Exception { String in = (String)source(); UriBuilderFactory instance = null; out = instance.uriString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[0];ReturnValue;taint;manual" @@ -1287,49 +1287,49 @@ public void test() throws Exception { String in = (String)source(); DefaultUriBuilderFactory instance = null; out = instance.uriString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriBuilderFactory;true;uriString;;;Argument[this];ReturnValue;taint;manual" UriBuilder out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.uriString(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents$UriTemplateVariables;true;getValue;;;MapValue of Argument[this];ReturnValue;value;manual" Object out = null; UriComponents.UriTemplateVariables in = new StubUriTemplateVariables(Map.of(null, source())); out = in.getValue(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } // { // // "org.springframework.web.util;UriComponents;false;UriComponents;;;Argument[0..1];Argument[this];taint;manual" // UriComponents out = null; // String in = (String)source(); // out = new UriComponents(null, in); - // sink(out); // $hasTaintFlow + // sink(out); // $ hasTaintFlow // } // { // // "org.springframework.web.util;UriComponents;false;UriComponents;;;Argument[0..1];Argument[this];taint;manual" // UriComponents out = null; // String in = (String)source(); // out = new UriComponents(in, null); - // sink(out); // $hasTaintFlow + // sink(out); // $ hasTaintFlow // } { // "org.springframework.web.util;UriComponents;false;encode;;;Argument[this];ReturnValue;taint;manual" UriComponents out = null; UriComponents in = (UriComponents)source(); out = in.encode(null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;encode;;;Argument[this];ReturnValue;taint;manual" UriComponents out = null; UriComponents in = (UriComponents)source(); out = in.encode(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" @@ -1337,7 +1337,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriComponents instance = null; out = instance.expand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -1345,7 +1345,7 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriComponents instance = null; out = instance.expand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;expand;(UriTemplateVariables);;MapValue of Argument[0];ReturnValue;taint;manual" @@ -1353,91 +1353,91 @@ public void test() throws Exception { UriComponents.UriTemplateVariables in = new StubUriTemplateVariables(Map.of(null, source())); UriComponents instance = null; out = instance.expand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getFragment;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getFragment(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getHost;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getHost(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getPath;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getPath(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getPathSegments;;;Argument[this];ReturnValue;taint;manual" List out = null; UriComponents in = (UriComponents)source(); out = in.getPathSegments(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getQuery;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getQuery(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getQueryParams;;;Argument[this];Element of MapValue of ReturnValue;taint;manual" MultiValueMap out = null; UriComponents in = (UriComponents)source(); out = in.getQueryParams(); - sink(getElement((List)getMapValue(out))); // $hasTaintFlow + sink(getElement((List)getMapValue(out))); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getQueryParams;;;Argument[this];MapKey of ReturnValue;taint;manual" MultiValueMap out = null; UriComponents in = (UriComponents)source(); out = in.getQueryParams(); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getScheme;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getScheme(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getSchemeSpecificPart;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getSchemeSpecificPart(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;getUserInfo;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.getUserInfo(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;toUri;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriComponents in = (UriComponents)source(); out = in.toUri(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponents;false;toUriString;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponents in = (UriComponents)source(); out = in.toUriString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;build;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" @@ -1445,7 +1445,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriComponentsBuilder instance = null; out = instance.build(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;build;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -1453,35 +1453,35 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriComponentsBuilder instance = null; out = instance.build(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" UriComponents out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.build(false); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" UriComponents out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.build(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.build((Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;build;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.build((Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" @@ -1489,7 +1489,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriComponentsBuilder instance = null; out = instance.buildAndExpand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;buildAndExpand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -1497,35 +1497,35 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriComponentsBuilder instance = null; out = instance.buildAndExpand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;cloneBuilder;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.cloneBuilder(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;encode;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.encode(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;encode;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.encode(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.fragment(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fragment;;;Argument[0];ReturnValue;taint;manual" @@ -1533,56 +1533,56 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.fragment(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fromHttpRequest;;;Argument[0];ReturnValue;taint;manual" UriComponentsBuilder out = null; HttpRequest in = (HttpRequest)source(); out = UriComponentsBuilder.fromHttpRequest(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fromHttpUrl;;;Argument[0];ReturnValue;taint;manual" UriComponentsBuilder out = null; String in = (String)source(); out = UriComponentsBuilder.fromHttpUrl(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fromOriginHeader;;;Argument[0];ReturnValue;taint;manual" UriComponentsBuilder out = null; String in = (String)source(); out = UriComponentsBuilder.fromOriginHeader(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fromPath;;;Argument[0];ReturnValue;taint;manual" UriComponentsBuilder out = null; String in = (String)source(); out = UriComponentsBuilder.fromPath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fromUri;;;Argument[0];ReturnValue;taint;manual" UriComponentsBuilder out = null; URI in = (URI)source(); out = UriComponentsBuilder.fromUri(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;fromUriString;;;Argument[0];ReturnValue;taint;manual" UriComponentsBuilder out = null; String in = (String)source(); out = UriComponentsBuilder.fromUriString(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.host(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;host;;;Argument[0];ReturnValue;taint;manual" @@ -1590,28 +1590,28 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.host(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;parseForwardedFor;;;Argument[0..1];ReturnValue;taint;manual" InetSocketAddress out = null; InetSocketAddress in = (InetSocketAddress)source(); out = UriComponentsBuilder.parseForwardedFor(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;parseForwardedFor;;;Argument[0..1];ReturnValue;taint;manual" InetSocketAddress out = null; HttpRequest in = (HttpRequest)source(); out = UriComponentsBuilder.parseForwardedFor(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.path(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;path;;;Argument[0];ReturnValue;taint;manual" @@ -1619,14 +1619,14 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.path(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.pathSegment((String[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;pathSegment;;;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -1634,7 +1634,7 @@ public void test() throws Exception { String[] in = new String[]{(String)source()}; UriComponentsBuilder instance = null; out = instance.pathSegment(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;port;(String);;Argument[0];ReturnValue;taint;manual" @@ -1642,28 +1642,28 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.port(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;port;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.port(0); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;port;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.port((String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.query(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;query;;;Argument[0];ReturnValue;taint;manual" @@ -1671,7 +1671,7 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.query(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint;manual" @@ -1679,7 +1679,7 @@ public void test() throws Exception { Collection in = List.of(source()); UriComponentsBuilder instance = null; out = instance.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -1687,21 +1687,21 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriComponentsBuilder instance = null; out = instance.queryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.queryParam((String)null, (Object[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.queryParam((String)null, (Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1709,7 +1709,7 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.queryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1717,14 +1717,14 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.queryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.queryParamIfPresent(null, null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Argument[0];ReturnValue;taint;manual" @@ -1732,7 +1732,7 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.queryParamIfPresent(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParamIfPresent;;;Element of Argument[1];ReturnValue;taint;manual" @@ -1740,14 +1740,14 @@ public void test() throws Exception { Optional in = Optional.of(source()); UriComponentsBuilder instance = null; out = instance.queryParamIfPresent(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.queryParams(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;MapKey of Argument[0];ReturnValue;taint;manual" @@ -1755,7 +1755,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UriComponentsBuilder instance = null; out = instance.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;queryParams;;;Element of MapValue of Argument[0];ReturnValue;taint;manual" @@ -1763,14 +1763,14 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UriComponentsBuilder instance = null; out = instance.queryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.replacePath(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replacePath;;;Argument[0];ReturnValue;taint;manual" @@ -1778,14 +1778,14 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.replacePath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.replaceQuery(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQuery;;;Argument[0];ReturnValue;taint;manual" @@ -1793,7 +1793,7 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.replaceQuery(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Collection);;Element of Argument[1];ReturnValue;taint;manual" @@ -1801,7 +1801,7 @@ public void test() throws Exception { Collection in = List.of(source()); UriComponentsBuilder instance = null; out = instance.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -1809,21 +1809,21 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriComponentsBuilder instance = null; out = instance.replaceQueryParam((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.replaceQueryParam((String)null, (Object[])null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.replaceQueryParam((String)null, (Collection)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1831,7 +1831,7 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.replaceQueryParam(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParam;;;Argument[0];ReturnValue;taint;manual" @@ -1839,14 +1839,14 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.replaceQueryParam(in, (Collection)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.replaceQueryParams(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;MapKey of Argument[0];ReturnValue;taint;manual" @@ -1854,7 +1854,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UriComponentsBuilder instance = null; out = instance.replaceQueryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;replaceQueryParams;;;Element of MapValue of Argument[0];ReturnValue;taint;manual" @@ -1862,14 +1862,14 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UriComponentsBuilder instance = null; out = instance.replaceQueryParams(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.scheme(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;scheme;;;Argument[0];ReturnValue;taint;manual" @@ -1877,14 +1877,14 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.scheme(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.schemeSpecificPart(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;schemeSpecificPart;;;Argument[0];ReturnValue;taint;manual" @@ -1892,21 +1892,21 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.schemeSpecificPart(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;toUriString;;;Argument[this];ReturnValue;taint;manual" String out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.toUriString(); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;uri;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.uri(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;uri;;;Argument[0];ReturnValue;taint;manual" @@ -1914,14 +1914,14 @@ public void test() throws Exception { URI in = (URI)source(); UriComponentsBuilder instance = null; out = instance.uri(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.uriComponents(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;uriComponents;;;Argument[0];ReturnValue;taint;manual" @@ -1929,14 +1929,14 @@ public void test() throws Exception { UriComponents in = (UriComponents)source(); UriComponentsBuilder instance = null; out = instance.uriComponents(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.uriVariables(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;uriVariables;;;MapValue of Argument[0];ReturnValue;taint;manual" @@ -1944,14 +1944,14 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriComponentsBuilder instance = null; out = instance.uriVariables(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[this];ReturnValue;value;manual" UriComponentsBuilder out = null; UriComponentsBuilder in = (UriComponentsBuilder)source(); out = in.userInfo(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;UriComponentsBuilder;false;userInfo;;;Argument[0];ReturnValue;taint;manual" @@ -1959,7 +1959,7 @@ public void test() throws Exception { String in = (String)source(); UriComponentsBuilder instance = null; out = instance.userInfo(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplate;false;expand;(Map);;MapValue of Argument[0];ReturnValue;taint;manual" @@ -1967,7 +1967,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriTemplate instance = null; out = instance.expand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplate;false;expand;(Object[]);;ArrayElement of Argument[0];ReturnValue;taint;manual" @@ -1975,14 +1975,14 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriTemplate instance = null; out = instance.expand(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplate;false;getVariableNames;;;Argument[this];Element of ReturnValue;taint;manual" List out = null; UriTemplate in = (UriTemplate)source(); out = in.getVariableNames(); - sink(getElement(out)); // $hasTaintFlow + sink(getElement(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplate;false;match;;;Argument[0];MapValue of ReturnValue;taint;manual" @@ -1990,7 +1990,7 @@ public void test() throws Exception { String in = (String)source(); UriTemplate instance = null; out = instance.match(in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint;manual" @@ -1998,7 +1998,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UriTemplateHandler instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint;manual" @@ -2006,7 +2006,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); DefaultUriBuilderFactory instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Map);;MapValue of Argument[1];ReturnValue;taint;manual" @@ -2014,7 +2014,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); AbstractUriTemplateHandler instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -2022,7 +2022,7 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; UriTemplateHandler instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -2030,7 +2030,7 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; DefaultUriBuilderFactory instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;(String,Object[]);;ArrayElement of Argument[1];ReturnValue;taint;manual" @@ -2038,21 +2038,21 @@ public void test() throws Exception { Object[] in = new Object[]{source()}; AbstractUriTemplateHandler instance = null; out = instance.expand((String)null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriTemplateHandler in = (UriTemplateHandler)source(); out = in.expand((String)null, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; UriTemplateHandler in = (UriTemplateHandler)source(); out = in.expand((String)null, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[0];ReturnValue;taint;manual" @@ -2060,7 +2060,7 @@ public void test() throws Exception { String in = (String)source(); UriTemplateHandler instance = null; out = instance.expand(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[0];ReturnValue;taint;manual" @@ -2068,7 +2068,7 @@ public void test() throws Exception { String in = (String)source(); UriTemplateHandler instance = null; out = instance.expand(in, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[0];ReturnValue;taint;manual" @@ -2076,7 +2076,7 @@ public void test() throws Exception { String in = (String)source(); DefaultUriBuilderFactory instance = null; out = instance.expand(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[0];ReturnValue;taint;manual" @@ -2084,7 +2084,7 @@ public void test() throws Exception { String in = (String)source(); DefaultUriBuilderFactory instance = null; out = instance.expand(in, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[0];ReturnValue;taint;manual" @@ -2092,7 +2092,7 @@ public void test() throws Exception { String in = (String)source(); AbstractUriTemplateHandler instance = null; out = instance.expand(in, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[0];ReturnValue;taint;manual" @@ -2100,245 +2100,245 @@ public void test() throws Exception { String in = (String)source(); AbstractUriTemplateHandler instance = null; out = instance.expand(in, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.expand((String)null, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; DefaultUriBuilderFactory in = (DefaultUriBuilderFactory)source(); out = in.expand((String)null, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; AbstractUriTemplateHandler in = (AbstractUriTemplateHandler)source(); out = in.expand((String)null, (Object[])null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriTemplateHandler;true;expand;;;Argument[this];ReturnValue;taint;manual" URI out = null; AbstractUriTemplateHandler in = (AbstractUriTemplateHandler)source(); out = in.expand((String)null, (Map)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;decode;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.decode(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;decode;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.decode(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encode;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encode(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encode;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encode(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeAuthority;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeAuthority(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeAuthority;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeAuthority(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeFragment;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeFragment(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeFragment;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeFragment(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeHost;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeHost(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeHost;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeHost(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodePath;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodePath(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodePath;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodePath(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodePathSegment;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodePathSegment(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodePathSegment;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodePathSegment(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodePort;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodePort(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodePort;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodePort(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeQuery;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeQuery(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeQuery;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeQuery(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeQueryParam;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeQueryParam(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeQueryParam;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeQueryParam(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeQueryParams;;;MapKey of Argument[0];MapKey of ReturnValue;taint;manual" MultiValueMap out = null; MultiValueMap in = newMultiValueMapWithKey(source()); out = UriUtils.encodeQueryParams(in); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeQueryParams;;;MapValue of Argument[0];MapValue of ReturnValue;taint;manual" MultiValueMap out = null; MultiValueMap in = newMultiValueMapWithValue(source()); out = UriUtils.encodeQueryParams(in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeScheme;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeScheme(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeScheme;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeScheme(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Map);;MapKey of Argument[0];MapKey of ReturnValue;taint;manual" Map out = null; Map in = newMapWithKey(source()); out = UriUtils.encodeUriVariables(in); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Map);;MapValue of Argument[0];MapValue of ReturnValue;taint;manual" Map out = null; Map in = newMapWithValue(source()); out = UriUtils.encodeUriVariables(in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeUriVariables;(Object[]);;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint;manual" Object[] out = null; Object[] in = new Object[]{source()}; out = UriUtils.encodeUriVariables(in); - sink(out[0]); // $hasTaintFlow + sink(out[0]); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeUserInfo;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeUserInfo(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;encodeUserInfo;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.encodeUserInfo(in, (Charset)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UriUtils;false;extractFileExtension;;;Argument[0];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = UriUtils.extractFileExtension(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UrlPathHelper;false;decodeMatrixVariables;;;MapKey of Argument[1];MapKey of ReturnValue;value;manual" @@ -2346,7 +2346,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithKey(source()); UrlPathHelper instance = null; out = instance.decodeMatrixVariables(null, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.web.util;UrlPathHelper;false;decodeMatrixVariables;;;MapValue of Argument[1];MapValue of ReturnValue;taint;manual" @@ -2354,7 +2354,7 @@ public void test() throws Exception { MultiValueMap in = newMultiValueMapWithValue(source()); UrlPathHelper instance = null; out = instance.decodeMatrixVariables(null, in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UrlPathHelper;false;decodePathVariables;;;MapKey of Argument[1];MapKey of ReturnValue;value;manual" @@ -2362,7 +2362,7 @@ public void test() throws Exception { Map in = newMapWithKey(source()); UrlPathHelper instance = null; out = instance.decodePathVariables(null, in); - sink(getMapKey(out)); // $hasValueFlow + sink(getMapKey(out)); // $ hasValueFlow } { // "org.springframework.web.util;UrlPathHelper;false;decodePathVariables;;;MapValue of Argument[1];MapValue of ReturnValue;taint;manual" @@ -2370,7 +2370,7 @@ public void test() throws Exception { Map in = newMapWithValue(source()); UrlPathHelper instance = null; out = instance.decodePathVariables(null, in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;UrlPathHelper;false;decodeRequestString;;;Argument[1];ReturnValue;taint;manual" @@ -2378,7 +2378,7 @@ public void test() throws Exception { String in = (String)source(); UrlPathHelper instance = null; out = instance.decodeRequestString(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UrlPathHelper;false;getContextPath;;;Argument[0];ReturnValue;taint;manual" @@ -2386,7 +2386,7 @@ public void test() throws Exception { HttpServletRequest in = (HttpServletRequest)source(); UrlPathHelper instance = null; out = instance.getContextPath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UrlPathHelper;false;getOriginatingContextPath;;;Argument[0];ReturnValue;taint;manual" @@ -2394,7 +2394,7 @@ public void test() throws Exception { HttpServletRequest in = (HttpServletRequest)source(); UrlPathHelper instance = null; out = instance.getOriginatingContextPath(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;UrlPathHelper;false;removeSemicolonContent;;;Argument[0];ReturnValue;taint;manual" @@ -2402,98 +2402,98 @@ public void test() throws Exception { String in = (String)source(); UrlPathHelper instance = null; out = instance.removeSemicolonContent(in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;findParameterValue;(Map,String);;MapValue of Argument[0];ReturnValue;value;manual" String out = null; Map in = newMapWithValue(source()); out = WebUtils.findParameterValue(in, (String)null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "org.springframework.web.util;WebUtils;false;findParameterValue;(ServletRequest,String);;Argument[0];ReturnValue;taint;manual" String out = null; ServletRequest in = (ServletRequest)source(); out = WebUtils.findParameterValue(in, (String)null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getCookie;;;Argument[0];ReturnValue;taint;manual" Cookie out = null; HttpServletRequest in = (HttpServletRequest)source(); out = WebUtils.getCookie(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getNativeRequest;;;Argument[0];ReturnValue;taint;manual" Object out = null; ServletRequest in = (ServletRequest)source(); out = WebUtils.getNativeRequest(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getNativeResponse;;;Argument[0];ReturnValue;taint;manual" Object out = null; ServletResponse in = (ServletResponse)source(); out = WebUtils.getNativeResponse(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getParametersStartingWith;;;Argument[0];MapKey of ReturnValue;taint;manual" Map out = null; ServletRequest in = (ServletRequest)source(); out = WebUtils.getParametersStartingWith(in, null); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getParametersStartingWith;;;Argument[0];MapValue of ReturnValue;taint;manual" Map out = null; ServletRequest in = (ServletRequest)source(); out = WebUtils.getParametersStartingWith(in, null); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getRealPath;;;Argument[0..1];ReturnValue;taint;manual" String out = null; String in = (String)source(); out = WebUtils.getRealPath(null, in); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getRealPath;;;Argument[0..1];ReturnValue;taint;manual" String out = null; ServletContext in = (ServletContext)source(); out = WebUtils.getRealPath(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getRequiredSessionAttribute;;;Argument[0];ReturnValue;taint;manual" Object out = null; HttpServletRequest in = (HttpServletRequest)source(); out = WebUtils.getRequiredSessionAttribute(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;getSessionAttribute;;;Argument[0];ReturnValue;taint;manual" Object out = null; HttpServletRequest in = (HttpServletRequest)source(); out = WebUtils.getSessionAttribute(in, null); - sink(out); // $hasTaintFlow + sink(out); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;parseMatrixVariables;;;Argument[0];MapKey of ReturnValue;taint;manual" MultiValueMap out = null; String in = (String)source(); out = WebUtils.parseMatrixVariables(in); - sink(getMapKey(out)); // $hasTaintFlow + sink(getMapKey(out)); // $ hasTaintFlow } { // "org.springframework.web.util;WebUtils;false;parseMatrixVariables;;;Argument[0];MapValue of ReturnValue;taint;manual" MultiValueMap out = null; String in = (String)source(); out = WebUtils.parseMatrixVariables(in); - sink(getMapValue(out)); // $hasTaintFlow + sink(getMapValue(out)); // $ hasTaintFlow } { // "org.springframework.web.util;HtmlUtils;false;htmlEscape;;;Argument[0];ReturnValue;taint;manual" diff --git a/java/ql/test/library-tests/guards/Guards.java b/java/ql/test/library-tests/guards/Guards.java index 689795038c6e..35e3b7c09a9a 100644 --- a/java/ql/test/library-tests/guards/Guards.java +++ b/java/ql/test/library-tests/guards/Guards.java @@ -39,10 +39,10 @@ void t1(int[] a, String s) { chk(); // $ guarded='s:match "bar"' guarded='s:bar' break; case "foo": - chk(); // $ guarded='s:match "foo"' guarded='s:foo' guarded=g(3):false + chk(); // $ guarded='s:non-match "bar"' guarded='s:not bar' guarded='s:match "foo"' guarded='s:foo' guarded=g(3):false break; default: - chk(); // $ guarded='s:non-match "bar"' guarded='s:non-match "foo"' guarded='s:not bar' guarded='s:not foo' guarded='s:match default' guarded=g(3):false + chk(); // $ guarded='s:non-match "bar"' guarded='s:non-match "foo"' guarded='s:not bar' guarded='s:not foo' guarded=g(3):false break; } @@ -92,10 +92,10 @@ void t4() { chk(); // $ guarded='x:match E1' guarded='x:E1' guarded=g(1):true guarded=g(2):false guarded=g(Alt2):false guarded=g(3):false break; case E2: - chk(); // $ guarded='x:match E2' guarded='x:E2' guarded=g(3):false + chk(); // $ guarded='x:non-match E1' guarded='x:not E1' guarded='x:match E2' guarded='x:E2' guarded=g(3):false break; case E3: - chk(); // $ guarded='x:match E3' guarded='x:E3' guarded=g(3):true + chk(); // $ guarded='x:non-match E1' guarded='x:non-match E2' guarded='x:not E1' guarded='x:not E2' guarded='x:match E3' guarded='x:E3' guarded=g(3):true break; } Object o = g(4) ? new Object() : null; @@ -198,7 +198,7 @@ void testWrappers(String s, Integer i) { chk(); // $ guarded='testEnumWrapper(...):SUCCESS' guarded='testEnumWrapper(...):match SUCCESS' guarded=g(1):true break; case FAILURE: - chk(); // $ guarded='testEnumWrapper(...):FAILURE' guarded='testEnumWrapper(...):match FAILURE' guarded=g(1):false + chk(); // $ guarded='testEnumWrapper(...):not SUCCESS' guarded='testEnumWrapper(...):non-match SUCCESS' guarded='testEnumWrapper(...):FAILURE' guarded='testEnumWrapper(...):match FAILURE' guarded=g(1):false break; } } diff --git a/java/ql/test/library-tests/guards/GuardsInline.expected b/java/ql/test/library-tests/guards/GuardsInline.expected index b0bd3b04c62d..9d5ea1992c69 100644 --- a/java/ql/test/library-tests/guards/GuardsInline.expected +++ b/java/ql/test/library-tests/guards/GuardsInline.expected @@ -18,8 +18,9 @@ | Guards.java:39:9:39:13 | chk(...) | 's:match "bar"' | | Guards.java:42:9:42:13 | chk(...) | 's:foo' | | Guards.java:42:9:42:13 | chk(...) | 's:match "foo"' | +| Guards.java:42:9:42:13 | chk(...) | 's:non-match "bar"' | +| Guards.java:42:9:42:13 | chk(...) | 's:not bar' | | Guards.java:42:9:42:13 | chk(...) | g(3):false | -| Guards.java:45:9:45:13 | chk(...) | 's:match default' | | Guards.java:45:9:45:13 | chk(...) | 's:non-match "bar"' | | Guards.java:45:9:45:13 | chk(...) | 's:non-match "foo"' | | Guards.java:45:9:45:13 | chk(...) | 's:not bar' | @@ -61,9 +62,15 @@ | Guards.java:92:9:92:13 | chk(...) | g(Alt2):false | | Guards.java:95:9:95:13 | chk(...) | 'x:E2' | | Guards.java:95:9:95:13 | chk(...) | 'x:match E2' | +| Guards.java:95:9:95:13 | chk(...) | 'x:non-match E1' | +| Guards.java:95:9:95:13 | chk(...) | 'x:not E1' | | Guards.java:95:9:95:13 | chk(...) | g(3):false | | Guards.java:98:9:98:13 | chk(...) | 'x:E3' | | Guards.java:98:9:98:13 | chk(...) | 'x:match E3' | +| Guards.java:98:9:98:13 | chk(...) | 'x:non-match E1' | +| Guards.java:98:9:98:13 | chk(...) | 'x:non-match E2' | +| Guards.java:98:9:98:13 | chk(...) | 'x:not E1' | +| Guards.java:98:9:98:13 | chk(...) | 'x:not E2' | | Guards.java:98:9:98:13 | chk(...) | g(3):true | | Guards.java:103:7:103:11 | chk(...) | '...?...:...:null' | | Guards.java:103:7:103:11 | chk(...) | 'o == null:true' | @@ -113,6 +120,8 @@ | Guards.java:198:9:198:13 | chk(...) | g(1):true | | Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):FAILURE' | | Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):match FAILURE' | +| Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):non-match SUCCESS' | +| Guards.java:201:9:201:13 | chk(...) | 'testEnumWrapper(...):not SUCCESS' | | Guards.java:201:9:201:13 | chk(...) | g(1):false | | Guards.java:213:5:213:9 | chk(...) | 'ensureNotNull(...):no exception' | | Guards.java:213:5:213:9 | chk(...) | 's:not null' | diff --git a/java/ql/test/library-tests/guards/GuardsInline.ql b/java/ql/test/library-tests/guards/GuardsInline.ql index 1b854659d87b..9f29af6de606 100644 --- a/java/ql/test/library-tests/guards/GuardsInline.ql +++ b/java/ql/test/library-tests/guards/GuardsInline.ql @@ -11,7 +11,9 @@ string ppGuard(Guard g, Boolean branch) { or exists(BinaryExpr bin | bin = g and - result = "'" + bin.getLeftOperand() + bin.getOp() + bin.getRightOperand() + ":" + branch + "'" + result = + "'" + bin.getLeftOperand() + " " + bin.getOp() + " " + bin.getRightOperand() + ":" + branch + + "'" ) or exists(SwitchCase cc, Expr s, string match, string value | diff --git a/java/ql/test/library-tests/guards/guards.ql b/java/ql/test/library-tests/guards/guards.ql index e2d80a4e7387..21a23534ed66 100644 --- a/java/ql/test/library-tests/guards/guards.ql +++ b/java/ql/test/library-tests/guards/guards.ql @@ -1,8 +1,9 @@ import java import semmle.code.java.controlflow.Guards +import utils.test.BasicBlock from ConditionBlock cb, boolean testIsTrue, BasicBlock controlled where cb.controls(controlled, testIsTrue) and cb.getEnclosingCallable().getDeclaringType().hasName("Test") -select cb.getCondition(), testIsTrue, controlled +select cb.getCondition(), testIsTrue, getFirstAstNode(controlled) diff --git a/java/ql/test/library-tests/guards/guardslogic.expected b/java/ql/test/library-tests/guards/guardslogic.expected index 6bf536d3ce1c..f186c385b8ce 100644 --- a/java/ql/test/library-tests/guards/guardslogic.expected +++ b/java/ql/test/library-tests/guards/guardslogic.expected @@ -19,13 +19,15 @@ | Logic.java:17:11:17:15 | ... > ... | false | Logic.java:15:29:15:29 | i | | Logic.java:17:11:17:15 | ... > ... | true | Logic.java:17:18:17:23 | break | | Logic.java:19:9:19:12 | g(...) | false | Logic.java:24:7:24:17 | case ... | +| Logic.java:19:9:19:12 | g(...) | false | Logic.java:24:12:24:16 | "foo" | | Logic.java:19:9:19:12 | g(...) | false | Logic.java:26:7:26:14 | default | | Logic.java:19:9:19:12 | g(...) | true | Logic.java:20:7:20:16 | ; | +| Logic.java:22:7:22:17 | case ... | false | Logic.java:24:7:24:17 | case ... | +| Logic.java:22:7:22:17 | case ... | false | Logic.java:24:12:24:16 | "foo" | | Logic.java:22:7:22:17 | case ... | false | Logic.java:26:7:26:14 | default | -| Logic.java:22:7:22:17 | case ... | true | Logic.java:22:7:22:17 | case ... | +| Logic.java:22:7:22:17 | case ... | true | Logic.java:22:12:22:16 | "bar" | | Logic.java:24:7:24:17 | case ... | false | Logic.java:26:7:26:14 | default | -| Logic.java:24:7:24:17 | case ... | true | Logic.java:24:7:24:17 | case ... | -| Logic.java:26:7:26:14 | default | true | Logic.java:26:7:26:14 | default | +| Logic.java:24:7:24:17 | case ... | true | Logic.java:24:12:24:16 | "foo" | | Logic.java:29:16:29:19 | g(...) | false | Logic.java:29:30:29:30 | s | | Logic.java:29:16:29:19 | g(...) | false | Logic.java:30:30:31:5 | { ... } | | Logic.java:29:16:29:19 | g(...) | true | Logic.java:29:23:29:26 | null | diff --git a/java/ql/test/library-tests/guards/guardslogic.ql b/java/ql/test/library-tests/guards/guardslogic.ql index f2ce9fdaa365..e68be505ff71 100644 --- a/java/ql/test/library-tests/guards/guardslogic.ql +++ b/java/ql/test/library-tests/guards/guardslogic.ql @@ -1,9 +1,10 @@ import java import semmle.code.java.controlflow.Guards +import utils.test.BasicBlock from Guard g, BasicBlock bb, GuardValue gv where g.valueControls(bb, gv) and g.getEnclosingCallable().getDeclaringType().hasName("Logic") and (exists(gv.asBooleanValue()) or gv.isThrowsException() or gv.getDualValue().isThrowsException()) -select g, gv, bb +select g, gv, getFirstAstNode(bb) diff --git a/java/ql/test/library-tests/guards/guardspreconditions.ql b/java/ql/test/library-tests/guards/guardspreconditions.ql index 77e4a4e48c08..849ee6087bf8 100644 --- a/java/ql/test/library-tests/guards/guardspreconditions.ql +++ b/java/ql/test/library-tests/guards/guardspreconditions.ql @@ -1,9 +1,10 @@ import java import semmle.code.java.controlflow.Guards +import utils.test.BasicBlock from Guard g, BasicBlock bb, GuardValue gv where g.valueControls(bb, gv) and g.getEnclosingCallable().getDeclaringType().hasName("Preconditions") and (gv.isThrowsException() or gv.getDualValue().isThrowsException()) -select g, gv, bb +select g, gv, getFirstAstNode(bb) diff --git a/java/ql/test/library-tests/guards12/guard.expected b/java/ql/test/library-tests/guards12/guard.expected index fade9fd4e8fc..e12bf8c6edb6 100644 --- a/java/ql/test/library-tests/guards12/guard.expected +++ b/java/ql/test/library-tests/guards12/guard.expected @@ -1,55 +1,80 @@ hasBranchEdge -| Test.java:4:7:4:22 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:4:7:4:22 | case ... | true | -| Test.java:5:7:5:17 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:5:7:5:17 | case ... | true | -| Test.java:6:7:6:17 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:6:7:6:17 | case ... | true | -| Test.java:7:7:7:16 | default | Test.java:2:39:36:3 | { ... } | Test.java:7:7:7:16 | default | true | -| Test.java:10:7:10:22 | case ... | Test.java:3:9:3:21 | x | Test.java:10:7:10:22 | case ... | true | -| Test.java:11:7:11:17 | case ... | Test.java:3:9:3:21 | x | Test.java:11:7:11:17 | case ... | true | -| Test.java:12:7:12:17 | case ... | Test.java:3:9:3:21 | x | Test.java:12:7:12:17 | case ... | true | -| Test.java:13:7:13:16 | default | Test.java:3:9:3:21 | x | Test.java:13:7:13:16 | default | true | +| Test.java:4:7:4:22 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:4:7:4:22 | After case ... [match] | true | +| Test.java:4:7:4:22 | case ... | Test.java:2:39:36:3 | { ... } | Test.java:5:7:5:17 | case ... | false | +| Test.java:5:7:5:17 | case ... | Test.java:5:7:5:17 | case ... | Test.java:5:12:5:14 | "c" | true | +| Test.java:5:7:5:17 | case ... | Test.java:5:7:5:17 | case ... | Test.java:6:7:6:17 | case ... | false | +| Test.java:6:7:6:17 | case ... | Test.java:6:7:6:17 | case ... | Test.java:6:12:6:14 | "d" | true | +| Test.java:6:7:6:17 | case ... | Test.java:6:7:6:17 | case ... | Test.java:7:7:7:16 | default | false | +| Test.java:10:7:10:22 | case ... | Test.java:3:9:3:21 | x | Test.java:10:7:10:22 | After case ... [match] | true | +| Test.java:10:7:10:22 | case ... | Test.java:3:9:3:21 | x | Test.java:11:7:11:17 | case ... | false | +| Test.java:11:7:11:17 | case ... | Test.java:11:7:11:17 | case ... | Test.java:11:12:11:14 | "c" | true | +| Test.java:11:7:11:17 | case ... | Test.java:11:7:11:17 | case ... | Test.java:12:7:12:17 | case ... | false | +| Test.java:12:7:12:17 | case ... | Test.java:12:7:12:17 | case ... | Test.java:12:12:12:14 | "d" | true | +| Test.java:12:7:12:17 | case ... | Test.java:12:7:12:17 | case ... | Test.java:13:7:13:16 | default | false | +| Test.java:17:7:17:36 | case | Test.java:15:5:15:25 | var ...; | Test.java:17:7:17:36 | After case [no-match] | false | | Test.java:17:7:17:36 | case | Test.java:15:5:15:25 | var ...; | Test.java:17:19:17:19 | | true | -| Test.java:17:7:17:36 | case | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | false | -| Test.java:17:7:17:36 | case | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | false | +| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | | Test.java:17:26:17:33 | After ... == ... [false] | false | | Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | | Test.java:17:38:17:40 | { ... } | true | -| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | | Test.java:18:7:18:17 | case ... | false | -| Test.java:17:26:17:33 | ... == ... | Test.java:17:19:17:19 | | Test.java:19:7:19:16 | default | false | -| Test.java:18:7:18:17 | case ... | Test.java:15:5:15:25 | var ...; | Test.java:18:7:18:17 | case ... | true | -| Test.java:18:7:18:17 | case ... | Test.java:17:19:17:19 | | Test.java:18:7:18:17 | case ... | true | -| Test.java:19:7:19:16 | default | Test.java:15:5:15:25 | var ...; | Test.java:19:7:19:16 | default | true | -| Test.java:19:7:19:16 | default | Test.java:17:19:17:19 | | Test.java:19:7:19:16 | default | true | +| Test.java:18:7:18:17 | case ... | Test.java:18:7:18:17 | case ... | Test.java:18:12:18:14 | "e" | true | +| Test.java:18:7:18:17 | case ... | Test.java:18:7:18:17 | case ... | Test.java:19:7:19:16 | default | false | | Test.java:21:13:21:19 | unknown | Test.java:21:5:21:42 | switch (...) | Test.java:21:23:21:23 | s | true | | Test.java:21:13:21:19 | unknown | Test.java:21:5:21:42 | switch (...) | Test.java:21:27:21:27 | s | false | -| Test.java:22:7:22:17 | case ... | Test.java:21:23:21:23 | s | Test.java:22:7:22:17 | case ... | true | -| Test.java:22:7:22:17 | case ... | Test.java:21:27:21:27 | s | Test.java:22:7:22:17 | case ... | true | +| Test.java:22:7:22:17 | case ... | Test.java:22:7:22:17 | case ... | Test.java:22:12:22:14 | "f" | true | +| Test.java:22:7:22:17 | case ... | Test.java:22:7:22:17 | case ... | Test.java:23:7:23:37 | case | false | +| Test.java:23:7:23:37 | case | Test.java:23:7:23:37 | case | Test.java:23:7:23:37 | After case [no-match] | false | | Test.java:23:7:23:37 | case | Test.java:23:7:23:37 | case | Test.java:23:19:23:20 | s2 | true | -| Test.java:23:7:23:37 | case | Test.java:23:7:23:37 | case | Test.java:24:7:24:17 | case ... | false | -| Test.java:23:7:23:37 | case | Test.java:23:7:23:37 | case | Test.java:25:7:25:16 | default | false | +| Test.java:23:27:23:34 | ... == ... | Test.java:23:19:23:20 | s2 | Test.java:23:27:23:34 | After ... == ... [false] | false | | Test.java:23:27:23:34 | ... == ... | Test.java:23:19:23:20 | s2 | Test.java:23:39:23:41 | { ... } | true | -| Test.java:23:27:23:34 | ... == ... | Test.java:23:19:23:20 | s2 | Test.java:24:7:24:17 | case ... | false | -| Test.java:23:27:23:34 | ... == ... | Test.java:23:19:23:20 | s2 | Test.java:25:7:25:16 | default | false | -| Test.java:24:7:24:17 | case ... | Test.java:23:7:23:37 | case | Test.java:24:7:24:17 | case ... | true | -| Test.java:24:7:24:17 | case ... | Test.java:23:19:23:20 | s2 | Test.java:24:7:24:17 | case ... | true | -| Test.java:25:7:25:16 | default | Test.java:23:7:23:37 | case | Test.java:25:7:25:16 | default | true | -| Test.java:25:7:25:16 | default | Test.java:23:19:23:20 | s2 | Test.java:25:7:25:16 | default | true | -| Test.java:28:7:28:15 | case ... | Test.java:27:5:27:14 | switch (...) | Test.java:28:7:28:15 | case ... | true | +| Test.java:24:7:24:17 | case ... | Test.java:24:7:24:17 | case ... | Test.java:24:12:24:14 | "g" | true | +| Test.java:24:7:24:17 | case ... | Test.java:24:7:24:17 | case ... | Test.java:25:7:25:16 | default | false | +| Test.java:28:7:28:15 | case ... | Test.java:27:5:27:14 | switch (...) | Test.java:28:12:28:14 | "h" | true | +| Test.java:28:7:28:15 | case ... | Test.java:27:5:27:14 | switch (...) | Test.java:29:7:29:34 | case | false | +| Test.java:29:7:29:34 | case | Test.java:29:7:29:34 | case | Test.java:29:7:29:34 | After case [no-match] | false | | Test.java:29:7:29:34 | case | Test.java:29:7:29:34 | case | Test.java:29:19:29:19 | | true | -| Test.java:29:7:29:34 | case | Test.java:29:7:29:34 | case | Test.java:30:7:30:15 | case ... | false | -| Test.java:29:7:29:34 | case | Test.java:29:7:29:34 | case | Test.java:33:7:33:14 | default | false | -| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | | Test.java:30:7:30:15 | case ... | false | -| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | | Test.java:30:7:30:15 | case ... | true | -| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | | Test.java:33:7:33:14 | default | false | -| Test.java:30:7:30:15 | case ... | Test.java:29:7:29:34 | case | Test.java:30:7:30:15 | case ... | true | -| Test.java:33:7:33:14 | default | Test.java:29:7:29:34 | case | Test.java:33:7:33:14 | default | true | -| Test.java:33:7:33:14 | default | Test.java:29:19:29:19 | | Test.java:33:7:33:14 | default | true | +| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | | Test.java:29:26:29:33 | After ... == ... [false] | false | +| Test.java:29:26:29:33 | ... == ... | Test.java:29:19:29:19 | | Test.java:29:26:29:33 | After ... == ... [true] | true | +| Test.java:30:7:30:15 | case ... | Test.java:30:7:30:15 | case ... | Test.java:30:12:30:14 | "i" | true | +| Test.java:30:7:30:15 | case ... | Test.java:30:7:30:15 | case ... | Test.java:33:7:33:14 | default | false | #select +| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | false | Test.java:6:7:6:17 | case ... | +| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | false | Test.java:6:12:6:14 | "d" | | Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | false | Test.java:7:7:7:16 | default | -| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | true | Test.java:5:7:5:17 | case ... | +| Test.java:5:7:5:17 | case ... | Test.java:3:20:3:20 | s | Test.java:5:12:5:14 | "c" | true | true | Test.java:5:12:5:14 | "c" | | Test.java:6:7:6:17 | case ... | Test.java:3:20:3:20 | s | Test.java:6:12:6:14 | "d" | true | false | Test.java:7:7:7:16 | default | -| Test.java:6:7:6:17 | case ... | Test.java:3:20:3:20 | s | Test.java:6:12:6:14 | "d" | true | true | Test.java:6:7:6:17 | case ... | +| Test.java:6:7:6:17 | case ... | Test.java:3:20:3:20 | s | Test.java:6:12:6:14 | "d" | true | true | Test.java:6:12:6:14 | "d" | +| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | false | Test.java:12:7:12:17 | case ... | +| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | false | Test.java:12:12:12:14 | "d" | | Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | false | Test.java:13:7:13:16 | default | -| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | true | Test.java:11:7:11:17 | case ... | +| Test.java:11:7:11:17 | case ... | Test.java:9:13:9:13 | s | Test.java:11:12:11:14 | "c" | true | true | Test.java:11:12:11:14 | "c" | | Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | false | Test.java:13:7:13:16 | default | -| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | true | Test.java:12:7:12:17 | case ... | +| Test.java:12:7:12:17 | case ... | Test.java:9:13:9:13 | s | Test.java:12:12:12:14 | "d" | true | true | Test.java:12:12:12:14 | "d" | +| Test.java:17:26:17:33 | ... == ... | Test.java:17:26:17:28 | len | Test.java:17:33:17:33 | 4 | true | false | Test.java:17:26:17:33 | After ... == ... [false] | | Test.java:17:26:17:33 | ... == ... | Test.java:17:26:17:28 | len | Test.java:17:33:17:33 | 4 | true | true | Test.java:17:38:17:40 | { ... } | +| Test.java:18:7:18:17 | case ... | Test.java:16:13:16:13 | s | Test.java:18:12:18:14 | "e" | true | false | Test.java:19:7:19:16 | default | +| Test.java:18:7:18:17 | case ... | Test.java:16:13:16:13 | s | Test.java:18:12:18:14 | "e" | true | true | Test.java:18:12:18:14 | "e" | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:23:7:23:37 | After case [no-match] | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:23:7:23:37 | case | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:23:19:23:20 | s2 | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:23:27:23:34 | After ... == ... [false] | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:23:39:23:41 | { ... } | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:24:7:24:17 | case ... | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:24:12:24:14 | "g" | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | false | Test.java:25:7:25:16 | default | +| Test.java:22:7:22:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:22:12:22:14 | "f" | true | true | Test.java:22:12:22:14 | "f" | +| Test.java:23:27:23:34 | ... == ... | Test.java:23:27:23:29 | len | Test.java:23:34:23:34 | 4 | true | false | Test.java:23:27:23:34 | After ... == ... [false] | | Test.java:23:27:23:34 | ... == ... | Test.java:23:27:23:29 | len | Test.java:23:34:23:34 | 4 | true | true | Test.java:23:39:23:41 | { ... } | -| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | true | Test.java:28:7:28:15 | case ... | +| Test.java:24:7:24:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:24:12:24:14 | "g" | true | false | Test.java:25:7:25:16 | default | +| Test.java:24:7:24:17 | case ... | Test.java:21:13:21:41 | ...?...:... | Test.java:24:12:24:14 | "g" | true | true | Test.java:24:12:24:14 | "g" | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:29:7:29:34 | After case [no-match] | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:29:7:29:34 | case | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:29:19:29:19 | | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:29:26:29:33 | After ... == ... [false] | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:29:26:29:33 | After ... == ... [true] | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:30:7:30:15 | case ... | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:30:12:30:14 | "i" | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | false | Test.java:33:7:33:14 | default | +| Test.java:28:7:28:15 | case ... | Test.java:27:13:27:13 | s | Test.java:28:12:28:14 | "h" | true | true | Test.java:28:12:28:14 | "h" | +| Test.java:29:26:29:33 | ... == ... | Test.java:29:26:29:28 | len | Test.java:29:33:29:33 | 4 | true | false | Test.java:29:26:29:33 | After ... == ... [false] | +| Test.java:29:26:29:33 | ... == ... | Test.java:29:26:29:28 | len | Test.java:29:33:29:33 | 4 | true | true | Test.java:29:26:29:33 | After ... == ... [true] | +| Test.java:30:7:30:15 | case ... | Test.java:27:13:27:13 | s | Test.java:30:12:30:14 | "i" | true | false | Test.java:33:7:33:14 | default | +| Test.java:30:7:30:15 | case ... | Test.java:27:13:27:13 | s | Test.java:30:12:30:14 | "i" | true | true | Test.java:30:12:30:14 | "i" | diff --git a/java/ql/test/library-tests/guards12/guard.ql b/java/ql/test/library-tests/guards12/guard.ql index d53dfdbc7135..39f9fdbe9394 100644 --- a/java/ql/test/library-tests/guards12/guard.ql +++ b/java/ql/test/library-tests/guards12/guard.ql @@ -1,8 +1,15 @@ import java import semmle.code.java.controlflow.Guards +import utils.test.BasicBlock -query predicate hasBranchEdge(Guard g, BasicBlock bb1, BasicBlock bb2, GuardValue branch) { - g.hasValueBranchEdge(bb1, bb2, branch) +query predicate hasBranchEdge( + Guard g, ControlFlowNode bb1ref, ControlFlowNode bb2ref, GuardValue branch +) { + exists(BasicBlock bb1, BasicBlock bb2 | + getFirstAstNodeOrSynth(bb1) = bb1ref and + getFirstAstNodeOrSynth(bb2) = bb2ref and + g.hasValueBranchEdge(bb1, bb2, branch) + ) } from Guard g, BasicBlock bb, boolean branch, Expr e1, Expr e2, boolean pol @@ -10,4 +17,4 @@ where g.controls(bb, branch) and g.isEquality(e1, e2, pol) and not e1 instanceof Literal -select g, e1, e2, pol, branch, bb +select g, e1, e2, pol, branch, getFirstAstNodeOrSynth(bb) diff --git a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected index d389eb658f5e..54bd6b9388f2 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected +++ b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.expected @@ -1,5 +1,9 @@ +| MultiCatch.java:6:14:6:23 | Entry | MultiCatch.java:6:14:6:23 | { ... } | +| MultiCatch.java:6:14:6:23 | Normal Exit | MultiCatch.java:6:14:6:23 | Exit | | MultiCatch.java:6:14:6:23 | super(...) | MultiCatch.java:6:14:6:23 | Normal Exit | | MultiCatch.java:6:14:6:23 | { ... } | MultiCatch.java:6:14:6:23 | super(...) | +| MultiCatch.java:7:14:7:23 | Entry | MultiCatch.java:8:2:20:2 | { ... } | +| MultiCatch.java:7:14:7:23 | Exceptional Exit | MultiCatch.java:7:14:7:23 | Exit | | MultiCatch.java:8:2:20:2 | { ... } | MultiCatch.java:9:3:19:3 | try ... | | MultiCatch.java:9:3:19:3 | try ... | MultiCatch.java:10:3:15:3 | { ... } | | MultiCatch.java:10:3:15:3 | { ... } | MultiCatch.java:11:4:11:8 | if (...) | @@ -10,6 +14,7 @@ | MultiCatch.java:12:11:12:27 | new IOException(...) | MultiCatch.java:12:5:12:28 | throw ... | | MultiCatch.java:14:5:14:29 | throw ... | MultiCatch.java:15:5:15:37 | catch (...) | | MultiCatch.java:14:11:14:28 | new SQLException(...) | MultiCatch.java:14:5:14:29 | throw ... | +| MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:7:14:7:23 | Exceptional Exit | | MultiCatch.java:15:5:15:37 | catch (...) | MultiCatch.java:15:36:15:36 | e | | MultiCatch.java:15:36:15:36 | e | MultiCatch.java:16:3:19:3 | { ... } | | MultiCatch.java:16:3:19:3 | { ... } | MultiCatch.java:17:4:17:23 | ; | @@ -18,6 +23,9 @@ | MultiCatch.java:17:4:17:23 | ; | MultiCatch.java:17:4:17:4 | e | | MultiCatch.java:18:4:18:11 | throw ... | MultiCatch.java:7:14:7:23 | Exceptional Exit | | MultiCatch.java:18:10:18:10 | e | MultiCatch.java:18:4:18:11 | throw ... | +| MultiCatch.java:22:14:22:24 | Entry | MultiCatch.java:23:2:33:2 | { ... } | +| MultiCatch.java:22:14:22:24 | Exceptional Exit | MultiCatch.java:22:14:22:24 | Exit | +| MultiCatch.java:22:14:22:24 | Normal Exit | MultiCatch.java:22:14:22:24 | Exit | | MultiCatch.java:23:2:33:2 | { ... } | MultiCatch.java:24:3:32:4 | try ... | | MultiCatch.java:24:3:32:4 | try ... | MultiCatch.java:25:3:31:3 | { ... } | | MultiCatch.java:25:3:31:3 | { ... } | MultiCatch.java:26:4:26:8 | if (...) | @@ -31,12 +39,14 @@ | MultiCatch.java:28:12:28:12 | c | MultiCatch.java:30:10:30:24 | new Exception(...) | | MultiCatch.java:29:5:29:29 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) | | MultiCatch.java:29:11:29:28 | new SQLException(...) | MultiCatch.java:29:5:29:29 | throw ... | -| MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:22:14:22:24 | Exceptional Exit | | MultiCatch.java:30:4:30:25 | throw ... | MultiCatch.java:31:5:31:37 | catch (...) | | MultiCatch.java:30:10:30:24 | new Exception(...) | MultiCatch.java:30:4:30:25 | throw ... | +| MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:22:14:22:24 | Exceptional Exit | | MultiCatch.java:31:5:31:37 | catch (...) | MultiCatch.java:31:36:31:36 | e | | MultiCatch.java:31:36:31:36 | e | MultiCatch.java:32:3:32:4 | { ... } | | MultiCatch.java:32:3:32:4 | { ... } | MultiCatch.java:22:14:22:24 | Normal Exit | +| MultiCatch.java:35:14:35:26 | Entry | MultiCatch.java:36:2:42:2 | { ... } | +| MultiCatch.java:35:14:35:26 | Normal Exit | MultiCatch.java:35:14:35:26 | Exit | | MultiCatch.java:36:2:42:2 | { ... } | MultiCatch.java:37:3:41:4 | try ... | | MultiCatch.java:37:3:41:4 | try ... | MultiCatch.java:38:3:40:3 | { ... } | | MultiCatch.java:38:3:40:3 | { ... } | MultiCatch.java:39:10:39:26 | new IOException(...) | diff --git a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.ql b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.ql index d9263e160888..1f589cc46083 100644 --- a/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.ql +++ b/java/ql/test/library-tests/java7/MultiCatch/MultiCatchControlFlow.ql @@ -1,5 +1,6 @@ import default +import utils.test.AstCfg from ControlFlowNode n -where n.getEnclosingStmt().getCompilationUnit().fromSource() -select n, n.getASuccessor() +where n.getEnclosingCallable().getCompilationUnit().fromSource() +select n, getAnAstSuccessor(n) diff --git a/java/ql/test/library-tests/optional/FunctionalTest.java b/java/ql/test/library-tests/optional/FunctionalTest.java index 334ec0004518..576056a00534 100644 --- a/java/ql/test/library-tests/optional/FunctionalTest.java +++ b/java/ql/test/library-tests/optional/FunctionalTest.java @@ -11,48 +11,48 @@ void sink(Object o) { void test() { Optional o = Optional.of(source()); o.ifPresent(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }); o.ifPresentOrElse(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }, () -> { // no-op }); o.map(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow return v; }).ifPresent(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }); o.flatMap(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow return Optional.of(v); }).ifPresent(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }); o.flatMap(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow return Optional.of("safe"); }).ifPresent(v -> { sink(v); // no value flow }); o.filter(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow return true; }).ifPresent(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }); Optional.of("safe").map(v -> { sink(v); // no value flow return v; }).or(() -> o).ifPresent(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }); Optional safe = Optional.of("safe"); o.or(() -> safe).ifPresent(v -> { - sink(v); // $hasValueFlow + sink(v); // $ hasValueFlow }); String value = safe.orElseGet(() -> source()); - sink(value); // $hasValueFlow + sink(value); // $ hasValueFlow } } diff --git a/java/ql/test/library-tests/optional/Test.java b/java/ql/test/library-tests/optional/Test.java index 5d956c74d45f..d50b8b7abf39 100644 --- a/java/ql/test/library-tests/optional/Test.java +++ b/java/ql/test/library-tests/optional/Test.java @@ -19,35 +19,35 @@ public void test() { Optional out = null; Optional in = newWithElement(source()); out = in.filter(null); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "java.util;Optional;false;get;;;Element of Argument[this];ReturnValue;value;manual" Object out = null; Optional in = newWithElement(source()); out = in.get(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "java.util;Optional;false;of;;;Argument[0];Element of ReturnValue;value;manual" Optional out = null; Object in = (Object)source(); out = Optional.of(in); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "java.util;Optional;false;ofNullable;;;Argument[0];Element of ReturnValue;value;manual" Optional out = null; Object in = (Object)source(); out = Optional.ofNullable(in); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "java.util;Optional;false;or;;;Element of Argument[this];Element of ReturnValue;value;manual" Optional out = null; Optional in = newWithElement(source()); out = in.or(null); - sink(getElement(out)); // $hasValueFlow + sink(getElement(out)); // $ hasValueFlow } { // "java.util;Optional;false;orElse;;;Argument[0];ReturnValue;value;manual" @@ -55,44 +55,44 @@ public void test() { Object in = (Object)source(); Optional instance = null; out = instance.orElse(in); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "java.util;Optional;false;orElse;;;Element of Argument[this];ReturnValue;value;manual" Object out = null; Optional in = newWithElement(source()); out = in.orElse(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "java.util;Optional;false;orElseGet;;;Element of Argument[this];ReturnValue;value;manual" Object out = null; Optional in = newWithElement(source()); out = in.orElseGet(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "java.util;Optional;false;orElseThrow;;;Element of Argument[this];ReturnValue;value;manual" Object out = null; Optional in = newWithElement(source()); out = in.orElseThrow(null); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "java.util;Optional;false;orElseThrow;;;Element of Argument[this];ReturnValue;value;manual" Object out = null; Optional in = newWithElement(source()); out = in.orElseThrow(); - sink(out); // $hasValueFlow + sink(out); // $ hasValueFlow } { // "java.util;Optional;false;stream;;;Element of Argument[this];Element of ReturnValue;value;manual" Stream out = null; Optional in = newWithElement(source()); out = in.stream(); - sink(getStreamElement(out)); // $hasValueFlow + sink(getStreamElement(out)); // $ hasValueFlow } } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/pattern-instanceof/cfg.expected b/java/ql/test/library-tests/pattern-instanceof/cfg.expected index 5ef73c8ac78d..92f64965223d 100644 --- a/java/ql/test/library-tests/pattern-instanceof/cfg.expected +++ b/java/ql/test/library-tests/pattern-instanceof/cfg.expected @@ -1,8 +1,8 @@ -| Test.java:1:14:1:17 | Exceptional Exit | Test.java:1:14:1:17 | Exit | +| Test.java:1:14:1:17 | Entry | Test.java:1:14:1:17 | { ... } | | Test.java:1:14:1:17 | Normal Exit | Test.java:1:14:1:17 | Exit | | Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Normal Exit | | Test.java:1:14:1:17 | { ... } | Test.java:1:14:1:17 | super(...) | -| Test.java:3:22:3:25 | Exceptional Exit | Test.java:3:22:3:25 | Exit | +| Test.java:3:22:3:25 | Entry | Test.java:3:40:20:3 | { ... } | | Test.java:3:22:3:25 | Normal Exit | Test.java:3:22:3:25 | Exit | | Test.java:3:40:20:3 | { ... } | Test.java:5:5:5:34 | var ...; | | Test.java:5:5:5:34 | var ...; | Test.java:5:26:5:33 | source(...) | @@ -50,35 +50,39 @@ | Test.java:17:7:17:26 | sink(...) | Test.java:3:22:3:25 | Normal Exit | | Test.java:17:7:17:27 | ; | Test.java:17:12:17:25 | alsoNotTainted | | Test.java:17:12:17:25 | alsoNotTainted | Test.java:17:7:17:26 | sink(...) | -| Test.java:22:24:22:29 | Exceptional Exit | Test.java:22:24:22:29 | Exit | +| Test.java:22:24:22:29 | Entry | Test.java:22:33:22:53 | { ... } | | Test.java:22:24:22:29 | Normal Exit | Test.java:22:24:22:29 | Exit | | Test.java:22:33:22:53 | { ... } | Test.java:22:42:22:50 | "tainted" | | Test.java:22:35:22:51 | return ... | Test.java:22:24:22:29 | Normal Exit | | Test.java:22:42:22:50 | "tainted" | Test.java:22:35:22:51 | return ... | -| Test.java:23:22:23:25 | Exceptional Exit | Test.java:23:22:23:25 | Exit | +| Test.java:23:22:23:25 | Entry | Test.java:23:40:23:42 | { ... } | | Test.java:23:22:23:25 | Normal Exit | Test.java:23:22:23:25 | Exit | | Test.java:23:40:23:42 | { ... } | Test.java:23:22:23:25 | Normal Exit | | Test.java:27:8:27:12 | ...=... | Test.java:27:8:27:12 | ; | | Test.java:27:8:27:12 | ...=... | Test.java:27:8:27:12 | Normal Exit | | Test.java:27:8:27:12 | ; | Test.java:27:8:27:12 | this | | Test.java:27:8:27:12 | ; | Test.java:27:8:27:12 | this | -| Test.java:27:8:27:12 | Exceptional Exit | Test.java:27:8:27:12 | Exit | +| Test.java:27:8:27:12 | Entry | Test.java:27:8:27:12 | { ... } | | Test.java:27:8:27:12 | Normal Exit | Test.java:27:8:27:12 | Exit | | Test.java:27:8:27:12 | i | Test.java:27:8:27:12 | ...=... | | Test.java:27:8:27:12 | otherField | Test.java:27:8:27:12 | ...=... | | Test.java:27:8:27:12 | super(...) | Test.java:27:8:27:12 | ; | -| Test.java:27:8:27:12 | this | Test.java:27:8:27:12 | i | -| Test.java:27:8:27:12 | this | Test.java:27:8:27:12 | otherField | +| Test.java:27:8:27:12 | this | Test.java:27:8:27:12 | this.i | +| Test.java:27:8:27:12 | this | Test.java:27:8:27:12 | this.otherField | +| Test.java:27:8:27:12 | this.i | Test.java:27:8:27:12 | i | +| Test.java:27:8:27:12 | this.otherField | Test.java:27:8:27:12 | otherField | | Test.java:27:8:27:12 | { ... } | Test.java:27:8:27:12 | super(...) | | Test.java:28:8:28:12 | ...=... | Test.java:28:8:28:12 | ; | | Test.java:28:8:28:12 | ...=... | Test.java:28:8:28:12 | Normal Exit | | Test.java:28:8:28:12 | ; | Test.java:28:8:28:12 | this | | Test.java:28:8:28:12 | ; | Test.java:28:8:28:12 | this | -| Test.java:28:8:28:12 | Exceptional Exit | Test.java:28:8:28:12 | Exit | +| Test.java:28:8:28:12 | Entry | Test.java:28:8:28:12 | { ... } | | Test.java:28:8:28:12 | Normal Exit | Test.java:28:8:28:12 | Exit | | Test.java:28:8:28:12 | nonTaintedField | Test.java:28:8:28:12 | ...=... | | Test.java:28:8:28:12 | super(...) | Test.java:28:8:28:12 | ; | | Test.java:28:8:28:12 | taintedField | Test.java:28:8:28:12 | ...=... | -| Test.java:28:8:28:12 | this | Test.java:28:8:28:12 | nonTaintedField | -| Test.java:28:8:28:12 | this | Test.java:28:8:28:12 | taintedField | +| Test.java:28:8:28:12 | this | Test.java:28:8:28:12 | this.nonTaintedField | +| Test.java:28:8:28:12 | this | Test.java:28:8:28:12 | this.taintedField | +| Test.java:28:8:28:12 | this.nonTaintedField | Test.java:28:8:28:12 | nonTaintedField | +| Test.java:28:8:28:12 | this.taintedField | Test.java:28:8:28:12 | taintedField | | Test.java:28:8:28:12 | { ... } | Test.java:28:8:28:12 | super(...) | diff --git a/java/ql/test/library-tests/pattern-instanceof/cfg.ql b/java/ql/test/library-tests/pattern-instanceof/cfg.ql index db2cc49bc0b6..7f87f2d61f5c 100644 --- a/java/ql/test/library-tests/pattern-instanceof/cfg.ql +++ b/java/ql/test/library-tests/pattern-instanceof/cfg.ql @@ -1,5 +1,6 @@ import java +import utils.test.AstCfg from ControlFlowNode cn where cn.getLocation().getFile().getBaseName() = "Test.java" -select cn, cn.getASuccessor() +select cn, getAnAstSuccessor(cn) diff --git a/java/ql/test/library-tests/pattern-switch/cfg/test.expected b/java/ql/test/library-tests/pattern-switch/cfg/test.expected index f9058bd8f4c2..d398c5f6ecd3 100644 --- a/java/ql/test/library-tests/pattern-switch/cfg/test.expected +++ b/java/ql/test/library-tests/pattern-switch/cfg/test.expected @@ -1,32 +1,35 @@ -| Exhaustive.java:1:14:1:23 | Exceptional Exit | Exhaustive.java:1:14:1:23 | Exit | +| Exhaustive.java:1:14:1:23 | Entry | Exhaustive.java:1:14:1:23 | { ... } | | Exhaustive.java:1:14:1:23 | Normal Exit | Exhaustive.java:1:14:1:23 | Exit | | Exhaustive.java:1:14:1:23 | super(...) | Exhaustive.java:1:14:1:23 | Normal Exit | | Exhaustive.java:1:14:1:23 | { ... } | Exhaustive.java:1:14:1:23 | super(...) | -| Exhaustive.java:3:8:3:8 | Exceptional Exit | Exhaustive.java:3:8:3:8 | Exit | -| Exhaustive.java:3:8:3:8 | Exceptional Exit | Exhaustive.java:3:8:3:8 | Exit | +| Exhaustive.java:3:8:3:8 | Entry | Exhaustive.java:3:8:3:8 | { ... } | +| Exhaustive.java:3:8:3:8 | Entry | Exhaustive.java:3:8:3:8 | { ... } | | Exhaustive.java:3:8:3:8 | Normal Exit | Exhaustive.java:3:8:3:8 | Exit | | Exhaustive.java:3:8:3:8 | Normal Exit | Exhaustive.java:3:8:3:8 | Exit | | Exhaustive.java:3:8:3:8 | super(...) | Exhaustive.java:3:8:3:8 | Normal Exit | | Exhaustive.java:3:8:3:8 | { ... } | Exhaustive.java:3:8:3:8 | super(...) | | Exhaustive.java:3:8:3:8 | { ... } | Exhaustive.java:3:12:3:12 | ; | | Exhaustive.java:3:12:3:12 | ...=... | Exhaustive.java:3:15:3:15 | ; | -| Exhaustive.java:3:12:3:12 | ; | Exhaustive.java:3:12:3:12 | new E(...) | +| Exhaustive.java:3:12:3:12 | ; | Exhaustive.java:3:12:3:12 | A | +| Exhaustive.java:3:12:3:12 | A | Exhaustive.java:3:12:3:12 | new E(...) | | Exhaustive.java:3:12:3:12 | new E(...) | Exhaustive.java:3:12:3:12 | ...=... | | Exhaustive.java:3:15:3:15 | ...=... | Exhaustive.java:3:18:3:18 | ; | -| Exhaustive.java:3:15:3:15 | ; | Exhaustive.java:3:15:3:15 | new E(...) | +| Exhaustive.java:3:15:3:15 | ; | Exhaustive.java:3:15:3:15 | B | +| Exhaustive.java:3:15:3:15 | B | Exhaustive.java:3:15:3:15 | new E(...) | | Exhaustive.java:3:15:3:15 | new E(...) | Exhaustive.java:3:15:3:15 | ...=... | | Exhaustive.java:3:18:3:18 | ...=... | Exhaustive.java:3:8:3:8 | Normal Exit | -| Exhaustive.java:3:18:3:18 | ; | Exhaustive.java:3:18:3:18 | new E(...) | +| Exhaustive.java:3:18:3:18 | ; | Exhaustive.java:3:18:3:18 | C | +| Exhaustive.java:3:18:3:18 | C | Exhaustive.java:3:18:3:18 | new E(...) | | Exhaustive.java:3:18:3:18 | new E(...) | Exhaustive.java:3:18:3:18 | ...=... | -| Exhaustive.java:5:15:5:15 | Exceptional Exit | Exhaustive.java:5:15:5:15 | Exit | +| Exhaustive.java:5:15:5:15 | Entry | Exhaustive.java:5:15:5:15 | { ... } | | Exhaustive.java:5:15:5:15 | Normal Exit | Exhaustive.java:5:15:5:15 | Exit | | Exhaustive.java:5:15:5:15 | super(...) | Exhaustive.java:5:15:5:15 | Normal Exit | | Exhaustive.java:5:15:5:15 | { ... } | Exhaustive.java:5:15:5:15 | super(...) | -| Exhaustive.java:6:15:6:15 | Exceptional Exit | Exhaustive.java:6:15:6:15 | Exit | +| Exhaustive.java:6:15:6:15 | Entry | Exhaustive.java:6:15:6:15 | { ... } | | Exhaustive.java:6:15:6:15 | Normal Exit | Exhaustive.java:6:15:6:15 | Exit | | Exhaustive.java:6:15:6:15 | super(...) | Exhaustive.java:6:15:6:15 | Normal Exit | | Exhaustive.java:6:15:6:15 | { ... } | Exhaustive.java:6:15:6:15 | super(...) | -| Exhaustive.java:8:22:8:25 | Exceptional Exit | Exhaustive.java:8:22:8:25 | Exit | +| Exhaustive.java:8:22:8:25 | Entry | Exhaustive.java:8:47:35:3 | { ... } | | Exhaustive.java:8:22:8:25 | Normal Exit | Exhaustive.java:8:22:8:25 | Exit | | Exhaustive.java:8:47:35:3 | { ... } | Exhaustive.java:11:5:11:14 | switch (...) | | Exhaustive.java:11:5:11:14 | switch (...) | Exhaustive.java:11:13:11:13 | o | @@ -40,14 +43,17 @@ | Exhaustive.java:13:25:13:27 | { ... } | Exhaustive.java:18:5:18:14 | switch (...) | | Exhaustive.java:18:5:18:14 | switch (...) | Exhaustive.java:18:13:18:13 | e | | Exhaustive.java:18:13:18:13 | e | Exhaustive.java:19:7:19:15 | case ... | -| Exhaustive.java:18:13:18:13 | e | Exhaustive.java:20:7:20:15 | case ... | -| Exhaustive.java:18:13:18:13 | e | Exhaustive.java:21:7:21:15 | case ... | -| Exhaustive.java:18:13:18:13 | e | Exhaustive.java:24:5:24:14 | switch (...) | -| Exhaustive.java:19:7:19:15 | case ... | Exhaustive.java:19:17:19:19 | { ... } | +| Exhaustive.java:19:7:19:15 | case ... | Exhaustive.java:19:12:19:12 | A | +| Exhaustive.java:19:7:19:15 | case ... | Exhaustive.java:20:7:20:15 | case ... | +| Exhaustive.java:19:12:19:12 | A | Exhaustive.java:19:17:19:19 | { ... } | | Exhaustive.java:19:17:19:19 | { ... } | Exhaustive.java:24:5:24:14 | switch (...) | -| Exhaustive.java:20:7:20:15 | case ... | Exhaustive.java:20:17:20:19 | { ... } | +| Exhaustive.java:20:7:20:15 | case ... | Exhaustive.java:20:12:20:12 | B | +| Exhaustive.java:20:7:20:15 | case ... | Exhaustive.java:21:7:21:15 | case ... | +| Exhaustive.java:20:12:20:12 | B | Exhaustive.java:20:17:20:19 | { ... } | | Exhaustive.java:20:17:20:19 | { ... } | Exhaustive.java:24:5:24:14 | switch (...) | -| Exhaustive.java:21:7:21:15 | case ... | Exhaustive.java:21:17:21:19 | { ... } | +| Exhaustive.java:21:7:21:15 | case ... | Exhaustive.java:21:12:21:12 | C | +| Exhaustive.java:21:7:21:15 | case ... | Exhaustive.java:24:5:24:14 | switch (...) | +| Exhaustive.java:21:12:21:12 | C | Exhaustive.java:21:17:21:19 | { ... } | | Exhaustive.java:21:17:21:19 | { ... } | Exhaustive.java:24:5:24:14 | switch (...) | | Exhaustive.java:24:5:24:14 | switch (...) | Exhaustive.java:24:13:24:13 | i | | Exhaustive.java:24:13:24:13 | i | Exhaustive.java:25:7:25:17 | case | @@ -65,11 +71,11 @@ | Exhaustive.java:31:14:31:14 | | Exhaustive.java:8:22:8:25 | Normal Exit | | Exhaustive.java:32:7:32:15 | case | Exhaustive.java:32:14:32:14 | | | Exhaustive.java:32:14:32:14 | | Exhaustive.java:8:22:8:25 | Normal Exit | -| Test.java:1:14:1:17 | Exceptional Exit | Test.java:1:14:1:17 | Exit | +| Test.java:1:14:1:17 | Entry | Test.java:1:14:1:17 | { ... } | | Test.java:1:14:1:17 | Normal Exit | Test.java:1:14:1:17 | Exit | | Test.java:1:14:1:17 | super(...) | Test.java:1:14:1:17 | Normal Exit | | Test.java:1:14:1:17 | { ... } | Test.java:1:14:1:17 | super(...) | -| Test.java:3:22:3:25 | Exceptional Exit | Test.java:3:22:3:25 | Exit | +| Test.java:3:22:3:25 | Entry | Test.java:3:41:134:3 | { ... } | | Test.java:3:22:3:25 | Normal Exit | Test.java:3:22:3:25 | Exit | | Test.java:3:41:134:3 | { ... } | Test.java:5:6:5:19 | switch (...) | | Test.java:5:6:5:19 | switch (...) | Test.java:5:14:5:18 | thing | @@ -79,14 +85,12 @@ | Test.java:6:20:6:20 | s | Test.java:6:25:6:34 | System.out | | Test.java:6:25:6:34 | System.out | Test.java:6:44:6:44 | s | | Test.java:6:25:6:45 | println(...) | Test.java:11:6:11:19 | switch (...) | -| Test.java:6:25:6:46 | ; | Test.java:6:25:6:34 | System.out | | Test.java:6:44:6:44 | s | Test.java:6:25:6:45 | println(...) | | Test.java:7:8:7:24 | case | Test.java:7:21:7:21 | i | | Test.java:7:8:7:24 | case | Test.java:8:8:8:17 | default | | Test.java:7:21:7:21 | i | Test.java:7:26:7:35 | System.out | | Test.java:7:26:7:35 | System.out | Test.java:7:45:7:58 | "An integer: " | | Test.java:7:26:7:63 | println(...) | Test.java:11:6:11:19 | switch (...) | -| Test.java:7:26:7:64 | ; | Test.java:7:26:7:35 | System.out | | Test.java:7:45:7:58 | "An integer: " | Test.java:7:62:7:62 | i | | Test.java:7:45:7:62 | ... + ... | Test.java:7:26:7:63 | println(...) | | Test.java:7:62:7:62 | i | Test.java:7:45:7:62 | ... + ... | @@ -136,19 +140,19 @@ | Test.java:28:34:28:38 | thing | Test.java:29:8:29:21 | case | | Test.java:29:8:29:21 | case | Test.java:29:20:29:20 | s | | Test.java:29:8:29:21 | case | Test.java:31:8:31:22 | case | -| Test.java:29:20:29:20 | s | Test.java:30:10:30:17 | yield ... | -| Test.java:30:10:30:17 | yield ... | Test.java:30:16:30:16 | s | -| Test.java:30:16:30:16 | s | Test.java:28:10:28:39 | thingAsString2 | +| Test.java:29:20:29:20 | s | Test.java:30:16:30:16 | s | +| Test.java:30:10:30:17 | yield ... | Test.java:28:10:28:39 | thingAsString2 | +| Test.java:30:16:30:16 | s | Test.java:30:10:30:17 | yield ... | | Test.java:31:8:31:22 | case | Test.java:31:21:31:21 | i | | Test.java:31:8:31:22 | case | Test.java:33:8:33:15 | default | -| Test.java:31:21:31:21 | i | Test.java:32:10:32:34 | yield ... | -| Test.java:32:10:32:34 | yield ... | Test.java:32:16:32:29 | "An integer: " | +| Test.java:31:21:31:21 | i | Test.java:32:16:32:29 | "An integer: " | +| Test.java:32:10:32:34 | yield ... | Test.java:28:10:28:39 | thingAsString2 | | Test.java:32:16:32:29 | "An integer: " | Test.java:32:33:32:33 | i | -| Test.java:32:16:32:33 | ... + ... | Test.java:28:10:28:39 | thingAsString2 | +| Test.java:32:16:32:33 | ... + ... | Test.java:32:10:32:34 | yield ... | | Test.java:32:33:32:33 | i | Test.java:32:16:32:33 | ... + ... | -| Test.java:33:8:33:15 | default | Test.java:34:10:34:32 | yield ... | -| Test.java:34:10:34:32 | yield ... | Test.java:34:16:34:31 | "Something else" | -| Test.java:34:16:34:31 | "Something else" | Test.java:28:10:28:39 | thingAsString2 | +| Test.java:33:8:33:15 | default | Test.java:34:16:34:31 | "Something else" | +| Test.java:34:10:34:32 | yield ... | Test.java:28:10:28:39 | thingAsString2 | +| Test.java:34:16:34:31 | "Something else" | Test.java:34:10:34:32 | yield ... | | Test.java:37:6:37:18 | switch (...) | Test.java:37:13:37:17 | thing | | Test.java:37:13:37:17 | thing | Test.java:38:8:38:42 | case | | Test.java:38:8:38:42 | case | Test.java:38:20:38:20 | s | @@ -195,7 +199,6 @@ | Test.java:50:41:50:41 | 3 | Test.java:50:27:50:41 | ... == ... | | Test.java:50:46:50:55 | System.out | Test.java:50:65:50:74 | "Length 3" | | Test.java:50:46:50:75 | println(...) | Test.java:55:6:55:26 | switch (...) | -| Test.java:50:46:50:76 | ; | Test.java:50:46:50:55 | System.out | | Test.java:50:65:50:74 | "Length 3" | Test.java:50:46:50:75 | println(...) | | Test.java:51:8:51:44 | case | Test.java:51:20:51:20 | s | | Test.java:51:8:51:44 | case | Test.java:52:8:52:17 | default | @@ -207,22 +210,22 @@ | Test.java:51:41:51:41 | 5 | Test.java:51:27:51:41 | ... == ... | | Test.java:51:46:51:55 | System.out | Test.java:51:65:51:74 | "Length 5" | | Test.java:51:46:51:75 | println(...) | Test.java:55:6:55:26 | switch (...) | -| Test.java:51:46:51:76 | ; | Test.java:51:46:51:55 | System.out | | Test.java:51:65:51:74 | "Length 5" | Test.java:51:46:51:75 | println(...) | | Test.java:52:8:52:17 | default | Test.java:52:19:52:21 | { ... } | | Test.java:52:19:52:21 | { ... } | Test.java:55:6:55:26 | switch (...) | | Test.java:55:6:55:26 | switch (...) | Test.java:55:21:55:25 | thing | | Test.java:55:13:55:25 | (...)... | Test.java:56:8:56:21 | case ... | -| Test.java:55:13:55:25 | (...)... | Test.java:58:8:58:21 | case ... | -| Test.java:55:13:55:25 | (...)... | Test.java:61:8:61:42 | case | -| Test.java:55:13:55:25 | (...)... | Test.java:69:8:69:26 | case null, default | | Test.java:55:21:55:25 | thing | Test.java:55:13:55:25 | (...)... | -| Test.java:56:8:56:21 | case ... | Test.java:57:10:57:44 | ; | +| Test.java:56:8:56:21 | case ... | Test.java:56:13:56:20 | "Const1" | +| Test.java:56:8:56:21 | case ... | Test.java:58:8:58:21 | case ... | +| Test.java:56:13:56:20 | "Const1" | Test.java:57:10:57:44 | ; | | Test.java:57:10:57:19 | System.out | Test.java:57:29:57:42 | "It's Const1!" | -| Test.java:57:10:57:43 | println(...) | Test.java:58:8:58:21 | case ... | +| Test.java:57:10:57:43 | println(...) | Test.java:59:10:59:54 | ; | | Test.java:57:10:57:44 | ; | Test.java:57:10:57:19 | System.out | | Test.java:57:29:57:42 | "It's Const1!" | Test.java:57:10:57:43 | println(...) | -| Test.java:58:8:58:21 | case ... | Test.java:59:10:59:54 | ; | +| Test.java:58:8:58:21 | case ... | Test.java:58:13:58:20 | "Const2" | +| Test.java:58:8:58:21 | case ... | Test.java:61:8:61:42 | case | +| Test.java:58:13:58:20 | "Const2" | Test.java:59:10:59:54 | ; | | Test.java:59:10:59:19 | System.out | Test.java:59:29:59:52 | "It's Const1 or Const2!" | | Test.java:59:10:59:53 | println(...) | Test.java:60:10:60:15 | break | | Test.java:59:10:59:54 | ; | Test.java:59:10:59:19 | System.out | @@ -230,27 +233,27 @@ | Test.java:60:10:60:15 | break | Test.java:73:6:73:18 | switch (...) | | Test.java:61:8:61:42 | case | Test.java:61:20:61:20 | s | | Test.java:61:8:61:42 | case | Test.java:63:8:63:21 | case ... | -| Test.java:61:8:61:42 | case | Test.java:66:8:66:22 | case ... | -| Test.java:61:8:61:42 | case | Test.java:69:8:69:26 | case null, default | | Test.java:61:20:61:20 | s | Test.java:61:27:61:27 | s | | Test.java:61:27:61:27 | s | Test.java:61:27:61:36 | length(...) | | Test.java:61:27:61:36 | length(...) | Test.java:61:41:61:41 | 6 | | Test.java:61:27:61:41 | ... <= ... | Test.java:62:10:62:83 | ; | | Test.java:61:27:61:41 | ... <= ... | Test.java:63:8:63:21 | case ... | -| Test.java:61:27:61:41 | ... <= ... | Test.java:66:8:66:22 | case ... | -| Test.java:61:27:61:41 | ... <= ... | Test.java:69:8:69:26 | case null, default | | Test.java:61:41:61:41 | 6 | Test.java:61:27:61:41 | ... <= ... | | Test.java:62:10:62:19 | System.out | Test.java:62:29:62:81 | "It's <= 6 chars long, and neither Const1 nor Const2" | -| Test.java:62:10:62:82 | println(...) | Test.java:63:8:63:21 | case ... | +| Test.java:62:10:62:82 | println(...) | Test.java:64:10:64:96 | ; | | Test.java:62:10:62:83 | ; | Test.java:62:10:62:19 | System.out | | Test.java:62:29:62:81 | "It's <= 6 chars long, and neither Const1 nor Const2" | Test.java:62:10:62:82 | println(...) | -| Test.java:63:8:63:21 | case ... | Test.java:64:10:64:96 | ; | +| Test.java:63:8:63:21 | case ... | Test.java:63:13:63:20 | "Const3" | +| Test.java:63:8:63:21 | case ... | Test.java:66:8:66:22 | case ... | +| Test.java:63:13:63:20 | "Const3" | Test.java:64:10:64:96 | ; | | Test.java:64:10:64:19 | System.out | Test.java:64:29:64:94 | "It's (<= 6 chars long, and neither Const1 nor Const2), or Const3" | | Test.java:64:10:64:95 | println(...) | Test.java:65:10:65:15 | break | | Test.java:64:10:64:96 | ; | Test.java:64:10:64:19 | System.out | | Test.java:64:29:64:94 | "It's (<= 6 chars long, and neither Const1 nor Const2), or Const3" | Test.java:64:10:64:95 | println(...) | | Test.java:65:10:65:15 | break | Test.java:73:6:73:18 | switch (...) | -| Test.java:66:8:66:22 | case ... | Test.java:67:10:67:44 | ; | +| Test.java:66:8:66:22 | case ... | Test.java:66:13:66:21 | "Const30" | +| Test.java:66:8:66:22 | case ... | Test.java:69:8:69:26 | case null, default | +| Test.java:66:13:66:21 | "Const30" | Test.java:67:10:67:44 | ; | | Test.java:67:10:67:19 | System.out | Test.java:67:29:67:42 | "It's Const30" | | Test.java:67:10:67:43 | println(...) | Test.java:68:10:68:15 | break | | Test.java:67:10:67:44 | ; | Test.java:67:10:67:19 | System.out | @@ -263,16 +266,17 @@ | Test.java:70:29:70:58 | "It's null, or something else" | Test.java:70:10:70:59 | println(...) | | Test.java:73:6:73:18 | switch (...) | Test.java:73:13:73:17 | thing | | Test.java:73:13:73:17 | thing | Test.java:74:8:74:21 | case | -| Test.java:73:13:73:17 | thing | Test.java:77:8:77:17 | case ... | | Test.java:74:8:74:21 | case | Test.java:74:20:74:20 | s | -| Test.java:74:8:74:21 | case | Test.java:80:8:80:22 | case | +| Test.java:74:8:74:21 | case | Test.java:77:8:77:17 | case ... | | Test.java:74:20:74:20 | s | Test.java:75:10:75:31 | ; | | Test.java:75:10:75:19 | System.out | Test.java:75:29:75:29 | s | | Test.java:75:10:75:30 | println(...) | Test.java:76:10:76:15 | break | | Test.java:75:10:75:31 | ; | Test.java:75:10:75:19 | System.out | | Test.java:75:29:75:29 | s | Test.java:75:10:75:30 | println(...) | | Test.java:76:10:76:15 | break | Test.java:87:6:87:18 | switch (...) | -| Test.java:77:8:77:17 | case ... | Test.java:78:10:78:41 | ; | +| Test.java:77:8:77:17 | case ... | Test.java:77:13:77:16 | null | +| Test.java:77:8:77:17 | case ... | Test.java:80:8:80:22 | case | +| Test.java:77:13:77:16 | null | Test.java:78:10:78:41 | ; | | Test.java:78:10:78:19 | System.out | Test.java:78:29:78:39 | "It's null" | | Test.java:78:10:78:40 | println(...) | Test.java:79:10:79:15 | break | | Test.java:78:10:78:41 | ; | Test.java:78:10:78:19 | System.out | @@ -347,7 +351,7 @@ | Test.java:110:26:110:30 | thing | Test.java:111:8:111:20 | case | | Test.java:111:8:111:20 | case | Test.java:111:15:111:15 | | | Test.java:111:8:111:20 | case | Test.java:112:8:112:77 | case | -| Test.java:111:13:111:19 | B(...) | Test.java:114:10:114:17 | yield ... | +| Test.java:111:13:111:19 | B(...) | Test.java:114:16:114:16 | 1 | | Test.java:111:15:111:15 | | Test.java:111:18:111:18 | | | Test.java:111:18:111:18 | | Test.java:111:13:111:19 | B(...) | | Test.java:112:8:112:77 | case | Test.java:112:21:112:21 | | @@ -362,32 +366,34 @@ | Test.java:112:47:112:51 | thing | Test.java:112:47:112:62 | toString(...) | | Test.java:112:47:112:62 | toString(...) | Test.java:112:71:112:75 | "abc" | | Test.java:112:47:112:76 | equals(...) | Test.java:113:8:113:20 | case | -| Test.java:112:47:112:76 | equals(...) | Test.java:114:10:114:17 | yield ... | +| Test.java:112:47:112:76 | equals(...) | Test.java:114:16:114:16 | 1 | | Test.java:112:71:112:75 | "abc" | Test.java:112:47:112:76 | equals(...) | | Test.java:113:8:113:20 | case | Test.java:113:19:113:19 | | | Test.java:113:8:113:20 | case | Test.java:115:8:115:15 | default | -| Test.java:113:19:113:19 | | Test.java:114:10:114:17 | yield ... | -| Test.java:114:10:114:17 | yield ... | Test.java:114:16:114:16 | 1 | -| Test.java:114:16:114:16 | 1 | Test.java:110:10:110:31 | result | -| Test.java:115:8:115:15 | default | Test.java:116:10:116:17 | yield ... | -| Test.java:116:10:116:17 | yield ... | Test.java:116:16:116:16 | 2 | -| Test.java:116:16:116:16 | 2 | Test.java:110:10:110:31 | result | +| Test.java:113:19:113:19 | | Test.java:114:16:114:16 | 1 | +| Test.java:114:10:114:17 | yield ... | Test.java:110:10:110:31 | result | +| Test.java:114:16:114:16 | 1 | Test.java:114:10:114:17 | yield ... | +| Test.java:115:8:115:15 | default | Test.java:116:16:116:16 | 2 | +| Test.java:116:10:116:17 | yield ... | Test.java:110:10:110:31 | result | +| Test.java:116:16:116:16 | 2 | Test.java:116:10:116:17 | yield ... | | Test.java:119:6:119:27 | switch (...) | Test.java:119:22:119:26 | thing | | Test.java:119:14:119:26 | (...)... | Test.java:120:8:120:16 | case ... | -| Test.java:119:14:119:26 | (...)... | Test.java:121:8:121:56 | case | | Test.java:119:22:119:26 | thing | Test.java:119:14:119:26 | (...)... | -| Test.java:120:8:120:16 | case ... | Test.java:122:8:122:16 | case ... | +| Test.java:120:8:120:16 | case ... | Test.java:120:13:120:15 | "a" | +| Test.java:120:8:120:16 | case ... | Test.java:121:8:121:56 | case | +| Test.java:120:13:120:15 | "a" | Test.java:123:10:123:15 | break | | Test.java:121:8:121:56 | case | Test.java:121:20:121:20 | | | Test.java:121:8:121:56 | case | Test.java:122:8:122:16 | case ... | -| Test.java:121:8:121:56 | case | Test.java:124:8:124:15 | default | | Test.java:121:20:121:20 | | Test.java:121:36:121:40 | thing | | Test.java:121:27:121:50 | length(...) | Test.java:121:55:121:55 | 5 | | Test.java:121:27:121:55 | ... == ... | Test.java:122:8:122:16 | case ... | -| Test.java:121:27:121:55 | ... == ... | Test.java:124:8:124:15 | default | +| Test.java:121:27:121:55 | ... == ... | Test.java:123:10:123:15 | break | | Test.java:121:28:121:40 | (...)... | Test.java:121:27:121:50 | length(...) | | Test.java:121:36:121:40 | thing | Test.java:121:28:121:40 | (...)... | | Test.java:121:55:121:55 | 5 | Test.java:121:27:121:55 | ... == ... | -| Test.java:122:8:122:16 | case ... | Test.java:123:10:123:15 | break | +| Test.java:122:8:122:16 | case ... | Test.java:122:13:122:15 | "b" | +| Test.java:122:8:122:16 | case ... | Test.java:124:8:124:15 | default | +| Test.java:122:13:122:15 | "b" | Test.java:123:10:123:15 | break | | Test.java:123:10:123:15 | break | Test.java:129:6:129:18 | switch (...) | | Test.java:124:8:124:15 | default | Test.java:125:10:125:15 | break | | Test.java:125:10:125:15 | break | Test.java:129:6:129:18 | switch (...) | @@ -395,29 +401,33 @@ | Test.java:129:13:129:17 | thing | Test.java:130:8:130:21 | case | | Test.java:130:8:130:21 | case | Test.java:130:20:130:20 | | | Test.java:130:8:130:21 | case | Test.java:131:8:131:15 | default | -| Test.java:130:20:130:20 | | Test.java:131:8:131:15 | default | +| Test.java:130:20:130:20 | | Test.java:3:22:3:25 | Normal Exit | | Test.java:131:8:131:15 | default | Test.java:3:22:3:25 | Normal Exit | | Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | ; | | Test.java:138:8:138:8 | ...=... | Test.java:138:8:138:8 | Normal Exit | | Test.java:138:8:138:8 | ; | Test.java:138:8:138:8 | this | | Test.java:138:8:138:8 | ; | Test.java:138:8:138:8 | this | -| Test.java:138:8:138:8 | Exceptional Exit | Test.java:138:8:138:8 | Exit | +| Test.java:138:8:138:8 | Entry | Test.java:138:8:138:8 | { ... } | | Test.java:138:8:138:8 | Normal Exit | Test.java:138:8:138:8 | Exit | | Test.java:138:8:138:8 | b | Test.java:138:8:138:8 | ...=... | | Test.java:138:8:138:8 | field3 | Test.java:138:8:138:8 | ...=... | | Test.java:138:8:138:8 | super(...) | Test.java:138:8:138:8 | ; | -| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | b | -| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | field3 | +| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | this.b | +| Test.java:138:8:138:8 | this | Test.java:138:8:138:8 | this.field3 | +| Test.java:138:8:138:8 | this.b | Test.java:138:8:138:8 | b | +| Test.java:138:8:138:8 | this.field3 | Test.java:138:8:138:8 | field3 | | Test.java:138:8:138:8 | { ... } | Test.java:138:8:138:8 | super(...) | | Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | ; | | Test.java:139:8:139:8 | ...=... | Test.java:139:8:139:8 | Normal Exit | | Test.java:139:8:139:8 | ; | Test.java:139:8:139:8 | this | | Test.java:139:8:139:8 | ; | Test.java:139:8:139:8 | this | -| Test.java:139:8:139:8 | Exceptional Exit | Test.java:139:8:139:8 | Exit | +| Test.java:139:8:139:8 | Entry | Test.java:139:8:139:8 | { ... } | | Test.java:139:8:139:8 | Normal Exit | Test.java:139:8:139:8 | Exit | | Test.java:139:8:139:8 | field1 | Test.java:139:8:139:8 | ...=... | | Test.java:139:8:139:8 | field2 | Test.java:139:8:139:8 | ...=... | | Test.java:139:8:139:8 | super(...) | Test.java:139:8:139:8 | ; | -| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | field1 | -| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | field2 | +| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | this.field1 | +| Test.java:139:8:139:8 | this | Test.java:139:8:139:8 | this.field2 | +| Test.java:139:8:139:8 | this.field1 | Test.java:139:8:139:8 | field1 | +| Test.java:139:8:139:8 | this.field2 | Test.java:139:8:139:8 | field2 | | Test.java:139:8:139:8 | { ... } | Test.java:139:8:139:8 | super(...) | diff --git a/java/ql/test/library-tests/pattern-switch/cfg/test.ql b/java/ql/test/library-tests/pattern-switch/cfg/test.ql index 7e0a85af822a..f858ec60eeb7 100644 --- a/java/ql/test/library-tests/pattern-switch/cfg/test.ql +++ b/java/ql/test/library-tests/pattern-switch/cfg/test.ql @@ -1,5 +1,6 @@ import java +import utils.test.AstCfg from ControlFlowNode cn where cn.getLocation().getFile().getBaseName() = ["Test.java", "Exhaustive.java"] -select cn, cn.getASuccessor() +select cn, getAnAstSuccessor(cn) diff --git a/java/ql/test/library-tests/ssa/captures.expected b/java/ql/test/library-tests/ssa/captures.expected index 3d8b8e136024..e3ccd98ce162 100644 --- a/java/ql/test/library-tests/ssa/captures.expected +++ b/java/ql/test/library-tests/ssa/captures.expected @@ -1,9 +1,9 @@ -| Nested.java:8:29:8:57 | SSA capture def(next(..).p1) | Nested.java:4:34:10:3 | SSA param(p1) | -| Nested.java:8:29:8:57 | SSA capture def(next(..).x1) | Nested.java:5:9:5:14 | SSA def(x1) | +| Nested.java:8:22:8:25 | SSA capture def(next(..).p1) | Nested.java:4:21:4:24 | SSA param(p1) | +| Nested.java:8:22:8:25 | SSA capture def(next(..).x1) | Nested.java:5:9:5:14 | SSA def(x1) | | Nested.java:16:22:16:34 | SSA capture def(getInt(..).obj) | Nested.java:15:12:15:29 | SSA def(obj) | -| Nested.java:19:27:22:7 | SSA capture def(getInt(..).hash) | Nested.java:16:15:16:34 | SSA def(hash) | -| Nested.java:19:27:22:7 | SSA capture def(getInt(..).x2) | Nested.java:17:9:17:15 | SSA def(x2) | +| Nested.java:19:18:19:23 | SSA capture def(getInt(..).hash) | Nested.java:16:15:16:34 | SSA def(hash) | +| Nested.java:19:18:19:23 | SSA capture def(getInt(..).x2) | Nested.java:17:9:17:15 | SSA def(x2) | | Nested.java:20:27:20:39 | SSA capture def(getInt(..).obj) | Nested.java:15:12:15:29 | SSA def(obj) | -| Nested.java:30:23:30:36 | SSA capture def(getInt(..).obj2) | Nested.java:30:5:30:37 | SSA phi(obj2) | -| Nested.java:37:20:37:25 | SSA capture def(getInt(..).x3) | Nested.java:36:7:36:12 | SSA def(x3) | -| Nested.java:40:20:40:25 | SSA capture def(getInt(..).x3) | Nested.java:39:7:39:12 | SSA def(x3) | +| Nested.java:30:23:30:36 | SSA capture def(getInt(..).obj2) | Nested.java:25:5:25:24 | SSA phi(obj2) | +| Nested.java:37:14:37:25 | SSA capture def(getInt(..).x3) | Nested.java:36:7:36:12 | SSA def(x3) | +| Nested.java:40:14:40:25 | SSA capture def(getInt(..).x3) | Nested.java:39:7:39:12 | SSA def(x3) | diff --git a/java/ql/test/library-tests/ssa/firstUse.expected b/java/ql/test/library-tests/ssa/firstUse.expected index 6494791be346..a92573377387 100644 --- a/java/ql/test/library-tests/ssa/firstUse.expected +++ b/java/ql/test/library-tests/ssa/firstUse.expected @@ -1,11 +1,11 @@ -| Fields.java:12:19:21:3 | SSA entry def(this.xs) | Fields.java:13:15:13:16 | xs | +| Fields.java:12:15:12:15 | SSA entry def(this.xs) | Fields.java:13:15:13:16 | xs | | Fields.java:14:5:14:9 | SSA call def(this.xs) | Fields.java:15:9:15:10 | xs | | Fields.java:15:5:15:10 | SSA def(x) | Fields.java:16:9:16:9 | x | +| Fields.java:16:5:16:17 | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs | | Fields.java:17:7:17:11 | SSA call def(this.xs) | Fields.java:18:9:18:15 | this.xs | -| Fields.java:18:5:18:16 | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs | | Fields.java:19:5:19:19 | SSA def(this.xs) | Fields.java:20:9:20:10 | xs | -| Fields.java:23:19:49:3 | SSA entry def(Fields.stat) | Fields.java:27:15:27:18 | stat | -| Fields.java:23:19:49:3 | SSA entry def(this.xs) | Fields.java:26:15:26:16 | xs | +| Fields.java:23:15:23:15 | SSA entry def(Fields.stat) | Fields.java:27:15:27:18 | stat | +| Fields.java:23:15:23:15 | SSA entry def(this.xs) | Fields.java:26:15:26:16 | xs | | Fields.java:24:12:24:27 | SSA def(f) | Fields.java:25:15:25:15 | f | | Fields.java:24:12:24:27 | SSA qualifier def(f.xs) | Fields.java:25:15:25:18 | f.xs | | Fields.java:24:16:24:27 | SSA call def(Fields.stat) | Fields.java:27:15:27:18 | stat | @@ -18,52 +18,52 @@ | Fields.java:36:5:36:19 | SSA def(this.xs) | Fields.java:38:9:38:10 | xs | | Fields.java:39:5:39:21 | SSA def(f.xs) | Fields.java:40:9:40:12 | f.xs | | Fields.java:41:5:41:10 | SSA def(z) | Fields.java:42:9:42:9 | z | +| Fields.java:42:5:42:17 | SSA phi(Fields.stat) | Fields.java:48:9:48:12 | stat | +| Fields.java:42:5:42:17 | SSA phi(f) | Fields.java:44:9:44:9 | f | +| Fields.java:42:5:42:17 | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs | | Fields.java:43:7:43:22 | SSA def(f) | Fields.java:44:9:44:9 | f | | Fields.java:43:7:43:22 | SSA qualifier def(f.xs) | Fields.java:44:9:44:12 | f.xs | | Fields.java:43:11:43:22 | SSA call def(Fields.stat) | Fields.java:48:9:48:12 | stat | -| Fields.java:44:5:44:13 | SSA phi(Fields.stat) | Fields.java:48:9:48:12 | stat | -| Fields.java:44:5:44:13 | SSA phi(f) | Fields.java:44:9:44:9 | f | -| Fields.java:44:5:44:13 | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs | | Fields.java:45:5:45:16 | SSA call def(Fields.stat) | Fields.java:48:9:48:12 | stat | -| Nested.java:8:29:8:57 | SSA capture def(next(..).p1) | Nested.java:8:38:8:39 | p1 | -| Nested.java:8:29:8:57 | SSA capture def(next(..).x1) | Nested.java:8:43:8:44 | x1 | +| Nested.java:8:22:8:25 | SSA capture def(next(..).p1) | Nested.java:8:38:8:39 | p1 | +| Nested.java:8:22:8:25 | SSA capture def(next(..).x1) | Nested.java:8:43:8:44 | x1 | | Nested.java:16:22:16:34 | SSA capture def(getInt(..).obj) | Nested.java:16:22:16:24 | obj | | Nested.java:18:15:23:5 | SSA def(h2) | Nested.java:25:9:25:10 | h2 | -| Nested.java:19:27:22:7 | SSA capture def(getInt(..).hash) | Nested.java:21:21:21:24 | hash | -| Nested.java:19:27:22:7 | SSA capture def(getInt(..).x2) | Nested.java:21:16:21:17 | x2 | +| Nested.java:19:18:19:23 | SSA capture def(getInt(..).hash) | Nested.java:21:21:21:24 | hash | +| Nested.java:19:18:19:23 | SSA capture def(getInt(..).x2) | Nested.java:21:16:21:17 | x2 | | Nested.java:20:19:20:39 | SSA def(hnest) | Nested.java:21:37:21:41 | hnest | | Nested.java:20:27:20:39 | SSA capture def(getInt(..).obj) | Nested.java:20:27:20:29 | obj | | Nested.java:30:23:30:36 | SSA capture def(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 | -| Nested.java:33:29:42:3 | SSA param(p3) | Nested.java:35:9:35:10 | p3 | -| Nested.java:37:20:37:25 | SSA capture def(getInt(..).x3) | Nested.java:37:20:37:21 | x3 | -| Nested.java:40:20:40:25 | SSA capture def(getInt(..).x3) | Nested.java:40:20:40:21 | x3 | -| Test.java:4:19:32:2 | SSA param(param) | Test.java:9:7:9:11 | param | +| Nested.java:33:13:33:19 | SSA param(p3) | Nested.java:35:9:35:10 | p3 | +| Nested.java:37:14:37:25 | SSA capture def(getInt(..).x3) | Nested.java:37:20:37:21 | x3 | +| Nested.java:40:14:40:25 | SSA capture def(getInt(..).x3) | Nested.java:40:20:40:21 | x3 | +| Test.java:4:6:4:6 | SSA param(param) | Test.java:9:7:9:11 | param | | Test.java:6:7:6:11 | SSA def(x) | Test.java:10:4:10:4 | x | | Test.java:6:7:6:11 | SSA def(x) | Test.java:20:10:20:10 | x | +| Test.java:9:3:9:16 | SSA phi(x) | Test.java:20:10:20:10 | x | +| Test.java:9:3:9:16 | SSA phi(y) | Test.java:20:14:20:14 | y | | Test.java:10:4:10:6 | SSA def(x) | Test.java:11:10:11:10 | x | | Test.java:11:4:11:10 | SSA def(y) | Test.java:20:14:20:14 | y | | Test.java:11:8:11:10 | SSA def(x) | Test.java:20:10:20:10 | x | | Test.java:14:4:14:8 | SSA def(y) | Test.java:15:4:15:4 | y | | Test.java:15:4:15:9 | SSA def(y) | Test.java:20:14:20:14 | y | -| Test.java:19:3:19:3 | SSA phi(x) | Test.java:20:10:20:10 | x | -| Test.java:19:3:19:3 | SSA phi(y) | Test.java:20:14:20:14 | y | -| Test.java:20:10:20:10 | SSA phi(param) | Test.java:21:8:21:12 | param | -| Test.java:20:10:20:10 | SSA phi(y) | Test.java:20:14:20:14 | y | +| Test.java:20:3:20:15 | SSA phi(param) | Test.java:21:8:21:12 | param | +| Test.java:20:3:20:15 | SSA phi(y) | Test.java:20:14:20:14 | y | | Test.java:21:8:21:14 | SSA def(param) | Test.java:21:8:21:12 | param | | Test.java:24:4:24:9 | SSA def(y) | Test.java:20:14:20:14 | y | | Test.java:27:12:27:16 | SSA def(i) | Test.java:27:19:27:19 | i | -| Test.java:27:19:27:19 | SSA phi(i) | Test.java:27:19:27:19 | i | -| Test.java:27:19:27:19 | SSA phi(x) | Test.java:28:4:28:4 | x | -| Test.java:27:19:27:19 | SSA phi(x) | Test.java:31:10:31:10 | x | +| Test.java:27:19:27:22 | SSA phi(i) | Test.java:27:19:27:19 | i | +| Test.java:27:19:27:22 | SSA phi(x) | Test.java:28:4:28:4 | x | +| Test.java:27:19:27:22 | SSA phi(x) | Test.java:31:10:31:10 | x | | Test.java:27:25:27:27 | SSA def(i) | Test.java:27:19:27:19 | i | | Test.java:28:4:28:9 | SSA def(x) | Test.java:28:4:28:4 | x | | Test.java:28:4:28:9 | SSA def(x) | Test.java:31:10:31:10 | x | -| TestInstanceOfPattern.java:3:24:9:2 | SSA param(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj | +| TestInstanceOfPattern.java:3:7:3:10 | SSA param(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj | | TestInstanceOfPattern.java:4:29:4:29 | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s | -| TestInstanceOfPattern.java:10:25:16:2 | SSA param(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj | +| TestInstanceOfPattern.java:10:7:10:11 | SSA param(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj | | TestInstanceOfPattern.java:11:31:11:31 | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s | -| TestInstanceOfPattern.java:17:25:23:2 | SSA param(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj | +| TestInstanceOfPattern.java:17:7:17:11 | SSA param(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj | | TestInstanceOfPattern.java:18:29:18:29 | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s | -| TestInstanceOfPattern.java:24:25:30:2 | SSA entry def(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s | -| TestInstanceOfPattern.java:24:25:30:2 | SSA entry def(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s | -| TestInstanceOfPattern.java:24:25:30:2 | SSA param(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj | +| TestInstanceOfPattern.java:24:7:24:11 | SSA entry def(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s | +| TestInstanceOfPattern.java:24:7:24:11 | SSA entry def(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s | +| TestInstanceOfPattern.java:24:7:24:11 | SSA param(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj | diff --git a/java/ql/test/library-tests/ssa/ssaDef.expected b/java/ql/test/library-tests/ssa/ssaDef.expected index a10b9d327b27..2deba0dcebba 100644 --- a/java/ql/test/library-tests/ssa/ssaDef.expected +++ b/java/ql/test/library-tests/ssa/ssaDef.expected @@ -1,75 +1,75 @@ | Fields.java:13:5:13:17 | x | Fields.java:15:5:15:10 | ...=... | SSA def(x) | -| Fields.java:13:15:13:16 | this.xs | Fields.java:12:19:21:3 | { ... } | SSA entry def(this.xs) | +| Fields.java:13:15:13:16 | this.xs | Fields.java:12:15:12:15 | Entry | SSA entry def(this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:14:5:14:9 | upd(...) | SSA call def(this.xs) | +| Fields.java:13:15:13:16 | this.xs | Fields.java:16:5:16:17 | After if (...) | SSA phi(this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:17:7:17:11 | upd(...) | SSA call def(this.xs) | -| Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | ; | SSA phi(this.xs) | | Fields.java:13:15:13:16 | this.xs | Fields.java:19:5:19:19 | ...=... | SSA def(this.xs) | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | +| Fields.java:24:5:24:28 | f | Fields.java:42:5:42:17 | After if (...) | SSA phi(f) | | Fields.java:24:5:24:28 | f | Fields.java:43:7:43:22 | ...=... | SSA def(f) | -| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | ; | SSA phi(f) | | Fields.java:25:15:25:18 | f.xs | Fields.java:24:12:24:27 | f | SSA qualifier def(f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:39:5:39:21 | ...=... | SSA def(f.xs) | +| Fields.java:25:15:25:18 | f.xs | Fields.java:42:5:42:17 | After if (...) | SSA phi(f.xs) | | Fields.java:25:15:25:18 | f.xs | Fields.java:43:7:43:22 | ...=... | SSA qualifier def(f.xs) | -| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | ; | SSA phi(f.xs) | | Fields.java:26:5:26:17 | z | Fields.java:41:5:41:10 | ...=... | SSA def(z) | -| Fields.java:26:15:26:16 | this.xs | Fields.java:23:19:49:3 | { ... } | SSA entry def(this.xs) | +| Fields.java:26:15:26:16 | this.xs | Fields.java:23:15:23:15 | Entry | SSA entry def(this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(this.xs) | | Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | -| Fields.java:27:15:27:18 | Fields.stat | Fields.java:23:19:49:3 | { ... } | SSA entry def(Fields.stat) | +| Fields.java:27:15:27:18 | Fields.stat | Fields.java:23:15:23:15 | Entry | SSA entry def(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:24:16:24:27 | new Fields(...) | SSA call def(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:28:5:28:12 | f(...) | SSA call def(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:32:5:32:9 | f(...) | SSA call def(Fields.stat) | +| Fields.java:27:15:27:18 | Fields.stat | Fields.java:42:5:42:17 | After if (...) | SSA phi(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:43:11:43:22 | new Fields(...) | SSA call def(Fields.stat) | -| Fields.java:27:15:27:18 | Fields.stat | Fields.java:44:5:44:13 | ; | SSA phi(Fields.stat) | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:45:5:45:16 | new Fields(...) | SSA call def(Fields.stat) | -| Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).p1) | -| Nested.java:4:26:4:31 | p1 | Nested.java:4:34:10:3 | { ... } | SSA param(p1) | -| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | +| Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:22:8:25 | Entry | SSA capture def(next(..).p1) | +| Nested.java:4:26:4:31 | p1 | Nested.java:4:21:4:24 | Entry | SSA param(p1) | +| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:22:8:25 | Entry | SSA capture def(next(..).x1) | | Nested.java:5:5:5:15 | x1 | Nested.java:5:9:5:14 | x1 | SSA def(x1) | -| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | { ... } | SSA capture def(getInt(..).obj) | -| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | { ... } | SSA capture def(getInt(..).obj) | +| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | Entry | SSA capture def(getInt(..).obj) | +| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | Entry | SSA capture def(getInt(..).obj) | | Nested.java:15:5:15:30 | obj | Nested.java:15:12:15:29 | obj | SSA def(obj) | -| Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).hash) | +| Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:18:19:23 | Entry | SSA capture def(getInt(..).hash) | | Nested.java:16:5:16:35 | hash | Nested.java:16:15:16:34 | hash | SSA def(hash) | -| Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).x2) | +| Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:18:19:23 | Entry | SSA capture def(getInt(..).x2) | | Nested.java:17:5:17:16 | x2 | Nested.java:17:9:17:15 | x2 | SSA def(x2) | | Nested.java:18:5:23:6 | h2 | Nested.java:18:15:23:5 | h2 | SSA def(h2) | | Nested.java:20:9:20:40 | hnest | Nested.java:20:19:20:39 | hnest | SSA def(hnest) | -| Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | { ... } | SSA capture def(getInt(..).obj2) | +| Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | Entry | SSA capture def(getInt(..).obj2) | +| Nested.java:24:5:24:31 | obj2 | Nested.java:25:5:25:24 | After if (...) | SSA phi(obj2) | | Nested.java:24:5:24:31 | obj2 | Nested.java:26:7:26:25 | ...=... | SSA def(obj2) | | Nested.java:24:5:24:31 | obj2 | Nested.java:28:7:28:25 | ...=... | SSA def(obj2) | -| Nested.java:24:5:24:31 | obj2 | Nested.java:30:5:30:37 | var ...; | SSA phi(obj2) | -| Nested.java:33:21:33:26 | p3 | Nested.java:33:29:42:3 | { ... } | SSA param(p3) | -| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:20:37:25 | { ... } | SSA capture def(getInt(..).x3) | -| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:20:40:25 | { ... } | SSA capture def(getInt(..).x3) | +| Nested.java:33:21:33:26 | p3 | Nested.java:33:13:33:19 | Entry | SSA param(p3) | +| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:14:37:25 | Entry | SSA capture def(getInt(..).x3) | +| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:14:40:25 | Entry | SSA capture def(getInt(..).x3) | | Nested.java:34:5:34:11 | x3 | Nested.java:36:7:36:12 | ...=... | SSA def(x3) | | Nested.java:34:5:34:11 | x3 | Nested.java:39:7:39:12 | ...=... | SSA def(x3) | -| Test.java:4:8:4:16 | param | Test.java:4:19:32:2 | { ... } | SSA param(param) | -| Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | SSA phi(param) | +| Test.java:4:8:4:16 | param | Test.java:4:6:4:6 | Entry | SSA param(param) | +| Test.java:4:8:4:16 | param | Test.java:20:3:20:15 | [LoopHeader] while (...) | SSA phi(param) | | Test.java:4:8:4:16 | param | Test.java:21:8:21:14 | ...++ | SSA def(param) | | Test.java:6:3:6:12 | x | Test.java:6:7:6:11 | x | SSA def(x) | +| Test.java:6:3:6:12 | x | Test.java:9:3:9:16 | After if (...) | SSA phi(x) | | Test.java:6:3:6:12 | x | Test.java:10:4:10:6 | ...++ | SSA def(x) | | Test.java:6:3:6:12 | x | Test.java:11:8:11:10 | ++... | SSA def(x) | -| Test.java:6:3:6:12 | x | Test.java:19:3:19:3 | ; | SSA phi(x) | -| Test.java:6:3:6:12 | x | Test.java:27:19:27:19 | i | SSA phi(x) | +| Test.java:6:3:6:12 | x | Test.java:27:19:27:22 | Before ... < ... | SSA phi(x) | | Test.java:6:3:6:12 | x | Test.java:28:4:28:9 | ...+=... | SSA def(x) | +| Test.java:7:3:7:8 | y | Test.java:9:3:9:16 | After if (...) | SSA phi(y) | | Test.java:7:3:7:8 | y | Test.java:11:4:11:10 | ...=... | SSA def(y) | | Test.java:7:3:7:8 | y | Test.java:14:4:14:8 | ...=... | SSA def(y) | | Test.java:7:3:7:8 | y | Test.java:15:4:15:9 | ...+=... | SSA def(y) | -| Test.java:7:3:7:8 | y | Test.java:19:3:19:3 | ; | SSA phi(y) | -| Test.java:7:3:7:8 | y | Test.java:20:10:20:10 | x | SSA phi(y) | +| Test.java:7:3:7:8 | y | Test.java:20:3:20:15 | [LoopHeader] while (...) | SSA phi(y) | | Test.java:7:3:7:8 | y | Test.java:24:4:24:9 | ...-=... | SSA def(y) | | Test.java:27:8:27:16 | i | Test.java:27:12:27:16 | i | SSA def(i) | -| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | +| Test.java:27:8:27:16 | i | Test.java:27:19:27:22 | Before ... < ... | SSA phi(i) | | Test.java:27:8:27:16 | i | Test.java:27:25:27:27 | ...++ | SSA def(i) | -| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | { ... } | SSA param(obj) | +| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:7:3:10 | Entry | SSA param(obj) | | TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) | -| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | { ... } | SSA param(obj) | +| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:7:10:11 | Entry | SSA param(obj) | | TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) | -| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | { ... } | SSA param(obj) | +| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:7:17:11 | Entry | SSA param(obj) | | TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | -| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA param(obj) | -| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | +| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:7:24:11 | Entry | SSA param(obj) | +| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:7:24:11 | Entry | SSA entry def(this.s) | diff --git a/java/ql/test/library-tests/ssa/ssaPhi.expected b/java/ql/test/library-tests/ssa/ssaPhi.expected index b002ee81b3e3..afdf8bde2bdf 100644 --- a/java/ql/test/library-tests/ssa/ssaPhi.expected +++ b/java/ql/test/library-tests/ssa/ssaPhi.expected @@ -1,22 +1,22 @@ -| Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | ; | Fields.java:14:5:14:9 | upd(...) | -| Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | ; | Fields.java:17:7:17:11 | upd(...) | -| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | ; | Fields.java:24:12:24:27 | f | -| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | ; | Fields.java:43:7:43:22 | ...=... | -| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | ; | Fields.java:39:5:39:21 | ...=... | -| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | ; | Fields.java:43:7:43:22 | ...=... | -| Fields.java:27:15:27:18 | Fields.stat | Fields.java:44:5:44:13 | ; | Fields.java:32:5:32:9 | f(...) | -| Fields.java:27:15:27:18 | Fields.stat | Fields.java:44:5:44:13 | ; | Fields.java:43:11:43:22 | new Fields(...) | -| Nested.java:24:5:24:31 | obj2 | Nested.java:30:5:30:37 | var ...; | Nested.java:26:7:26:25 | ...=... | -| Nested.java:24:5:24:31 | obj2 | Nested.java:30:5:30:37 | var ...; | Nested.java:28:7:28:25 | ...=... | -| Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | Test.java:4:19:32:2 | { ... } | -| Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | Test.java:21:8:21:14 | ...++ | -| Test.java:6:3:6:12 | x | Test.java:19:3:19:3 | ; | Test.java:6:7:6:11 | x | -| Test.java:6:3:6:12 | x | Test.java:19:3:19:3 | ; | Test.java:11:8:11:10 | ++... | -| Test.java:6:3:6:12 | x | Test.java:27:19:27:19 | i | Test.java:19:3:19:3 | ; | -| Test.java:6:3:6:12 | x | Test.java:27:19:27:19 | i | Test.java:28:4:28:9 | ...+=... | -| Test.java:7:3:7:8 | y | Test.java:19:3:19:3 | ; | Test.java:11:4:11:10 | ...=... | -| Test.java:7:3:7:8 | y | Test.java:19:3:19:3 | ; | Test.java:15:4:15:9 | ...+=... | -| Test.java:7:3:7:8 | y | Test.java:20:10:20:10 | x | Test.java:19:3:19:3 | ; | -| Test.java:7:3:7:8 | y | Test.java:20:10:20:10 | x | Test.java:24:4:24:9 | ...-=... | -| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | Test.java:27:12:27:16 | i | -| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | Test.java:27:25:27:27 | ...++ | +| Fields.java:13:15:13:16 | this.xs | Fields.java:16:5:16:17 | After if (...) | Fields.java:14:5:14:9 | upd(...) | +| Fields.java:13:15:13:16 | this.xs | Fields.java:16:5:16:17 | After if (...) | Fields.java:17:7:17:11 | upd(...) | +| Fields.java:24:5:24:28 | f | Fields.java:42:5:42:17 | After if (...) | Fields.java:24:12:24:27 | f | +| Fields.java:24:5:24:28 | f | Fields.java:42:5:42:17 | After if (...) | Fields.java:43:7:43:22 | ...=... | +| Fields.java:25:15:25:18 | f.xs | Fields.java:42:5:42:17 | After if (...) | Fields.java:39:5:39:21 | ...=... | +| Fields.java:25:15:25:18 | f.xs | Fields.java:42:5:42:17 | After if (...) | Fields.java:43:7:43:22 | ...=... | +| Fields.java:27:15:27:18 | Fields.stat | Fields.java:42:5:42:17 | After if (...) | Fields.java:32:5:32:9 | f(...) | +| Fields.java:27:15:27:18 | Fields.stat | Fields.java:42:5:42:17 | After if (...) | Fields.java:43:11:43:22 | new Fields(...) | +| Nested.java:24:5:24:31 | obj2 | Nested.java:25:5:25:24 | After if (...) | Nested.java:26:7:26:25 | ...=... | +| Nested.java:24:5:24:31 | obj2 | Nested.java:25:5:25:24 | After if (...) | Nested.java:28:7:28:25 | ...=... | +| Test.java:4:8:4:16 | param | Test.java:20:3:20:15 | [LoopHeader] while (...) | Test.java:4:6:4:6 | Entry | +| Test.java:4:8:4:16 | param | Test.java:20:3:20:15 | [LoopHeader] while (...) | Test.java:21:8:21:14 | ...++ | +| Test.java:6:3:6:12 | x | Test.java:9:3:9:16 | After if (...) | Test.java:6:7:6:11 | x | +| Test.java:6:3:6:12 | x | Test.java:9:3:9:16 | After if (...) | Test.java:11:8:11:10 | ++... | +| Test.java:6:3:6:12 | x | Test.java:27:19:27:22 | Before ... < ... | Test.java:9:3:9:16 | After if (...) | +| Test.java:6:3:6:12 | x | Test.java:27:19:27:22 | Before ... < ... | Test.java:28:4:28:9 | ...+=... | +| Test.java:7:3:7:8 | y | Test.java:9:3:9:16 | After if (...) | Test.java:11:4:11:10 | ...=... | +| Test.java:7:3:7:8 | y | Test.java:9:3:9:16 | After if (...) | Test.java:15:4:15:9 | ...+=... | +| Test.java:7:3:7:8 | y | Test.java:20:3:20:15 | [LoopHeader] while (...) | Test.java:9:3:9:16 | After if (...) | +| Test.java:7:3:7:8 | y | Test.java:20:3:20:15 | [LoopHeader] while (...) | Test.java:24:4:24:9 | ...-=... | +| Test.java:27:8:27:16 | i | Test.java:27:19:27:22 | Before ... < ... | Test.java:27:12:27:16 | i | +| Test.java:27:8:27:16 | i | Test.java:27:19:27:22 | Before ... < ... | Test.java:27:25:27:27 | ...++ | diff --git a/java/ql/test/library-tests/ssa/ssaUse.expected b/java/ql/test/library-tests/ssa/ssaUse.expected index 8525f62a883c..b1e309591e34 100644 --- a/java/ql/test/library-tests/ssa/ssaUse.expected +++ b/java/ql/test/library-tests/ssa/ssaUse.expected @@ -1,7 +1,7 @@ | Fields.java:13:5:13:17 | x | Fields.java:15:5:15:10 | ...=... | SSA def(x) | Fields.java:16:9:16:9 | x | -| Fields.java:13:15:13:16 | this.xs | Fields.java:12:19:21:3 | { ... } | SSA entry def(this.xs) | Fields.java:13:15:13:16 | xs | +| Fields.java:13:15:13:16 | this.xs | Fields.java:12:15:12:15 | Entry | SSA entry def(this.xs) | Fields.java:13:15:13:16 | xs | | Fields.java:13:15:13:16 | this.xs | Fields.java:14:5:14:9 | upd(...) | SSA call def(this.xs) | Fields.java:15:9:15:10 | xs | -| Fields.java:13:15:13:16 | this.xs | Fields.java:18:5:18:16 | ; | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs | +| Fields.java:13:15:13:16 | this.xs | Fields.java:16:5:16:17 | After if (...) | SSA phi(this.xs) | Fields.java:18:9:18:15 | this.xs | | Fields.java:13:15:13:16 | this.xs | Fields.java:19:5:19:19 | ...=... | SSA def(this.xs) | Fields.java:20:9:20:10 | xs | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:25:15:25:15 | f | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:29:9:29:9 | f | @@ -10,17 +10,17 @@ | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:37:9:37:9 | f | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:39:5:39:5 | f | | Fields.java:24:5:24:28 | f | Fields.java:24:12:24:27 | f | SSA def(f) | Fields.java:40:9:40:9 | f | -| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | ; | SSA phi(f) | Fields.java:44:9:44:9 | f | -| Fields.java:24:5:24:28 | f | Fields.java:44:5:44:13 | ; | SSA phi(f) | Fields.java:46:9:46:9 | f | +| Fields.java:24:5:24:28 | f | Fields.java:42:5:42:17 | After if (...) | SSA phi(f) | Fields.java:44:9:44:9 | f | +| Fields.java:24:5:24:28 | f | Fields.java:42:5:42:17 | After if (...) | SSA phi(f) | Fields.java:46:9:46:9 | f | | Fields.java:25:15:25:18 | f.xs | Fields.java:24:12:24:27 | f | SSA qualifier def(f.xs) | Fields.java:25:15:25:18 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(f.xs) | Fields.java:29:9:29:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(f.xs) | Fields.java:33:9:33:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(f.xs) | Fields.java:37:9:37:12 | f.xs | | Fields.java:25:15:25:18 | f.xs | Fields.java:39:5:39:21 | ...=... | SSA def(f.xs) | Fields.java:40:9:40:12 | f.xs | -| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | ; | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs | -| Fields.java:25:15:25:18 | f.xs | Fields.java:44:5:44:13 | ; | SSA phi(f.xs) | Fields.java:46:9:46:12 | f.xs | +| Fields.java:25:15:25:18 | f.xs | Fields.java:42:5:42:17 | After if (...) | SSA phi(f.xs) | Fields.java:44:9:44:12 | f.xs | +| Fields.java:25:15:25:18 | f.xs | Fields.java:42:5:42:17 | After if (...) | SSA phi(f.xs) | Fields.java:46:9:46:12 | f.xs | | Fields.java:26:5:26:17 | z | Fields.java:41:5:41:10 | ...=... | SSA def(z) | Fields.java:42:9:42:9 | z | -| Fields.java:26:15:26:16 | this.xs | Fields.java:23:19:49:3 | { ... } | SSA entry def(this.xs) | Fields.java:26:15:26:16 | xs | +| Fields.java:26:15:26:16 | this.xs | Fields.java:23:15:23:15 | Entry | SSA entry def(this.xs) | Fields.java:26:15:26:16 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:28:5:28:12 | f(...) | SSA call def(this.xs) | Fields.java:30:9:30:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:32:5:32:9 | f(...) | SSA call def(this.xs) | Fields.java:34:9:34:10 | xs | | Fields.java:26:15:26:16 | this.xs | Fields.java:36:5:36:19 | ...=... | SSA def(this.xs) | Fields.java:38:9:38:10 | xs | @@ -30,42 +30,42 @@ | Fields.java:27:15:27:18 | Fields.stat | Fields.java:28:5:28:12 | f(...) | SSA call def(Fields.stat) | Fields.java:31:9:31:12 | stat | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:32:5:32:9 | f(...) | SSA call def(Fields.stat) | Fields.java:35:9:35:12 | stat | | Fields.java:27:15:27:18 | Fields.stat | Fields.java:45:5:45:16 | new Fields(...) | SSA call def(Fields.stat) | Fields.java:48:9:48:12 | stat | -| Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).p1) | Nested.java:8:38:8:39 | p1 | -| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | Nested.java:8:43:8:44 | x1 | -| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | Nested.java:8:48:8:49 | x1 | -| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:29:8:57 | { ... } | SSA capture def(next(..).x1) | Nested.java:8:53:8:54 | x1 | -| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | { ... } | SSA capture def(getInt(..).obj) | Nested.java:16:22:16:24 | obj | -| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | { ... } | SSA capture def(getInt(..).obj) | Nested.java:20:27:20:29 | obj | -| Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).hash) | Nested.java:21:21:21:24 | hash | -| Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:27:22:7 | { ... } | SSA capture def(getInt(..).x2) | Nested.java:21:16:21:17 | x2 | +| Nested.java:4:26:4:31 | next(..).p1 | Nested.java:8:22:8:25 | Entry | SSA capture def(next(..).p1) | Nested.java:8:38:8:39 | p1 | +| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:22:8:25 | Entry | SSA capture def(next(..).x1) | Nested.java:8:43:8:44 | x1 | +| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:22:8:25 | Entry | SSA capture def(next(..).x1) | Nested.java:8:48:8:49 | x1 | +| Nested.java:5:5:5:15 | next(..).x1 | Nested.java:8:22:8:25 | Entry | SSA capture def(next(..).x1) | Nested.java:8:53:8:54 | x1 | +| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:16:22:16:34 | Entry | SSA capture def(getInt(..).obj) | Nested.java:16:22:16:24 | obj | +| Nested.java:15:5:15:30 | getInt(..).obj | Nested.java:20:27:20:39 | Entry | SSA capture def(getInt(..).obj) | Nested.java:20:27:20:29 | obj | +| Nested.java:16:5:16:35 | getInt(..).hash | Nested.java:19:18:19:23 | Entry | SSA capture def(getInt(..).hash) | Nested.java:21:21:21:24 | hash | +| Nested.java:17:5:17:16 | getInt(..).x2 | Nested.java:19:18:19:23 | Entry | SSA capture def(getInt(..).x2) | Nested.java:21:16:21:17 | x2 | | Nested.java:18:5:23:6 | h2 | Nested.java:18:15:23:5 | h2 | SSA def(h2) | Nested.java:25:9:25:10 | h2 | | Nested.java:20:9:20:40 | hnest | Nested.java:20:19:20:39 | hnest | SSA def(hnest) | Nested.java:21:37:21:41 | hnest | -| Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | { ... } | SSA capture def(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 | -| Nested.java:33:21:33:26 | p3 | Nested.java:33:29:42:3 | { ... } | SSA param(p3) | Nested.java:35:9:35:10 | p3 | -| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:20:37:25 | { ... } | SSA capture def(getInt(..).x3) | Nested.java:37:20:37:21 | x3 | -| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:20:40:25 | { ... } | SSA capture def(getInt(..).x3) | Nested.java:40:20:40:21 | x3 | -| Test.java:4:8:4:16 | param | Test.java:4:19:32:2 | { ... } | SSA param(param) | Test.java:9:7:9:11 | param | -| Test.java:4:8:4:16 | param | Test.java:20:10:20:10 | x | SSA phi(param) | Test.java:21:8:21:12 | param | +| Nested.java:24:5:24:31 | getInt(..).obj2 | Nested.java:30:23:30:36 | Entry | SSA capture def(getInt(..).obj2) | Nested.java:30:23:30:26 | obj2 | +| Nested.java:33:21:33:26 | p3 | Nested.java:33:13:33:19 | Entry | SSA param(p3) | Nested.java:35:9:35:10 | p3 | +| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:37:14:37:25 | Entry | SSA capture def(getInt(..).x3) | Nested.java:37:20:37:21 | x3 | +| Nested.java:34:5:34:11 | getInt(..).x3 | Nested.java:40:14:40:25 | Entry | SSA capture def(getInt(..).x3) | Nested.java:40:20:40:21 | x3 | +| Test.java:4:8:4:16 | param | Test.java:4:6:4:6 | Entry | SSA param(param) | Test.java:9:7:9:11 | param | +| Test.java:4:8:4:16 | param | Test.java:20:3:20:15 | [LoopHeader] while (...) | SSA phi(param) | Test.java:21:8:21:12 | param | | Test.java:6:3:6:12 | x | Test.java:6:7:6:11 | x | SSA def(x) | Test.java:10:4:10:4 | x | +| Test.java:6:3:6:12 | x | Test.java:9:3:9:16 | After if (...) | SSA phi(x) | Test.java:20:10:20:10 | x | | Test.java:6:3:6:12 | x | Test.java:10:4:10:6 | ...++ | SSA def(x) | Test.java:11:10:11:10 | x | -| Test.java:6:3:6:12 | x | Test.java:19:3:19:3 | ; | SSA phi(x) | Test.java:20:10:20:10 | x | -| Test.java:6:3:6:12 | x | Test.java:27:19:27:19 | i | SSA phi(x) | Test.java:28:4:28:4 | x | -| Test.java:6:3:6:12 | x | Test.java:27:19:27:19 | i | SSA phi(x) | Test.java:31:10:31:10 | x | +| Test.java:6:3:6:12 | x | Test.java:27:19:27:22 | Before ... < ... | SSA phi(x) | Test.java:28:4:28:4 | x | +| Test.java:6:3:6:12 | x | Test.java:27:19:27:22 | Before ... < ... | SSA phi(x) | Test.java:31:10:31:10 | x | | Test.java:7:3:7:8 | y | Test.java:14:4:14:8 | ...=... | SSA def(y) | Test.java:15:4:15:4 | y | -| Test.java:7:3:7:8 | y | Test.java:20:10:20:10 | x | SSA phi(y) | Test.java:20:14:20:14 | y | -| Test.java:7:3:7:8 | y | Test.java:20:10:20:10 | x | SSA phi(y) | Test.java:24:4:24:4 | y | -| Test.java:7:3:7:8 | y | Test.java:20:10:20:10 | x | SSA phi(y) | Test.java:31:14:31:14 | y | -| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:19:27:19 | i | -| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:27:25:27:25 | i | -| Test.java:27:8:27:16 | i | Test.java:27:19:27:19 | i | SSA phi(i) | Test.java:28:9:28:9 | i | -| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:24:9:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj | +| Test.java:7:3:7:8 | y | Test.java:20:3:20:15 | [LoopHeader] while (...) | SSA phi(y) | Test.java:20:14:20:14 | y | +| Test.java:7:3:7:8 | y | Test.java:20:3:20:15 | [LoopHeader] while (...) | SSA phi(y) | Test.java:24:4:24:4 | y | +| Test.java:7:3:7:8 | y | Test.java:20:3:20:15 | [LoopHeader] while (...) | SSA phi(y) | Test.java:31:14:31:14 | y | +| Test.java:27:8:27:16 | i | Test.java:27:19:27:22 | Before ... < ... | SSA phi(i) | Test.java:27:19:27:19 | i | +| Test.java:27:8:27:16 | i | Test.java:27:19:27:22 | Before ... < ... | SSA phi(i) | Test.java:27:25:27:25 | i | +| Test.java:27:8:27:16 | i | Test.java:27:19:27:22 | Before ... < ... | SSA phi(i) | Test.java:28:9:28:9 | i | +| TestInstanceOfPattern.java:3:12:3:21 | obj | TestInstanceOfPattern.java:3:7:3:10 | Entry | SSA param(obj) | TestInstanceOfPattern.java:4:7:4:9 | obj | | TestInstanceOfPattern.java:4:22:4:29 | s | TestInstanceOfPattern.java:4:29:4:29 | s | SSA def(s) | TestInstanceOfPattern.java:5:8:5:8 | s | -| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:25:16:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj | +| TestInstanceOfPattern.java:10:13:10:22 | obj | TestInstanceOfPattern.java:10:7:10:11 | Entry | SSA param(obj) | TestInstanceOfPattern.java:11:9:11:11 | obj | | TestInstanceOfPattern.java:11:24:11:31 | s | TestInstanceOfPattern.java:11:31:11:31 | s | SSA def(s) | TestInstanceOfPattern.java:14:8:14:8 | s | -| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:25:23:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj | +| TestInstanceOfPattern.java:17:13:17:22 | obj | TestInstanceOfPattern.java:17:7:17:11 | Entry | SSA param(obj) | TestInstanceOfPattern.java:18:7:18:9 | obj | | TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:18:34:18:34 | s | | TestInstanceOfPattern.java:18:22:18:29 | s | TestInstanceOfPattern.java:18:29:18:29 | s | SSA def(s) | TestInstanceOfPattern.java:19:8:19:8 | s | -| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA param(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj | -| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s | -| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s | -| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:25:30:2 | { ... } | SSA entry def(this.s) | TestInstanceOfPattern.java:28:8:28:8 | s | +| TestInstanceOfPattern.java:24:13:24:22 | obj | TestInstanceOfPattern.java:24:7:24:11 | Entry | SSA param(obj) | TestInstanceOfPattern.java:25:7:25:9 | obj | +| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:7:24:11 | Entry | SSA entry def(this.s) | TestInstanceOfPattern.java:25:34:25:34 | s | +| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:7:24:11 | Entry | SSA entry def(this.s) | TestInstanceOfPattern.java:26:8:26:8 | s | +| TestInstanceOfPattern.java:25:34:25:34 | this.s | TestInstanceOfPattern.java:24:7:24:11 | Entry | SSA entry def(this.s) | TestInstanceOfPattern.java:28:8:28:8 | s | diff --git a/java/ql/test/library-tests/successors/CloseReaderTest/FalseSuccessors.ql b/java/ql/test/library-tests/successors/CloseReaderTest/FalseSuccessors.ql deleted file mode 100644 index aee4021bee69..000000000000 --- a/java/ql/test/library-tests/successors/CloseReaderTest/FalseSuccessors.ql +++ /dev/null @@ -1,4 +0,0 @@ -import java - -from ConditionNode c -select c, c.getAFalseSuccessor() diff --git a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected index fc529feba134..6889eb8da32d 100644 --- a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected +++ b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.expected @@ -1,7 +1,8 @@ -| CloseReaderTest.java:8:14:8:28 | Exceptional Exit | CloseReaderTest.java:8:14:8:28 | Exit | +| CloseReaderTest.java:8:14:8:28 | Entry | CloseReaderTest.java:8:14:8:28 | { ... } | | CloseReaderTest.java:8:14:8:28 | Normal Exit | CloseReaderTest.java:8:14:8:28 | Exit | | CloseReaderTest.java:8:14:8:28 | super(...) | CloseReaderTest.java:8:14:8:28 | Normal Exit | | CloseReaderTest.java:8:14:8:28 | { ... } | CloseReaderTest.java:8:14:8:28 | super(...) | +| CloseReaderTest.java:9:23:9:34 | Entry | CloseReaderTest.java:10:2:24:2 | { ... } | | CloseReaderTest.java:9:23:9:34 | Exceptional Exit | CloseReaderTest.java:9:23:9:34 | Exit | | CloseReaderTest.java:9:23:9:34 | Normal Exit | CloseReaderTest.java:9:23:9:34 | Exit | | CloseReaderTest.java:10:2:24:2 | { ... } | CloseReaderTest.java:12:3:13:42 | ; | @@ -27,6 +28,7 @@ | CloseReaderTest.java:19:11:19:15 | stdin | CloseReaderTest.java:19:11:19:26 | readLine(...) | | CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:19:4:19:27 | return ... | | CloseReaderTest.java:19:11:19:26 | readLine(...) | CloseReaderTest.java:20:5:20:26 | catch (...) | +| CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:9:23:9:34 | Exceptional Exit | | CloseReaderTest.java:20:5:20:26 | catch (...) | CloseReaderTest.java:20:24:20:25 | ex | | CloseReaderTest.java:20:24:20:25 | ex | CloseReaderTest.java:21:3:23:3 | { ... } | | CloseReaderTest.java:21:3:23:3 | { ... } | CloseReaderTest.java:22:11:22:14 | null | diff --git a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.ql b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.ql index 6fca436fbfdb..68c50a85c58a 100644 --- a/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.ql +++ b/java/ql/test/library-tests/successors/CloseReaderTest/TestSucc.ql @@ -1,8 +1,9 @@ import java +import utils.test.AstCfg from ControlFlowNode n, ControlFlowNode succ where - succ = n.getASuccessor() and + succ = getAnAstSuccessor(n) and n.getLocation().getFile().getExtension() = "java" and not n.getLocation().getFile().getStem() = "PopulateRuntimeException" select n, succ diff --git a/java/ql/test/library-tests/successors/LoopVarReadTest/FalseSuccessors.expected b/java/ql/test/library-tests/successors/LoopVarReadTest/FalseSuccessors.expected deleted file mode 100644 index 9d836931bede..000000000000 --- a/java/ql/test/library-tests/successors/LoopVarReadTest/FalseSuccessors.expected +++ /dev/null @@ -1 +0,0 @@ -| LoopVarReadTest.java:7:19:7:24 | ... < ... | LoopVarReadTest.java:12:3:12:13 | var ...; | diff --git a/java/ql/test/library-tests/successors/LoopVarReadTest/FalseSuccessors.ql b/java/ql/test/library-tests/successors/LoopVarReadTest/FalseSuccessors.ql deleted file mode 100644 index aee4021bee69..000000000000 --- a/java/ql/test/library-tests/successors/LoopVarReadTest/FalseSuccessors.ql +++ /dev/null @@ -1,4 +0,0 @@ -import java - -from ConditionNode c -select c, c.getAFalseSuccessor() diff --git a/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected b/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected index 3566cc8753f2..61b12a6f5d7e 100644 --- a/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected +++ b/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.expected @@ -1,8 +1,8 @@ -| LoopVarReadTest.java:3:14:3:28 | Exceptional Exit | LoopVarReadTest.java:3:14:3:28 | Exit | +| LoopVarReadTest.java:3:14:3:28 | Entry | LoopVarReadTest.java:3:14:3:28 | { ... } | | LoopVarReadTest.java:3:14:3:28 | Normal Exit | LoopVarReadTest.java:3:14:3:28 | Exit | | LoopVarReadTest.java:3:14:3:28 | super(...) | LoopVarReadTest.java:3:14:3:28 | Normal Exit | | LoopVarReadTest.java:3:14:3:28 | { ... } | LoopVarReadTest.java:3:14:3:28 | super(...) | -| LoopVarReadTest.java:4:21:4:28 | Exceptional Exit | LoopVarReadTest.java:4:21:4:28 | Exit | +| LoopVarReadTest.java:4:21:4:28 | Entry | LoopVarReadTest.java:5:2:15:2 | { ... } | | LoopVarReadTest.java:4:21:4:28 | Normal Exit | LoopVarReadTest.java:4:21:4:28 | Exit | | LoopVarReadTest.java:5:2:15:2 | { ... } | LoopVarReadTest.java:6:3:6:12 | var ...; | | LoopVarReadTest.java:6:3:6:12 | var ...; | LoopVarReadTest.java:6:11:6:11 | 2 | diff --git a/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.ql b/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.ql index 6fca436fbfdb..68c50a85c58a 100644 --- a/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.ql +++ b/java/ql/test/library-tests/successors/LoopVarReadTest/TestSucc.ql @@ -1,8 +1,9 @@ import java +import utils.test.AstCfg from ControlFlowNode n, ControlFlowNode succ where - succ = n.getASuccessor() and + succ = getAnAstSuccessor(n) and n.getLocation().getFile().getExtension() = "java" and not n.getLocation().getFile().getStem() = "PopulateRuntimeException" select n, succ diff --git a/java/ql/test/library-tests/successors/SaveFileTest/FalseSuccessors.expected b/java/ql/test/library-tests/successors/SaveFileTest/FalseSuccessors.expected deleted file mode 100644 index 8f3e2d0dd3e8..000000000000 --- a/java/ql/test/library-tests/successors/SaveFileTest/FalseSuccessors.expected +++ /dev/null @@ -1,2 +0,0 @@ -| SaveFileTest.java:18:7:18:26 | startsWith(...) | SaveFileTest.java:24:3:24:33 | var ...; | -| SaveFileTest.java:34:11:34:54 | ... != ... | SaveFileTest.java:39:4:40:41 | ; | diff --git a/java/ql/test/library-tests/successors/SaveFileTest/FalseSuccessors.ql b/java/ql/test/library-tests/successors/SaveFileTest/FalseSuccessors.ql deleted file mode 100644 index aee4021bee69..000000000000 --- a/java/ql/test/library-tests/successors/SaveFileTest/FalseSuccessors.ql +++ /dev/null @@ -1,4 +0,0 @@ -import java - -from ConditionNode c -select c, c.getAFalseSuccessor() diff --git a/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected b/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected index 640e731147f9..19943a7ab1a1 100644 --- a/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected +++ b/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.expected @@ -1,7 +1,8 @@ -| SaveFileTest.java:11:14:11:25 | Exceptional Exit | SaveFileTest.java:11:14:11:25 | Exit | +| SaveFileTest.java:11:14:11:25 | Entry | SaveFileTest.java:11:14:11:25 | { ... } | | SaveFileTest.java:11:14:11:25 | Normal Exit | SaveFileTest.java:11:14:11:25 | Exit | | SaveFileTest.java:11:14:11:25 | super(...) | SaveFileTest.java:11:14:11:25 | Normal Exit | | SaveFileTest.java:11:14:11:25 | { ... } | SaveFileTest.java:11:14:11:25 | super(...) | +| SaveFileTest.java:12:14:12:21 | Entry | SaveFileTest.java:15:2:55:2 | { ... } | | SaveFileTest.java:12:14:12:21 | Exceptional Exit | SaveFileTest.java:12:14:12:21 | Exit | | SaveFileTest.java:12:14:12:21 | Normal Exit | SaveFileTest.java:12:14:12:21 | Exit | | SaveFileTest.java:15:2:55:2 | { ... } | SaveFileTest.java:17:3:17:25 | var ...; | @@ -14,8 +15,9 @@ | SaveFileTest.java:18:7:18:26 | startsWith(...) | SaveFileTest.java:24:3:24:33 | var ...; | | SaveFileTest.java:18:23:18:25 | "/" | SaveFileTest.java:18:7:18:26 | startsWith(...) | | SaveFileTest.java:19:3:21:3 | { ... } | SaveFileTest.java:20:4:20:32 | ; | +| SaveFileTest.java:20:4:20:11 | savePath | SaveFileTest.java:20:15:20:18 | path | | SaveFileTest.java:20:4:20:31 | ...=... | SaveFileTest.java:24:3:24:33 | var ...; | -| SaveFileTest.java:20:4:20:32 | ; | SaveFileTest.java:20:15:20:18 | path | +| SaveFileTest.java:20:4:20:32 | ; | SaveFileTest.java:20:4:20:11 | savePath | | SaveFileTest.java:20:15:20:18 | path | SaveFileTest.java:20:30:20:30 | 1 | | SaveFileTest.java:20:15:20:31 | substring(...) | SaveFileTest.java:20:4:20:31 | ...=... | | SaveFileTest.java:20:30:20:30 | 1 | SaveFileTest.java:20:15:20:31 | substring(...) | @@ -44,20 +46,20 @@ | SaveFileTest.java:30:22:30:25 | null | SaveFileTest.java:30:16:30:25 | bos | | SaveFileTest.java:31:3:53:3 | try ... | SaveFileTest.java:32:3:41:3 | { ... } | | SaveFileTest.java:32:3:41:3 | { ... } | SaveFileTest.java:33:4:33:40 | ; | +| SaveFileTest.java:33:4:33:6 | bos | SaveFileTest.java:33:31:33:38 | saveFile | | SaveFileTest.java:33:4:33:39 | ...=... | SaveFileTest.java:34:4:34:55 | while (...) | -| SaveFileTest.java:33:4:33:40 | ; | SaveFileTest.java:33:31:33:38 | saveFile | +| SaveFileTest.java:33:4:33:40 | ; | SaveFileTest.java:33:4:33:6 | bos | | SaveFileTest.java:33:10:33:39 | new FileOutputStream(...) | SaveFileTest.java:33:4:33:39 | ...=... | | SaveFileTest.java:33:10:33:39 | new FileOutputStream(...) | SaveFileTest.java:41:5:41:23 | catch (...) | -| SaveFileTest.java:33:10:33:39 | new FileOutputStream(...) | SaveFileTest.java:45:3:53:3 | { ... } | | SaveFileTest.java:33:31:33:38 | saveFile | SaveFileTest.java:33:10:33:39 | new FileOutputStream(...) | -| SaveFileTest.java:34:4:34:55 | while (...) | SaveFileTest.java:34:24:34:25 | is | +| SaveFileTest.java:34:4:34:55 | while (...) | SaveFileTest.java:34:12:34:20 | bytesRead | | SaveFileTest.java:34:11:34:54 | ... != ... | SaveFileTest.java:35:4:37:4 | { ... } | | SaveFileTest.java:34:11:34:54 | ... != ... | SaveFileTest.java:39:4:40:41 | ; | +| SaveFileTest.java:34:12:34:20 | bytesRead | SaveFileTest.java:34:24:34:25 | is | | SaveFileTest.java:34:12:34:47 | ...=... | SaveFileTest.java:34:54:34:54 | 1 | | SaveFileTest.java:34:24:34:25 | is | SaveFileTest.java:34:32:34:37 | buffer | | SaveFileTest.java:34:24:34:47 | read(...) | SaveFileTest.java:34:12:34:47 | ...=... | | SaveFileTest.java:34:24:34:47 | read(...) | SaveFileTest.java:41:5:41:23 | catch (...) | -| SaveFileTest.java:34:24:34:47 | read(...) | SaveFileTest.java:45:3:53:3 | { ... } | | SaveFileTest.java:34:32:34:37 | buffer | SaveFileTest.java:34:40:34:40 | 0 | | SaveFileTest.java:34:40:34:40 | 0 | SaveFileTest.java:34:43:34:46 | 8192 | | SaveFileTest.java:34:43:34:46 | 8192 | SaveFileTest.java:34:24:34:47 | read(...) | @@ -65,9 +67,8 @@ | SaveFileTest.java:34:54:34:54 | 1 | SaveFileTest.java:34:53:34:54 | -... | | SaveFileTest.java:35:4:37:4 | { ... } | SaveFileTest.java:36:5:36:36 | ; | | SaveFileTest.java:36:5:36:7 | bos | SaveFileTest.java:36:15:36:20 | buffer | -| SaveFileTest.java:36:5:36:35 | write(...) | SaveFileTest.java:34:24:34:25 | is | +| SaveFileTest.java:36:5:36:35 | write(...) | SaveFileTest.java:34:12:34:20 | bytesRead | | SaveFileTest.java:36:5:36:35 | write(...) | SaveFileTest.java:41:5:41:23 | catch (...) | -| SaveFileTest.java:36:5:36:35 | write(...) | SaveFileTest.java:45:3:53:3 | { ... } | | SaveFileTest.java:36:5:36:36 | ; | SaveFileTest.java:36:5:36:7 | bos | | SaveFileTest.java:36:15:36:20 | buffer | SaveFileTest.java:36:23:36:23 | 0 | | SaveFileTest.java:36:23:36:23 | 0 | SaveFileTest.java:36:26:36:34 | bytesRead | @@ -82,7 +83,6 @@ | SaveFileTest.java:40:8:40:15 | saveFile | SaveFileTest.java:40:8:40:33 | getAbsolutePath(...) | | SaveFileTest.java:40:8:40:33 | getAbsolutePath(...) | SaveFileTest.java:39:23:40:33 | ... + ... | | SaveFileTest.java:40:8:40:33 | getAbsolutePath(...) | SaveFileTest.java:41:5:41:23 | catch (...) | -| SaveFileTest.java:40:8:40:33 | getAbsolutePath(...) | SaveFileTest.java:45:3:53:3 | { ... } | | SaveFileTest.java:40:37:40:39 | "]" | SaveFileTest.java:39:23:40:39 | ... + ... | | SaveFileTest.java:41:5:41:23 | catch (...) | SaveFileTest.java:41:22:41:22 | e | | SaveFileTest.java:41:22:41:22 | e | SaveFileTest.java:42:3:44:3 | { ... } | diff --git a/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.ql b/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.ql index 6fca436fbfdb..68c50a85c58a 100644 --- a/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.ql +++ b/java/ql/test/library-tests/successors/SaveFileTest/TestSucc.ql @@ -1,8 +1,9 @@ import java +import utils.test.AstCfg from ControlFlowNode n, ControlFlowNode succ where - succ = n.getASuccessor() and + succ = getAnAstSuccessor(n) and n.getLocation().getFile().getExtension() = "java" and not n.getLocation().getFile().getStem() = "PopulateRuntimeException" select n, succ diff --git a/java/ql/test/library-tests/successors/SchackTest/FalseSuccessors.expected b/java/ql/test/library-tests/successors/SchackTest/FalseSuccessors.expected deleted file mode 100644 index 3f3f897cda80..000000000000 --- a/java/ql/test/library-tests/successors/SchackTest/FalseSuccessors.expected +++ /dev/null @@ -1,6 +0,0 @@ -| SchackTest.java:8:9:8:12 | ... == ... | SchackTest.java:10:5:10:13 | if (...) | -| SchackTest.java:10:9:10:12 | ... == ... | SchackTest.java:12:14:15:4 | { ... } | -| SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:16:4:16:41 | ; | -| SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:17:5:17:17 | catch (...) | -| SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:21:13:23:3 | { ... } | -| SchackTest.java:27:7:27:24 | ... > ... | SchackTest.java:29:10:29:22 | random(...) | diff --git a/java/ql/test/library-tests/successors/SchackTest/FalseSuccessors.ql b/java/ql/test/library-tests/successors/SchackTest/FalseSuccessors.ql deleted file mode 100644 index aee4021bee69..000000000000 --- a/java/ql/test/library-tests/successors/SchackTest/FalseSuccessors.ql +++ /dev/null @@ -1,4 +0,0 @@ -import java - -from ConditionNode c -select c, c.getAFalseSuccessor() diff --git a/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected b/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected index a23f6a2bc54e..19fef193edba 100644 --- a/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected +++ b/java/ql/test/library-tests/successors/SchackTest/TestSucc.expected @@ -1,15 +1,16 @@ -| SchackTest.java:1:14:1:23 | Exceptional Exit | SchackTest.java:1:14:1:23 | Exit | +| SchackTest.java:1:14:1:23 | Entry | SchackTest.java:1:14:1:23 | { ... } | | SchackTest.java:1:14:1:23 | Normal Exit | SchackTest.java:1:14:1:23 | Exit | | SchackTest.java:1:14:1:23 | super(...) | SchackTest.java:1:14:1:23 | Normal Exit | | SchackTest.java:1:14:1:23 | { ... } | SchackTest.java:1:14:1:23 | super(...) | -| SchackTest.java:2:8:2:10 | Exceptional Exit | SchackTest.java:2:8:2:10 | Exit | +| SchackTest.java:2:8:2:10 | Entry | SchackTest.java:2:8:2:10 | { ... } | | SchackTest.java:2:8:2:10 | Normal Exit | SchackTest.java:2:8:2:10 | Exit | | SchackTest.java:2:8:2:10 | super(...) | SchackTest.java:2:8:2:10 | Normal Exit | | SchackTest.java:2:8:2:10 | { ... } | SchackTest.java:2:8:2:10 | super(...) | -| SchackTest.java:3:8:3:10 | Exceptional Exit | SchackTest.java:3:8:3:10 | Exit | +| SchackTest.java:3:8:3:10 | Entry | SchackTest.java:3:8:3:10 | { ... } | | SchackTest.java:3:8:3:10 | Normal Exit | SchackTest.java:3:8:3:10 | Exit | | SchackTest.java:3:8:3:10 | super(...) | SchackTest.java:3:8:3:10 | Normal Exit | | SchackTest.java:3:8:3:10 | { ... } | SchackTest.java:3:8:3:10 | super(...) | +| SchackTest.java:5:7:5:9 | Entry | SchackTest.java:5:18:24:2 | { ... } | | SchackTest.java:5:7:5:9 | Exceptional Exit | SchackTest.java:5:7:5:9 | Exit | | SchackTest.java:5:7:5:9 | Normal Exit | SchackTest.java:5:7:5:9 | Exit | | SchackTest.java:5:18:24:2 | { ... } | SchackTest.java:6:3:23:3 | try ... | @@ -36,7 +37,6 @@ | SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:14:6:14:42 | ; | | SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:16:4:16:41 | ; | | SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:17:5:17:17 | catch (...) | -| SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:19:5:19:17 | catch (...) | | SchackTest.java:13:9:13:13 | bar(...) | SchackTest.java:21:13:23:3 | { ... } | | SchackTest.java:14:6:14:15 | System.out | SchackTest.java:14:25:14:40 | "true successor" | | SchackTest.java:14:6:14:41 | println(...) | SchackTest.java:16:4:16:41 | ; | @@ -45,10 +45,12 @@ | SchackTest.java:14:6:14:42 | ; | SchackTest.java:14:6:14:15 | System.out | | SchackTest.java:14:25:14:40 | "true successor" | SchackTest.java:14:6:14:41 | println(...) | | SchackTest.java:16:4:16:13 | System.out | SchackTest.java:16:23:16:39 | "false successor" | +| SchackTest.java:16:4:16:40 | println(...) | SchackTest.java:17:5:17:17 | catch (...) | | SchackTest.java:16:4:16:40 | println(...) | SchackTest.java:21:13:23:3 | { ... } | | SchackTest.java:16:4:16:41 | ; | SchackTest.java:16:4:16:13 | System.out | | SchackTest.java:16:23:16:39 | "false successor" | SchackTest.java:16:4:16:40 | println(...) | | SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:17:16:17:16 | e | +| SchackTest.java:17:5:17:17 | catch (...) | SchackTest.java:19:5:19:17 | catch (...) | | SchackTest.java:17:16:17:16 | e | SchackTest.java:17:19:19:3 | { ... } | | SchackTest.java:17:19:19:3 | { ... } | SchackTest.java:18:4:18:41 | ; | | SchackTest.java:18:4:18:13 | System.out | SchackTest.java:18:23:18:39 | "false successor" | @@ -56,6 +58,7 @@ | SchackTest.java:18:4:18:41 | ; | SchackTest.java:18:4:18:13 | System.out | | SchackTest.java:18:23:18:39 | "false successor" | SchackTest.java:18:4:18:40 | println(...) | | SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:19:16:19:16 | e | +| SchackTest.java:19:5:19:17 | catch (...) | SchackTest.java:21:13:23:3 | { ... } | | SchackTest.java:19:16:19:16 | e | SchackTest.java:19:19:21:3 | { ... } | | SchackTest.java:19:19:21:3 | { ... } | SchackTest.java:20:4:20:74 | ; | | SchackTest.java:20:4:20:13 | System.out | SchackTest.java:20:23:20:72 | "successor (but neither true nor false successor)" | @@ -68,6 +71,7 @@ | SchackTest.java:22:4:22:40 | println(...) | SchackTest.java:5:7:5:9 | Normal Exit | | SchackTest.java:22:4:22:41 | ; | SchackTest.java:22:4:22:13 | System.out | | SchackTest.java:22:23:22:39 | "false successor" | SchackTest.java:22:4:22:40 | println(...) | +| SchackTest.java:26:18:26:20 | Entry | SchackTest.java:26:35:30:2 | { ... } | | SchackTest.java:26:18:26:20 | Exceptional Exit | SchackTest.java:26:18:26:20 | Exit | | SchackTest.java:26:18:26:20 | Normal Exit | SchackTest.java:26:18:26:20 | Exit | | SchackTest.java:26:35:30:2 | { ... } | SchackTest.java:27:3:27:25 | if (...) | diff --git a/java/ql/test/library-tests/successors/SchackTest/TestSucc.ql b/java/ql/test/library-tests/successors/SchackTest/TestSucc.ql index 6fca436fbfdb..68c50a85c58a 100644 --- a/java/ql/test/library-tests/successors/SchackTest/TestSucc.ql +++ b/java/ql/test/library-tests/successors/SchackTest/TestSucc.ql @@ -1,8 +1,9 @@ import java +import utils.test.AstCfg from ControlFlowNode n, ControlFlowNode succ where - succ = n.getASuccessor() and + succ = getAnAstSuccessor(n) and n.getLocation().getFile().getExtension() = "java" and not n.getLocation().getFile().getStem() = "PopulateRuntimeException" select n, succ diff --git a/java/ql/test/library-tests/successors/TestBreak/FalseSuccessors.expected b/java/ql/test/library-tests/successors/TestBreak/FalseSuccessors.expected deleted file mode 100644 index 6d5fbfbded61..000000000000 --- a/java/ql/test/library-tests/successors/TestBreak/FalseSuccessors.expected +++ /dev/null @@ -1,5 +0,0 @@ -| TestBreak.java:12:9:12:14 | ... == ... | TestBreak.java:16:5:27:5 | { ... } | -| TestBreak.java:19:11:19:16 | ... == ... | TestBreak.java:23:7:25:7 | { ... } | -| TestBreak.java:32:8:32:13 | ... == ... | TestBreak.java:36:4:46:4 | { ... } | -| TestBreak.java:39:10:39:15 | ... == ... | TestBreak.java:43:6:43:15 | ; | -| TestBreak.java:44:14:44:19 | ... == ... | TestBreak.java:45:5:45:11 | ; | diff --git a/java/ql/test/library-tests/successors/TestBreak/FalseSuccessors.ql b/java/ql/test/library-tests/successors/TestBreak/FalseSuccessors.ql deleted file mode 100644 index aee4021bee69..000000000000 --- a/java/ql/test/library-tests/successors/TestBreak/FalseSuccessors.ql +++ /dev/null @@ -1,4 +0,0 @@ -import java - -from ConditionNode c -select c, c.getAFalseSuccessor() diff --git a/java/ql/test/library-tests/successors/TestBreak/TestSucc.expected b/java/ql/test/library-tests/successors/TestBreak/TestSucc.expected index 3fc266a0928c..ad033101fd6f 100644 --- a/java/ql/test/library-tests/successors/TestBreak/TestSucc.expected +++ b/java/ql/test/library-tests/successors/TestBreak/TestSucc.expected @@ -1,8 +1,8 @@ -| TestBreak.java:3:14:3:22 | Exceptional Exit | TestBreak.java:3:14:3:22 | Exit | +| TestBreak.java:3:14:3:22 | Entry | TestBreak.java:3:14:3:22 | { ... } | | TestBreak.java:3:14:3:22 | Normal Exit | TestBreak.java:3:14:3:22 | Exit | | TestBreak.java:3:14:3:22 | super(...) | TestBreak.java:3:14:3:22 | Normal Exit | | TestBreak.java:3:14:3:22 | { ... } | TestBreak.java:3:14:3:22 | super(...) | -| TestBreak.java:4:14:4:14 | Exceptional Exit | TestBreak.java:4:14:4:14 | Exit | +| TestBreak.java:4:14:4:14 | Entry | TestBreak.java:5:2:85:2 | { ... } | | TestBreak.java:4:14:4:14 | Normal Exit | TestBreak.java:4:14:4:14 | Exit | | TestBreak.java:5:2:85:2 | { ... } | TestBreak.java:7:3:8:11 |