diff --git a/.github/workflows/compile-queries.yml b/.github/workflows/compile-queries.yml index 38452f97d36b..dfd99f6b806a 100644 --- a/.github/workflows/compile-queries.yml +++ b/.github/workflows/compile-queries.yml @@ -33,9 +33,9 @@ jobs: # run with --check-only if running in a PR (github.sha != main) if : ${{ github.event_name == 'pull_request' }} shell: bash - run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 + run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 --ram=56000 - name: compile queries - full # do full compile if running on main - this populates the cache if : ${{ github.event_name != 'pull_request' }} shell: bash - run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 + run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 --ram=56000 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 68df2f6f498b..5d9a735d379f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -38,6 +38,93 @@ "command": "${config:python.pythonPath}", }, "problemMatcher": [] + }, + { + "label": "Create query change note", + "type": "process", + "command": "python3", + "args": [ + "misc/scripts/create-change-note.py", + "${input:language}", + "src", + "${input:name}", + "${input:categoryQuery}" + ], + "presentation": { + "reveal": "never", + "close": true + }, + "problemMatcher": [] + }, + { + "label": "Create library change note", + "type": "process", + "command": "python3", + "args": [ + "misc/scripts/create-change-note.py", + "${input:language}", + "lib", + "${input:name}", + "${input:categoryLibrary}" + ], + "presentation": { + "reveal": "never", + "close": true + }, + "problemMatcher": [] + } + ], + "inputs": [ + { + "type": "pickString", + "id": "language", + "description": "Language", + "options": + [ + "go", + "java", + "javascript", + "cpp", + "csharp", + "python", + "ruby", + "rust", + "swift", + ] + }, + { + "type": "promptString", + "id": "name", + "description": "Short name (kebab-case)" + }, + { + "type": "pickString", + "id": "categoryQuery", + "description": "Category (query change)", + "options": + [ + "breaking", + "deprecated", + "newQuery", + "queryMetadata", + "majorAnalysis", + "minorAnalysis", + "fix", + ] + }, + { + "type": "pickString", + "id": "categoryLibrary", + "description": "Category (library change)", + "options": + [ + "breaking", + "deprecated", + "feature", + "majorAnalysis", + "minorAnalysis", + "fix", + ] } ] } diff --git a/2024-11-25-ts57.md b/2024-11-25-ts57.md new file mode 100644 index 000000000000..3a92872d6d60 --- /dev/null +++ b/2024-11-25-ts57.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* Added support for TypeScript 5.7. diff --git a/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/old.dbscheme b/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/old.dbscheme new file mode 100644 index 000000000000..f0156f5f88ab --- /dev/null +++ b/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/old.dbscheme @@ -0,0 +1,2339 @@ + +/** + * 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 +); + +/** + * 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, 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 +); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * 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( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * 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_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * 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_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: 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_default 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 +); + +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 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 + 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +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 +); + +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_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable 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 +); + +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 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _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 +; + +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 +; + +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 +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this 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. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* +case @usertype.kind of + 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +| 5 = @typedef // classic C: typedef typedef type name +| 6 = @template +| 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 // a using name = type style typedef +; +*/ + +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 +); + +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 +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location 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 +); + +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 +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +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; + +@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; + +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_expr 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_expr 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 +; + +@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 + ; + +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 +); + +/** + * 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 +); + +/** + * 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 +); + +@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 +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof; + +sizeof_bind( + unique int expr: @runtime_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 +); + +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_stmt 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 +; + +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 +); + +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 +); + +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; + +@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 +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +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 +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target 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/f0156f5f88ab5967c79162012c20f30600ca5ebf/semmlecode.cpp.dbscheme b/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/semmlecode.cpp.dbscheme new file mode 100644 index 000000000000..e51fad7a2436 --- /dev/null +++ b/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/semmlecode.cpp.dbscheme @@ -0,0 +1,2323 @@ + +/** + * 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 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, 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 +); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * 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( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * 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_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * 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_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: 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_default 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 +); + +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 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 + 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +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 +); + +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_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable 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 +); + +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 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _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 +; + +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 +; + +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 +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this 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. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* +case @usertype.kind of + 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +| 5 = @typedef // classic C: typedef typedef type name +| 6 = @template +| 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 // a using name = type style typedef +; +*/ + +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 +); + +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 +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location 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 +); + +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 +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +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; + +@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; + +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_expr 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_expr 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 +; + +@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 + ; + +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 +); + +/** + * 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 +); + +/** + * 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 +); + +@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 +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof; + +sizeof_bind( + unique int expr: @runtime_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 +); + +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_stmt 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 +; + +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 +); + +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 +); + +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; + +@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 +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +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 +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target 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/f0156f5f88ab5967c79162012c20f30600ca5ebf/upgrade.properties b/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/upgrade.properties new file mode 100644 index 000000000000..cf362f384dae --- /dev/null +++ b/cpp/downgrades/f0156f5f88ab5967c79162012c20f30600ca5ebf/upgrade.properties @@ -0,0 +1,3 @@ +description: Implement compilation_build_mode/2 +compatibility: full +compilation_build_mode.rel: delete diff --git a/cpp/ql/lib/semmle/code/cpp/Compilation.qll b/cpp/ql/lib/semmle/code/cpp/Compilation.qll index 1a8d90f991c1..407dc31e05f1 100644 --- a/cpp/ql/lib/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/lib/semmle/code/cpp/Compilation.qll @@ -112,4 +112,7 @@ class Compilation extends @compilation { * termination, but crashing due to something like a segfault is not. */ predicate normalTermination() { compilation_finished(this, _, _) } + + /** Holds if this compilation was compiled using the "none" build mode. */ + predicate buildModeNone() { compilation_build_mode(this, 0) } } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll index 07cb26708588..49610b7c85b6 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll @@ -793,28 +793,27 @@ private Element interpretElement0( ) { ( // Non-member functions - elementSpec(namespace, type, subtypes, name, signature, _) and + funcHasQualifiedName(result, namespace, name) and subtypes = false and type = "" and ( elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature) or signature = "" and - elementSpec(namespace, type, subtypes, name, "", _) and - funcHasQualifiedName(result, namespace, name) + elementSpec(namespace, type, subtypes, name, signature, _) ) or // Member functions exists(Class namedClass, Class classWithMethod | + hasClassAndName(classWithMethod, result, name) and + classHasQualifiedName(namedClass, namespace, type) + | ( - elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature) and - hasClassAndName(classWithMethod, result, name) + elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature) or signature = "" and - elementSpec(namespace, type, subtypes, name, "", _) and - hasClassAndName(classWithMethod, result, name) + elementSpec(namespace, type, subtypes, name, "", _) ) and - classHasQualifiedName(namedClass, namespace, type) and ( // member declared in the named type or a subtype of it subtypes = true and diff --git a/cpp/ql/lib/semmle/code/cpp/models/Models.qll b/cpp/ql/lib/semmle/code/cpp/models/Models.qll index 1e0b6cd33ed2..f6776a623ffe 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/Models.qll @@ -49,3 +49,4 @@ private import implementations.PostgreSql private import implementations.System private import implementations.StructuredExceptionHandling private import implementations.ZMQ +private import implementations.Win32CommandExecution diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Win32CommandExecution.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Win32CommandExecution.qll new file mode 100644 index 000000000000..13d7ffae8075 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Win32CommandExecution.qll @@ -0,0 +1,56 @@ +private import semmle.code.cpp.models.interfaces.CommandExecution + +/** The `ShellExecute` family of functions from Win32. */ +class ShellExecute extends Function { + ShellExecute() { this.hasGlobalName("ShellExecute" + ["", "A", "W"]) } +} + +private class ShellExecuteModel extends ShellExecute, CommandExecutionFunction { + override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(2) } +} + +/** The `WinExec` function from Win32. */ +class WinExec extends Function { + WinExec() { this.hasGlobalName("WinExec") } +} + +private class WinExecModel extends WinExec, CommandExecutionFunction { + override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(0) } +} + +/** The `CreateProcess` family of functions from Win32. */ +class CreateProcess extends Function { + CreateProcess() { this.hasGlobalName("CreateProcess" + ["", "A", "W"]) } +} + +private class CreateProcessModel extends CreateProcess, CommandExecutionFunction { + override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(0) } +} + +/** The `CreateProcessAsUser` family of functions from Win32. */ +class CreateProcessAsUser extends Function { + CreateProcessAsUser() { this.hasGlobalName("CreateProcessAsUser" + ["", "A", "W"]) } +} + +private class CreateProcessAsUserModel extends CreateProcessAsUser, CommandExecutionFunction { + override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(1) } +} + +/** The `CreateProcessWithLogonW` function from Win32. */ +class CreateProcessWithLogonW extends Function { + CreateProcessWithLogonW() { this.hasGlobalName("CreateProcessWithLogonW") } +} + +private class CreateProcessWithLogonModel extends CreateProcessWithLogonW, CommandExecutionFunction { + override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(4) } +} + +/** The `CreateProcessWithTokenW` function from Win32. */ +class CreateProcessWithTokenW extends Function { + CreateProcessWithTokenW() { this.hasGlobalName("CreateProcessWithTokenW") } +} + +private class CreateProcessWithTokenWModel extends CreateProcessWithTokenW, CommandExecutionFunction +{ + override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(2) } +} diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme b/cpp/ql/lib/semmlecode.cpp.dbscheme index e51fad7a2436..f0156f5f88ab 100644 --- a/cpp/ql/lib/semmlecode.cpp.dbscheme +++ b/cpp/ql/lib/semmlecode.cpp.dbscheme @@ -46,6 +46,22 @@ compilation_args( 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 diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats index 7f0d99272e7e..758aba346080 100644 --- a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats @@ -18,7 +18,7 @@ @location_default - 29764890 + 29746763 @location_stmt @@ -34,11 +34,11 @@ @file - 123251 + 123176 @folder - 16340 + 16330 @macro_expansion @@ -46,23 +46,23 @@ @other_macro_reference - 859029 + 858505 @function - 4179363 + 4176817 @fun_decl - 4543516 + 4541216 @var_decl - 8039391 + 8034962 @type_decl - 3283451 + 3281452 @namespace_decl @@ -70,11 +70,11 @@ @using_declaration - 363219 + 362998 @using_directive - 6536 + 6532 @using_enum_declaration @@ -86,7 +86,7 @@ @parameter - 6190611 + 6186841 @membervariable @@ -98,7 +98,7 @@ @localvariable - 576945 + 576952 @enumconstant @@ -330,15 +330,15 @@ @pointer - 568173 + 567827 @type_with_specifiers - 852026 + 851507 @array - 110179 + 110112 @routineptr @@ -346,7 +346,7 @@ @reference - 1276405 + 1275627 @gnu_vector @@ -358,7 +358,7 @@ @rvalue_reference - 333340 + 333137 @block @@ -366,15 +366,15 @@ @decltype - 27078 + 27061 @usertype - 5234008 + 5230820 @mangledname - 6061757 + 6058065 @type_mention @@ -386,15 +386,15 @@ @ptrtomember - 37815 + 37792 @specifier - 24743 + 24728 @gnuattribute - 553700 + 553363 @stdattribute @@ -410,15 +410,15 @@ @alignas - 4668 + 4665 @attribute_arg_token - 25210 + 25195 @attribute_arg_constant_expr - 318400 + 318207 @attribute_arg_empty @@ -450,7 +450,7 @@ @namespace - 12138 + 12131 @specialnamequalifyingelement @@ -482,7 +482,7 @@ @parexpr - 3587463 + 3587464 @arithnegexpr @@ -582,11 +582,11 @@ @gtexpr - 104110 + 104047 @ltexpr - 101776 + 101714 @geexpr @@ -634,7 +634,7 @@ @assignorexpr - 23627 + 23628 @assignxorexpr @@ -662,11 +662,11 @@ @subscriptexpr - 364477 + 364481 @callexpr - 316533 + 316340 @vastartexpr @@ -678,7 +678,7 @@ @vaendexpr - 2801 + 2799 @vacopyexpr @@ -830,7 +830,7 @@ @sizeof_pack - 5602 + 5598 @hasassignexpr @@ -978,7 +978,7 @@ @lambdaexpr - 21475 + 21462 @param_ref @@ -1022,7 +1022,7 @@ @istriviallycopyableexpr - 3734 + 3732 @isliteraltypeexpr @@ -1374,7 +1374,7 @@ @lambdacapture - 28011 + 27994 @stmt_expr @@ -1398,11 +1398,11 @@ @stmt_return - 1280140 + 1279827 @stmt_block - 1419265 + 1418867 @stmt_end_test_while @@ -1430,7 +1430,7 @@ @stmt_empty - 192682 + 192685 @stmt_continue @@ -1462,7 +1462,7 @@ @stmt_range_based_for - 8403 + 8398 @stmt_handler @@ -1478,31 +1478,31 @@ @ppd_if - 667148 + 666741 @ppd_ifdef - 263311 + 263150 @ppd_ifndef - 266579 + 266416 @ppd_elif - 25210 + 25195 @ppd_else - 209154 + 209027 @ppd_endif - 1197038 + 1196309 @ppd_plain_include - 311398 + 311208 @ppd_define @@ -1510,15 +1510,15 @@ @ppd_undef - 258642 + 258484 @ppd_include_next - 1867 + 1866 @ppd_line - 27520 + 27521 @ppd_error @@ -1900,6 +1900,54 @@ + + compilation_build_mode + 9742 + + + id + 9742 + + + mode + 11 + + + + + id + mode + + + 12 + + + 1 + 2 + 9742 + + + + + + + mode + id + + + 12 + + + 863 + 864 + 11 + + + + + + + compilation_compiling_files 11546 @@ -2164,7 +2212,7 @@ seconds - 8429 + 8030 @@ -2245,47 +2293,52 @@ 3 4 - 639 + 799 4 5 - 359 + 199 - 6 + 5 7 119 8 - 10 - 159 + 9 + 79 - 10 - 11 + 9 + 10 119 - 11 - 15 + 10 + 12 159 - 16 - 19 + 12 + 16 + 119 + + + 17 + 20 159 - 19 - 24 + 21 + 42 159 - 40 - 89 - 119 + 55 + 90 + 79 @@ -2368,7 +2421,7 @@ 6 7 - 439 + 399 7 @@ -2377,18 +2430,18 @@ 8 - 10 - 279 + 9 + 239 - 10 - 26 + 9 + 24 279 - 28 - 81 - 199 + 25 + 85 + 279 @@ -2439,8 +2492,8 @@ 79 - 125 - 126 + 124 + 125 39 @@ -2462,27 +2515,37 @@ 1 2 - 3635 + 3755 2 3 - 1917 + 1398 3 4 - 1558 + 998 4 + 5 + 759 + + + 5 6 - 719 + 439 6 - 48 - 599 + 25 + 639 + + + 46 + 47 + 39 @@ -2498,27 +2561,27 @@ 1 2 - 3595 + 3515 2 3 - 1438 + 1278 3 4 - 1358 + 599 4 5 - 639 + 878 5 6 - 479 + 759 6 @@ -2527,8 +2590,8 @@ 8 - 73 - 239 + 76 + 319 @@ -2544,12 +2607,12 @@ 1 2 - 6512 + 5753 2 3 - 1917 + 2277 @@ -2893,7 +2956,7 @@ cpu_seconds - 7507 + 7292 elapsed_seconds @@ -2943,17 +3006,17 @@ 1 2 - 6242 + 5937 2 3 - 835 + 846 3 - 15 - 428 + 16 + 507 @@ -2969,12 +3032,12 @@ 1 2 - 6976 + 6682 2 3 - 530 + 609 @@ -3003,48 +3066,48 @@ 11 - 6 - 7 + 7 + 8 11 - 9 - 10 + 8 + 9 11 - 11 - 12 + 12 + 13 11 - 16 - 17 + 13 + 14 11 - 49 - 50 + 51 + 52 11 - 154 - 155 + 163 + 164 11 - 160 - 161 + 167 + 168 11 - 204 - 205 + 187 + 188 11 - 248 - 249 + 249 + 250 11 @@ -3074,48 +3137,48 @@ 11 - 6 - 7 + 7 + 8 11 - 9 - 10 + 8 + 9 11 - 11 - 12 + 12 + 13 11 - 16 - 17 + 13 + 14 11 - 47 - 48 + 49 + 50 11 - 118 - 119 + 120 + 121 11 - 128 - 129 + 123 + 124 11 - 149 - 150 + 138 + 139 11 - 222 - 223 + 224 + 225 11 @@ -4888,31 +4951,31 @@ locations_default - 29764890 + 29746763 id - 29764890 + 29746763 container - 123251 + 123176 startLine - 2095283 + 2094007 startColumn - 36882 + 36859 endLine - 2099485 + 2098207 endColumn - 48086 + 48057 @@ -4926,7 +4989,7 @@ 1 2 - 29764890 + 29746763 @@ -4942,7 +5005,7 @@ 1 2 - 29764890 + 29746763 @@ -4958,7 +5021,7 @@ 1 2 - 29764890 + 29746763 @@ -4974,7 +5037,7 @@ 1 2 - 29764890 + 29746763 @@ -4990,7 +5053,7 @@ 1 2 - 29764890 + 29746763 @@ -5006,67 +5069,67 @@ 1 11 - 9804 + 9798 11 18 - 10270 + 10264 18 30 - 9337 + 9331 30 42 - 9804 + 9798 43 61 - 9804 + 9798 61 79 - 9337 + 9331 80 106 - 9804 + 9798 108 149 - 9337 + 9331 149 199 - 9337 + 9331 206 291 - 9337 + 9331 304 469 - 9337 + 9331 482 850 - 9337 + 9331 936 2380 - 8403 + 8398 @@ -5082,67 +5145,67 @@ 1 8 - 9337 + 9331 8 13 - 9337 + 9331 13 20 - 9804 + 9798 20 32 - 9337 + 9331 32 43 - 9804 + 9798 44 61 - 9337 + 9331 62 72 - 9337 + 9331 73 93 - 9337 + 9331 97 128 - 9337 + 9331 128 180 - 9337 + 9331 180 267 - 9337 + 9331 277 414 - 9337 + 9331 439 1465 - 9337 + 9331 1557 @@ -5163,67 +5226,67 @@ 1 4 - 8870 + 8865 4 5 - 7936 + 7931 5 6 - 7469 + 7465 6 8 - 11204 + 11197 8 10 - 9337 + 9331 10 15 - 10737 + 10731 15 23 - 9804 + 9798 23 28 - 11204 + 11197 28 34 - 9804 + 9798 34 44 - 9337 + 9331 44 55 - 9337 + 9331 55 66 - 9804 + 9798 66 77 - 8403 + 8398 @@ -5239,67 +5302,67 @@ 1 8 - 9337 + 9331 8 13 - 9337 + 9331 13 20 - 9804 + 9798 20 32 - 9337 + 9331 32 43 - 9804 + 9798 43 60 - 9337 + 9331 61 71 - 9337 + 9331 72 93 - 9337 + 9331 94 127 - 9337 + 9331 128 179 - 9337 + 9331 180 268 - 9337 + 9331 278 413 - 9337 + 9331 437 1465 - 9337 + 9331 1554 @@ -5320,67 +5383,67 @@ 1 9 - 9804 + 9798 9 13 - 9337 + 9331 13 18 - 9337 + 9331 18 26 - 10270 + 10264 27 33 - 9337 + 9331 33 39 - 9337 + 9331 39 47 - 10270 + 10264 47 53 - 9337 + 9331 53 60 - 10270 + 10264 60 66 - 9337 + 9331 66 74 - 9804 + 9798 74 78 - 9804 + 9798 78 90 - 7002 + 6998 @@ -5396,52 +5459,52 @@ 1 2 - 583112 + 582757 2 3 - 314199 + 314007 3 4 - 195615 + 195496 4 6 - 162001 + 161903 6 10 - 183010 + 182899 10 16 - 162935 + 162836 16 25 - 169004 + 168901 25 46 - 161067 + 160969 46 169 - 157333 + 157237 169 265 - 7002 + 6998 @@ -5457,42 +5520,42 @@ 1 2 - 871167 + 870636 2 3 - 273582 + 273415 3 5 - 193748 + 193630 5 8 - 173673 + 173567 8 13 - 188146 + 188031 13 20 - 161067 + 160969 20 51 - 159667 + 159570 51 265 - 74231 + 74186 @@ -5508,47 +5571,47 @@ 1 2 - 612058 + 611685 2 3 - 313265 + 313074 3 4 - 198417 + 198296 4 6 - 183010 + 182899 6 9 - 173206 + 173100 9 13 - 163402 + 163302 13 19 - 174606 + 174500 19 29 - 164802 + 164702 29 52 - 112514 + 112445 @@ -5564,22 +5627,22 @@ 1 2 - 1531779 + 1530846 2 3 - 348747 + 348534 3 5 - 162001 + 161903 5 16 - 52755 + 52723 @@ -5595,47 +5658,47 @@ 1 2 - 587781 + 587423 2 3 - 316066 + 315874 3 4 - 197483 + 197363 4 6 - 168537 + 168435 6 9 - 158266 + 158170 9 14 - 170872 + 170768 14 21 - 175073 + 174967 21 32 - 162468 + 162369 32 63 - 157799 + 157703 64 @@ -5656,67 +5719,67 @@ 1 31 - 2801 + 2799 42 85 - 2801 + 2799 86 128 - 2801 + 2799 129 229 - 2801 + 2799 247 286 - 2801 + 2799 291 360 - 2801 + 2799 373 457 - 2801 + 2799 473 565 - 2801 + 2799 566 619 - 2801 + 2799 619 689 - 2801 + 2799 696 807 - 2801 + 2799 819 1563 - 2801 + 2799 1634 5631 - 2801 + 2799 15295 @@ -5737,67 +5800,67 @@ 1 18 - 2801 + 2799 23 35 - 3268 + 3266 38 43 - 2801 + 2799 44 61 - 2801 + 2799 65 73 - 2801 + 2799 73 84 - 3268 + 3266 84 96 - 2801 + 2799 96 101 - 3268 + 3266 101 105 - 3268 + 3266 107 112 - 2801 + 2799 112 126 - 2801 + 2799 137 170 - 2801 + 2799 195 265 - 1400 + 1399 @@ -5813,67 +5876,67 @@ 1 19 - 2801 + 2799 30 72 - 2801 + 2799 83 122 - 2801 + 2799 122 205 - 2801 + 2799 214 261 - 2801 + 2799 265 322 - 2801 + 2799 322 379 - 2801 + 2799 404 430 - 2801 + 2799 453 474 - 2801 + 2799 478 505 - 2801 + 2799 511 583 - 2801 + 2799 585 836 - 2801 + 2799 1104 2196 - 2801 + 2799 2387 @@ -5894,67 +5957,67 @@ 1 19 - 2801 + 2799 30 72 - 2801 + 2799 83 122 - 2801 + 2799 122 205 - 2801 + 2799 214 261 - 2801 + 2799 265 322 - 2801 + 2799 322 380 - 2801 + 2799 404 430 - 2801 + 2799 453 474 - 2801 + 2799 477 504 - 2801 + 2799 514 582 - 2801 + 2799 585 835 - 2801 + 2799 1109 2203 - 2801 + 2799 2382 @@ -5975,67 +6038,67 @@ 1 7 - 2801 + 2799 7 11 - 3268 + 3266 11 16 - 3268 + 3266 16 22 - 2801 + 2799 22 24 - 3268 + 3266 24 28 - 2801 + 2799 29 34 - 3268 + 3266 34 41 - 3268 + 3266 41 46 - 2801 + 2799 47 49 - 1867 + 1866 49 54 - 2801 + 2799 54 74 - 2801 + 2799 75 86 - 1867 + 1866 @@ -6051,52 +6114,52 @@ 1 2 - 593383 + 593022 2 3 - 306262 + 306076 3 4 - 198417 + 198296 4 6 - 159667 + 159570 6 10 - 182543 + 182432 10 16 - 162001 + 161903 16 25 - 171338 + 171234 25 46 - 158733 + 158636 46 161 - 158266 + 158170 162 265 - 8870 + 8865 @@ -6112,47 +6175,47 @@ 1 2 - 886574 + 886034 2 3 - 260043 + 259884 3 4 - 125119 + 125043 4 6 - 140992 + 140906 6 10 - 184877 + 184765 10 15 - 168537 + 168435 15 26 - 163402 + 163302 26 120 - 158266 + 158170 121 265 - 11671 + 11664 @@ -6168,22 +6231,22 @@ 1 2 - 1529445 + 1528513 2 3 - 341744 + 341536 3 5 - 170872 + 170768 5 10 - 57424 + 57389 @@ -6199,47 +6262,47 @@ 1 2 - 623262 + 622883 2 3 - 303461 + 303276 3 4 - 201685 + 201562 4 6 - 183944 + 183832 6 9 - 169938 + 169834 9 13 - 166670 + 166568 13 19 - 175073 + 174967 19 29 - 161067 + 160969 29 52 - 114381 + 114311 @@ -6255,52 +6318,52 @@ 1 2 - 599919 + 599554 2 3 - 306262 + 306076 3 4 - 197016 + 196896 4 6 - 169004 + 168901 6 9 - 156399 + 156304 9 14 - 169004 + 168901 14 21 - 177875 + 177766 21 32 - 162001 + 161903 32 60 - 158266 + 158170 60 65 - 3734 + 3732 @@ -6316,67 +6379,67 @@ 1 2 - 5135 + 5132 2 8 - 3734 + 3732 9 186 - 3734 + 3732 193 288 - 3734 + 3732 294 495 - 3734 + 3732 503 555 - 3734 + 3732 561 633 - 3734 + 3732 640 758 - 3734 + 3732 758 869 - 3734 + 3732 875 1074 - 3734 + 3732 1074 1281 - 3734 + 3732 1289 1590 - 3734 + 3732 1685 2418 - 1867 + 1866 @@ -6392,62 +6455,62 @@ 1 2 - 5602 + 5598 2 5 - 3734 + 3732 5 65 - 3734 + 3732 70 100 - 3734 + 3732 100 111 - 3734 + 3732 112 122 - 4201 + 4199 122 140 - 3734 + 3732 143 153 - 3734 + 3732 153 161 - 4201 + 4199 161 173 - 4201 + 4199 173 178 - 3734 + 3732 188 265 - 3734 + 3732 @@ -6463,62 +6526,62 @@ 1 2 - 5602 + 5598 2 8 - 3734 + 3732 9 105 - 3734 + 3732 155 241 - 3734 + 3732 253 336 - 3734 + 3732 340 426 - 3734 + 3732 434 488 - 3734 + 3732 489 572 - 3734 + 3732 573 623 - 3734 + 3732 626 696 - 4201 + 4199 701 813 - 3734 + 3732 818 1095 - 3734 + 3732 1172 @@ -6539,67 +6602,67 @@ 1 2 - 6069 + 6065 2 4 - 3734 + 3732 4 8 - 4201 + 4199 8 15 - 3734 + 3732 15 23 - 3734 + 3732 23 29 - 3734 + 3732 29 35 - 4201 + 4199 35 39 - 3268 + 3266 39 42 - 3268 + 3266 42 44 - 3268 + 3266 44 46 - 3734 + 3732 46 49 - 3734 + 3732 49 53 - 1400 + 1399 @@ -6615,67 +6678,67 @@ 1 2 - 5602 + 5598 2 8 - 3734 + 3732 9 156 - 3734 + 3732 159 240 - 3734 + 3732 251 335 - 3734 + 3732 342 430 - 3734 + 3732 432 490 - 3734 + 3732 490 573 - 3734 + 3732 574 622 - 3734 + 3732 626 698 - 3734 + 3732 700 798 - 3734 + 3732 811 987 - 3734 + 3732 1096 1180 - 1400 + 1399 @@ -10599,23 +10662,23 @@ numlines - 1383783 + 1382941 element_id - 1376780 + 1375942 num_lines - 101776 + 101714 num_code - 84969 + 84917 num_comment - 59758 + 59722 @@ -10629,12 +10692,12 @@ 1 2 - 1369777 + 1368943 2 3 - 7002 + 6998 @@ -10650,12 +10713,12 @@ 1 2 - 1370711 + 1369876 2 3 - 6069 + 6065 @@ -10671,7 +10734,7 @@ 1 2 - 1376780 + 1375942 @@ -10687,27 +10750,27 @@ 1 2 - 68162 + 68120 2 3 - 12138 + 12131 3 4 - 7469 + 7465 4 21 - 7936 + 7931 29 921 - 6069 + 6065 @@ -10723,27 +10786,27 @@ 1 2 - 70496 + 70453 2 3 - 12138 + 12131 3 4 - 8403 + 8398 4 6 - 9337 + 9331 6 7 - 1400 + 1399 @@ -10759,22 +10822,22 @@ 1 2 - 69562 + 69520 2 3 - 14939 + 14930 3 4 - 10737 + 10731 4 7 - 6536 + 6532 @@ -10790,27 +10853,27 @@ 1 2 - 52755 + 52723 2 3 - 14472 + 14463 3 5 - 6536 + 6532 5 42 - 6536 + 6532 44 922 - 4668 + 4665 @@ -10826,27 +10889,27 @@ 1 2 - 52755 + 52723 2 3 - 16807 + 16796 3 5 - 6069 + 6065 5 8 - 6536 + 6532 8 12 - 2801 + 2799 @@ -10862,27 +10925,27 @@ 1 2 - 53222 + 53190 2 3 - 15873 + 15863 3 5 - 7469 + 7465 5 7 - 5135 + 5132 7 10 - 3268 + 3266 @@ -10898,32 +10961,32 @@ 1 2 - 34547 + 34526 2 3 - 9337 + 9331 3 4 - 4201 + 4199 4 6 - 4668 + 4665 6 11 - 5135 + 5132 17 2596 - 1867 + 1866 @@ -10939,32 +11002,32 @@ 1 2 - 34547 + 34526 2 3 - 9337 + 9331 3 4 - 4201 + 4199 4 6 - 4668 + 4665 6 8 - 4668 + 4665 10 38 - 2334 + 2332 @@ -10980,32 +11043,32 @@ 1 2 - 34547 + 34526 2 3 - 9337 + 9331 3 4 - 4201 + 4199 4 6 - 4668 + 4665 6 10 - 4668 + 4665 10 37 - 2334 + 2332 @@ -11647,15 +11710,15 @@ files - 123251 + 123176 id - 123251 + 123176 name - 123251 + 123176 @@ -11669,7 +11732,7 @@ 1 2 - 123251 + 123176 @@ -11685,7 +11748,7 @@ 1 2 - 123251 + 123176 @@ -11695,15 +11758,15 @@ folders - 16340 + 16330 id - 16340 + 16330 name - 16340 + 16330 @@ -11717,7 +11780,7 @@ 1 2 - 16340 + 16330 @@ -11733,7 +11796,7 @@ 1 2 - 16340 + 16330 @@ -11743,15 +11806,15 @@ containerparent - 138658 + 138574 parent - 16340 + 16330 child - 138658 + 138574 @@ -11765,32 +11828,32 @@ 1 2 - 7469 + 7465 2 3 - 3268 + 3266 3 4 - 1400 + 1399 4 12 - 1400 + 1399 23 28 - 1400 + 1399 40 67 - 1400 + 1399 @@ -11806,7 +11869,7 @@ 1 2 - 138658 + 138574 @@ -12392,15 +12455,15 @@ inmacroexpansion - 109779080 + 109779103 id - 18027694 + 18027697 inv - 2700160 + 2700159 @@ -12414,12 +12477,12 @@ 1 3 - 1582361 + 1582360 3 5 - 1077793 + 1077794 5 @@ -12429,17 +12492,17 @@ 6 7 - 4819903 + 4819904 7 8 - 6385932 + 6385934 8 9 - 2605242 + 2605243 9 @@ -12460,12 +12523,12 @@ 1 2 - 378424 + 378422 2 3 - 544104 + 544105 3 @@ -12500,7 +12563,7 @@ 11 337 - 224847 + 224845 339 @@ -12520,15 +12583,15 @@ affectedbymacroexpansion - 35689251 + 35689257 id - 5156949 + 5156948 inv - 2784762 + 2784761 @@ -12542,7 +12605,7 @@ 1 2 - 2816079 + 2816078 2 @@ -12588,7 +12651,7 @@ 1 4 - 229116 + 229115 4 @@ -12603,12 +12666,12 @@ 9 12 - 251119 + 251120 12 13 - 333984 + 333985 13 @@ -12628,7 +12691,7 @@ 16 17 - 276608 + 276609 17 @@ -13607,19 +13670,19 @@ functions - 4179363 + 4176817 id - 4179363 + 4176817 name - 1895466 + 1894311 kind - 3268 + 3266 @@ -13633,7 +13696,7 @@ 1 2 - 4179363 + 4176817 @@ -13649,7 +13712,7 @@ 1 2 - 4179363 + 4176817 @@ -13665,22 +13728,22 @@ 1 2 - 1498165 + 1497253 2 3 - 153131 + 153038 3 5 - 142860 + 142773 5 952 - 101309 + 101247 @@ -13696,7 +13759,7 @@ 1 2 - 1894999 + 1893845 2 @@ -13798,15 +13861,15 @@ function_entry_point - 1151752 + 1151517 id - 1141948 + 1141719 entry_point - 1151752 + 1151517 @@ -13820,12 +13883,12 @@ 1 2 - 1132144 + 1131921 2 3 - 9804 + 9798 @@ -13841,7 +13904,7 @@ 1 2 - 1151752 + 1151517 @@ -13851,15 +13914,15 @@ function_return_type - 4184498 + 4181950 id - 4179363 + 4176817 return_type - 817945 + 817446 @@ -13873,12 +13936,12 @@ 1 2 - 4174227 + 4171685 2 3 - 5135 + 5132 @@ -13894,22 +13957,22 @@ 1 2 - 506080 + 505771 2 3 - 211489 + 211360 3 7 - 66294 + 66254 7 2231 - 34081 + 34060 @@ -14200,33 +14263,33 @@ function_deleted - 96173 + 96115 id - 96173 + 96115 function_defaulted - 73764 + 73719 id - 73764 + 73719 function_prototyped - 4087391 + 4084901 id - 4087391 + 4084901 @@ -14379,27 +14442,27 @@ fun_decls - 4548652 + 4546348 id - 4543516 + 4541216 function - 4035569 + 4033111 type_id - 816544 + 816047 name - 1797891 + 1796796 location - 3370755 + 3368702 @@ -14413,7 +14476,7 @@ 1 2 - 4543516 + 4541216 @@ -14429,12 +14492,12 @@ 1 2 - 4538381 + 4536084 2 3 - 5135 + 5132 @@ -14450,7 +14513,7 @@ 1 2 - 4543516 + 4541216 @@ -14466,7 +14529,7 @@ 1 2 - 4543516 + 4541216 @@ -14482,17 +14545,17 @@ 1 2 - 3606521 + 3603858 2 3 - 356216 + 356466 3 7 - 72830 + 72786 @@ -14508,12 +14571,12 @@ 1 2 - 3995885 + 3993452 2 3 - 39683 + 39659 @@ -14529,7 +14592,7 @@ 1 2 - 4035569 + 4033111 @@ -14545,17 +14608,17 @@ 1 2 - 3663012 + 3660781 2 3 - 311864 + 311674 3 6 - 60692 + 60655 @@ -14571,22 +14634,22 @@ 1 2 - 431381 + 431119 2 3 - 274048 + 273882 3 6 - 63493 + 63454 6 - 2476 - 47620 + 2477 + 47591 @@ -14602,22 +14665,22 @@ 1 2 - 515417 + 515103 2 3 - 203085 + 202961 3 7 - 63026 + 62988 7 2192 - 35014 + 34993 @@ -14633,17 +14696,17 @@ 1 2 - 690024 + 689604 2 4 - 67228 + 67187 4 773 - 59291 + 59255 @@ -14659,22 +14722,22 @@ 1 2 - 595251 + 594888 2 3 - 121384 + 121310 3 7 - 63493 + 63454 7 1959 - 36415 + 36393 @@ -14690,27 +14753,27 @@ 1 2 - 1228318 + 1227570 2 3 - 267045 + 266883 3 4 - 77966 + 77918 4 7 - 146128 + 146039 7 986 - 78433 + 78385 @@ -14726,22 +14789,22 @@ 1 2 - 1407593 + 1406736 2 3 - 152197 + 152104 3 5 - 136791 + 136707 5 936 - 101309 + 101247 @@ -14757,17 +14820,17 @@ 1 2 - 1579399 + 1578437 2 4 - 134923 + 134841 4 562 - 83568 + 83517 @@ -14783,27 +14846,27 @@ 1 2 - 1236254 + 1235502 2 3 - 293190 + 293011 3 4 - 78899 + 78851 4 8 - 137257 + 137174 8 542 - 52288 + 52256 @@ -14819,17 +14882,17 @@ 1 2 - 2966451 + 2964644 2 4 - 277783 + 277614 4 55 - 126520 + 126442 @@ -14845,17 +14908,17 @@ 1 2 - 3033679 + 3031832 2 7 - 244169 + 244020 7 55 - 92905 + 92849 @@ -14871,12 +14934,12 @@ 1 2 - 3207353 + 3205399 2 18 - 163402 + 163302 @@ -14892,12 +14955,12 @@ 1 2 - 3232563 + 3230595 2 13 - 138191 + 138107 @@ -14907,22 +14970,22 @@ fun_def - 1888930 + 1888246 id - 1888930 + 1888246 fun_specialized - 26144 + 26128 id - 26144 + 26128 @@ -14940,15 +15003,15 @@ fun_decl_specifiers - 2906692 + 2904922 id - 1689579 + 1688550 name - 2801 + 2799 @@ -14962,17 +15025,17 @@ 1 2 - 491140 + 490841 2 3 - 1179764 + 1179045 3 4 - 18674 + 18663 @@ -15144,11 +15207,11 @@ fun_decl_empty_throws - 1472021 + 1471124 fun_decl - 1472021 + 1471124 @@ -15208,11 +15271,11 @@ fun_decl_empty_noexcept - 863230 + 863171 fun_decl - 863230 + 863171 @@ -15317,19 +15380,19 @@ param_decl_bind - 6995017 + 6991224 id - 6995017 + 6991224 index - 7936 + 7931 fun_decl - 3835284 + 3833415 @@ -15343,7 +15406,7 @@ 1 2 - 6995017 + 6991224 @@ -15359,7 +15422,7 @@ 1 2 - 6995017 + 6991224 @@ -15438,8 +15501,8 @@ 466 - 8215 - 8216 + 8216 + 8217 466 @@ -15519,8 +15582,8 @@ 466 - 8215 - 8216 + 8216 + 8217 466 @@ -15537,27 +15600,27 @@ 1 2 - 1973899 + 1973163 2 3 - 1061647 + 1061001 3 4 - 502812 + 502505 4 8 - 290856 + 290678 8 18 - 6069 + 6065 @@ -15573,27 +15636,27 @@ 1 2 - 1973899 + 1973163 2 3 - 1061647 + 1061001 3 4 - 502812 + 502505 4 8 - 290856 + 290678 8 18 - 6069 + 6065 @@ -15603,27 +15666,27 @@ var_decls - 8110354 + 8105882 id - 8039391 + 8034962 variable - 7027231 + 7022951 type_id - 2043462 + 2042217 name - 667614 + 667208 location - 5311974 + 5308739 @@ -15637,7 +15700,7 @@ 1 2 - 8039391 + 8034962 @@ -15653,12 +15716,12 @@ 1 2 - 7971229 + 7966841 2 3 - 68162 + 68120 @@ -15674,7 +15737,7 @@ 1 2 - 8039391 + 8034962 @@ -15690,12 +15753,12 @@ 1 2 - 8036590 + 8032162 2 3 - 2801 + 2799 @@ -15711,17 +15774,17 @@ 1 2 - 6175205 + 6170977 2 3 - 698427 + 698469 3 7 - 153598 + 153504 @@ -15737,12 +15800,12 @@ 1 2 - 6855892 + 6851717 2 4 - 171338 + 171234 @@ -15758,12 +15821,12 @@ 1 2 - 6911916 + 6907706 2 3 - 115315 + 115245 @@ -15779,17 +15842,17 @@ 1 2 - 6481934 + 6477987 2 3 - 542962 + 542631 3 4 - 2334 + 2332 @@ -15805,27 +15868,27 @@ 1 2 - 1165758 + 1165048 2 3 - 477134 + 476377 3 4 - 94773 + 95182 4 7 - 184877 + 184765 7 762 - 120917 + 120844 @@ -15841,22 +15904,22 @@ 1 2 - 1299281 + 1298490 2 3 - 452390 + 452115 3 6 - 155932 + 155837 6 724 - 135857 + 135774 @@ -15872,17 +15935,17 @@ 1 2 - 1539249 + 1538311 2 3 - 383295 + 383061 3 128 - 120917 + 120844 @@ -15898,22 +15961,22 @@ 1 2 - 1365576 + 1364744 2 3 - 404303 + 404057 3 7 - 173206 + 173100 7 592 - 100375 + 100314 @@ -15929,37 +15992,37 @@ 1 2 - 341277 + 341069 2 3 - 86836 + 86783 3 4 - 48553 + 48524 4 6 - 51821 + 51790 6 12 - 52288 + 52256 12 33 - 50421 + 50390 34 - 2384 - 36415 + 2385 + 36393 @@ -15975,37 +16038,37 @@ 1 2 - 368822 + 368597 2 3 - 77966 + 77918 3 4 - 45285 + 45258 4 6 - 49487 + 49457 6 14 - 53222 + 53190 14 56 - 50888 + 50857 56 2301 - 21942 + 21929 @@ -16021,27 +16084,27 @@ 1 2 - 457059 + 456781 2 3 - 93839 + 93782 3 5 - 46686 + 46657 5 19 - 50888 + 50857 19 1182 - 19141 + 19129 @@ -16057,32 +16120,32 @@ 1 2 - 379093 + 378862 2 3 - 90571 + 90516 3 5 - 59758 + 59722 5 9 - 51354 + 51323 9 21 - 50421 + 50390 21 1010 - 36415 + 36393 @@ -16098,17 +16161,17 @@ 1 2 - 4496363 + 4493625 2 3 - 531757 + 531433 3 - 896 - 283853 + 897 + 283680 @@ -16124,17 +16187,17 @@ 1 2 - 4885727 + 4882752 2 17 - 415508 + 415255 17 892 - 10737 + 10731 @@ -16150,12 +16213,12 @@ 1 2 - 4961826 + 4958804 2 759 - 350147 + 349934 @@ -16171,12 +16234,12 @@ 1 2 - 5302637 + 5299407 2 6 - 9337 + 9331 @@ -16186,26 +16249,26 @@ var_def - 3994952 + 3992985 id - 3994952 + 3992985 var_decl_specifiers - 378626 + 378395 id - 378626 + 378395 name - 1867 + 1866 @@ -16219,7 +16282,7 @@ 1 2 - 378626 + 378395 @@ -16271,19 +16334,19 @@ type_decls - 3283451 + 3281452 id - 3283451 + 3281452 type_id - 3233030 + 3231061 location - 3166269 + 3164340 @@ -16297,7 +16360,7 @@ 1 2 - 3283451 + 3281452 @@ -16313,7 +16376,7 @@ 1 2 - 3283451 + 3281452 @@ -16329,12 +16392,12 @@ 1 2 - 3191479 + 3189536 2 5 - 41550 + 41525 @@ -16350,12 +16413,12 @@ 1 2 - 3191479 + 3189536 2 5 - 41550 + 41525 @@ -16371,12 +16434,12 @@ 1 2 - 3113980 + 3112083 2 20 - 52288 + 52256 @@ -16392,12 +16455,12 @@ 1 2 - 3113980 + 3112083 2 20 - 52288 + 52256 @@ -16407,22 +16470,22 @@ type_def - 2641981 + 2640372 id - 2641981 + 2640372 type_decl_top - 743713 + 743260 type_decl - 743713 + 743260 @@ -16795,19 +16858,19 @@ usings - 369755 + 369530 id - 369755 + 369530 element_id - 315599 + 315407 location - 247904 + 247753 kind @@ -16825,7 +16888,7 @@ 1 2 - 369755 + 369530 @@ -16841,7 +16904,7 @@ 1 2 - 369755 + 369530 @@ -16857,7 +16920,7 @@ 1 2 - 369755 + 369530 @@ -16873,17 +16936,17 @@ 1 2 - 263311 + 263150 2 3 - 50888 + 50857 3 5 - 1400 + 1399 @@ -16899,17 +16962,17 @@ 1 2 - 263311 + 263150 2 3 - 50888 + 50857 3 5 - 1400 + 1399 @@ -16925,7 +16988,7 @@ 1 2 - 315599 + 315407 @@ -16941,22 +17004,22 @@ 1 2 - 202618 + 202495 2 4 - 10737 + 10731 4 5 - 31279 + 31260 5 11 - 3268 + 3266 @@ -16972,22 +17035,22 @@ 1 2 - 202618 + 202495 2 4 - 10737 + 10731 4 5 - 31279 + 31260 5 11 - 3268 + 3266 @@ -17003,7 +17066,7 @@ 1 2 - 247904 + 247753 @@ -17787,23 +17850,23 @@ params - 6354480 + 6350610 id - 6190611 + 6186841 function - 3491673 + 3489546 index - 7936 + 7931 type_id - 1846445 + 1845321 @@ -17817,7 +17880,7 @@ 1 2 - 6190611 + 6186841 @@ -17833,7 +17896,7 @@ 1 2 - 6190611 + 6186841 @@ -17849,12 +17912,12 @@ 1 2 - 6066892 + 6063198 2 4 - 123718 + 123643 @@ -17870,22 +17933,22 @@ 1 2 - 1867454 + 1866317 2 3 - 952868 + 952288 3 4 - 429981 + 429719 4 18 - 241368 + 241221 @@ -17901,22 +17964,22 @@ 1 2 - 1867454 + 1866317 2 3 - 952868 + 952288 3 4 - 429981 + 429719 4 18 - 241368 + 241221 @@ -17932,22 +17995,22 @@ 1 2 - 2165780 + 2164461 2 3 - 826815 + 826311 3 4 - 346412 + 346201 4 12 - 152664 + 152571 @@ -18145,7 +18208,7 @@ 6 7 - 1400 + 1399 7 @@ -18201,22 +18264,22 @@ 1 2 - 1183966 + 1183245 2 3 - 406171 + 405923 3 7 - 154064 + 153971 7 518 - 102243 + 102180 @@ -18232,22 +18295,22 @@ 1 2 - 1404792 + 1403937 2 3 - 212422 + 212293 3 7 - 147528 + 147439 7 502 - 81701 + 81651 @@ -18263,17 +18326,17 @@ 1 2 - 1420199 + 1419334 2 3 - 347346 + 347135 3 13 - 78899 + 78851 @@ -18283,11 +18346,11 @@ overrides - 125725 + 125735 new - 122752 + 122762 old @@ -18305,7 +18368,7 @@ 1 2 - 119788 + 119797 2 @@ -18713,11 +18776,11 @@ localvariables - 576945 + 576952 id - 576945 + 576952 type_id @@ -18725,7 +18788,7 @@ name - 90547 + 90549 @@ -18739,7 +18802,7 @@ 1 2 - 576945 + 576952 @@ -18755,7 +18818,7 @@ 1 2 - 576945 + 576952 @@ -18812,7 +18875,7 @@ 1 2 - 26912 + 26913 2 @@ -18848,12 +18911,12 @@ 1 2 - 57031 + 57032 2 3 - 14284 + 14285 3 @@ -18884,7 +18947,7 @@ 1 2 - 76491 + 76492 2 @@ -18894,7 +18957,7 @@ 3 1486 - 6644 + 6645 @@ -19922,31 +19985,31 @@ builtintypes - 26144 + 26128 id - 26144 + 26128 name - 26144 + 26128 kind - 26144 + 26128 size - 3268 + 3266 sign - 1400 + 1399 alignment - 2334 + 2332 @@ -19960,7 +20023,7 @@ 1 2 - 26144 + 26128 @@ -19976,7 +20039,7 @@ 1 2 - 26144 + 26128 @@ -19992,7 +20055,7 @@ 1 2 - 26144 + 26128 @@ -20008,7 +20071,7 @@ 1 2 - 26144 + 26128 @@ -20024,7 +20087,7 @@ 1 2 - 26144 + 26128 @@ -20040,7 +20103,7 @@ 1 2 - 26144 + 26128 @@ -20056,7 +20119,7 @@ 1 2 - 26144 + 26128 @@ -20072,7 +20135,7 @@ 1 2 - 26144 + 26128 @@ -20088,7 +20151,7 @@ 1 2 - 26144 + 26128 @@ -20104,7 +20167,7 @@ 1 2 - 26144 + 26128 @@ -20120,7 +20183,7 @@ 1 2 - 26144 + 26128 @@ -20136,7 +20199,7 @@ 1 2 - 26144 + 26128 @@ -20152,7 +20215,7 @@ 1 2 - 26144 + 26128 @@ -20168,7 +20231,7 @@ 1 2 - 26144 + 26128 @@ -20184,7 +20247,7 @@ 1 2 - 26144 + 26128 @@ -20343,7 +20406,7 @@ 3 4 - 2334 + 2332 @@ -20359,12 +20422,12 @@ 1 2 - 1867 + 1866 2 3 - 1400 + 1399 @@ -20479,7 +20542,7 @@ 5 6 - 1400 + 1399 @@ -20603,7 +20666,7 @@ 2 3 - 2334 + 2332 @@ -20619,7 +20682,7 @@ 3 4 - 2334 + 2332 @@ -20629,23 +20692,23 @@ derivedtypes - 3669548 + 3667313 id - 3669548 + 3667313 name - 1552788 + 1551842 kind - 2801 + 2799 type_id - 2362796 + 2361357 @@ -20659,7 +20722,7 @@ 1 2 - 3669548 + 3667313 @@ -20675,7 +20738,7 @@ 1 2 - 3669548 + 3667313 @@ -20691,7 +20754,7 @@ 1 2 - 3669548 + 3667313 @@ -20707,17 +20770,17 @@ 1 2 - 1324025 + 1323218 2 4 - 120450 + 120377 4 1153 - 108312 + 108246 @@ -20733,7 +20796,7 @@ 1 2 - 1551854 + 1550909 2 @@ -20754,17 +20817,17 @@ 1 2 - 1324025 + 1323218 2 4 - 120450 + 120377 4 1135 - 108312 + 108246 @@ -20903,22 +20966,22 @@ 1 2 - 1515439 + 1514516 2 3 - 546230 + 545897 3 4 - 218492 + 218359 4 72 - 82634 + 82584 @@ -20934,22 +20997,22 @@ 1 2 - 1526644 + 1525714 2 3 - 538760 + 538432 3 4 - 215690 + 215559 4 72 - 81701 + 81651 @@ -20965,22 +21028,22 @@ 1 2 - 1519641 + 1518715 2 3 - 549965 + 549630 3 4 - 217558 + 217425 4 6 - 75631 + 75585 @@ -20990,11 +21053,11 @@ pointerishsize - 2707342 + 2705693 id - 2707342 + 2705693 size @@ -21016,7 +21079,7 @@ 1 2 - 2707342 + 2705693 @@ -21032,7 +21095,7 @@ 1 2 - 2707342 + 2705693 @@ -21106,23 +21169,23 @@ arraysizes - 88237 + 88183 id - 88237 + 88183 num_elements - 31746 + 31727 bytesize - 33147 + 33127 alignment - 1867 + 1866 @@ -21136,7 +21199,7 @@ 1 2 - 88237 + 88183 @@ -21152,7 +21215,7 @@ 1 2 - 88237 + 88183 @@ -21168,7 +21231,7 @@ 1 2 - 88237 + 88183 @@ -21184,22 +21247,22 @@ 1 2 - 1867 + 1866 2 3 - 23810 + 23795 3 5 - 2801 + 2799 5 13 - 2801 + 2799 13 @@ -21220,17 +21283,17 @@ 1 2 - 26611 + 26595 2 3 - 2334 + 2332 3 7 - 2801 + 2799 @@ -21246,17 +21309,17 @@ 1 2 - 26611 + 26595 2 3 - 2801 + 2799 3 5 - 2334 + 2332 @@ -21272,27 +21335,27 @@ 1 2 - 1867 + 1866 2 3 - 23810 + 23795 3 4 - 3268 + 3266 4 6 - 2334 + 2332 7 16 - 1867 + 1866 @@ -21308,17 +21371,17 @@ 1 2 - 27544 + 27528 2 3 - 3734 + 3732 3 5 - 1867 + 1866 @@ -21334,12 +21397,12 @@ 1 2 - 27544 + 27528 2 3 - 4668 + 4665 4 @@ -21791,19 +21854,19 @@ usertypes - 5234008 + 5230820 id - 5234008 + 5230820 name - 1352503 + 1351680 kind - 5135 + 5132 @@ -21817,7 +21880,7 @@ 1 2 - 5234008 + 5230820 @@ -21833,7 +21896,7 @@ 1 2 - 5234008 + 5230820 @@ -21849,27 +21912,27 @@ 1 2 - 983681 + 983082 2 3 - 153598 + 153504 3 7 - 104577 + 104513 7 61 - 101776 + 101714 65 874 - 8870 + 8865 @@ -21885,17 +21948,17 @@ 1 2 - 1211977 + 1211239 2 3 - 125586 + 125509 3 7 - 14939 + 14930 @@ -22037,19 +22100,19 @@ usertypesize - 1706386 + 1705347 id - 1706386 + 1705347 size - 13539 + 13530 alignment - 2334 + 2332 @@ -22063,7 +22126,7 @@ 1 2 - 1706386 + 1705347 @@ -22079,7 +22142,7 @@ 1 2 - 1706386 + 1705347 @@ -22095,12 +22158,12 @@ 1 2 - 3268 + 3266 2 3 - 4201 + 4199 3 @@ -22151,12 +22214,12 @@ 1 2 - 10270 + 10264 2 3 - 2801 + 2799 3 @@ -22307,15 +22370,15 @@ mangled_name - 9019338 + 9013845 id - 9019338 + 9013845 mangled_name - 6061757 + 6058065 is_complete @@ -22333,7 +22396,7 @@ 1 2 - 9019338 + 9013845 @@ -22349,7 +22412,7 @@ 1 2 - 9019338 + 9013845 @@ -22365,12 +22428,12 @@ 1 2 - 5789108 + 5785583 2 874 - 272648 + 272482 @@ -22386,7 +22449,7 @@ 1 2 - 6061757 + 6058065 @@ -22439,48 +22502,48 @@ is_standard_layout_class - 1253995 + 1253232 id - 1253995 + 1253232 is_complete - 1645694 + 1644692 id - 1645694 + 1644692 is_class_template - 398234 + 397992 id - 398234 + 397992 class_instantiation - 1089659 + 1088996 to - 1089659 + 1088996 from - 168537 + 168435 @@ -22494,7 +22557,7 @@ 1 2 - 1089659 + 1088996 @@ -22510,47 +22573,47 @@ 1 2 - 59758 + 59722 2 3 - 29412 + 29394 3 4 - 15873 + 15863 4 5 - 13072 + 13064 5 6 - 9804 + 9798 6 10 - 12605 + 12597 10 16 - 13072 + 13064 16 70 - 13539 + 13530 70 84 - 1400 + 1399 @@ -22801,19 +22864,19 @@ class_template_argument_value - 495342 + 495040 type_id - 304861 + 304676 index - 1867 + 1866 arg_value - 495342 + 495040 @@ -22827,17 +22890,17 @@ 1 2 - 249772 + 249619 2 3 - 53222 + 53190 3 4 - 1867 + 1866 @@ -22853,22 +22916,22 @@ 1 2 - 189546 + 189431 2 3 - 81234 + 81184 3 4 - 12138 + 12131 4 9 - 21942 + 21929 @@ -22946,7 +23009,7 @@ 1 2 - 495342 + 495040 @@ -22962,7 +23025,7 @@ 1 2 - 495342 + 495040 @@ -22972,15 +23035,15 @@ is_proxy_class_for - 62092 + 62055 id - 62092 + 62055 templ_param_id - 62092 + 62055 @@ -22994,7 +23057,7 @@ 1 2 - 62092 + 62055 @@ -23010,7 +23073,7 @@ 1 2 - 62092 + 62055 @@ -23316,11 +23379,11 @@ is_function_template - 1402925 + 1402070 id - 1402925 + 1402070 @@ -24451,19 +24514,19 @@ routinetypeargs - 983214 + 982616 routine - 423445 + 423187 index - 7936 + 7931 type_id - 226895 + 226757 @@ -24477,27 +24540,27 @@ 1 2 - 152664 + 152571 2 3 - 133989 + 133908 3 4 - 63493 + 63454 4 5 - 45752 + 45724 5 18 - 27544 + 27528 @@ -24513,27 +24576,27 @@ 1 2 - 182543 + 182432 2 3 - 133522 + 133441 3 4 - 58824 + 58788 4 5 - 33614 + 33593 5 11 - 14939 + 14930 @@ -24574,7 +24637,7 @@ 10 11 - 1400 + 1399 13 @@ -24635,7 +24698,7 @@ 4 5 - 1400 + 1399 5 @@ -24691,27 +24754,27 @@ 1 2 - 146595 + 146505 2 3 - 30812 + 30794 3 5 - 16807 + 16796 5 12 - 18207 + 18196 12 110 - 14472 + 14463 @@ -24727,22 +24790,22 @@ 1 2 - 172739 + 172634 2 3 - 30812 + 30794 3 6 - 18674 + 18663 6 14 - 4668 + 4665 @@ -24752,19 +24815,19 @@ ptrtomembers - 37815 + 37792 id - 37815 + 37792 type_id - 37815 + 37792 class_id - 15406 + 15397 @@ -24778,7 +24841,7 @@ 1 2 - 37815 + 37792 @@ -24794,7 +24857,7 @@ 1 2 - 37815 + 37792 @@ -24810,7 +24873,7 @@ 1 2 - 37815 + 37792 @@ -24826,7 +24889,7 @@ 1 2 - 37815 + 37792 @@ -24842,12 +24905,12 @@ 1 2 - 13539 + 13530 8 9 - 1400 + 1399 28 @@ -24868,12 +24931,12 @@ 1 2 - 13539 + 13530 8 9 - 1400 + 1399 28 @@ -24888,15 +24951,15 @@ specifiers - 24743 + 24728 id - 24743 + 24728 str - 24743 + 24728 @@ -24910,7 +24973,7 @@ 1 2 - 24743 + 24728 @@ -24926,7 +24989,7 @@ 1 2 - 24743 + 24728 @@ -24936,15 +24999,15 @@ typespecifiers - 1132144 + 1131454 type_id - 1113936 + 1113258 spec_id - 3734 + 3732 @@ -24958,12 +25021,12 @@ 1 2 - 1095728 + 1095061 2 3 - 18207 + 18196 @@ -25019,15 +25082,15 @@ funspecifiers - 10305080 + 10298338 func_id - 4068249 + 4065772 spec_id - 8403 + 8398 @@ -25041,27 +25104,27 @@ 1 2 - 1357639 + 1356812 2 3 - 640536 + 640613 3 4 - 985549 + 984482 4 5 - 780129 + 779654 5 8 - 304395 + 304209 @@ -25160,8 +25223,8 @@ 466 - 6435 - 6436 + 6434 + 6435 466 @@ -25172,15 +25235,15 @@ varspecifiers - 2246080 + 2244713 var_id - 1225050 + 1224304 spec_id - 3734 + 3732 @@ -25194,22 +25257,22 @@ 1 2 - 730174 + 729730 2 3 - 202618 + 202495 3 4 - 58357 + 58322 4 5 - 233898 + 233756 @@ -25318,19 +25381,19 @@ attributes - 561636 + 561294 id - 561636 + 561294 kind - 1400 + 1399 name - 11204 + 11197 name_space @@ -25338,7 +25401,7 @@ location - 481336 + 481043 @@ -25352,7 +25415,7 @@ 1 2 - 561636 + 561294 @@ -25368,7 +25431,7 @@ 1 2 - 561636 + 561294 @@ -25384,7 +25447,7 @@ 1 2 - 561636 + 561294 @@ -25400,7 +25463,7 @@ 1 2 - 561636 + 561294 @@ -25591,7 +25654,7 @@ 1 2 - 10270 + 10264 2 @@ -25612,7 +25675,7 @@ 1 2 - 11204 + 11197 @@ -25783,17 +25846,17 @@ 1 2 - 431848 + 431585 2 3 - 20075 + 20062 3 7 - 29412 + 29394 @@ -25809,7 +25872,7 @@ 1 2 - 481336 + 481043 @@ -25825,17 +25888,17 @@ 1 2 - 433249 + 432985 2 3 - 19608 + 19596 3 4 - 28478 + 28461 @@ -25851,7 +25914,7 @@ 1 2 - 481336 + 481043 @@ -25861,27 +25924,27 @@ attribute_args - 344078 + 343868 id - 344078 + 343868 kind - 1400 + 1399 attribute - 262844 + 262684 index - 1400 + 1399 location - 327738 + 327538 @@ -25895,7 +25958,7 @@ 1 2 - 344078 + 343868 @@ -25911,7 +25974,7 @@ 1 2 - 344078 + 343868 @@ -25927,7 +25990,7 @@ 1 2 - 344078 + 343868 @@ -25943,7 +26006,7 @@ 1 2 - 344078 + 343868 @@ -26058,17 +26121,17 @@ 1 2 - 197483 + 197363 2 3 - 49487 + 49457 3 4 - 15873 + 15863 @@ -26084,12 +26147,12 @@ 1 2 - 252573 + 252419 2 3 - 10270 + 10264 @@ -26105,17 +26168,17 @@ 1 2 - 197483 + 197363 2 3 - 49487 + 49457 3 4 - 15873 + 15863 @@ -26131,17 +26194,17 @@ 1 2 - 197483 + 197363 2 3 - 49487 + 49457 3 4 - 15873 + 15863 @@ -26256,12 +26319,12 @@ 1 2 - 313732 + 313541 2 7 - 14005 + 13997 @@ -26277,12 +26340,12 @@ 1 2 - 315132 + 314941 2 3 - 12605 + 12597 @@ -26298,12 +26361,12 @@ 1 2 - 313732 + 313541 2 7 - 14005 + 13997 @@ -26319,7 +26382,7 @@ 1 2 - 327738 + 327538 @@ -26329,15 +26392,15 @@ attribute_arg_value - 25210 + 25195 arg - 25210 + 25195 value - 15873 + 15863 @@ -26351,7 +26414,7 @@ 1 2 - 25210 + 25195 @@ -26367,12 +26430,12 @@ 1 2 - 14472 + 14463 2 16 - 1400 + 1399 @@ -26430,15 +26493,15 @@ attribute_arg_constant - 318400 + 318207 arg - 318400 + 318207 constant - 318400 + 318207 @@ -26452,7 +26515,7 @@ 1 2 - 318400 + 318207 @@ -26468,7 +26531,7 @@ 1 2 - 318400 + 318207 @@ -26647,15 +26710,15 @@ funcattributes - 630265 + 629882 func_id - 443520 + 443250 spec_id - 524754 + 524435 @@ -26669,17 +26732,17 @@ 1 2 - 338476 + 338269 2 3 - 64427 + 64387 3 6 - 39683 + 39659 6 @@ -26700,12 +26763,12 @@ 1 2 - 506080 + 505771 2 17 - 18674 + 18663 @@ -26841,15 +26904,15 @@ unspecifiedtype - 9488069 + 9482291 type_id - 9488069 + 9482291 unspecified_type_id - 6490338 + 6486385 @@ -26863,7 +26926,7 @@ 1 2 - 9488069 + 9482291 @@ -26879,17 +26942,17 @@ 1 2 - 4558923 + 4556146 2 3 - 1715723 + 1714678 3 145 - 215690 + 215559 @@ -26899,19 +26962,19 @@ member - 3881037 + 3878673 parent - 545763 + 545431 index - 92905 + 92849 child - 3809607 + 3807287 @@ -26925,47 +26988,47 @@ 1 2 - 129788 + 129709 2 3 - 64894 + 64854 3 4 - 73297 + 73252 4 5 - 75165 + 75119 5 6 - 40617 + 40592 6 8 - 46686 + 46657 8 14 - 45752 + 45724 14 30 - 41550 + 41525 30 200 - 28011 + 27994 @@ -26981,52 +27044,52 @@ 1 2 - 129788 + 129709 2 3 - 64894 + 64854 3 4 - 73297 + 73252 4 5 - 76098 + 76052 5 6 - 39683 + 39659 6 7 - 24276 + 24262 7 9 - 42017 + 41992 9 17 - 43885 + 43858 17 41 - 41550 + 41525 41 200 - 10270 + 10264 @@ -27042,62 +27105,62 @@ 1 2 - 26144 + 26128 2 3 - 7002 + 6998 3 4 - 3734 + 3732 4 5 - 7936 + 7931 5 6 - 5602 + 5598 6 7 - 5602 + 5598 7 9 - 7469 + 7465 9 16 - 7002 + 6998 16 52 - 7002 + 6998 52 107 - 7002 + 6998 108 577 - 7002 + 6998 737 1162 - 1400 + 1399 @@ -27113,62 +27176,62 @@ 1 2 - 26144 + 26128 2 3 - 7002 + 6998 3 4 - 3734 + 3732 4 5 - 7936 + 7931 5 6 - 5602 + 5598 6 7 - 5602 + 5598 7 9 - 7469 + 7465 9 16 - 7002 + 6998 16 52 - 7002 + 6998 52 107 - 7002 + 6998 108 577 - 7002 + 6998 738 1163 - 1400 + 1399 @@ -27184,7 +27247,7 @@ 1 2 - 3809607 + 3807287 @@ -27200,12 +27263,12 @@ 1 2 - 3738177 + 3735900 2 3 - 71430 + 71386 @@ -28735,15 +28798,15 @@ commentbinding - 3091104 + 3089221 id - 2445431 + 2443942 element - 3014538 + 3012702 @@ -28757,12 +28820,12 @@ 1 2 - 2368399 + 2366956 2 97 - 77032 + 76985 @@ -28778,12 +28841,12 @@ 1 2 - 2937972 + 2936183 2 3 - 76565 + 76519 @@ -28793,15 +28856,15 @@ exprconv - 7032991 + 7032993 converted - 7032991 + 7032993 conversion - 7032991 + 7032993 @@ -28815,7 +28878,7 @@ 1 2 - 7032991 + 7032993 @@ -28831,7 +28894,7 @@ 1 2 - 7032991 + 7032993 @@ -29188,15 +29251,15 @@ namespaces - 12138 + 12131 id - 12138 + 12131 name - 9804 + 9798 @@ -29210,7 +29273,7 @@ 1 2 - 12138 + 12131 @@ -29226,7 +29289,7 @@ 1 2 - 8403 + 8398 2 @@ -29246,26 +29309,26 @@ namespace_inline - 1400 + 1399 id - 1400 + 1399 namespacembrs - 2388007 + 2386553 parentid - 10270 + 10264 memberid - 2388007 + 2386553 @@ -29279,7 +29342,7 @@ 1 2 - 1867 + 1866 2 @@ -29340,7 +29403,7 @@ 1 2 - 2388007 + 2386553 @@ -29836,7 +29899,7 @@ qualifyingelement - 97518 + 97537 location @@ -29950,7 +30013,7 @@ 1 2 - 58401 + 58420 2 @@ -29986,7 +30049,7 @@ 1 2 - 58401 + 58420 2 @@ -30022,7 +30085,7 @@ 1 2 - 63815 + 63834 2 @@ -30135,12 +30198,12 @@ 1 2 - 137073 + 137054 2 3 - 55684 + 55703 3 @@ -32081,7 +32144,7 @@ expr_types - 18451442 + 18451397 id @@ -32107,12 +32170,12 @@ 1 2 - 18188121 + 18188166 2 3 - 131660 + 131615 @@ -32149,17 +32212,17 @@ 2 3 - 249334 + 249345 3 4 - 102840 + 102817 4 5 - 81865 + 81877 5 @@ -32174,12 +32237,12 @@ 14 41 - 91664 + 91653 41 125325 - 44579 + 44590 @@ -33706,11 +33769,11 @@ lambdas - 21475 + 21462 expr - 21475 + 21462 default_capture @@ -33732,7 +33795,7 @@ 1 2 - 21475 + 21462 @@ -33748,7 +33811,7 @@ 1 2 - 21475 + 21462 @@ -33822,15 +33885,15 @@ lambda_capture - 28011 + 27994 id - 28011 + 27994 lambda - 20541 + 20529 index @@ -33838,7 +33901,7 @@ field - 28011 + 27994 captured_by_reference @@ -33850,7 +33913,7 @@ location - 2801 + 2799 @@ -33864,7 +33927,7 @@ 1 2 - 28011 + 27994 @@ -33880,7 +33943,7 @@ 1 2 - 28011 + 27994 @@ -33896,7 +33959,7 @@ 1 2 - 28011 + 27994 @@ -33912,7 +33975,7 @@ 1 2 - 28011 + 27994 @@ -33928,7 +33991,7 @@ 1 2 - 28011 + 27994 @@ -33944,7 +34007,7 @@ 1 2 - 28011 + 27994 @@ -33960,12 +34023,12 @@ 1 2 - 13072 + 13064 2 3 - 7469 + 7465 @@ -33981,12 +34044,12 @@ 1 2 - 13072 + 13064 2 3 - 7469 + 7465 @@ -34002,12 +34065,12 @@ 1 2 - 13072 + 13064 2 3 - 7469 + 7465 @@ -34023,7 +34086,7 @@ 1 2 - 20541 + 20529 @@ -34039,7 +34102,7 @@ 1 2 - 20541 + 20529 @@ -34055,12 +34118,12 @@ 1 2 - 13072 + 13064 2 3 - 7469 + 7465 @@ -34192,7 +34255,7 @@ 1 2 - 28011 + 27994 @@ -34208,7 +34271,7 @@ 1 2 - 28011 + 27994 @@ -34224,7 +34287,7 @@ 1 2 - 28011 + 27994 @@ -34240,7 +34303,7 @@ 1 2 - 28011 + 27994 @@ -34256,7 +34319,7 @@ 1 2 - 28011 + 27994 @@ -34272,7 +34335,7 @@ 1 2 - 28011 + 27994 @@ -34480,7 +34543,7 @@ 8 9 - 1867 + 1866 14 @@ -34501,7 +34564,7 @@ 8 9 - 1867 + 1866 14 @@ -34522,7 +34585,7 @@ 1 2 - 2801 + 2799 @@ -34538,7 +34601,7 @@ 8 9 - 1867 + 1866 14 @@ -34559,7 +34622,7 @@ 1 2 - 2801 + 2799 @@ -34575,7 +34638,7 @@ 1 2 - 2801 + 2799 @@ -36318,11 +36381,11 @@ stmt_decl_bind - 580842 + 580849 stmt - 541060 + 541066 num @@ -36330,7 +36393,7 @@ decl - 580738 + 580745 @@ -36344,7 +36407,7 @@ 1 2 - 520371 + 520377 2 @@ -36365,7 +36428,7 @@ 1 2 - 520371 + 520377 2 @@ -36568,7 +36631,7 @@ 1 2 - 580700 + 580707 2 @@ -36589,7 +36652,7 @@ 1 2 - 580738 + 580745 @@ -36599,11 +36662,11 @@ stmt_decl_entry_bind - 580842 + 580849 stmt - 541060 + 541066 num @@ -36611,7 +36674,7 @@ decl_entry - 580784 + 580791 @@ -36625,7 +36688,7 @@ 1 2 - 520371 + 520377 2 @@ -36646,7 +36709,7 @@ 1 2 - 520371 + 520377 2 @@ -36849,7 +36912,7 @@ 1 2 - 580763 + 580770 3 @@ -36870,7 +36933,7 @@ 1 2 - 580784 + 580791 @@ -36880,15 +36943,15 @@ blockscope - 1410861 + 1410469 block - 1410861 + 1410469 enclosing - 1295546 + 1295224 @@ -36902,7 +36965,7 @@ 1 2 - 1410861 + 1410469 @@ -36918,12 +36981,12 @@ 1 2 - 1230185 + 1229903 2 13 - 65360 + 65321 @@ -37119,19 +37182,19 @@ preprocdirects - 4190567 + 4188015 id - 4190567 + 4188015 kind - 5135 + 5132 location - 4149950 + 4147423 @@ -37145,7 +37208,7 @@ 1 2 - 4190567 + 4188015 @@ -37161,7 +37224,7 @@ 1 2 - 4190567 + 4188015 @@ -37309,7 +37372,7 @@ 1 2 - 4149483 + 4146956 88 @@ -37330,7 +37393,7 @@ 1 2 - 4149950 + 4147423 @@ -37340,15 +37403,15 @@ preprocpair - 1431403 + 1430532 begin - 1197038 + 1196309 elseelifend - 1431403 + 1430532 @@ -37362,17 +37425,17 @@ 1 2 - 978546 + 977950 2 3 - 208221 + 208094 3 11 - 10270 + 10264 @@ -37388,7 +37451,7 @@ 1 2 - 1431403 + 1430532 @@ -37398,22 +37461,22 @@ preproctrue - 767056 + 766589 branch - 767056 + 766589 preprocfalse - 331473 + 331271 branch - 331473 + 331271 @@ -37566,15 +37629,15 @@ includes - 313265 + 313074 id - 313265 + 313074 included - 117182 + 117111 @@ -37588,7 +37651,7 @@ 1 2 - 313265 + 313074 @@ -37604,32 +37667,32 @@ 1 2 - 61159 + 61121 2 3 - 21942 + 21929 3 4 - 12605 + 12597 4 6 - 10270 + 10264 6 14 - 8870 + 8865 14 47 - 2334 + 2332 diff --git a/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/old.dbscheme b/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/old.dbscheme new file mode 100644 index 000000000000..e51fad7a2436 --- /dev/null +++ b/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/old.dbscheme @@ -0,0 +1,2323 @@ + +/** + * 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 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, 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 +); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * 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( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * 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_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * 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_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: 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_default 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 +); + +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 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 + 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +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 +); + +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_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable 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 +); + +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 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _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 +; + +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 +; + +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 +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this 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. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* +case @usertype.kind of + 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +| 5 = @typedef // classic C: typedef typedef type name +| 6 = @template +| 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 // a using name = type style typedef +; +*/ + +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 +); + +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 +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location 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 +); + +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 +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +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; + +@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; + +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_expr 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_expr 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 +; + +@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 + ; + +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 +); + +/** + * 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 +); + +/** + * 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 +); + +@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 +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof; + +sizeof_bind( + unique int expr: @runtime_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 +); + +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_stmt 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 +; + +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 +); + +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 +); + +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; + +@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 +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +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 +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target 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/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/semmlecode.cpp.dbscheme b/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/semmlecode.cpp.dbscheme new file mode 100644 index 000000000000..f0156f5f88ab --- /dev/null +++ b/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/semmlecode.cpp.dbscheme @@ -0,0 +1,2339 @@ + +/** + * 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 +); + +/** + * 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, 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 +); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +extractor_version( + string codeql_version: string ref, + string frontend_version: string ref +) + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * 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( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * 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_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * 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_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: 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_default 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 +); + +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 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 + 1 = @normal_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +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 +); + +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_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) +is_structured_binding(unique int id: @variable 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 +); + +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 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _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 +; + +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 +; + +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 +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this 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. + */ +#keyset[id, expr] +decltypes( + int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* +case @usertype.kind of + 1 = @struct +| 2 = @class +| 3 = @union +| 4 = @enum +| 5 = @typedef // classic C: typedef typedef type name +| 6 = @template +| 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 // a using name = type style typedef +; +*/ + +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 +); + +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 +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location 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 +); + +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 +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +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; + +@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; + +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_expr 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_expr 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 +; + +@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 + ; + +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 +); + +/** + * 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 +); + +/** + * 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 +); + +@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 +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof; + +sizeof_bind( + unique int expr: @runtime_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 +); + +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_stmt 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 +; + +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 +); + +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 +); + +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; + +@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 +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +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 +); + +link_targets( + int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target 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/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/upgrade.properties b/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/upgrade.properties new file mode 100644 index 000000000000..08e1dc42eb29 --- /dev/null +++ b/cpp/ql/lib/upgrades/e51fad7a2436caefab0c6bd52f05e28e7cce4d92/upgrade.properties @@ -0,0 +1,2 @@ +description: Implement compilation_build_mode/2 +compatibility: backwards diff --git a/cpp/ql/src/Critical/UseAfterFree.qhelp b/cpp/ql/src/Critical/UseAfterFree.qhelp index 6a532ed4d358..60dd1a6690eb 100644 --- a/cpp/ql/src/Critical/UseAfterFree.qhelp +++ b/cpp/ql/src/Critical/UseAfterFree.qhelp @@ -8,7 +8,7 @@

This rule finds accesses through a pointer of a memory location that has already been freed (i.e. through a dangling pointer). Such memory blocks have already been released to the dynamic memory manager, and modifying them can lead to anything -from a segfault to memory corruption that would cause subsequent calls to the dynamic memory manger to behave +from a segfault to memory corruption that would cause subsequent calls to the dynamic memory manager to behave erratically, to a possible security vulnerability.

diff --git a/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.qll b/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.qll index 6f3f4d43e9aa..218a54b36c51 100644 --- a/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.qll +++ b/cpp/ql/src/Likely Bugs/Underspecified Functions/TooFewArguments.qll @@ -51,5 +51,7 @@ predicate tooFewArguments(FunctionCall fc, Function f) { hasDefiniteNumberOfParameters(fde) | fde.getNumberOfParameters() > fc.getNumberOfArguments() - ) + ) and + // Don't report on implicit function declarations, as these are likely extraction errors. + not f.getADeclarationEntry().isImplicit() } diff --git a/cpp/ql/src/Telemetry/CompilerErrors.ql b/cpp/ql/src/Telemetry/CompilerErrors.ql deleted file mode 100644 index 0f5166f9e9f5..000000000000 --- a/cpp/ql/src/Telemetry/CompilerErrors.ql +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @name Compiler errors - * @description A count of all compiler errors, grouped by error text. - * @kind metric - * @tags summary telemetry - * @id cpp/telemetry/compiler-errors - */ - -import Metrics - -from CppMetrics::ErrorCount m -where RankMetric::getRank(m) <= 50 -select m.toString(), m.getValue() diff --git a/cpp/ql/src/Telemetry/DatabaseQuality.ql b/cpp/ql/src/Telemetry/DatabaseQuality.ql deleted file mode 100644 index af8e340507b8..000000000000 --- a/cpp/ql/src/Telemetry/DatabaseQuality.ql +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name Database quality - * @description Metrics that indicate the quality of the database. - * @kind metric - * @tags summary telemetry - * @id cpp/telemetry/database-quality - */ - -import Metrics - -from QualityMetric m -select m.toString(), m.getValue() diff --git a/cpp/ql/src/Telemetry/Diagnostics.qll b/cpp/ql/src/Telemetry/Diagnostics.qll deleted file mode 100644 index cc7dcb3a36d7..000000000000 --- a/cpp/ql/src/Telemetry/Diagnostics.qll +++ /dev/null @@ -1,29 +0,0 @@ -import cpp - -/** - * A syntax error. - */ -class SyntaxError extends CompilerError { - SyntaxError() { - this.getTag().matches("exp_%") or - this.getTag() = - [ - "bad_data_member_initialization", "bad_pure_specifier", "bad_return", "bad_uuid_string", - "literal_without_initializer", "missing_class_definition", "missing_exception_declaration", - "nonstd_const_member_decl_not_allowed", "operator_name_not_allowed", - "wide_string_invalid_in_asm" - ] - } -} - -/** - * A cannot open file error. - * Typically this is due to a missing include. - */ -class CannotOpenFileError extends CompilerError { - CannotOpenFileError() { this.hasTag(["cannot_open_file", "cannot_open_file_reason"]) } - - string getIncludedFile() { - result = this.getMessage().regexpCapture("cannot open source file '([^']+)'", 1) - } -} diff --git a/cpp/ql/src/Telemetry/ExtractionMetrics.ql b/cpp/ql/src/Telemetry/ExtractionMetrics.ql deleted file mode 100644 index 968bf456ecb9..000000000000 --- a/cpp/ql/src/Telemetry/ExtractionMetrics.ql +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name Extraction metrics - * @description Raw metrics relating to extraction. - * @kind metric - * @tags summary telemetry - * @id cpp/telemetry/extraction-metrics - */ - -import Metrics - -from ExtractionMetric m -select m.toString(), m.getValue() diff --git a/cpp/ql/src/Telemetry/Metrics.qll b/cpp/ql/src/Telemetry/Metrics.qll deleted file mode 100644 index b3c90af84501..000000000000 --- a/cpp/ql/src/Telemetry/Metrics.qll +++ /dev/null @@ -1,269 +0,0 @@ -import cpp -import Diagnostics - -/** - * A metric is a string with a value. - */ -abstract class Metric extends string { - bindingset[this] - Metric() { any() } -} - -/** - * A metric that we want to report in cpp/telemetry/extraction-metrics - */ -abstract class ExtractionMetric extends Metric { - bindingset[this] - ExtractionMetric() { any() } - - /** Gets the value of this metric. */ - abstract int getValue(); -} - -/** - * A metric that provides a baseline for a SuccessMetric. - */ -abstract class BaseMetric extends ExtractionMetric { - bindingset[this] - BaseMetric() { any() } -} - -/** - * A metric that is relative to another metric, - * so can be used to calculate percentages. - * - * For clarity, metrics should express success, - * so higher values means better. - */ -abstract class SuccessMetric extends ExtractionMetric { - bindingset[this] - SuccessMetric() { any() } - - /** Gets the metric this is relative to. */ - abstract BaseMetric getBaseline(); -} - -/** - * A metric used to report database quality. - */ -class QualityMetric extends Metric { - BaseMetric baseMetric; - SuccessMetric relativeMetric; - - QualityMetric() { - baseMetric = relativeMetric.getBaseline() and this = "Percentage of " + relativeMetric - } - - float getValue() { - baseMetric.getValue() > 0 and - result = 100.0 * relativeMetric.getValue() / baseMetric.getValue() - } -} - -signature class RankedMetric extends Metric { - int getValue(); -} - -module RankMetric { - int getRank(M s) { s = rank[result](M m | | m order by m.getValue() desc) } -} - -/** Various metrics we want to report. */ -module CppMetrics { - class Compilations extends BaseMetric { - Compilations() { this = "compilations" } - - override int getValue() { result = count(Compilation c) } - } - - class SourceAndHeaderFiles extends BaseMetric { - SourceAndHeaderFiles() { this = "source/header files" } - - override int getValue() { result = count(File f | f.fromSource()) } - } - - class SourceAndHeaderFilesWithoutErrors extends SuccessMetric { - SourceAndHeaderFilesWithoutErrors() { this = "source/header files without errors" } - - override int getValue() { - result = count(File f | f.fromSource() and not exists(CompilerError e | f = e.getFile())) - } - - override SourceAndHeaderFiles getBaseline() { any() } - } - - class CompilationsWithoutErrors extends SuccessMetric { - CompilationsWithoutErrors() { this = "compilations without errors" } - - override int getValue() { - result = count(Compilation c | not exists(Diagnostic d | d.getFile() = c.getAFileCompiled())) - } - - override Compilations getBaseline() { any() } - } - - class Expressions extends BaseMetric { - Expressions() { this = "expressions" } - - override int getValue() { result = count(Expr e) } - } - - class SucceededExpressions extends SuccessMetric { - SucceededExpressions() { this = "non-error expressions" } - - override int getValue() { result = count(Expr e) - count(ErrorExpr e) } - - override Expressions getBaseline() { any() } - } - - class TypedExpressions extends SuccessMetric { - TypedExpressions() { this = "expressions with a known type" } - - override int getValue() { result = count(Expr e | not e.getType() instanceof ErroneousType) } - - override Expressions getBaseline() { any() } - } - - class Calls extends BaseMetric { - Calls() { this = "calls" } - - override int getValue() { result = count(Call c) } - } - - class CallsWithExplicitTarget extends SuccessMetric { - CallsWithExplicitTarget() { this = "calls with an explicit target" } - - override int getValue() { - result = count(Call c | not c.getTarget().getADeclarationEntry().isImplicit()) - } - - override Calls getBaseline() { any() } - } - - class Variables extends BaseMetric { - Variables() { this = "variables" } - - override int getValue() { result = count(Variable v) } - } - - class VariablesKnownType extends SuccessMetric { - VariablesKnownType() { this = "variables with a known type" } - - override int getValue() { - result = count(Variable v | not v.getType() instanceof ErroneousType) - } - - override Variables getBaseline() { any() } - } - - class LinesOfText extends BaseMetric { - LinesOfText() { this = "lines of text" } - - override int getValue() { result = sum(File f | | f.getMetrics().getNumberOfLines()) } - } - - class LinesOfCode extends BaseMetric { - LinesOfCode() { this = "lines of code" } - - override int getValue() { result = sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) } - } - - private predicate errorLine(File file, int line) { - exists(Locatable l, Location loc | - loc = l.getLocation() and - loc.getFile() = file and - line in [loc.getStartLine() .. loc.getEndLine()] - | - l instanceof Diagnostic - or - l instanceof ErrorExpr - ) - } - - class SucceededLines extends SuccessMetric { - SucceededLines() { this = "lines of code without errors" } - - override int getValue() { - result = - sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) - - count(File f, int line | errorLine(f, line)) - } - - override LinesOfCode getBaseline() { any() } - } - - class Functions extends BaseMetric { - Functions() { this = "functions" } - - override int getValue() { result = count(Function f) } - } - - class SucceededFunctions extends SuccessMetric { - SucceededFunctions() { this = "functions without errors" } - - override int getValue() { result = count(Function f | not f.hasErrors()) } - - override Functions getBaseline() { any() } - } - - class Includes extends BaseMetric { - Includes() { this = "#include directives" } - - override int getValue() { result = count(Include i) + count(CannotOpenFileError e) } - } - - class SucceededIncludes extends SuccessMetric { - SucceededIncludes() { this = "successfully resolved #include directives" } - - override int getValue() { result = count(Include i) } - - override Includes getBaseline() { any() } - } - - class SucceededIncludeCount extends Metric { - string includeText; - - SucceededIncludeCount() { - exists(Include i | - i.getIncludeText() = includeText and - exists(i.getFile().getRelativePath()) // Only report includes from the repo - ) and - this = "Successfully included " + includeText - } - - int getValue() { result = count(Include i | i.getIncludeText() = includeText) } - - string getIncludeText() { result = includeText } - } - - class MissingIncludeCount extends Metric { - string includeText; - - MissingIncludeCount() { - exists(CannotOpenFileError e | e.getIncludedFile() = includeText) and - this = "Failed to include '" + includeText + "'" - } - - int getValue() { result = count(CannotOpenFileError e | e.getIncludedFile() = includeText) } - - string getIncludeText() { result = includeText } - } - - class CompilerErrors extends ExtractionMetric { - CompilerErrors() { this = "compiler errors" } - - override int getValue() { result = count(CompilerError e) } - } - - class ErrorCount extends Metric { - ErrorCount() { exists(CompilerError e | e.getMessage() = this) } - - int getValue() { result = count(CompilerError e | e.getMessage() = this) } - } - - class SyntaxErrorCount extends ExtractionMetric { - SyntaxErrorCount() { this = "syntax errors" } - - override int getValue() { result = count(SyntaxError e) } - } -} diff --git a/cpp/ql/src/Telemetry/MissingIncludes.ql b/cpp/ql/src/Telemetry/MissingIncludes.ql deleted file mode 100644 index 6ff58729dd2b..000000000000 --- a/cpp/ql/src/Telemetry/MissingIncludes.ql +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @name Failed to include header file - * @description A count of all failed includes, grouped by filename. - * @kind metric - * @tags summary telemetry - * @id cpp/telemetry/failed-includes - */ - -import Metrics - -from CppMetrics::MissingIncludeCount e -where RankMetric::getRank(e) <= 50 -select e.getIncludeText(), e.getValue() diff --git a/cpp/ql/src/Telemetry/SucceededIncludes.ql b/cpp/ql/src/Telemetry/SucceededIncludes.ql deleted file mode 100644 index aa08acd9fdb7..000000000000 --- a/cpp/ql/src/Telemetry/SucceededIncludes.ql +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @name Successfully included header files - * @description A count of all succeeded includes, grouped by filename. - * @kind metric - * @tags summary telemetry - * @id cpp/telemetry/succeeded-includes - */ - -import Metrics - -from CppMetrics::SucceededIncludeCount m -where RankMetric::getRank(m) <= 50 -select m.getIncludeText(), m.getValue() diff --git a/cpp/ql/src/change-notes/2024-11-22-too-few-arguments.md b/cpp/ql/src/change-notes/2024-11-22-too-few-arguments.md new file mode 100644 index 000000000000..116df08838a1 --- /dev/null +++ b/cpp/ql/src/change-notes/2024-11-22-too-few-arguments.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Call to function with fewer arguments than declared parameters" query (`cpp/too-few-arguments`) query no longer produces results if the function has been implicitly declared. diff --git a/cpp/ql/src/experimental/Best Practices/GuardedFree.ql b/cpp/ql/src/experimental/Best Practices/GuardedFree.ql index 2d504d9bc057..66c7a31111b5 100644 --- a/cpp/ql/src/experimental/Best Practices/GuardedFree.ql +++ b/cpp/ql/src/experimental/Best Practices/GuardedFree.ql @@ -18,9 +18,31 @@ class FreeCall extends FunctionCall { FreeCall() { this.getTarget().hasGlobalName("free") } } +predicate blockContainsPreprocessorBranches(BasicBlock bb) { + exists(PreprocessorBranch ppb, Location bbLoc, Location ppbLoc | + bbLoc = bb.(Stmt).getLocation() and ppbLoc = ppb.getLocation() + | + bbLoc.getFile() = ppb.getFile() and + bbLoc.getStartLine() < ppbLoc.getStartLine() and + ppbLoc.getEndLine() < bbLoc.getEndLine() + ) +} + from GuardCondition gc, FreeCall fc, Variable v, BasicBlock bb where gc.ensuresEq(v.getAnAccess(), 0, bb, false) and fc.getArgument(0) = v.getAnAccess() and - bb = fc.getEnclosingStmt() + bb = fc.getBasicBlock() and + ( + // No block statement: if (x) free(x); + bb = fc.getEnclosingStmt() + or + // Block statement with a single nested statement: if (x) { free(x); } + strictcount(bb.(BlockStmt).getAStmt()) = 1 + ) and + strictcount(BasicBlock bb2 | gc.ensuresEq(_, 0, bb2, _) | bb2) = 1 and + not fc.isInMacroExpansion() and + not blockContainsPreprocessorBranches(bb) and + not (gc instanceof BinaryOperation and not gc instanceof ComparisonOperation) and + not exists(CommaExpr c | c.getAChild*() = fc) select gc, "unnecessary NULL check before call to $@", fc, "free" diff --git a/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/GuardedFree.expected b/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/GuardedFree.expected index 209bae407b82..a9a189218c62 100644 --- a/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/GuardedFree.expected +++ b/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/GuardedFree.expected @@ -1,10 +1,5 @@ | test.cpp:5:7:5:7 | x | unnecessary NULL check before call to $@ | test.cpp:6:5:6:8 | call to free | free | -| test.cpp:23:7:23:7 | x | unnecessary NULL check before call to $@ | test.cpp:26:5:26:8 | call to free | free | -| test.cpp:31:7:31:8 | ! ... | unnecessary NULL check before call to $@ | test.cpp:35:3:35:6 | call to free | free | -| test.cpp:31:7:31:24 | ... \|\| ... | unnecessary NULL check before call to $@ | test.cpp:35:3:35:6 | call to free | free | -| test.cpp:31:8:31:8 | x | unnecessary NULL check before call to $@ | test.cpp:35:3:35:6 | call to free | free | -| test.cpp:94:12:94:12 | x | unnecessary NULL check before call to $@ | test.cpp:94:3:94:13 | call to free | free | -| test.cpp:98:7:98:8 | ! ... | unnecessary NULL check before call to $@ | test.cpp:101:3:101:6 | call to free | free | -| test.cpp:98:8:98:8 | x | unnecessary NULL check before call to $@ | test.cpp:101:3:101:6 | call to free | free | +| test.cpp:10:7:10:7 | x | unnecessary NULL check before call to $@ | test.cpp:11:5:11:8 | call to free | free | +| test.cpp:42:7:42:7 | x | unnecessary NULL check before call to $@ | test.cpp:43:5:43:8 | call to free | free | +| test.cpp:49:7:49:7 | x | unnecessary NULL check before call to $@ | test.cpp:50:5:50:8 | call to free | free | | test.cpp:106:7:106:18 | ... != ... | unnecessary NULL check before call to $@ | test.cpp:107:5:107:8 | call to free | free | -| test.cpp:113:7:113:18 | ... != ... | unnecessary NULL check before call to $@ | test.cpp:114:17:114:20 | call to free | free | diff --git a/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/test.cpp b/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/test.cpp index 12b1fb2364e7..d52bcef72d16 100644 --- a/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Best Practices/GuardedFree/test.cpp @@ -20,7 +20,7 @@ void test2(int *x) { } void test3(int *x, bool b) { - if (x) { // GOOD [FALSE POSITIVE]: x is being accessed in the body of the if + if (x) { // GOOD: x is being accessed in the body of the if if (b) *x = 42; free(x); @@ -28,7 +28,7 @@ void test3(int *x, bool b) { } bool test4(char *x, char *y) { - if (!x || strcmp(x, y)) { // GOOD [FALSE POSITIVE]: x is being accessed in the guard and return value depends on x + if (!x || strcmp(x, y)) { // GOOD: x is being accessed in the guard and return value depends on x free(x); return true; } @@ -91,11 +91,11 @@ void test10(char *x) { if (x) free(x); void test11(char *x) { - TRY_FREE(x) // BAD + TRY_FREE(x) // BAD [NOT DETECTED] } bool test12(char *x) { - if (!x) // GOOD [FALSE POSITIVE]: return value depends on x + if (!x) // GOOD: return value depends on x return false; free(x); @@ -110,6 +110,6 @@ void test13(char *x) { void inspect(char *x); void test14(char *x) { - if (x != nullptr) // GOOD [FALSE POSITIVE]: x might be accessed in the first operand of the comma operator + if (x != nullptr) // GOOD: x might be accessed in the first operand of the comma operator inspect(x), free(x); } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/format.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/format.cpp index d123ed5cc155..b69a0b3d58f7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/format.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/format.cpp @@ -164,4 +164,10 @@ void test_format() { auto s2 = std::format(string::source()); sink(s2); // $ ir MISSING: ast +} + +void test(std::format_string s) { + int x = source(); + int y = std::same_signature_as_format_but_different_name(s, x); + sink(y); // clean } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 7de6914e8aac..b5ddf84747ae 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -451,6 +451,9 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future | format.cpp:162:24:162:27 | {} | format.cpp:162:24:162:27 | call to basic_format_string | TAINT | | format.cpp:165:13:165:23 | call to format | format.cpp:166:8:166:9 | s2 | | | format.cpp:165:25:165:38 | call to source | format.cpp:165:25:165:40 | call to basic_format_string | TAINT | +| format.cpp:169:30:169:30 | s | format.cpp:171:60:171:60 | s | | +| format.cpp:170:11:170:16 | call to source | format.cpp:171:63:171:63 | x | | +| format.cpp:171:11:171:58 | call to same_signature_as_format_but_different_name | format.cpp:172:8:172:8 | y | | | map.cpp:21:28:21:28 | call to pair | map.cpp:23:2:23:2 | a | | | map.cpp:21:28:21:28 | call to pair | map.cpp:24:7:24:7 | a | | | map.cpp:21:28:21:28 | call to pair | map.cpp:25:7:25:7 | a | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h index 9647f41cb7c4..01e5f3b929b0 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.h @@ -676,4 +676,9 @@ namespace std { using format_string = basic_format_string; // simplified from `char, std::type_identity_t...` template string format( format_string fmt, Args&&... args ); + + // This function has the same signature as `format`, but a different name. It should NOT be able to use + // the model for `format`. + template + int same_signature_as_format_but_different_name(format_string, Args &&...args); } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected index 0d27fdaf0fda..26031f42c0ac 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_mad-signatures.expected @@ -265,6 +265,8 @@ signatureMatches | stl.h:678:33:678:38 | format | (format_string,Args &&) | | format | 0 | | stl.h:678:33:678:38 | format | (format_string,Args &&) | | format | 1 | | stl.h:678:33:678:38 | format | (format_string,Args &&) | | format | 1 | +| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | (format_string,Args &&) | | format | 0 | +| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | (format_string,Args &&) | | format | 1 | getSignatureParameterName | (InputIt,InputIt) | deque | assign | 0 | func:0 | | (InputIt,InputIt) | deque | assign | 1 | func:0 | @@ -729,6 +731,8 @@ getParameterTypeName | stl.h:678:33:678:38 | format | 0 | format_string | | stl.h:678:33:678:38 | format | 1 | func:0 && | | stl.h:678:33:678:38 | format | 1 | func:0 && | +| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | 0 | format_string | +| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | 1 | func:0 && | | stringstream.cpp:18:6:18:9 | sink | 0 | const basic_ostream> & | | stringstream.cpp:21:6:21:9 | sink | 0 | const basic_istream> & | | stringstream.cpp:24:6:24:9 | sink | 0 | const basic_iostream> & | diff --git a/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected b/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected deleted file mode 100644 index 1e4e4c8e3c60..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.expected +++ /dev/null @@ -1,10 +0,0 @@ -| 'this' may only be used inside a nonstatic member function | 1 | -| There was an error during this compilation | 1 | -| expected a ')' | 1 | -| expected a ';' | 1 | -| expected an expression | 1 | -| identifier 'no_such_function' is undefined | 1 | -| identifier 'nsf2' is undefined | 1 | -| identifier 'so_is_this' is undefined | 1 | -| identifier 'uint32_t' is undefined | 1 | -| too few arguments in function call | 1 | diff --git a/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref b/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref deleted file mode 100644 index fd0c287c00dc..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/CompilerErrors.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/CompilerErrors.ql diff --git a/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected b/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected deleted file mode 100644 index 6d9cea2d734d..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.expected +++ /dev/null @@ -1,9 +0,0 @@ -| Percentage of calls with an explicit target | 50.0 | -| Percentage of compilations without errors | 50.0 | -| Percentage of expressions with a known type | 30.0 | -| Percentage of functions without errors | 75.0 | -| Percentage of lines of code without errors | 63.1578947368421 | -| Percentage of non-error expressions | 30.0 | -| Percentage of source/header files without errors | 66.66666666666667 | -| Percentage of successfully resolved #include directives | 100.0 | -| Percentage of variables with a known type | 90.0 | diff --git a/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref b/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref deleted file mode 100644 index b2c536f00d70..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/DatabaseQuality.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/DatabaseQuality.ql diff --git a/cpp/ql/test/library-tests/extraction_errors/ErrorExprs.expected b/cpp/ql/test/library-tests/extraction_errors/ErrorExprs.expected deleted file mode 100644 index 3f437a7fd26a..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/ErrorExprs.expected +++ /dev/null @@ -1,7 +0,0 @@ -| test.cpp:6:13:6:31 | initializer for x | test.cpp:6:13:6:31 | | -| test.cpp:7:5:7:8 | ExprStmt | file://:0:0:0:0 | | -| test.cpp:8:5:8:23 | ExprStmt | file://:0:0:0:0 | | -| test.cpp:9:5:9:21 | ExprStmt | file://:0:0:0:0 | | -| test.cpp:11:5:11:8 | ExprStmt | file://:0:0:0:0 | | -| test.cpp:15:5:15:8 | ExprStmt | file://:0:0:0:0 | | -| test.cpp:16:5:16:16 | ExprStmt | file://:0:0:0:0 | | diff --git a/cpp/ql/test/library-tests/extraction_errors/ErrorExprs.ql b/cpp/ql/test/library-tests/extraction_errors/ErrorExprs.ql deleted file mode 100644 index 25c2118e0108..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/ErrorExprs.ql +++ /dev/null @@ -1,4 +0,0 @@ -import cpp - -from ErrorExpr e -select e.getParent(), e diff --git a/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected b/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected deleted file mode 100644 index ee2cc0f99630..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.expected +++ /dev/null @@ -1,20 +0,0 @@ -| #include directives | 2 | -| calls | 2 | -| calls with an explicit target | 1 | -| compilations | 2 | -| compilations without errors | 1 | -| compiler errors | 10 | -| expressions | 10 | -| expressions with a known type | 3 | -| functions | 8 | -| functions without errors | 6 | -| lines of code | 19 | -| lines of code without errors | 12 | -| lines of text | 24 | -| non-error expressions | 3 | -| source/header files | 3 | -| source/header files without errors | 2 | -| successfully resolved #include directives | 2 | -| syntax errors | 3 | -| variables | 10 | -| variables with a known type | 9 | diff --git a/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref b/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref deleted file mode 100644 index 80547fdfd981..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/ExtractionMetrics.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/ExtractionMetrics.ql \ No newline at end of file diff --git a/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected b/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected deleted file mode 100644 index 13536ce172c5..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.expected +++ /dev/null @@ -1 +0,0 @@ -| "test.h" | 2 | diff --git a/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref b/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref deleted file mode 100644 index 055b6af49a75..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/SucceededIncludes.qlref +++ /dev/null @@ -1 +0,0 @@ -Telemetry/SucceededIncludes.ql diff --git a/cpp/ql/test/library-tests/extraction_errors/diags.expected b/cpp/ql/test/library-tests/extraction_errors/diags.expected deleted file mode 100644 index 68e5c9c154c4..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/diags.expected +++ /dev/null @@ -1,10 +0,0 @@ -| file://:0:0:0:0 | There was an error during this compilation | -| test.cpp:6:14:6:14 | identifier 'no_such_function' is undefined | -| test.cpp:9:14:9:14 | identifier 'nsf2' is undefined | -| test.cpp:11:7:11:7 | too few arguments in function call | -| test.cpp:14:1:14:1 | identifier 'uint32_t' is undefined | -| test.cpp:15:5:15:5 | 'this' may only be used inside a nonstatic member function | -| test.cpp:15:10:15:10 | expected a ';' | -| test.cpp:16:5:16:5 | identifier 'so_is_this' is undefined | -| test.cpp:16:16:16:16 | expected a ')' | -| test.cpp:16:16:16:16 | expected an expression | diff --git a/cpp/ql/test/library-tests/extraction_errors/diags.ql b/cpp/ql/test/library-tests/extraction_errors/diags.ql deleted file mode 100644 index 3fa864748e16..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/diags.ql +++ /dev/null @@ -1,4 +0,0 @@ -import cpp - -from Diagnostic d -select d diff --git a/cpp/ql/test/library-tests/extraction_errors/error_variables.expected b/cpp/ql/test/library-tests/extraction_errors/error_variables.expected deleted file mode 100644 index d5b216dba71a..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/error_variables.expected +++ /dev/null @@ -1 +0,0 @@ -| test.cpp:6:10:6:10 | x | This variable does not have a type. | diff --git a/cpp/ql/test/library-tests/extraction_errors/error_variables.ql b/cpp/ql/test/library-tests/extraction_errors/error_variables.ql deleted file mode 100644 index e3867462b568..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/error_variables.ql +++ /dev/null @@ -1,5 +0,0 @@ -import cpp - -from Variable v -where v.getType() instanceof ErroneousType or not exists(v.getType()) -select v, "This variable does not have a type." diff --git a/cpp/ql/test/library-tests/extraction_errors/functions.expected b/cpp/ql/test/library-tests/extraction_errors/functions.expected deleted file mode 100644 index db80ede06555..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/functions.expected +++ /dev/null @@ -1,6 +0,0 @@ -| test.c:3:6:3:6 | g | -| test.c:4:13:4:13 | no_such_function | -| test.cpp:5:6:5:25 | function_with_errors | -| test.cpp:14:10:14:12 | fn2 | -| test.h:2:5:2:5 | f | -| test.h:2:5:2:5 | f | diff --git a/cpp/ql/test/library-tests/extraction_errors/functions.ql b/cpp/ql/test/library-tests/extraction_errors/functions.ql deleted file mode 100644 index ac52eec7309d..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/functions.ql +++ /dev/null @@ -1,5 +0,0 @@ -import cpp - -from Function fn -where fn.fromSource() -select fn diff --git a/cpp/ql/test/library-tests/extraction_errors/test.c b/cpp/ql/test/library-tests/extraction_errors/test.c deleted file mode 100644 index e247964f71ca..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/test.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "test.h" - -void g() { - int x = no_such_function(); -} diff --git a/cpp/ql/test/library-tests/extraction_errors/test.cpp b/cpp/ql/test/library-tests/extraction_errors/test.cpp deleted file mode 100644 index b2ca86bcbaa6..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/test.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// semmle-extractor-options: --expect_errors - -#include "test.h" - -void function_with_errors() { - auto x = no_such_function(); - x+2; - no_such_function(); - ADD(x+1, nsf2()); - f(1); - f(); -} - -uint32_t fn2() { - this is a syntax error; - so_is_this(; -} diff --git a/cpp/ql/test/library-tests/extraction_errors/test.h b/cpp/ql/test/library-tests/extraction_errors/test.h deleted file mode 100644 index a3941657c0e3..000000000000 --- a/cpp/ql/test/library-tests/extraction_errors/test.h +++ /dev/null @@ -1,2 +0,0 @@ -#define ADD(A,B) ((A)+(B)) -int f(int); diff --git a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.expected b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.expected index 8547894e769b..d3e0ecbd591b 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/ImplicitFunctionDeclaration.expected @@ -1,9 +1,9 @@ | test.c:28:3:28:12 | call to undeclared | Function call implicitly declares 'undeclared'. | | test.c:31:3:31:19 | call to not_yet_declared1 | Function call implicitly declares 'not_yet_declared1'. | | test.c:32:3:32:19 | call to not_yet_declared2 | Function call implicitly declares 'not_yet_declared2'. | -| test.c:43:3:43:27 | call to not_declared_defined_with | Function call implicitly declares 'not_declared_defined_with'. | -| test.c:54:3:54:21 | call to defined_with_double | Function call implicitly declares 'defined_with_double'. | -| test.c:66:3:66:22 | call to defined_with_ptr_ptr | Function call implicitly declares 'defined_with_ptr_ptr'. | -| test.c:68:3:68:22 | call to defined_with_ptr_arr | Function call implicitly declares 'defined_with_ptr_arr'. | -| test.c:132:3:132:22 | call to implicit_declaration | Function call implicitly declares 'implicit_declaration'. | -| test.c:133:3:133:30 | call to implicit_declaration_k_and_r | Function call implicitly declares 'implicit_declaration_k_and_r'. | +| test.c:44:3:44:27 | call to not_declared_defined_with | Function call implicitly declares 'not_declared_defined_with'. | +| test.c:55:3:55:21 | call to defined_with_double | Function call implicitly declares 'defined_with_double'. | +| test.c:67:3:67:22 | call to defined_with_ptr_ptr | Function call implicitly declares 'defined_with_ptr_ptr'. | +| test.c:69:3:69:22 | call to defined_with_ptr_arr | Function call implicitly declares 'defined_with_ptr_arr'. | +| test.c:133:3:133:22 | call to implicit_declaration | Function call implicitly declares 'implicit_declaration'. | +| test.c:134:3:134:30 | call to implicit_declaration_k_and_r | Function call implicitly declares 'implicit_declaration_k_and_r'. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.expected index b6015dad4564..d067430aba9c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.expected @@ -1,18 +1,18 @@ -| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:3:32:3 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int[4] | int[4] | test.c:76:24:76:26 | (unnamed parameter 0) | int (unnamed parameter 0) | -| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:76:6:76:22 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int[4] | int[4] | test.c:76:24:76:26 | (unnamed parameter 0) | int (unnamed parameter 0) | -| test.c:40:3:40:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:77:6:77:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:40:31:40:32 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:77:38:77:38 | x | int x | -| test.c:44:3:44:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:80:6:80:30 | not_declared_defined_with | not_declared_defined_with | test.c:44:29:44:31 | 4 | 4 | file://:0:0:0:0 | long long | long long | test.c:80:36:80:36 | x | int x | -| test.c:44:3:44:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:80:6:80:30 | not_declared_defined_with | not_declared_defined_with | test.c:44:37:44:42 | 2500000000.0 | 2500000000.0 | file://:0:0:0:0 | float | float | test.c:80:50:80:50 | z | int z | -| test.c:47:3:47:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:5:6:5:27 | declared_with_pointers | declared_with_pointers | test.c:47:26:47:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:92:34:92:34 | x | int * x | -| test.c:47:3:47:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:5:6:5:27 | declared_with_pointers | declared_with_pointers | test.c:47:34:47:34 | 0 | 0 | file://:0:0:0:0 | int | int | test.c:92:43:92:43 | y | void * y | -| test.c:47:3:47:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:92:6:92:27 | declared_with_pointers | declared_with_pointers | test.c:47:26:47:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:92:34:92:34 | x | int * x | -| test.c:47:3:47:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:92:6:92:27 | declared_with_pointers | declared_with_pointers | test.c:47:34:47:34 | 0 | 0 | file://:0:0:0:0 | int | int | test.c:92:43:92:43 | y | void * y | -| test.c:49:3:49:21 | call to declared_with_array | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:6:6:6:24 | declared_with_array | declared_with_array | test.c:49:23:49:24 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:93:31:93:31 | a | char[6] a | -| test.c:49:3:49:21 | call to declared_with_array | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:93:6:93:24 | declared_with_array | declared_with_array | test.c:49:23:49:24 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:93:31:93:31 | a | char[6] a | -| test.c:51:3:51:20 | call to defined_with_float | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:95:7:95:24 | defined_with_float | defined_with_float | test.c:51:22:51:24 | 2.0 | 2.0 | file://:0:0:0:0 | float | float | test.c:95:32:95:32 | f | float f | -| test.c:52:3:52:20 | call to defined_with_float | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:95:7:95:24 | defined_with_float | defined_with_float | test.c:52:22:52:24 | 2.0 | 2.0 | file://:0:0:0:0 | double | double | test.c:95:32:95:32 | f | float f | -| test.c:55:3:55:21 | call to defined_with_double | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:99:8:99:26 | defined_with_double | defined_with_double | test.c:55:23:55:25 | 99 | 99 | file://:0:0:0:0 | int | int | test.c:99:35:99:35 | d | double d | -| test.c:57:3:57:24 | call to defined_with_long_long | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:103:11:103:32 | defined_with_long_long | defined_with_long_long | test.c:57:26:57:28 | 99 | 99 | file://:0:0:0:0 | int | int | test.c:103:44:103:45 | ll | long long ll | -| test.c:58:3:58:24 | call to defined_with_long_long | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:103:11:103:32 | defined_with_long_long | defined_with_long_long | test.c:58:26:58:26 | 3 | 3 | file://:0:0:0:0 | int | int | test.c:103:44:103:45 | ll | long long ll | -| test.c:60:3:60:21 | call to defined_with_double | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:99:8:99:26 | defined_with_double | defined_with_double | test.c:60:23:60:25 | 2 | 2 | file://:0:0:0:0 | long long | long long | test.c:99:35:99:35 | d | double d | -| test.c:61:3:61:24 | call to defined_with_long_long | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:103:11:103:32 | defined_with_long_long | defined_with_long_long | test.c:61:26:61:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:103:44:103:45 | ll | long long ll | +| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:32:3:32:3 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int[4] | int[4] | test.c:77:24:77:26 | (unnamed parameter 0) | int (unnamed parameter 0) | +| test.c:33:3:33:19 | call to not_yet_declared2 | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:77:6:77:22 | not_yet_declared2 | not_yet_declared2 | test.c:33:21:33:22 | ca | ca | file://:0:0:0:0 | int[4] | int[4] | test.c:77:24:77:26 | (unnamed parameter 0) | int (unnamed parameter 0) | +| test.c:41:3:41:29 | call to declared_empty_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:78:6:78:32 | declared_empty_defined_with | declared_empty_defined_with | test.c:41:31:41:32 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:78:38:78:38 | x | int x | +| test.c:45:3:45:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:81:6:81:30 | not_declared_defined_with | not_declared_defined_with | test.c:45:29:45:31 | 4 | 4 | file://:0:0:0:0 | long long | long long | test.c:81:36:81:36 | x | int x | +| test.c:45:3:45:27 | call to not_declared_defined_with | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:81:6:81:30 | not_declared_defined_with | not_declared_defined_with | test.c:45:37:45:42 | 2500000000.0 | 2500000000.0 | file://:0:0:0:0 | float | float | test.c:81:50:81:50 | z | int z | +| test.c:48:3:48:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:5:6:5:27 | declared_with_pointers | declared_with_pointers | test.c:48:26:48:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:93:34:93:34 | x | int * x | +| test.c:48:3:48:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:5:6:5:27 | declared_with_pointers | declared_with_pointers | test.c:48:34:48:34 | 0 | 0 | file://:0:0:0:0 | int | int | test.c:93:43:93:43 | y | void * y | +| test.c:48:3:48:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:93:6:93:27 | declared_with_pointers | declared_with_pointers | test.c:48:26:48:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:93:34:93:34 | x | int * x | +| test.c:48:3:48:24 | call to declared_with_pointers | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:93:6:93:27 | declared_with_pointers | declared_with_pointers | test.c:48:34:48:34 | 0 | 0 | file://:0:0:0:0 | int | int | test.c:93:43:93:43 | y | void * y | +| test.c:50:3:50:21 | call to declared_with_array | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:6:6:6:24 | declared_with_array | declared_with_array | test.c:50:23:50:24 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:94:31:94:31 | a | char[6] a | +| test.c:50:3:50:21 | call to declared_with_array | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:94:6:94:24 | declared_with_array | declared_with_array | test.c:50:23:50:24 | & ... | & ... | file://:0:0:0:0 | int * | int * | test.c:94:31:94:31 | a | char[6] a | +| test.c:52:3:52:20 | call to defined_with_float | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:96:7:96:24 | defined_with_float | defined_with_float | test.c:52:22:52:24 | 2.0 | 2.0 | file://:0:0:0:0 | float | float | test.c:96:32:96:32 | f | float f | +| test.c:53:3:53:20 | call to defined_with_float | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:96:7:96:24 | defined_with_float | defined_with_float | test.c:53:22:53:24 | 2.0 | 2.0 | file://:0:0:0:0 | double | double | test.c:96:32:96:32 | f | float f | +| test.c:56:3:56:21 | call to defined_with_double | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:100:8:100:26 | defined_with_double | defined_with_double | test.c:56:23:56:25 | 99 | 99 | file://:0:0:0:0 | int | int | test.c:100:35:100:35 | d | double d | +| test.c:58:3:58:24 | call to defined_with_long_long | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:104:11:104:32 | defined_with_long_long | defined_with_long_long | test.c:58:26:58:28 | 99 | 99 | file://:0:0:0:0 | int | int | test.c:104:44:104:45 | ll | long long ll | +| test.c:59:3:59:24 | call to defined_with_long_long | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:104:11:104:32 | defined_with_long_long | defined_with_long_long | test.c:59:26:59:26 | 3 | 3 | file://:0:0:0:0 | int | int | test.c:104:44:104:45 | ll | long long ll | +| test.c:61:3:61:21 | call to defined_with_double | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:100:8:100:26 | defined_with_double | defined_with_double | test.c:61:23:61:25 | 2 | 2 | file://:0:0:0:0 | long long | long long | test.c:100:35:100:35 | d | double d | +| test.c:62:3:62:24 | call to defined_with_long_long | Calling $@: argument $@ of type $@ is incompatible with parameter $@. | test.c:104:11:104:32 | defined_with_long_long | defined_with_long_long | test.c:62:26:62:31 | 3500000000000000.0 | 3500000000000000.0 | file://:0:0:0:0 | double | double | test.c:104:44:104:45 | ll | long long ll | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooFewArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooFewArguments.expected index 42c4f7f94559..90468d3a9bfc 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooFewArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooFewArguments.expected @@ -1,4 +1,2 @@ -| test.c:34:3:34:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:32:3:32:3 | not_yet_declared2 | not_yet_declared2 | -| test.c:34:3:34:19 | call to not_yet_declared2 | This call has fewer arguments than required by $@. | test.c:76:6:76:22 | not_yet_declared2 | not_yet_declared2 | -| test.c:36:3:36:29 | call to declared_empty_defined_with | This call has fewer arguments than required by $@. | test.c:77:6:77:32 | declared_empty_defined_with | declared_empty_defined_with | -| test.c:87:10:87:20 | call to dereference | This call has fewer arguments than required by $@. | test.c:90:5:90:15 | dereference | dereference | +| test.c:37:3:37:29 | call to declared_empty_defined_with | This call has fewer arguments than required by $@. | test.c:78:6:78:32 | declared_empty_defined_with | declared_empty_defined_with | +| test.c:88:10:88:20 | call to dereference | This call has fewer arguments than required by $@. | test.c:91:5:91:15 | dereference | dereference | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooManyArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooManyArguments.expected index bc64434578b2..6eff27c3adb3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooManyArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/TooManyArguments.expected @@ -1,2 +1,2 @@ -| test.c:41:3:41:29 | call to declared_empty_defined_with | This call has more arguments than required by $@. | test.c:77:6:77:32 | declared_empty_defined_with | declared_empty_defined_with | -| test.c:72:3:72:28 | call to declared_and_defined_empty | This call has more arguments than required by $@. | test.c:114:6:114:31 | declared_and_defined_empty | declared_and_defined_empty | +| test.c:42:3:42:29 | call to declared_empty_defined_with | This call has more arguments than required by $@. | test.c:78:6:78:32 | declared_empty_defined_with | declared_empty_defined_with | +| test.c:73:3:73:28 | call to declared_and_defined_empty | This call has more arguments than required by $@. | test.c:115:6:115:31 | declared_and_defined_empty | declared_and_defined_empty | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/test.c b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/test.c index 86e940a8e282..d77c16683ed6 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/test.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Underspecified Functions/test.c @@ -30,8 +30,9 @@ void test(int *argv[]) { not_yet_declared1(1); // BAD (GOOD for everything except for cpp/implicit-function-declaration) not_yet_declared2(1); // BAD (GOOD for everything except for cpp/implicit-function-declaration) - not_yet_declared2(ca); // BAD - not_yet_declared2(); // BAD + not_yet_declared2(ca); // BAD (GOOD for everything except for cpp/mistyped-function-arguments + // and cpp/too-few-arguments. Not detected in the case of cpp/too-few-arguments.) + not_yet_declared2(); // BAD [NOT DETECTED] (GOOD for everything except for cpp/too-few-arguments) declared_empty_defined_with(); // BAD declared_empty_defined_with(1); // GOOD diff --git a/csharp/.vscode/launch.json b/csharp/.vscode/launch.json index 468588610474..1f598f5e44f7 100644 --- a/csharp/.vscode/launch.json +++ b/csharp/.vscode/launch.json @@ -6,7 +6,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "dotnet: build", - "program": "${workspaceFolder}/extractor/Semmle.Extraction.CSharp.Standalone/bin/Debug/net8.0/Semmle.Extraction.CSharp.Standalone.dll", + "program": "${workspaceFolder}/extractor/Semmle.Extraction.CSharp.Standalone/bin/Debug/net9.0/Semmle.Extraction.CSharp.Standalone.dll", "args": [], // Set the path to the folder that should be extracted: "cwd": "${workspaceFolder}/ql/test/library-tests/standalone/standalonemode", @@ -35,7 +35,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "dotnet: build", - "program": "${workspaceFolder}/autobuilder/Semmle.Autobuild.CSharp/bin/Debug/net8.0/Semmle.Autobuild.CSharp.dll", + "program": "${workspaceFolder}/autobuilder/Semmle.Autobuild.CSharp/bin/Debug/net9.0/Semmle.Autobuild.CSharp.dll", // Set the path to the folder that should be extracted: "cwd": "${workspaceFolder}/ql/integration-tests/all-platforms/autobuild", "stopAtEntry": true, @@ -53,7 +53,7 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "dotnet: build", - "program": "${workspaceFolder}/extractor/Semmle.Extraction.CSharp.Driver/bin/Debug/net8.0/Semmle.Extraction.CSharp.Driver.dll", + "program": "${workspaceFolder}/extractor/Semmle.Extraction.CSharp.Driver/bin/Debug/net9.0/Semmle.Extraction.CSharp.Driver.dll", "stopAtEntry": true, "args": [ "--binlog", diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs index e58c8ddccd96..b3efe64b7e95 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs @@ -49,11 +49,9 @@ public BuildScript Analyse(IAutobuilder builder, bool au tryCleanExtractorArgsLogs & BuildScript.DeleteFile(Extractor.GetCSharpLogPath()); - /// - /// Execute script `s` and check that the C# extractor has been executed. - /// If either fails, attempt to cleanup any artifacts produced by the extractor, - /// and exit with code 1, in order to proceed to the next attempt. - /// + // Execute script `s` and check that the C# extractor has been executed. + // If either fails, attempt to cleanup any artifacts produced by the extractor, + // and exit with code 1, in order to proceed to the next attempt. BuildScript IntermediateAttempt(BuildScript s) => (s & this.autobuilder.CheckExtractorRun(false)) | (attemptExtractorCleanup & BuildScript.Failure); diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs index 371352cf5e24..919e3821750b 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs @@ -195,7 +195,7 @@ protected Autobuilder(IBuildActions actions, TAutobuildOptions options, Diagnost } /// - /// Retrieves the value of an environment variable named or throws + /// Retrieves the value of an environment variable named or throws /// an exception if no such environment variable has been set. /// /// The name of the environment variable. @@ -228,7 +228,7 @@ protected string RequireEnvironmentVariable(string name) private readonly IDiagnosticsWriter diagnostics; /// - /// Makes relative to the root source directory. + /// Makes relative to the root source directory. /// /// The path which to make relative. /// The relative path. diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs index 13a3533eb319..f5721910a966 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs @@ -22,7 +22,7 @@ public static class MarkdownUtil public static string ToMarkdownLink(this string link, string title) => $"[{title}]({link})"; /// - /// Renders as a markdown list of the project paths. + /// Renders as a markdown list of the project paths. /// /// /// The list of projects whose paths should be rendered as a markdown list. @@ -35,7 +35,7 @@ public static string ToMarkdownList(this IEnumerable project } /// - /// Renders as a markdown list. + /// Renders as a markdown list. /// /// The item type. /// The list that should be formatted as a markdown list. diff --git a/csharp/documentation/library-coverage/coverage.csv b/csharp/documentation/library-coverage/coverage.csv index 10b1c58ef31b..6a48878f13eb 100644 --- a/csharp/documentation/library-coverage/coverage.csv +++ b/csharp/documentation/library-coverage/coverage.csv @@ -8,39 +8,40 @@ ILLink.Shared,,,31,,,,,,,,,,,,,,,,,,,11,20 ILLink.Tasks,,,5,,,,,,,,,,,,,,,,,,,4,1 Internal.IL,,,54,,,,,,,,,,,,,,,,,,,28,26 Internal.Pgo,,,9,,,,,,,,,,,,,,,,,,,2,7 -Internal.TypeSystem,,,328,,,,,,,,,,,,,,,,,,,201,127 +Internal.TypeSystem,,,329,,,,,,,,,,,,,,,,,,,201,128 JsonToItemsTaskFactory,,,11,,,,,,,,,,,,,,,,,,,1,10 Microsoft.Android.Build,,1,14,,,,,,,,,,,,,1,,,,,,12,2 Microsoft.Apple.Build,,,7,,,,,,,,,,,,,,,,,,,7, Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,,,28,,,,,,,,,, Microsoft.CSharp,,,2,,,,,,,,,,,,,,,,,,,2, -Microsoft.Diagnostics.Tools.Pgo,,,23,,,,,,,,,,,,,,,,,,,2,21 +Microsoft.Diagnostics.Tools.Pgo,,,25,,,,,,,,,,,,,,,,,,,2,23 Microsoft.DotNet.Build.Tasks,,,10,,,,,,,,,,,,,,,,,,,8,2 +Microsoft.DotNet.PlatformAbstractions,,,1,,,,,,,,,,,,,,,,,,,1, Microsoft.EntityFrameworkCore,6,,12,,,,,,,,,,6,,,,,,,,,,12 Microsoft.Extensions.Caching.Distributed,,,3,,,,,,,,,,,,,,,,,,,,3 -Microsoft.Extensions.Caching.Memory,,,31,,,,,,,,,,,,,,,,,,,5,26 -Microsoft.Extensions.Configuration,,3,91,,,,,,,,,,,,,3,,,,,,25,66 -Microsoft.Extensions.DependencyInjection,,,130,,,,,,,,,,,,,,,,,,,17,113 +Microsoft.Extensions.Caching.Memory,,,37,,,,,,,,,,,,,,,,,,,5,32 +Microsoft.Extensions.Configuration,,3,101,,,,,,,,,,,,,3,,,,,,29,72 +Microsoft.Extensions.DependencyInjection,,,202,,,,,,,,,,,,,,,,,,,15,187 Microsoft.Extensions.DependencyModel,,1,16,,,,,,,,,,,,,1,,,,,,14,2 Microsoft.Extensions.Diagnostics.Metrics,,,14,,,,,,,,,,,,,,,,,,,1,13 Microsoft.Extensions.FileProviders,,,17,,,,,,,,,,,,,,,,,,,7,10 -Microsoft.Extensions.FileSystemGlobbing,,,22,,,,,,,,,,,,,,,,,,,11,11 -Microsoft.Extensions.Hosting,,,39,,,,,,,,,,,,,,,,,,,29,10 +Microsoft.Extensions.FileSystemGlobbing,,,21,,,,,,,,,,,,,,,,,,,10,11 +Microsoft.Extensions.Hosting,,,58,,,,,,,,,,,,,,,,,,,29,29 Microsoft.Extensions.Http,,,9,,,,,,,,,,,,,,,,,,,7,2 -Microsoft.Extensions.Logging,,,64,,,,,,,,,,,,,,,,,,,25,39 -Microsoft.Extensions.Options,,,14,,,,,,,,,,,,,,,,,,,14, -Microsoft.Extensions.Primitives,,,72,,,,,,,,,,,,,,,,,,,67,5 -Microsoft.Interop,,,137,,,,,,,,,,,,,,,,,,,70,67 +Microsoft.Extensions.Logging,,,91,,,,,,,,,,,,,,,,,,,25,66 +Microsoft.Extensions.Options,,,68,,,,,,,,,,,,,,,,,,,44,24 +Microsoft.Extensions.Primitives,,,73,,,,,,,,,,,,,,,,,,,67,6 +Microsoft.Interop,,,159,,,,,,,,,,,,,,,,,,,75,84 Microsoft.NET.Build.Tasks,,,5,,,,,,,,,,,,,,,,,,,3,2 Microsoft.NET.Sdk.WebAssembly,,,2,,,,,,,,,,,,,,,,,,,1,1 Microsoft.NET.WebAssembly.Webcil,,,6,,,,,,,,,,,,,,,,,,,6, Microsoft.VisualBasic,,,13,,,,,,,,,,,,,,,,,,,1,12 Microsoft.WebAssembly.Build.Tasks,,,9,,,,,,,,,,,,,,,,,,,8,1 Microsoft.Win32,,4,2,,,,,,,,,,,,,,,,,,4,,2 -Mono.Linker,,,287,,,,,,,,,,,,,,,,,,,145,142 +Mono.Linker,,,293,,,,,,,,,,,,,,,,,,,145,148 MySql.Data.MySqlClient,48,,,,,,,,,,,,48,,,,,,,,,, Newtonsoft.Json,,,91,,,,,,,,,,,,,,,,,,,73,18 ServiceStack,194,,7,27,,,,,75,,,,92,,,,,,,,,7, SourceGenerators,,,5,,,,,,,,,,,,,,,,,,,,5 -System,54,47,10313,,6,5,5,,,4,1,,33,2,,6,15,17,4,3,,5351,4962 +System,54,47,10818,,6,5,5,,,4,1,,33,2,,6,15,17,4,3,,5511,5307 Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,,,,,, diff --git a/csharp/documentation/library-coverage/coverage.rst b/csharp/documentation/library-coverage/coverage.rst index 5eaaad174573..82aa21d3d919 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,10313,54,5 - Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.DotNet.Build.Tasks``, ``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.NET.Build.Tasks``, ``Microsoft.NET.Sdk.WebAssembly``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",57,1848,148, - Totals,,104,12168,396,5 + System,"``System.*``, ``System``",47,10818,54,5 + Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``JsonToItemsTaskFactory``, ``Microsoft.Android.Build``, ``Microsoft.Apple.Build``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``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.NET.Build.Tasks``, ``Microsoft.NET.Sdk.WebAssembly``, ``Microsoft.NET.WebAssembly.Webcil``, ``Microsoft.VisualBasic``, ``Microsoft.WebAssembly.Build.Tasks``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",57,2068,148, + Totals,,104,12893,396,5 diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs index 4a6b401038ef..13235ba19885 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/Assets.cs @@ -127,21 +127,21 @@ private void AddPackageDependencies(JObject json, string jsonPath) /// /// Example: /// "project": { - // "version": "1.0.0", - // "frameworks": { - // "net7.0": { - // "frameworkReferences": { - // "Microsoft.AspNetCore.App": { - // "privateAssets": "none" - // }, - // "Microsoft.NETCore.App": { - // "privateAssets": "all" - // } - // } - // } - // } - // } - // + /// "version": "1.0.0", + /// "frameworks": { + /// "net7.0": { + /// "frameworkReferences": { + /// "Microsoft.AspNetCore.App": { + /// "privateAssets": "none" + /// }, + /// "Microsoft.NETCore.App": { + /// "privateAssets": "all" + /// } + /// } + /// } + /// } + /// } + /// /// Adds the following dependencies /// Paths: { /// "microsoft.aspnetcore.app.ref", diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetVersion.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetVersion.cs index f62c279d2400..b4273d02b77a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetVersion.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/DotNetVersion.cs @@ -27,7 +27,7 @@ private string FullVersion * This is the same as FullPath, except that we assume that the * reference assemblies are in a directory called "packs" and * the reference assemblies themselves are in a directory called - * ".Ref/ref". + * "[Framework].Ref/ref". * Example: * FullPath: /usr/share/dotnet/shared/Microsoft.NETCore.App/7.0.2 * FullPathReferenceAssemblies: /usr/share/dotnet/packs/Microsoft.NETCore.App.Ref/7.0.2/ref diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs index f33329046cf6..f5199de1c13a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FileContent.cs @@ -38,8 +38,8 @@ public HashSet AllPackages /// True if any file in the source directory indicates that ASP.NET Core is used. /// The following heuristic is used to decide, if ASP.NET Core is used: /// If any file in the source directory contains something like (this will most like be a .csproj file) - /// - /// + /// <Project Sdk="Microsoft.NET.Sdk.Web"> + /// <FrameworkReference Include="Microsoft.AspNetCore.App"/> /// public bool UseAspNetCoreDlls { diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDotNetCliInvoker.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDotNetCliInvoker.cs index bfc8b44ee569..89631ffa861e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDotNetCliInvoker.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/IDotNetCliInvoker.cs @@ -10,20 +10,20 @@ internal interface IDotNetCliInvoker string Exec { get; } /// - /// Execute `dotnet ` and return true if the command succeeded, otherwise false. + /// Execute `dotnet ` and return true if the command succeeded, otherwise false. /// If `silent` is true the output of the command is logged as `debug` otherwise as `info`. /// bool RunCommand(string args, bool silent = true); /// - /// Execute `dotnet ` and return true if the command succeeded, otherwise false. + /// Execute `dotnet ` and return true if the command succeeded, otherwise false. /// The output of the command is returned in `output`. /// If `silent` is true the output of the command is logged as `debug` otherwise as `info`. /// bool RunCommand(string args, out IList output, bool silent = true); /// - /// Execute `dotnet ` in `` and return true if the command succeeded, otherwise false. + /// Execute `dotnet ` in `` and return true if the command succeeded, otherwise false. /// The output of the command is returned in `output`. /// If `silent` is true the output of the command is logged as `debug` otherwise as `info`. /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs index 2ffdd9dbcd65..72c45b797d8a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs @@ -133,9 +133,6 @@ bool IdDependsOnImpl(ITypeSymbol? type) /// /// Constructs a unique string for this type symbol. - /// - /// The supplied action is applied to the - /// syntactic sub terms of this type (if any). /// /// The extraction context. /// The trap builder used to store the result. @@ -495,31 +492,31 @@ public static bool IsReallyUnbound(this INamedTypeSymbol type) => /// /// Holds if this type is of the form int? or - /// System.Nullable. + /// System.Nullable<int>. /// public static bool IsBoundNullable(this ITypeSymbol type) => type.SpecialType == SpecialType.None && type.OriginalDefinition.IsUnboundNullable(); /// - /// Holds if this type is System.Nullable. + /// Holds if this type is System.Nullable<T>. /// public static bool IsUnboundNullable(this ITypeSymbol type) => type.SpecialType == SpecialType.System_Nullable_T; /// - /// Holds if this type is System.Span. + /// Holds if this type is System.Span<T>. /// public static bool IsUnboundSpan(this ITypeSymbol type) => type.ToString() == "System.Span"; /// - /// Holds if this type is of the form System.Span. + /// Holds if this type is of the form System.Span<byte>. /// public static bool IsBoundSpan(this ITypeSymbol type) => type.SpecialType == SpecialType.None && type.OriginalDefinition.IsUnboundSpan(); /// - /// Holds if this type is System.ReadOnlySpan. + /// Holds if this type is System.ReadOnlySpan<T>. /// public static bool IsUnboundReadOnlySpan(this ITypeSymbol type) => type.ToString() == "System.ReadOnlySpan"; @@ -536,7 +533,7 @@ attribute.AttributeClass is INamedTypeSymbol nt && } /// - /// Holds if this type is of the form System.ReadOnlySpan. + /// Holds if this type is of the form System.ReadOnlySpan<byte>. /// public static bool IsBoundReadOnlySpan(this ITypeSymbol type) => type.SpecialType == SpecialType.None && type.OriginalDefinition.IsUnboundReadOnlySpan(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/CachedEntity.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/CachedEntity.cs index ed0a21bc0836..96bef9732117 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/CachedEntity.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/CachedEntity.cs @@ -7,7 +7,7 @@ namespace Semmle.Extraction.CSharp.Entities /// /// A cached entity. /// - /// The property is used as label in caching. + /// The property is used as label in caching. /// public abstract class CachedEntity : LabelledEntity { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/IEntity.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/IEntity.cs index d8d3c538e42c..f6f60ff91468 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/IEntity.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Base/IEntity.cs @@ -9,12 +9,12 @@ namespace Semmle.Extraction.CSharp /// Entities are divided into two types: normal entities and cached /// entities. /// - /// Normal entities implement directly, and they + /// Normal entities implement directly, and they /// (may) emit contents to the trap file during object construction. /// - /// Cached entities implement , and they - /// emit contents to the trap file when - /// is called. Caching prevents + /// Cached entities implement , and they + /// emit contents to the trap file when + /// is called. Caching prevents /// from being called on entities that have already been emitted. /// public interface IEntity diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs index f5021d38eeb5..9241528eb752 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs @@ -77,7 +77,7 @@ internal void SetType(ITypeSymbol? type) /// /// Gets a string representation of a constant value. /// - /// The value. + /// The value. /// The string representation. public static string ValueAsString(object? value) { @@ -98,7 +98,6 @@ public static string ValueAsString(object? value) /// The node to extract. /// The parent entity. /// The child index. - /// A type hint. /// The new expression. public static Expression Create(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child, Boolean isCompilerGenerated = false) { @@ -120,7 +119,6 @@ public static Expression Create(Context cx, ExpressionSyntax node, IExpressionPa /// The node to extract. /// The parent entity. /// The child index. - /// A type hint. public static void CreateDeferred(Context cx, ExpressionSyntax node, IExpressionParentEntity parent, int child) { if (ContainsPattern(node)) @@ -244,7 +242,6 @@ public static ExprKind UnaryOperatorKind(Context cx, ExprKind originalKind, Expr /// to show the target of the call. Also note the dynamic method /// name if available. /// - /// Context /// The expression. public void OperatorCall(TextWriter trapFile, ExpressionSyntax node) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs index 6386e43a9b47..4c2670369e0c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression`1.cs @@ -20,7 +20,7 @@ protected Expression(ExpressionNodeInfo info) /// expressions and expr_location are populated by the constructor /// (should not fail), so even if expression-type specific population fails (e.g., in /// standalone extraction), the expression created via - /// will + /// will /// still be valid. /// protected abstract void PopulateExpression(TextWriter trapFile); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 189a07f6f476..b2106febaff3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -21,10 +21,9 @@ public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type); /// - /// Creates a named type entity from a tuple type. Unlike `Create`, this + /// Creates a named type entity from a tuple type. Unlike , this /// will create an entity for the underlying `System.ValueTuple` struct. - /// For example, `(int, string)` will result in an entity for - /// `System.ValueTuple`. + /// For example, `(int, string)` will result in an entity for `System.ValueTuple<int, string>`. /// public static NamedType CreateNamedTypeFromTupleType(Context cx, INamedTypeSymbol type) => UnderlyingTupleTypeFactory.Instance.CreateEntity(cx, (new SymbolEqualityWrapper(type), typeof(TupleType)), type); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs index 9791f386a199..add36226f165 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs @@ -209,8 +209,8 @@ public static IEnumerable GetAnnotatedTypeArguments(this An /// This is so that we can avoid populating nullability in most cases. /// For example, /// - /// IEnumerable<string?> // false - /// IEnumerable<string?>? // true + /// IEnumerable<string?> // false + /// IEnumerable<string?>? // true /// string? // true /// string[] // true /// string?[] // false diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index f2fc4b85d7f5..141bded87acf 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -86,7 +86,7 @@ private bool IsImplicitOperator(out ITypeSymbol containingType) /// Logs an error if the name is not found. /// /// Extractor context. - /// The method name. + /// The method symbol. /// The converted name. private static string OperatorSymbol(Context cx, IMethodSymbol method) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Context.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Context.cs index 8d819d715f9f..67bb2808ae62 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Context.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Context.cs @@ -152,7 +152,7 @@ internal void AddFreshLabel(Entity entity) /// /// Enqueue the given action to be performed later. /// - /// The action to run. + /// The action to run. public void PopulateLater(Action a, bool preserveDuplicationKey = true) { var key = preserveDuplicationKey ? GetCurrentTagStackKey() : null; @@ -598,7 +598,6 @@ public Entities.Location CreateLocation(Microsoft.CodeAnalysis.Location? locatio /// /// Register a program entity which can be bound to comments. /// - /// Extractor context. /// Program entity. /// Location of the entity. public void BindComments(Entity entity, Microsoft.CodeAnalysis.Location? l) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TrapWriter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TrapWriter.cs index 4830c3209c26..42e933c8eaf4 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TrapWriter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TrapWriter.cs @@ -171,7 +171,7 @@ private static bool TryMove(string sourceFile, string destFile) /// /// Close the trap file, and move it to the right place in the trap directory. /// If the file exists already, rename it to allow the new file (ending .trap.gz) - /// to sit alongside the old file (except if is true, + /// to sit alongside the old file (except if is true, /// in which case only the existing file is kept). /// public void Dispose() diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Trap/EscapingTextWriter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Trap/EscapingTextWriter.cs index 63f5e81c3586..28e1d0bf146c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Trap/EscapingTextWriter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Trap/EscapingTextWriter.cs @@ -8,7 +8,7 @@ namespace Semmle.Extraction.CSharp { /// /// A `TextWriter` object that wraps another `TextWriter` object, and which - /// HTML escapes the characters `&`, `{`, `}`, `"`, `@`, and `#`, before + /// HTML escapes the characters &, {, }, ", @, and #, before /// writing to the underlying object. /// public sealed class EscapingTextWriter : TextWriter diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Trap/TrapExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/Trap/TrapExtensions.cs index 787ba62e3e82..22e38bac51c0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Trap/TrapExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Trap/TrapExtensions.cs @@ -226,7 +226,7 @@ public static TextWriter AppendList(this EscapingTextWriter trapFile, string /// /// Builds a trap builder using a separator and an action for each item in the list. /// - /// The type of the items. + /// The type of the items. /// The trap builder to append to. /// The separator string (e.g. ",") /// The list of items. @@ -251,7 +251,7 @@ public static T1 BuildList(this T1 trapFile, string separator, IEnumerab /// /// Builds a trap builder using a separator and an action for each item in the list. /// - /// The type of the items. + /// The type of the items. /// The trap builder to append to. /// The separator string (e.g. ",") /// The list of items. diff --git a/csharp/extractor/Semmle.Util/CanonicalPathCache.cs b/csharp/extractor/Semmle.Util/CanonicalPathCache.cs index a79854333ac7..d3cbf41fa101 100644 --- a/csharp/extractor/Semmle.Util/CanonicalPathCache.cs +++ b/csharp/extractor/Semmle.Util/CanonicalPathCache.cs @@ -208,7 +208,7 @@ public enum Symlinks /// Create cache with a given capacity. /// /// The algorithm for determining the canonical path. - /// The size of the cache. + /// The size of the cache. public CanonicalPathCache(int maxCapacity, PathStrategy pathStrategy) { if (maxCapacity <= 0) @@ -230,7 +230,6 @@ public CanonicalPathCache(int maxCapacity, PathStrategy pathStrategy) /// /// /// Size of the cache. - /// Policy for following symlinks. /// A new CanonicalPathCache. public static CanonicalPathCache Create(ILogger logger, int maxCapacity) { diff --git a/csharp/extractor/Semmle.Util/CommandBuilder.cs b/csharp/extractor/Semmle.Util/CommandBuilder.cs index 3d8f907f8669..1b6cd3176c43 100644 --- a/csharp/extractor/Semmle.Util/CommandBuilder.cs +++ b/csharp/extractor/Semmle.Util/CommandBuilder.cs @@ -62,7 +62,6 @@ public CommandBuilder CallBatFile(string batFile, string? argumentsOpt = null) /// /// The argument to append. /// Whether to always quote the argument. - /// Whether to escape for cmd.exe /// /// /// This implementation is copied from diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py index c32d966acb4a..75ba09477fa0 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py @@ -1,7 +1,6 @@ import os def check_build_out(msg, s): - lines = s.splitlines() lines = s.splitlines() assert ( any (("[build-stdout]" in line) and (msg in line) for line in lines) diff --git a/csharp/ql/lib/change-notes/2024-11-26-model-microsoft.jsinterop.ijsruntime.md b/csharp/ql/lib/change-notes/2024-11-26-model-microsoft.jsinterop.ijsruntime.md new file mode 100644 index 000000000000..a99f9c8e0fd3 --- /dev/null +++ b/csharp/ql/lib/change-notes/2024-11-26-model-microsoft.jsinterop.ijsruntime.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* Added `js-interop` sinks for the `InvokeAsync` and `InvokeVoidAsync` methods of `Microsoft.JSInterop.IJSRuntime`, which can run arbitrary JavaScript. + diff --git a/csharp/ql/lib/ext/Microsoft.JSInterop.model.yml b/csharp/ql/lib/ext/Microsoft.JSInterop.model.yml new file mode 100644 index 000000000000..78f5c0964c15 --- /dev/null +++ b/csharp/ql/lib/ext/Microsoft.JSInterop.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: sinkModel + data: + - ["Microsoft.JSInterop", "JSRuntimeExtensions", True, "InvokeAsync", "", "", "Argument[1]", "js-injection", "manual"] + - ["Microsoft.JSInterop", "JSRuntimeExtensions", True, "InvokeVoidAsync", "", "", "Argument[1]", "js-injection", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected index 7b6e623288f3..efb6d30e660d 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected @@ -256,6 +256,12 @@ sink | Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Object[]);Argument[1];sql-injection;manual | | Microsoft.EntityFrameworkCore;RelationalDatabaseFacadeExtensions;ExecuteSqlRawAsync;(Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade,System.String,System.Threading.CancellationToken);Argument[1];sql-injection;manual | | Microsoft.EntityFrameworkCore;RelationalQueryableExtensions;FromSqlRaw;(Microsoft.EntityFrameworkCore.DbSet,System.String,System.Object[]);Argument[1];sql-injection;manual | +| Microsoft.JSInterop;JSRuntimeExtensions;InvokeAsync;(Microsoft.JSInterop.IJSRuntime,System.String,System.Object[]);Argument[1];js-injection;manual | +| Microsoft.JSInterop;JSRuntimeExtensions;InvokeAsync;(Microsoft.JSInterop.IJSRuntime,System.String,System.Threading.CancellationToken,System.Object[]);Argument[1];js-injection;manual | +| Microsoft.JSInterop;JSRuntimeExtensions;InvokeAsync;(Microsoft.JSInterop.IJSRuntime,System.String,System.TimeSpan,System.Object[]);Argument[1];js-injection;manual | +| Microsoft.JSInterop;JSRuntimeExtensions;InvokeVoidAsync;(Microsoft.JSInterop.IJSRuntime,System.String,System.Object[]);Argument[1];js-injection;manual | +| Microsoft.JSInterop;JSRuntimeExtensions;InvokeVoidAsync;(Microsoft.JSInterop.IJSRuntime,System.String,System.Threading.CancellationToken,System.Object[]);Argument[1];js-injection;manual | +| Microsoft.JSInterop;JSRuntimeExtensions;InvokeVoidAsync;(Microsoft.JSInterop.IJSRuntime,System.String,System.TimeSpan,System.Object[]);Argument[1];js-injection;manual | | ServiceStack.Messaging;BackgroundMqClient;SendAllOneWay;(System.Collections.Generic.IEnumerable);Argument[1].Element;file-content-store;manual | | ServiceStack.Messaging;BackgroundMqClient;SendOneWay;(System.Object);Argument[0];file-content-store;manual | | ServiceStack.Messaging;BackgroundMqClient;SendOneWay;(System.String,System.Object);Argument[1];file-content-store;manual | diff --git a/csharp/ql/test/resources/stubs/System.Web.cs b/csharp/ql/test/resources/stubs/System.Web.cs index d876a83e318f..d1942c07dc1d 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -390,6 +390,8 @@ public class JavaScriptSerializer public JavaScriptSerializer() => throw null; public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; public object DeserializeObject(string input) => throw null; + public T Deserialize (string input) => throw null; + public object Deserialize(string input, Type targetType) => throw null; } // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` diff --git a/docs/codeql/codeql-language-guides/codeql-for-go.rst b/docs/codeql/codeql-language-guides/codeql-for-go.rst index 360ff6bb82f2..30799c146a8e 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-go.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-go.rst @@ -12,6 +12,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat codeql-library-for-go abstract-syntax-tree-classes-for-working-with-go-programs modeling-data-flow-in-go-libraries + customizing-library-models-for-go - :doc:`Basic query for Go code `: Learn to write and run a simple CodeQL query. @@ -23,3 +24,5 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat - :doc:`Modeling data flow in Go libraries `: When analyzing a Go program, CodeQL does not examine the source code for external packages. To track the flow of untrusted data through a library, you can create a model of the library. + +- :doc:`Customizing library models for Go `: You can model frameworks and libraries that your codebase depends on using data extensions and publish them as CodeQL model packs. diff --git a/docs/codeql/codeql-language-guides/customizing-library-models-for-go.rst b/docs/codeql/codeql-language-guides/customizing-library-models-for-go.rst new file mode 100644 index 000000000000..c5b74ccd73ae --- /dev/null +++ b/docs/codeql/codeql-language-guides/customizing-library-models-for-go.rst @@ -0,0 +1,427 @@ +.. _customizing-library-models-for-go: + +Customizing library models for Go +================================= + +You can model the methods and functions that control data flow in any framework or library. This is especially useful for custom frameworks or niche libraries, that are not supported by the standard CodeQL libraries. + +.. include:: ../reusables/beta-note-customizing-library-models.rst + +About this article +------------------ + +This article contains reference material about how to define custom models for sources, sinks, and flow summaries for Go dependencies in data extension files. + +About data extensions +--------------------- + +You can customize analysis by defining models (summaries, sinks, and sources) of your code's Go dependencies in data extension files. Each model defines the behavior of one or more elements of your library or framework, such as functions, methods, and fields. When you run dataflow analysis, these models expand the potential sources and sinks tracked by dataflow analysis and improve the precision of results. + +Most of the security queries search for paths from a source of untrusted input to a sink that represents a vulnerability. This is known as taint tracking. Each source is a starting point for dataflow analysis to track tainted data and each sink is an end point. + +Taint tracking queries also need to know how data can flow through elements that are not included in the source code. These are modeled as summaries. A summary model enables queries to synthesize the flow behavior through elements in dependency code that is not stored in your repository. + +Syntax used to define an element in an extension file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each model of an element is defined using a data extension where each tuple constitutes a model. +A data extension file to extend the standard Go queries included with CodeQL is a YAML file with the form: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: + data: + - + - + - ... + +Each YAML file may contain one or more top-level extensions. + +- ``addsTo`` defines the CodeQL pack name and extensible predicate that the extension is injected into. +- ``data`` defines one or more rows of tuples that are injected as values into the extensible predicate. The number of columns and their types must match the definition of the extensible predicate. + +Data extensions use union semantics, which means that the tuples of all extensions for a single extensible predicate are combined, duplicates are removed, and all of the remaining tuples are queryable by referencing the extensible predicate. + +Publish data extension files in a CodeQL model pack to share +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can group one or more data extension files into a CodeQL model pack and publish it to the GitHub Container Registry. This makes it easy for anyone to download the model pack and use it to extend their analysis. For more information, see `Creating a CodeQL model pack `__ and `Publishing and using CodeQL packs `__ in the CodeQL CLI documentation. + +Extensible predicates used to create custom models in Go +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CodeQL library for Go analysis exposes the following extensible predicates: + +- ``sourceModel(package, type, subtypes, name, signature, ext, output, kind, provenance)``. This is used to model sources of potentially tainted data. The ``kind`` of the sources defined using this predicate determine which threat model they are associated with. Different threat models can be used to customize the sources used in an analysis. For more information, see ":ref:`Threat models `." +- ``sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)``. This is used to model sinks where tainted data may be used in a way that makes the code vulnerable. +- ``summaryModel(package, type, subtypes, name, signature, ext, input, output, kind, provenance)``. This is used to model flow through elements. +- ``neutralModel(package, type, name, signature, kind, provenance)``. This is similar to a summary model but used to model the flow of values that have only a minor impact on the dataflow analysis. Manual neutral models (those with a provenance such as ``manual`` or ``ai-manual``) can be used to override generated summary models (those with a provenance such as ``df-generated``), so that the summary model will be ignored. Other than that, neutral models have no effect. + +The extensible predicates are populated using the models defined in data extension files. + +Examples of custom model definitions +------------------------------------ + +The examples in this section are taken from the standard CodeQL Go query pack published by GitHub. They demonstrate how to add tuples to extend extensible predicates that are used by the standard queries. + +Example: Taint sink in the ``database/sql`` package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how the Go query pack models the argument of the ``Prepare`` method as a SQL injection sink. +This is the ``Prepare`` method of the ``DB`` type in the ``database/sql`` package which creates a prepared statement. + +.. code-block:: go + + func Tainted(db *sql.DB, name string) { + stmt, err := db.Prepare("SELECT * FROM users WHERE name = " + name) // The argument to this method is a SQL injection sink. + ... + } + +We need to add a tuple to the ``sinkModel``\(package, type, subtypes, name, signature, ext, input, kind, provenance) extensible predicate by updating a data extension file. + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["database/sql", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + +Since we want to add a new sink, we need to add a tuple to the ``sinkModel`` extensible predicate. +The first five values identify the function (in this case a method) to be modeled as a sink. + +- The first value ``database/sql`` is the package name. +- The second value ``DB`` is the name of the type that the method is associated with. +- The third value ``True`` is a flag that indicates whether or not the sink also applies to subtypes. This includes when the subtype embeds the given type, so that the method or field is promoted to be a method or field of the subtype. For interface methods it also includes types which implement the interface type. +- The fourth value ``Prepare`` is the method name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the sink. + +- The seventh value ``Argument[0]`` is the ``access path`` to the first argument passed to the method, which means that this is the location of the sink. +- The eighth value ``sql-injection`` is the kind of the sink. The sink kind is used to define the queries where the sink is in scope. In this case - the SQL injection queries. +- The ninth value ``manual`` is the provenance of the sink, which is used to identify the origin of the sink. + +Example: Taint source from the ``net/http`` package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example shows how the Go query pack models the return value from the ``FormValue`` method as a ``remote`` source. +This is the ``FormValue`` method of the ``Request`` type which is located in the ``net/http`` package. + +.. code-block:: go + + func Tainted(r *http.Request) { + name := r.FormValue("name") // The return value of this method is a source of tainted data. + ... + } + + +We need to add a tuple to the ``sourceModel``\(package, type, subtypes, name, signature, ext, output, kind, provenance) extensible predicate by updating a data extension file. + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["net/http", "Request", True, "FormValue", "", "", "ReturnValue", "remote", "manual"] + + +Since we are adding a new source, we need to add a tuple to the ``sourceModel`` extensible predicate. +The first five values identify the function to be modeled as a source. + +- The first value ``net/http`` is the package name. +- The second value ``Request`` is the type name, since the function is a method of the ``Request`` type. +- The third value ``True`` is a flag that indicates whether or not the sink also applies to subtypes. This includes when the subtype embeds the given type, so that the method or field is promoted to be a method or field of the subtype. For interface methods it also includes types which implement the interface type. +- The fourth value ``FormValue`` is the function name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the source. + +- The seventh value ``ReturnValue`` is the access path to the return of the method, which means that it is the return value that should be considered a source of tainted input. +- The eighth value ``remote`` is the kind of the source. The source kind is used to define the threat model where the source is in scope. ``remote`` applies to many of the security related queries as it means a remote source of untrusted data. As an example the SQL injection query uses ``remote`` sources. For more information, see ":ref:`Threat models `." +- The ninth value ``manual`` is the provenance of the source, which is used to identify the origin of the source. + +Example: Add flow through the ``Max`` function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how the Go query pack models flow through a function for a simple case. +This pattern covers many of the cases where we need to summarize flow through a function that is stored in a library or framework outside the repository. + +.. code-block:: go + + func ValueFlow { + a := []int{1, 2, 3} + max := slices.Max(a) // There is value flow from the elements of `a` to `max`. + ... + } + +We need to add a tuple to the ``summaryModel``\(package, type, subtypes, name, signature, ext, input, output, kind, provenance) extensible predicate by updating a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["slices", "", False, "Max", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"] + +Since we are adding flow through a method, we need to add tuples to the ``summaryModel`` extensible predicate. +The first row defines flow from the first argument (``a`` in the example) to the return value (``max`` in the example). + +The first five values identify the function to be modeled as a summary. + +- The first value ``slices`` is the package name. +- The second value ``""`` is left blank, since the function is not a method of a type. +- The third value ``False`` is a flag that indicates whether or not the sink also applies to subtypes. This has no effect for non-method functions. +- The fourth value ``Max`` is the function name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the summary. + +- The seventh value is the access path to the input (where data flows from). ``Argument[0].ArrayElement`` is the access path to the array elements of the first argument (the elements of the slice in the example). +- The eighth value ``ReturnValue`` is the access path to the output (where data flows to), in this case ``ReturnValue``, which means that the input flows to the return value. +- The ninth value ``value`` is the kind of the flow. ``value`` flow indicates an entire value is moved, ``taint`` means that taint is propagated through the call. +- The tenth value ``manual`` is the provenance of the summary, which is used to identify the origin of the summary. + +Example: Add flow through the ``Concat`` function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This example shows how the Go query pack models flow through a function for a simple case. +This pattern covers many of the cases where we need to summarize flow through a function that is stored in a library or framework outside the repository. + +.. code-block:: go + + func ValueFlow { + a := []int{1, 2, 3} + b := []int{4, 5, 6} + c := slices.Concat(a, b) // There is taint flow from `a` and `b` to `c`. + ... + } + +We need to add a tuple to the ``summaryModel``\(package, type, subtypes, name, signature, ext, input, output, kind, provenance) extensible predicate by updating a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["slices", "", False, "Concat", "", "", "Argument[0].ArrayElement.ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + +Since we are adding flow through a method, we need to add tuples to the ``summaryModel`` extensible predicate. +The first row defines flow from the arguments (``a`` and ``b`` in the example) to the return value (``c`` in the example). + +The first five values identify the function to be modeled as a summary. + +- The first value ``slices`` is the package name. +- The second value ``""`` is left blank, since the function is not a method of a type. +- The third value ``False`` is a flag that indicates whether or not the sink also applies to subtypes. This has no effect for non-method functions. +- The fourth value ``Max`` is the function name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the summary. + +- The seventh value is the access path to the input (where data flows from). ``Argument[0].ArrayElement.ArrayElement`` is the access path to the array elements of the array elements of the first argument. Note that a variadic parameter of type `...T` is treated as if it has type `[]T` and arguments corresponding to the variadic parameter are accessed as elements of this slice. +- The eighth value ``ReturnValue.ArrayElement`` is the access path to the output (where data flows to), in this case ``ReturnValue.ArrayElement``, which means that the input flows to the array elements of the return value. +- The ninth value ``value`` is the kind of the flow. ``value`` flow indicates an entire value is moved, ``taint`` means that taint is propagated through the call. +- The tenth value ``manual`` is the provenance of the summary, which is used to identify the origin of the summary. + +Example: Add flow through the ``Join`` function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example shows how the Go query pack models flow through a method for a simple case. +This pattern covers many of the cases where we need to summarize flow through a function that is stored in a library or framework outside the repository. + +.. code-block:: go + + func TaintFlow() { + elems := []string{"Hello", "World"} + sep := " " + t := strings.Join(elems, sep) // There is taint flow from elems and sep to t. + ... + } + +We need to add tuples to the ``summaryModel``\(package, type, subtypes, name, signature, ext, input, output, kind, provenance) extensible predicate by updating a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["strings", "", False, "Join", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["strings", "", False, "Join", "", "", "Argument[1]", "ReturnValue", "taint", "manual"] + +Since we are adding flow through a method, we need to add tuples to the ``summaryModel`` extensible predicate. +Each tuple defines flow from one argument to the return value. +The first row defines flow from the first argument (``elems`` in the example) to the return value (``t`` in the example) and the second row defines flow from the second argument (``sep`` in the example) to the return value (``t`` in the example). + +The first five values identify the function to be modeled as a summary. +These are the same for both of the rows above as we are adding two summaries for the same method. + +- The first value ``strings`` is the package name. +- The second value ``""`` is left blank, since the function is not a method of a type. +- The third value ``False`` is a flag that indicates whether or not the sink also applies to subtypes. This has no effect for non-method functions. +- The fourth value ``Join`` is the function name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the summary. + +- The seventh value is the access path to the input (where data flows from). ``Argument[0]`` is the access path to the first argument (``elems`` in the example) and ``Argument[1]`` is the access path to the second argument (``sep`` in the example). +- The eighth value ``ReturnValue`` is the access path to the output (where data flows to), in this case ``ReturnValue``, which means that the input flows to the return value. +- The ninth value ``taint`` is the kind of the flow. ``taint`` means that taint is propagated through the call. +- The tenth value ``manual`` is the provenance of the summary, which is used to identify the origin of the summary. + +It would also be possible to merge the two rows into one by using ".." to indicate a range in the seventh value. This would be useful if the method has many arguments and the flow is the same for all of them. + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["strings", "", False, "Join", "", "", "Argument[0..1]", "ReturnValue", "taint", "manual"] + +This row defines flow from both the first and the second argument to the return value. The seventh value ``Argument[0..1]`` is shorthand for specifying an access path to both ``Argument[0]`` and ``Argument[1]``. + +Example: Add flow through the ``Hostname`` method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example shows how the Go query pack models flow through a method for a simple case. + +.. code-block:: go + + func TaintFlow(u *url.URL) { + host := u.Hostname() // There is taint flow from u to host. + ... + } + +We need to add a tuple to the ``summaryModel``\(package, type, subtypes, name, signature, ext, input, output, kind, provenance) extensible predicate by updating a data extension file: + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + - ["net/url", "URL", True, "Hostname", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + +Since we are adding flow through a method, we need to add tuples to the ``summaryModel`` extensible predicate. +Each tuple defines flow from one argument to the return value. +The first row defines flow from the qualifier of the method call (``u`` in the example) to the return value (``host`` in the example). + +The first five values identify the function (in this case a method) to be modeled as a summary. + +- The first value ``net/url`` is the package name. +- The second value ``URL`` is the receiver type. +- The third value ``True`` is a flag that indicates whether or not the sink also applies to subtypes. This includes when the subtype embeds the given type, so that the method or field is promoted to be a method or field of the subtype. For interface methods it also includes types which implement the interface type. +- The fourth value ``Hostname`` is the method name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the summary. + +- The seventh value is the access path to the input (where data flows from). ``Argument[receiver]`` is the access path to the receiver (``u`` in the example). +- The eighth value ``ReturnValue`` is the access path to the output (where data flows to), in this case ``ReturnValue``, which means that the input flows to the return value. When there are multiple return values, use ``ReturnValue[i]`` to refer to the ``i`` th return value (starting from 0). +- The ninth value ``taint`` is the kind of the flow. ``taint`` means that taint is propagated through the call. +- The tenth value ``manual`` is the provenance of the summary, which is used to identify the origin of the summary. + +Example: Accessing the ``Body`` field of an HTTP request +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This example shows how we can model a field read as a source of tainted data. + +.. code-block:: go + + func TaintFlow(w http.ResponseWriter, r *http.Request) { + body := r.Body // The Body field of an HTTP request is a source of tainted data. + ... + } + +We need to add a tuple to the ``sourceModel``\(package, type, subtypes, name, signature, ext, output, kind, provenance) extensible predicate by updating a data extension file. + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: sourceModel + data: + - ["net/http", "Request", True, "Body", "", "", "", "remote", "manual"] + +Since we are adding a new source, we need to add a tuple to the ``sourceModel`` extensible predicate. +The first five values identify the field to be modeled as a source. + +- The first value ``net/http`` is the package name. +- The second value ``Request`` is the name of the type that the field is associated with. +- The third value ``True`` is a flag that indicates whether or not the sink also applies to subtypes. For fields this means when the field is accessed as a promoted field in another type. +- The fourth value ``Body`` is the field name. +- The fifth value ``""`` is the input type signature. For Go it should always be an empty string. It is needed for other languages where multiple functions may have the same name and they need to be distinguished by the number and types of the arguments. + +The sixth value should be left empty and is out of scope for this documentation. +The remaining values are used to define the ``access path``, the ``kind``, and the ``provenance`` (origin) of the source. + +- The seventh value ``""`` is left blank. Leaving the access path of a source model blank indicates that it is a field access. +- The eighth value ``remote`` is the source kind. This indicates that the source is a remote source of untrusted data. +- The ninth value ``manual`` is the provenance of the source, which is used to identify the origin of the source. + +Package versions +~~~~~~~~~~~~~~~~ + +When the major version number is greater than 1 it is included in the package import path. It usually looks like ``/v2`` after the module import path. This is called the major version suffix. We normally want our models to apply to all versions of a package. Rather than having to repeat models with the package column changed to include all available versions, we can just use the package name without the major version suffix and this will be matched to any version. So models with ``github.com/couchbase/gocb`` in the package column will match packages imported from ``github.com/couchbase/gocb`` and ``github.com/couchbase/gocb/v2`` (or any other version). + +Note that packages hosted at ``gopkg.in`` use a slightly different syntax: the major version suffix looks like ``.v2``, and it is present even for version 1. This is also supported. So models with ``gopkg.in/yaml`` in the package column will match packages imported from ``gopkg.in/yaml.v1``, ``gopkg.in/yaml.v2`` and ``gopkg.in/yaml.v3``. + +To write models that only apply to ``github.com/couchbase/gocb/v2``, it is sufficient to include the major version suffix (``/v2``) in the package column. To write models that only apply to ``github.com/couchbase/gocb``, you may prefix the package column with ``fixed-version:``. For example, here are two models for a method that has changed name from v1 to v2. + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["fixed-version:github.com/couchbase/gocb", "Cluster", True, "ExecuteAnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["github.com/couchbase/gocb/v2", "Cluster", True, "AnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + +Package grouping +~~~~~~~~~~~~~~~~ + +Since Go uses URLs for package identifiers, it is possible for packages to be imported with different paths. For example, the ``glog`` package can be imported using both the ``github.com/golang/glog`` and ``gopkg.in/glog`` paths. + +To handle this, the CodeQL Go library uses a mapping from the package path to a group name for the package. This mapping can be specified using the ``packageGrouping`` extensible predicate, and then the models for the APIs in the package +will use the the prefix ``group:`` followed by the group name in place of the package path. + +.. code-block:: yaml + + extensions: + - addsTo: + pack: codeql/go + extensible: packageGrouping + data: + - ["glog", "github.com/golang/glog"] + - ["glog", "gopkg.in/glog"] + - addsTo: + pack: codeql/go + extensible: sinkModel + data: + - ["group:glog", "", False, "Info", "", "", "Argument[0]", "log-injection", "manual"] + +.. _threat-models-go: + +Threat models +------------- + +.. include:: ../reusables/threat-model-description.rst diff --git a/docs/codeql/ql-language-reference/modules.rst b/docs/codeql/ql-language-reference/modules.rst index 75b61667246e..d0cbdd39e36d 100644 --- a/docs/codeql/ql-language-reference/modules.rst +++ b/docs/codeql/ql-language-reference/modules.rst @@ -431,10 +431,7 @@ The above query therefore evalutes to: BigInt ====== -The built-in ``QlBuiltins`` module provides an **experimental** type ``BigInt`` of arbitrary-precision integers. - -This type is not available in the CodeQL CLI by default, but you can enable it by passing the ``--allow-experimental=bigint`` -option to the CodeQL CLI. Consequently, BigInts are currently disallowed in query results and dbscheme columns. +The built-in ``QlBuiltins`` module provides a type ``BigInt`` of arbitrary-range integers. Unlike ``int`` and ``float``, there is no automatic conversion between ``BigInt`` and other numeric types. Instead, big integers can be constructed using the ``.toBigInt()`` methods of ``int`` and ``string``. @@ -451,3 +448,5 @@ The other built-in operations are: ``rank``, ``unique``, ``any``. * other: ``.pow(int)``, ``.abs()``, ``.gcd(BigInt)``, ``.minimum(BigInt)``, ``.maximum(BigInt)``. + +Note: big integers are currently disallowed in query results and dbscheme columns. diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 60e5ece73303..4c8fd30076a8 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -445,7 +445,7 @@ An integer value is of type ``int``. Each value is a 32-bit two's complement int A string is a finite sequence of 16-bit characters. The characters are interpreted as Unicode code points. -A :ref:`big integer ` value is of type ``QlBuiltins::BigInt``. Each value is a signed arbitrary-precision integer. +A :ref:`big integer ` value is of type ``QlBuiltins::BigInt``. Each value is a signed arbitrary-range integer. The database includes a number of opaque entity values. Each such value has a type that is one of the database types, and an identifying integer. An entity value is written as the name of its database type followed by its identifying integer in parentheses. For example, ``@tree(12)``, ``@person(16)``, and ``@location(38132)`` are entity values. The identifying integers are left opaque to programmers in this specification, so an implementation of QL is free to use some other set of countable labels to identify its entities. diff --git a/docs/codeql/ql-language-reference/types.rst b/docs/codeql/ql-language-reference/types.rst index e14f542dcf88..d2d79fe8409b 100644 --- a/docs/codeql/ql-language-reference/types.rst +++ b/docs/codeql/ql-language-reference/types.rst @@ -52,7 +52,7 @@ independent of the database that you are querying. QL has a range of built-in operations defined on primitive types. These are available by using dispatch on expressions of the appropriate type. For example, ``1.toString()`` is the string representation of the integer constant ``1``. For a full list of built-in operations available in QL, see the section on `built-ins `__ in the QL language specification. -Additionally, there is an experimental arbitrary-precision integer primitive type at :ref:`QlBuiltins::BigInt `. This type is not available in the CodeQL CLI by default, but you can enable it by passing the ``--allow-experimental=bigint`` option to the CodeQL CLI. +Additionally, there is an arbitrary-range integer primitive type at :ref:`QlBuiltins::BigInt `. .. index:: class .. _classes: diff --git a/go/documentation/library-coverage/coverage.csv b/go/documentation/library-coverage/coverage.csv index 364e17aa94b6..cf5a8b715b0d 100644 --- a/go/documentation/library-coverage/coverage.csv +++ b/go/documentation/library-coverage/coverage.csv @@ -1,121 +1,142 @@ -package,sink,source,summary,sink:command-injection,sink:credentials-key,sink:jwt,sink:path-injection,sink:regex-use[0],sink:regex-use[1],sink:regex-use[c],sink:request-forgery,sink:request-forgery[TCP Addr + Port],sink:url-redirection,sink:url-redirection[0],sink:url-redirection[receiver],sink:xpath-injection,source:environment,source:file,source:remote,summary:taint,summary:value -,,,8,,,,,,,,,,,,,,,,,3,5 -archive/tar,,,5,,,,,,,,,,,,,,,,,5, -archive/zip,,,6,,,,,,,,,,,,,,,,,6, -bufio,,,17,,,,,,,,,,,,,,,,,17, -bytes,,,43,,,,,,,,,,,,,,,,,43, -clevergo.tech/clevergo,1,,,,,,,,,,,,,,1,,,,,, -compress/bzip2,,,1,,,,,,,,,,,,,,,,,1, -compress/flate,,,4,,,,,,,,,,,,,,,,,4, -compress/gzip,,,3,,,,,,,,,,,,,,,,,3, -compress/lzw,,,1,,,,,,,,,,,,,,,,,1, -compress/zlib,,,4,,,,,,,,,,,,,,,,,4, -container/heap,,,5,,,,,,,,,,,,,,,,,5, -container/list,,,20,,,,,,,,,,,,,,,,,20, -container/ring,,,5,,,,,,,,,,,,,,,,,5, -context,,,5,,,,,,,,,,,,,,,,,5, -crypto,,,10,,,,,,,,,,,,,,,,,10, -database/sql,,,11,,,,,,,,,,,,,,,,,11, -encoding,,,77,,,,,,,,,,,,,,,,,77, -errors,,,3,,,,,,,,,,,,,,,,,3, -expvar,,,6,,,,,,,,,,,,,,,,,6, -fmt,,,16,,,,,,,,,,,,,,,,,16, -github.com/ChrisTrenkamp/goxpath,3,,,,,,,,,,,,,,,3,,,,, -github.com/antchfx/htmlquery,4,,,,,,,,,,,,,,,4,,,,, -github.com/antchfx/jsonquery,4,,,,,,,,,,,,,,,4,,,,, -github.com/antchfx/xmlquery,8,,,,,,,,,,,,,,,8,,,,, -github.com/antchfx/xpath,4,,,,,,,,,,,,,,,4,,,,, -github.com/appleboy/gin-jwt,1,,,,1,,,,,,,,,,,,,,,, -github.com/astaxie/beego,7,21,21,,,,5,,,,,,2,,,,,,21,21, -github.com/beego/beego,14,42,42,,,,10,,,,,,4,,,,,,42,42, -github.com/caarlos0/env,,5,2,,,,,,,,,,,,,,5,,,1,1 -github.com/clevergo/clevergo,1,,,,,,,,,,,,,,1,,,,,, -github.com/codeskyblue/go-sh,4,,,4,,,,,,,,,,,,,,,,, -github.com/couchbase/gocb,,,18,,,,,,,,,,,,,,,,,18, -github.com/couchbaselabs/gocb,,,18,,,,,,,,,,,,,,,,,18, -github.com/crankycoder/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -github.com/cristalhq/jwt,1,,,,1,,,,,,,,,,,,,,,, -github.com/dgrijalva/jwt-go,3,,9,,2,1,,,,,,,,,,,,,,9, -github.com/elazarl/goproxy,,2,2,,,,,,,,,,,,,,,,2,2, -github.com/emicklei/go-restful,,7,,,,,,,,,,,,,,,,,7,, -github.com/evanphx/json-patch,,,12,,,,,,,,,,,,,,,,,12, -github.com/form3tech-oss/jwt-go,2,,,,2,,,,,,,,,,,,,,,, -github.com/gin-gonic/gin,3,46,2,,,,3,,,,,,,,,,,,46,2, -github.com/go-chi/chi,,3,,,,,,,,,,,,,,,,,3,, -github.com/go-chi/jwtauth,1,,,,1,,,,,,,,,,,,,,,, -github.com/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,4, -github.com/go-kit/kit/auth/jwt,1,,,,1,,,,,,,,,,,,,,,, -github.com/go-pg/pg/orm,,,6,,,,,,,,,,,,,,,,,6, -github.com/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -github.com/gobuffalo/envy,,7,,,,,,,,,,,,,,,7,,,, -github.com/gobwas/ws,,2,,,,,,,,,,,,,,,,,2,, -github.com/gofiber/fiber,5,,,,,,4,,,,,,,,1,,,,,, -github.com/gogf/gf-jwt,1,,,,1,,,,,,,,,,,,,,,, -github.com/going/toolkit/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -github.com/golang-jwt/jwt,3,,11,,2,1,,,,,,,,,,,,,,11, -github.com/golang/protobuf/proto,,,4,,,,,,,,,,,,,,,,,4, -github.com/gorilla/mux,,1,,,,,,,,,,,,,,,,,1,, -github.com/gorilla/websocket,,3,,,,,,,,,,,,,,,,,3,, -github.com/hashicorp/go-envparse,,1,,,,,,,,,,,,,,,1,,,, -github.com/jbowtie/gokogiri/xml,4,,,,,,,,,,,,,,,4,,,,, -github.com/jbowtie/gokogiri/xpath,1,,,,,,,,,,,,,,,1,,,,, -github.com/joho/godotenv,,4,,,,,,,,,,,,,,,4,,,, -github.com/json-iterator/go,,,4,,,,,,,,,,,,,,,,,4, -github.com/kataras/iris/context,6,,,,,,6,,,,,,,,,,,,,, -github.com/kataras/iris/middleware/jwt,2,,,,2,,,,,,,,,,,,,,,, -github.com/kataras/iris/server/web/context,6,,,,,,6,,,,,,,,,,,,,, -github.com/kataras/jwt,5,,,,5,,,,,,,,,,,,,,,, -github.com/kelseyhightower/envconfig,,6,,,,,,,,,,,,,,,6,,,, -github.com/labstack/echo,3,12,2,,,,2,,,,,,1,,,,,,12,2, -github.com/lestrrat-go/jwx,2,,,,2,,,,,,,,,,,,,,,, -github.com/lestrrat-go/libxml2/parser,3,,,,,,,,,,,,,,,3,,,,, -github.com/lestrrat/go-jwx/jwk,1,,,,1,,,,,,,,,,,,,,,, -github.com/masterzen/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -github.com/moovweb/gokogiri/xml,4,,,,,,,,,,,,,,,4,,,,, -github.com/moovweb/gokogiri/xpath,1,,,,,,,,,,,,,,,1,,,,, -github.com/ory/fosite/token/jwt,2,,,,2,,,,,,,,,,,,,,,, -github.com/revel/revel,2,23,10,,,,1,,,,,,1,,,,,,23,10, -github.com/robfig/revel,2,23,10,,,,1,,,,,,1,,,,,,23,10, -github.com/santhosh-tekuri/xpathparser,2,,,,,,,,,,,,,,,2,,,,, -github.com/sendgrid/sendgrid-go/helpers/mail,,,1,,,,,,,,,,,,,,,,,1, -github.com/spf13/afero,34,,,,,,34,,,,,,,,,,,,,, -github.com/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,4, -github.com/valyala/fasthttp,35,50,5,,,,8,,,,17,8,2,,,,,,50,5, -go.uber.org/zap,,,11,,,,,,,,,,,,,,,,,11, -golang.org/x/crypto/ssh,4,,,4,,,,,,,,,,,,,,,,, -golang.org/x/net/context,,,5,,,,,,,,,,,,,,,,,5, -golang.org/x/net/html,,,16,,,,,,,,,,,,,,,,,16, -golang.org/x/net/websocket,,2,,,,,,,,,,,,,,,,,2,, -google.golang.org/protobuf/internal/encoding/text,,,1,,,,,,,,,,,,,,,,,1, -google.golang.org/protobuf/internal/impl,,,2,,,,,,,,,,,,,,,,,2, -google.golang.org/protobuf/proto,,,8,,,,,,,,,,,,,,,,,8, -google.golang.org/protobuf/reflect/protoreflect,,,1,,,,,,,,,,,,,,,,,1, -gopkg.in/couchbase/gocb,,,18,,,,,,,,,,,,,,,,,18, -gopkg.in/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,4, -gopkg.in/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -gopkg.in/macaron,1,12,1,,,,,,,,,,,,1,,,,12,1, -gopkg.in/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,4, -gopkg.in/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -gopkg.in/yaml,,,9,,,,,,,,,,,,,,,,,9, -html,,,8,,,,,,,,,,,,,,,,,8, -io,5,4,34,,,,5,,,,,,,,,,,4,,34, -k8s.io/api/core,,,10,,,,,,,,,,,,,,,,,10, -k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,47, -launchpad.net/xmlpath,2,,,,,,,,,,,,,,,2,,,,, -log,,,3,,,,,,,,,,,,,,,,,3, -math/big,,,1,,,,,,,,,,,,,,,,,1, -mime,,,14,,,,,,,,,,,,,,,,,14, -net,2,16,100,,,,1,,,,,,,1,,,,,16,100, -nhooyr.io/websocket,,2,,,,,,,,,,,,,,,,,2,, -os,29,10,6,3,,,26,,,,,,,,,,7,3,,6, -path,,,18,,,,,,,,,,,,,,,,,18, -reflect,,,37,,,,,,,,,,,,,,,,,37, -regexp,10,,20,,,,,3,3,4,,,,,,,,,,20, -sort,,,1,,,,,,,,,,,,,,,,,1, -strconv,,,9,,,,,,,,,,,,,,,,,9, -strings,,,34,,,,,,,,,,,,,,,,,34, -sync,,,34,,,,,,,,,,,,,,,,,34, -syscall,5,2,8,5,,,,,,,,,,,,,2,,,8, -text/scanner,,,3,,,,,,,,,,,,,,,,,3, -text/tabwriter,,,1,,,,,,,,,,,,,,,,,1, -text/template,,,6,,,,,,,,,,,,,,,,,6, +package,sink,source,summary,sink:command-injection,sink:credentials-key,sink:jwt,sink:log-injection,sink:nosql-injection,sink:path-injection,sink:regex-use[0],sink:regex-use[1],sink:regex-use[c],sink:request-forgery,sink:request-forgery[TCP Addr + Port],sink:sql-injection,sink:url-redirection,sink:url-redirection[0],sink:url-redirection[receiver],sink:xpath-injection,source:environment,source:file,source:remote,source:stdin,summary:taint,summary:value +,,,8,,,,,,,,,,,,,,,,,,,,,3,5 +archive/tar,,,5,,,,,,,,,,,,,,,,,,,,,5, +archive/zip,,,6,,,,,,,,,,,,,,,,,,,,,6, +bufio,,,17,,,,,,,,,,,,,,,,,,,,,17, +bytes,,,43,,,,,,,,,,,,,,,,,,,,,43, +clevergo.tech/clevergo,1,,,,,,,,,,,,,,,,,1,,,,,,, +compress/bzip2,,,1,,,,,,,,,,,,,,,,,,,,,1, +compress/flate,,,4,,,,,,,,,,,,,,,,,,,,,4, +compress/gzip,,,3,,,,,,,,,,,,,,,,,,,,,3, +compress/lzw,,,1,,,,,,,,,,,,,,,,,,,,,1, +compress/zlib,,,4,,,,,,,,,,,,,,,,,,,,,4, +container/heap,,,5,,,,,,,,,,,,,,,,,,,,,5, +container/list,,,20,,,,,,,,,,,,,,,,,,,,,20, +container/ring,,,5,,,,,,,,,,,,,,,,,,,,,5, +context,,,5,,,,,,,,,,,,,,,,,,,,,5, +crypto,,,10,,,,,,,,,,,,,,,,,,,,,10, +database/sql,30,,11,,,,,,,,,,,,30,,,,,,,,,11, +encoding,,,77,,,,,,,,,,,,,,,,,,,,,77, +errors,,,3,,,,,,,,,,,,,,,,,,,,,3, +expvar,,,6,,,,,,,,,,,,,,,,,,,,,6, +fmt,3,,16,,,,3,,,,,,,,,,,,,,,,,16, +github.com/ChrisTrenkamp/goxpath,3,,,,,,,,,,,,,,,,,,3,,,,,, +github.com/Masterminds/squirrel,32,,,,,,,,,,,,,,32,,,,,,,,,, +github.com/Sirupsen/logrus,145,,,,,,145,,,,,,,,,,,,,,,,,, +github.com/antchfx/htmlquery,4,,,,,,,,,,,,,,,,,,4,,,,,, +github.com/antchfx/jsonquery,4,,,,,,,,,,,,,,,,,,4,,,,,, +github.com/antchfx/xmlquery,8,,,,,,,,,,,,,,,,,,8,,,,,, +github.com/antchfx/xpath,4,,,,,,,,,,,,,,,,,,4,,,,,, +github.com/appleboy/gin-jwt,1,,,,1,,,,,,,,,,,,,,,,,,,, +github.com/astaxie/beego,71,21,21,,,,34,,5,,,,,,30,2,,,,,,21,,21, +github.com/beego/beego,142,42,42,,,,68,,10,,,,,,60,4,,,,,,42,,42, +github.com/caarlos0/env,,5,2,,,,,,,,,,,,,,,,,5,,,,1,1 +github.com/clevergo/clevergo,1,,,,,,,,,,,,,,,,,1,,,,,,, +github.com/codeskyblue/go-sh,4,,,4,,,,,,,,,,,,,,,,,,,,, +github.com/couchbase/gocb,8,,18,,,,,8,,,,,,,,,,,,,,,,18, +github.com/couchbaselabs/gocb,8,,18,,,,,8,,,,,,,,,,,,,,,,18, +github.com/crankycoder/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +github.com/cristalhq/jwt,1,,,,1,,,,,,,,,,,,,,,,,,,, +github.com/davecgh/go-spew/spew,9,,,,,,9,,,,,,,,,,,,,,,,,, +github.com/dgrijalva/jwt-go,3,,9,,2,1,,,,,,,,,,,,,,,,,,9, +github.com/elazarl/goproxy,2,2,2,,,,2,,,,,,,,,,,,,,,2,,2, +github.com/emicklei/go-restful,,7,,,,,,,,,,,,,,,,,,,,7,,, +github.com/evanphx/json-patch,,,12,,,,,,,,,,,,,,,,,,,,,12, +github.com/form3tech-oss/jwt-go,2,,,,2,,,,,,,,,,,,,,,,,,,, +github.com/gin-gonic/gin,3,46,2,,,,,,3,,,,,,,,,,,,,46,,2, +github.com/go-chi/chi,,3,,,,,,,,,,,,,,,,,,,,3,,, +github.com/go-chi/jwtauth,1,,,,1,,,,,,,,,,,,,,,,,,,, +github.com/go-gorm/gorm,13,,,,,,,,,,,,,,13,,,,,,,,,, +github.com/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4, +github.com/go-kit/kit/auth/jwt,1,,,,1,,,,,,,,,,,,,,,,,,,, +github.com/go-pg/pg/orm,,,6,,,,,,,,,,,,,,,,,,,,,6, +github.com/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +github.com/go-xorm/xorm,34,,,,,,,,,,,,,,34,,,,,,,,,, +github.com/gobuffalo/envy,,7,,,,,,,,,,,,,,,,,,7,,,,, +github.com/gobwas/ws,,2,,,,,,,,,,,,,,,,,,,,2,,, +github.com/gofiber/fiber,5,,,,,,,,4,,,,,,,,,1,,,,,,, +github.com/gogf/gf-jwt,1,,,,1,,,,,,,,,,,,,,,,,,,, +github.com/gogf/gf/database/gdb,51,,,,,,,,,,,,,,51,,,,,,,,,, +github.com/going/toolkit/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +github.com/golang-jwt/jwt,3,,11,,2,1,,,,,,,,,,,,,,,,,,11, +github.com/golang/glog,90,,,,,,90,,,,,,,,,,,,,,,,,, +github.com/golang/protobuf/proto,,,4,,,,,,,,,,,,,,,,,,,,,4, +github.com/gorilla/mux,,1,,,,,,,,,,,,,,,,,,,,1,,, +github.com/gorilla/websocket,,3,,,,,,,,,,,,,,,,,,,,3,,, +github.com/hashicorp/go-envparse,,1,,,,,,,,,,,,,,,,,,1,,,,, +github.com/jbowtie/gokogiri/xml,4,,,,,,,,,,,,,,,,,,4,,,,,, +github.com/jbowtie/gokogiri/xpath,1,,,,,,,,,,,,,,,,,,1,,,,,, +github.com/jinzhu/gorm,13,,,,,,,,,,,,,,13,,,,,,,,,, +github.com/jmoiron/sqlx,12,,,,,,,,,,,,,,12,,,,,,,,,, +github.com/joho/godotenv,,4,,,,,,,,,,,,,,,,,,4,,,,, +github.com/json-iterator/go,,,4,,,,,,,,,,,,,,,,,,,,,4, +github.com/kataras/iris/context,6,,,,,,,,6,,,,,,,,,,,,,,,, +github.com/kataras/iris/middleware/jwt,2,,,,2,,,,,,,,,,,,,,,,,,,, +github.com/kataras/iris/server/web/context,6,,,,,,,,6,,,,,,,,,,,,,,,, +github.com/kataras/jwt,5,,,,5,,,,,,,,,,,,,,,,,,,, +github.com/kelseyhightower/envconfig,,6,,,,,,,,,,,,,,,,,,6,,,,, +github.com/labstack/echo,3,12,2,,,,,,2,,,,,,,1,,,,,,12,,2, +github.com/lann/squirrel,32,,,,,,,,,,,,,,32,,,,,,,,,, +github.com/lestrrat-go/jwx,2,,,,2,,,,,,,,,,,,,,,,,,,, +github.com/lestrrat-go/libxml2/parser,3,,,,,,,,,,,,,,,,,,3,,,,,, +github.com/lestrrat/go-jwx/jwk,1,,,,1,,,,,,,,,,,,,,,,,,,, +github.com/masterzen/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +github.com/moovweb/gokogiri/xml,4,,,,,,,,,,,,,,,,,,4,,,,,, +github.com/moovweb/gokogiri/xpath,1,,,,,,,,,,,,,,,,,,1,,,,,, +github.com/ory/fosite/token/jwt,2,,,,2,,,,,,,,,,,,,,,,,,,, +github.com/raindog308/gorqlite,24,,,,,,,,,,,,,,24,,,,,,,,,, +github.com/revel/revel,2,23,10,,,,,,1,,,,,,,1,,,,,,23,,10, +github.com/robfig/revel,2,23,10,,,,,,1,,,,,,,1,,,,,,23,,10, +github.com/rqlite/gorqlite,24,,,,,,,,,,,,,,24,,,,,,,,,, +github.com/santhosh-tekuri/xpathparser,2,,,,,,,,,,,,,,,,,,2,,,,,, +github.com/sendgrid/sendgrid-go/helpers/mail,,,1,,,,,,,,,,,,,,,,,,,,,1, +github.com/sirupsen/logrus,145,,,,,,145,,,,,,,,,,,,,,,,,, +github.com/spf13/afero,34,,,,,,,,34,,,,,,,,,,,,,,,, +github.com/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4, +github.com/uptrace/bun,63,,,,,,,,,,,,,,63,,,,,,,,,, +github.com/valyala/fasthttp,35,50,5,,,,,,8,,,,17,8,,2,,,,,,50,,5, +go.mongodb.org/mongo-driver/mongo,14,,,,,,,14,,,,,,,,,,,,,,,,, +go.uber.org/zap,33,,11,,,,33,,,,,,,,,,,,,,,,,11, +golang.org/x/crypto/ssh,4,,,4,,,,,,,,,,,,,,,,,,,,, +golang.org/x/net/context,,,5,,,,,,,,,,,,,,,,,,,,,5, +golang.org/x/net/html,,,16,,,,,,,,,,,,,,,,,,,,,16, +golang.org/x/net/websocket,,2,,,,,,,,,,,,,,,,,,,,2,,, +google.golang.org/protobuf/internal/encoding/text,,,1,,,,,,,,,,,,,,,,,,,,,1, +google.golang.org/protobuf/internal/impl,,,2,,,,,,,,,,,,,,,,,,,,,2, +google.golang.org/protobuf/proto,,,8,,,,,,,,,,,,,,,,,,,,,8, +google.golang.org/protobuf/reflect/protoreflect,,,1,,,,,,,,,,,,,,,,,,,,,1, +gopkg.in/Masterminds/squirrel,32,,,,,,,,,,,,,,32,,,,,,,,,, +gopkg.in/couchbase/gocb,8,,18,,,,,8,,,,,,,,,,,,,,,,18, +gopkg.in/glog,90,,,,,,90,,,,,,,,,,,,,,,,,, +gopkg.in/go-jose/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4, +gopkg.in/go-xmlpath/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +gopkg.in/macaron,1,12,1,,,,,,,,,,,,,,,1,,,,12,,1, +gopkg.in/square/go-jose,3,,4,,2,1,,,,,,,,,,,,,,,,,,4, +gopkg.in/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +gopkg.in/yaml,,,9,,,,,,,,,,,,,,,,,,,,,9, +gorm.io/gorm,13,,,,,,,,,,,,,,13,,,,,,,,,, +html,,,8,,,,,,,,,,,,,,,,,,,,,8, +io,5,4,34,,,,,,5,,,,,,,,,,,,4,,,34, +k8s.io/api/core,,,10,,,,,,,,,,,,,,,,,,,,,10, +k8s.io/apimachinery/pkg/runtime,,,47,,,,,,,,,,,,,,,,,,,,,47, +k8s.io/klog,90,,,,,,90,,,,,,,,,,,,,,,,,, +launchpad.net/xmlpath,2,,,,,,,,,,,,,,,,,,2,,,,,, +log,20,,3,,,,20,,,,,,,,,,,,,,,,,3, +math/big,,,1,,,,,,,,,,,,,,,,,,,,,1, +mime,,,14,,,,,,,,,,,,,,,,,,,,,14, +net,2,16,100,,,,,,1,,,,,,,,1,,,,,16,,100, +nhooyr.io/websocket,,2,,,,,,,,,,,,,,,,,,,,2,,, +os,29,11,6,3,,,,,26,,,,,,,,,,,7,3,,1,6, +path,,,18,,,,,,,,,,,,,,,,,,,,,18, +reflect,,,37,,,,,,,,,,,,,,,,,,,,,37, +regexp,10,,20,,,,,,,3,3,4,,,,,,,,,,,,20, +slices,,,17,,,,,,,,,,,,,,,,,,,,,,17 +sort,,,1,,,,,,,,,,,,,,,,,,,,,1, +strconv,,,9,,,,,,,,,,,,,,,,,,,,,9, +strings,,,34,,,,,,,,,,,,,,,,,,,,,34, +sync,,,34,,,,,,,,,,,,,,,,,,,,,34, +syscall,5,2,8,5,,,,,,,,,,,,,,,,2,,,,8, +text/scanner,,,3,,,,,,,,,,,,,,,,,,,,,3, +text/tabwriter,,,1,,,,,,,,,,,,,,,,,,,,,1, +text/template,,,6,,,,,,,,,,,,,,,,,,,,,6, +xorm.io/xorm,34,,,,,,,,,,,,,,34,,,,,,,,,, diff --git a/go/documentation/library-coverage/coverage.rst b/go/documentation/library-coverage/coverage.rst index 848d989d2d58..48f24355a333 100644 --- a/go/documentation/library-coverage/coverage.rst +++ b/go/documentation/library-coverage/coverage.rst @@ -9,27 +9,27 @@ Go framework & library support Framework / library,Package,Flow sources,Taint & value steps,Sinks (total) `Afero `_,``github.com/spf13/afero*``,,,34 `CleverGo `_,"``clevergo.tech/clevergo*``, ``github.com/clevergo/clevergo*``",,,2 - `Couchbase official client(gocb) `_,"``github.com/couchbase/gocb*``, ``gopkg.in/couchbase/gocb*``",,36, - `Couchbase unofficial client `_,``github.com/couchbaselabs/gocb*``,,18, + `Couchbase official client(gocb) `_,"``github.com/couchbase/gocb*``, ``gopkg.in/couchbase/gocb*``",,36,16 + `Couchbase unofficial client `_,``github.com/couchbaselabs/gocb*``,,18,8 `Echo `_,``github.com/labstack/echo*``,12,2,3 `Fiber `_,``github.com/gofiber/fiber*``,,,5 `Fosite `_,``github.com/ory/fosite*``,,,2 `Gin `_,``github.com/gin-gonic/gin*``,46,2,3 - `Glog `_,"``github.com/golang/glog*``, ``gopkg.in/glog*``, ``k8s.io/klog*``",,, + `Glog `_,"``github.com/golang/glog*``, ``gopkg.in/glog*``, ``k8s.io/klog*``",,,270 `Go JOSE `_,"``github.com/go-jose/go-jose*``, ``github.com/square/go-jose*``, ``gopkg.in/square/go-jose*``, ``gopkg.in/go-jose/go-jose*``",,16,12 `Go kit `_,``github.com/go-kit/kit*``,,,1 - `Go-spew `_,``github.com/davecgh/go-spew/spew*``,,, + `Go-spew `_,``github.com/davecgh/go-spew/spew*``,,,9 `Gokogiri `_,"``github.com/jbowtie/gokogiri*``, ``github.com/moovweb/gokogiri*``",,,10 `Iris `_,``github.com/kataras/iris*``,,,14 `Kubernetes `_,"``k8s.io/api*``, ``k8s.io/apimachinery*``",,57, - `Logrus `_,"``github.com/Sirupsen/logrus*``, ``github.com/sirupsen/logrus*``",,, + `Logrus `_,"``github.com/Sirupsen/logrus*``, ``github.com/sirupsen/logrus*``",,,290 `Macaron `_,``gopkg.in/macaron*``,12,1,1 `Revel `_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4 `SendGrid `_,``github.com/sendgrid/sendgrid-go*``,,1, - `Standard library `_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",32,587,51 + `Standard library `_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",33,604,104 `XPath `_,``github.com/antchfx/xpath*``,,,4 `appleboy/gin-jwt `_,``github.com/appleboy/gin-jwt*``,,,1 - `beego `_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",63,63,21 + `beego `_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",63,63,213 `chi `_,``github.com/go-chi/chi*``,3,, `cristalhq/jwt `_,``github.com/cristalhq/jwt*``,,,1 `fasthttp `_,``github.com/valyala/fasthttp*``,50,5,35 @@ -39,7 +39,7 @@ Go framework & library support `go-sh `_,``github.com/codeskyblue/go-sh*``,,,4 `golang.org/x/crypto/ssh `_,``golang.org/x/crypto/ssh*``,,,4 `golang.org/x/net `_,``golang.org/x/net*``,2,21, - `goproxy `_,``github.com/elazarl/goproxy*``,2,2, + `goproxy `_,``github.com/elazarl/goproxy*``,2,2,2 `gorilla/mux `_,``github.com/gorilla/mux*``,1,, `gorilla/websocket `_,``github.com/gorilla/websocket*``,3,, `goxpath `_,``github.com/ChrisTrenkamp/goxpath*``,,,3 @@ -59,7 +59,7 @@ Go framework & library support `xmlquery `_,``github.com/antchfx/xmlquery*``,,,8 `xpathparser `_,``github.com/santhosh-tekuri/xpathparser*``,,,2 `yaml `_,``gopkg.in/yaml*``,,9, - `zap `_,``go.uber.org/zap*``,,11, - Others,"``github.com/caarlos0/env``, ``github.com/gobuffalo/envy``, ``github.com/hashicorp/go-envparse``, ``github.com/joho/godotenv``, ``github.com/kelseyhightower/envconfig``",23,2, - Totals,,306,911,268 + `zap `_,``go.uber.org/zap*``,,11,33 + Others,"``github.com/Masterminds/squirrel``, ``github.com/caarlos0/env``, ``github.com/go-gorm/gorm``, ``github.com/go-xorm/xorm``, ``github.com/gobuffalo/envy``, ``github.com/gogf/gf/database/gdb``, ``github.com/hashicorp/go-envparse``, ``github.com/jinzhu/gorm``, ``github.com/jmoiron/sqlx``, ``github.com/joho/godotenv``, ``github.com/kelseyhightower/envconfig``, ``github.com/lann/squirrel``, ``github.com/raindog308/gorqlite``, ``github.com/rqlite/gorqlite``, ``github.com/uptrace/bun``, ``go.mongodb.org/mongo-driver/mongo``, ``gopkg.in/Masterminds/squirrel``, ``gorm.io/gorm``, ``xorm.io/xorm``",23,2,391 + Totals,,307,928,1532 diff --git a/go/ql/lib/change-notes/2024-11-20-heuristic-logging-sinks.md b/go/ql/lib/change-notes/2024-11-20-heuristic-logging-sinks.md new file mode 100644 index 000000000000..46f5988b3798 --- /dev/null +++ b/go/ql/lib/change-notes/2024-11-20-heuristic-logging-sinks.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* A call to a method whose name starts with "Debug", "Error", "Fatal", "Info", "Log", "Output", "Panic", "Print", "Trace", "Warn" or "With" defined on an interface whose name ends in "logger" or "Logger" is now considered a LoggerCall. In particular, it is a sink for `go/clear-text-logging` and `go/log-injection`. This may lead to some more alerts in those queries. diff --git a/go/ql/lib/ext/database.sql.driver.model.yml b/go/ql/lib/ext/database.sql.driver.model.yml index c2d780bb7c86..10cfba9388a6 100644 --- a/go/ql/lib/ext/database.sql.driver.model.yml +++ b/go/ql/lib/ext/database.sql.driver.model.yml @@ -1,4 +1,14 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["database/sql/driver", "Execer", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql/driver", "ExecerContext", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql/driver", "Conn", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql/driver", "ConnPrepareContext", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql/driver", "Queryer", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql/driver", "QueryerContext", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/database.sql.model.yml b/go/ql/lib/ext/database.sql.model.yml index e1083f6e49a6..5854ced527d5 100644 --- a/go/ql/lib/ext/database.sql.model.yml +++ b/go/ql/lib/ext/database.sql.model.yml @@ -1,4 +1,32 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["database/sql", "Conn", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Conn", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "DB", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["database/sql", "Tx", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/fmt.model.yml b/go/ql/lib/ext/fmt.model.yml index cad64ce0fdf6..2baac68da3a0 100644 --- a/go/ql/lib/ext/fmt.model.yml +++ b/go/ql/lib/ext/fmt.model.yml @@ -1,4 +1,11 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["fmt", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["fmt", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["fmt", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/github.com.beego.beego.client.orm.model.yml b/go/ql/lib/ext/github.com.beego.beego.client.orm.model.yml new file mode 100644 index 000000000000..08c0572b894a --- /dev/null +++ b/go/ql/lib/ext/github.com.beego.beego.client.orm.model.yml @@ -0,0 +1,42 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["beego-orm", "github.com/beego/beego/client/orm"] + - ["beego-orm", "github.com/astaxie/beego/orm"] + - ["beego-orm", "github.com/beego/beego/orm"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:beego-orm", "Condition", True, "Raw", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "DB", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:beego-orm", "Ormer", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "And", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Delete", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "In", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "InnerJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "InsertInto", "", "", "Argument[0..1]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "LeftJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "On", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "RightJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Set", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Subquery", "", "", "Argument[0..1]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Update", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Values", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QueryBuilder", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:beego-orm", "QuerySeter", True, "FilterRaw", "", "", "Argument[1]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.beego.beego.core.logs.model.yml b/go/ql/lib/ext/github.com.beego.beego.core.logs.model.yml new file mode 100644 index 000000000000..b55c3be507dd --- /dev/null +++ b/go/ql/lib/ext/github.com.beego.beego.core.logs.model.yml @@ -0,0 +1,34 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["beego-logs", "github.com/astaxie/beego/logs"] + - ["beego-logs", "github.com/beego/beego/logs"] + - ["beego-logs", "github.com/beego/beego/core/logs"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:beego-logs", "", False, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Emergency", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Informational", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Notice", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "", False, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Emergency", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Informational", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Notice", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego-logs", "BeeLogger", True, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml b/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml index 4eb0688e37e7..63c05b920401 100644 --- a/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml +++ b/go/ql/lib/ext/github.com.beego.beego.core.utils.model.yml @@ -6,6 +6,11 @@ extensions: - ["beego-utils", "github.com/astaxie/beego/utils"] - ["beego-utils", "github.com/beego/beego/utils"] - ["beego-utils", "github.com/beego/beego/core/utils"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:beego-utils", "", False, "Display", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml b/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml index 963000fffccd..0c539522c5a7 100644 --- a/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml +++ b/go/ql/lib/ext/github.com.beego.beego.server.web.model.yml @@ -10,6 +10,18 @@ extensions: pack: codeql/go-all extensible: sinkModel data: + # log-injection + - ["group:beego", "", False, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Emergency", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Informational", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Notice", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:beego", "", False, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"] # path-injection - ["group:beego", "", False, "Walk", "", "", "Argument[1]", "path-injection", "manual"] - ["group:beego", "Controller", True, "SaveToFile", "", "", "Argument[1]", "path-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.couchbase.gocb.model.yml b/go/ql/lib/ext/github.com.couchbase.gocb.model.yml index ff0a4c22c8de..d17b53dd6da9 100644 --- a/go/ql/lib/ext/github.com.couchbase.gocb.model.yml +++ b/go/ql/lib/ext/github.com.couchbase.gocb.model.yml @@ -3,28 +3,43 @@ extensions: pack: codeql/go-all extensible: packageGrouping data: - - ["gocb", "github.com/couchbase/gocb"] - - ["gocb", "gopkg.in/couchbase/gocb"] - - ["gocb", "github.com/couchbaselabs/gocb"] + - ["gocb1", "fixed-version:github.com/couchbase/gocb"] + - ["gocb1", "fixed-version:gopkg.in/couchbase/gocb.v1"] + - ["gocb1", "fixed-version:github.com/couchbaselabs/gocb"] + - ["gocb2", "github.com/couchbase/gocb/v2"] + - ["gocb2", "gopkg.in/couchbase/gocb.v2"] + - ["gocb2", "github.com/couchbaselabs/gocb/v2"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:gocb1", "Bucket", True, "ExecuteN1qlQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb1", "Bucket", True, "ExecuteAnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb1", "Cluster", True, "ExecuteN1qlQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb1", "Cluster", True, "ExecuteAnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Cluster", True, "AnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Cluster", True, "Query", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Scope", True, "AnalyticsQuery", "", "", "Argument[0]", "nosql-injection", "manual"] + - ["group:gocb2", "Scope", True, "Query", "", "", "Argument[0]", "nosql-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel data: - - ["group:gocb", "", False, "NewAnalyticsQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "", False, "NewN1qlQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "ContextId", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "Deferred", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "Pretty", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "Priority", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "RawParam", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "AnalyticsQuery", True, "ServerSideTimeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "AdHoc", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Consistency", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "ConsistentWith", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Custom", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "PipelineBatch", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "PipelineCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Profile", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "ReadOnly", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "ScanCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] - - ["group:gocb", "N1qlQuery", True, "Timeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "", False, "NewAnalyticsQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "", False, "NewN1qlQuery", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "ContextId", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "Deferred", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "Pretty", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "Priority", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "RawParam", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "AnalyticsQuery", True, "ServerSideTimeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "AdHoc", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Consistency", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "ConsistentWith", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Custom", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "PipelineBatch", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "PipelineCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Profile", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "ReadOnly", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "ScanCap", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] + - ["group:gocb1", "N1qlQuery", True, "Timeout", "", "", "Argument[receiver]", "ReturnValue", "taint", "manual"] diff --git a/go/ql/lib/ext/github.com.davecgh.go-spew.spew.model.yml b/go/ql/lib/ext/github.com.davecgh.go-spew.spew.model.yml new file mode 100644 index 000000000000..4b4996926e31 --- /dev/null +++ b/go/ql/lib/ext/github.com.davecgh.go-spew.spew.model.yml @@ -0,0 +1,14 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/davecgh/go-spew/spew", "", False, "Dump", "", "", "Argument[0]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fdump", "", "", "Argument[1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fprint", "", "", "Argument[1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fprintf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Fprintln", "", "", "Argument[1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["github.com/davecgh/go-spew/spew", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml b/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml index 20e4a26f1cdb..9dc8284ea58f 100644 --- a/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml +++ b/go/ql/lib/ext/github.com.elazarl.goproxy.model.yml @@ -1,4 +1,10 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/elazarl/goproxy", "ProxyCtx", True, "Logf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["github.com/elazarl/goproxy", "ProxyCtx", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/github.com.gogf.gf.database.gdb.model.yml b/go/ql/lib/ext/github.com.gogf.gf.database.gdb.model.yml new file mode 100644 index 000000000000..030656c6eb8a --- /dev/null +++ b/go/ql/lib/ext/github.com.gogf.gf.database.gdb.model.yml @@ -0,0 +1,57 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + # These models are for v1. Some of them hold for v2, but we should model v2 properly. + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoCommit", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoExec", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoGetAll", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoQuery", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "DoPrepare", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetAll", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetArray", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetCount", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetScan", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetStruct", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetStructs", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "GetValue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Core", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoCommit", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoExec", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoGetAll", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoQuery", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "DoPrepare", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetAll", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetArray", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetCount", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetScan", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetStruct", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetStructs", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "GetValue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "DB", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoCommit", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoExec", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoGetAll", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoQuery", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "DoPrepare", "", "", "Argument[2]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetAll", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetArray", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetCount", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetScan", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetStruct", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetStructs", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "GetValue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/gogf/gf/database/gdb", "Tx", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.golang.glog.model.yml b/go/ql/lib/ext/github.com.golang.glog.model.yml new file mode 100644 index 000000000000..275450f2c447 --- /dev/null +++ b/go/ql/lib/ext/github.com.golang.glog.model.yml @@ -0,0 +1,102 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["glog", "github.com/golang/glog"] + - ["glog", "gopkg.in/glog"] + - ["glog", "k8s.io/klog"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:glog", "", False, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ErrorDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Exit", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "ExitDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Exitf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Exitln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "FatalDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "InfoDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "", False, "WarningDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "", False, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "", False, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ErrorDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Exit", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "ExitDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Exitf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Exitln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "FatalDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "InfoDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContext", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContextDepth", "", "", "Argument[2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContextDepthf", "", "", "Argument[2..3]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningContextf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningDepth", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "WarningDepthf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:glog", "Verbose", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml b/go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml new file mode 100644 index 000000000000..8c9d19b4b85b --- /dev/null +++ b/go/ql/lib/ext/github.com.jmoiron.sqlx.model.yml @@ -0,0 +1,17 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/jmoiron/sqlx", "DB", True, "Get", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "MustExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "NamedExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "DB", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "Get", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "MustExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "NamedExec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "NamedQuery", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "Queryx", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/jmoiron/sqlx", "Tx", True, "Select", "", "", "Argument[1]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.mastermind.squirrel.model.yml b/go/ql/lib/ext/github.com.mastermind.squirrel.model.yml new file mode 100644 index 000000000000..6f3c5830e457 --- /dev/null +++ b/go/ql/lib/ext/github.com.mastermind.squirrel.model.yml @@ -0,0 +1,51 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["squirrel", "github.com/Masterminds/squirrel"] + - ["squirrel", "gopkg.in/Masterminds/squirrel"] + - ["squirrel", "github.com/lann/squirrel"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:squirrel", "", False, "Delete", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "", False, "Expr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "", False, "Insert", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "", False, "Select", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "", False, "Update", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + + - ["group:squirrel", "DeleteBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "DeleteBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "DeleteBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "DeleteBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + # DeleteBuilder.Where has to be modeled in QL to avoid FPs when a non-string argument is used + + - ["group:squirrel", "InsertBuilder", True, "Columns", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "InsertBuilder", True, "Into", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "InsertBuilder", True, "Options", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "InsertBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "InsertBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + + - ["group:squirrel", "SelectBuilder", True, "CrossJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Column", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Columns", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "SelectBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "InnerJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "LeftJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Options", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "SelectBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "SelectBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "RightJoin", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "SelectBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + # SelectBuilder.Where has to be modeled in QL to avoid FPs when a non-string argument is used + + - ["group:squirrel", "UpdateBuilder", True, "From", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] # TODO: when sources can have access paths, use .ArrayElement + - ["group:squirrel", "UpdateBuilder", True, "Prefix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "Set", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "Suffix", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:squirrel", "UpdateBuilder", True, "Table", "", "", "Argument[0]", "sql-injection", "manual"] + # UpdateBuilder.Where has to be modeled in QL to avoid FPs when a non-string argument is used diff --git a/go/ql/lib/ext/github.com.rqlite.gorqlite.model.yml b/go/ql/lib/ext/github.com.rqlite.gorqlite.model.yml new file mode 100644 index 000000000000..62e24f2c920b --- /dev/null +++ b/go/ql/lib/ext/github.com.rqlite.gorqlite.model.yml @@ -0,0 +1,35 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["gorqlite", "github.com/rqlite/gorqlite"] + - ["gorqlite", "github.com/raindog308/gorqlite"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:gorqlite", "Connection", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOneContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOneParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryOneParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueryParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "Queue", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOneContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOneParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueOneParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "QueueParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "Write", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOne", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOneContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOneParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteOneParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteParameterized", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorqlite", "Connection", True, "WriteParameterizedContext", "", "", "Argument[1]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.sirupsen.logrus.model.yml b/go/ql/lib/ext/github.com.sirupsen.logrus.model.yml new file mode 100644 index 000000000000..06f9a54622b4 --- /dev/null +++ b/go/ql/lib/ext/github.com.sirupsen.logrus.model.yml @@ -0,0 +1,159 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["logrus", "github.com/sirupsen/logrus"] + - ["logrus", "github.com/Sirupsen/logrus"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:logrus", "", False, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "DebugFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "ErrorFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "FatalFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "InfoFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "PanicFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "PrintFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Trace", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "TraceFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Tracef", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Traceln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WarnFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WarningFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "", False, "WithTime", "", "", "Argument[0]", "log-injection", "manual"] + + - ["group:logrus", "Entry", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Log", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Logf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Logln", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Trace", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Tracef", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Traceln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Entry", True, "WithTime", "", "", "Argument[0]", "log-injection", "manual"] + + - ["group:logrus", "FieldLogger", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "FieldLogger", True, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + + - ["group:logrus", "Logger", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "DebugFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Debugln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "ErrorFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Errorln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "FatalFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "InfoFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Infoln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Log", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "LogFn", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Logf", "", "", "Argument[1..2]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Logln", "", "", "Argument[1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "PanicFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "PrintFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Trace", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "TraceFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Tracef", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Traceln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WarnFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warnln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warning", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WarningFn", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warningf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "Warningln", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithError", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithField", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithFields", "", "", "Argument[0]", "log-injection", "manual"] + - ["group:logrus", "Logger", True, "WithTime", "", "", "Argument[0]", "log-injection", "manual"] diff --git a/go/ql/lib/ext/github.com.uptrace.bun.model.yml b/go/ql/lib/ext/github.com.uptrace.bun.model.yml new file mode 100644 index 000000000000..a08adb07973d --- /dev/null +++ b/go/ql/lib/ext/github.com.uptrace.bun.model.yml @@ -0,0 +1,68 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["github.com/uptrace/bun", "", False, "NewRawQuery", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "AddColumnQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "AddColumnQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "AddColumnQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "NewRaw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "Conn", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateIndexQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateTableQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateTableQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "CreateTableQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "ExecContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "NewRaw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Prepare", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Query", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "QueryRow", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "PrepareContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "QueryContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "QueryRowContext", "", "", "Argument[1]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DB", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DeleteQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DeleteQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DeleteQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropColumnQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropColumnQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropColumnQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropTableQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "DropTableQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "InsertQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "MergeQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "MergeQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "RawQuery", True, "NewRaw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "ColumnExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "DistinctOn", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "For", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "GroupExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "OrderExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "SelectQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "TruncateTableQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "ModelTableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "TableExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["github.com/uptrace/bun", "UpdateQuery", True, "WhereOr", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/go.mongodb.org.mongo-driver.mongo.model.yml b/go/ql/lib/ext/go.mongodb.org.mongo-driver.mongo.model.yml new file mode 100644 index 000000000000..6c2d4afdeae2 --- /dev/null +++ b/go/ql/lib/ext/go.mongodb.org.mongo-driver.mongo.model.yml @@ -0,0 +1,19 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Aggregate", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "CountDocuments", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "DeleteMany", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "DeleteOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Distinct", "", "", "Argument[2]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Find", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOneAndDelete", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOneAndReplace", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "FindOneAndUpdate", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "ReplaceOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "UpdateMany", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "UpdateOne", "", "", "Argument[1]", "nosql-injection", "manual"] + - ["go.mongodb.org/mongo-driver/mongo", "Collection", True, "Watch", "", "", "Argument[1]", "nosql-injection", "manual"] diff --git a/go/ql/lib/ext/go.uber.org.zap.model.yml b/go/ql/lib/ext/go.uber.org.zap.model.yml index 2ca7f7e8a804..e9fc971e5fa2 100644 --- a/go/ql/lib/ext/go.uber.org.zap.model.yml +++ b/go/ql/lib/ext/go.uber.org.zap.model.yml @@ -1,4 +1,41 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["go.uber.org/zap", "Logger", True, "DPanic", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Error", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Fatal", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Info", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Named", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Panic", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "With", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "Logger", True, "WithOptions", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "DPanic", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "DPanicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "DPanicw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Debug", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Debugf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Debugw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Error", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Errorf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Errorw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Fatalw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Info", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Infof", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Infow", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Named", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Panicw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Warn", "", "", "Argument[0]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Warnf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "Warnw", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["go.uber.org/zap", "SugaredLogger", True, "With", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/gorm.io.gorm.model.yml b/go/ql/lib/ext/gorm.io.gorm.model.yml new file mode 100644 index 000000000000..bfcf1fa66a76 --- /dev/null +++ b/go/ql/lib/ext/gorm.io.gorm.model.yml @@ -0,0 +1,25 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["gorm", "gorm.io/gorm"] + - ["gorm", "github.com/jinzhu/gorm"] + - ["gorm", "github.com/go-gorm/gorm"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:gorm", "DB", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Raw", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Order", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Not", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Table", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Group", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Joins", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Exec", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Distinct", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:gorm", "DB", True, "Pluck", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/ext/log.model.yml b/go/ql/lib/ext/log.model.yml index 7f52a1733073..4d1df7cf0821 100644 --- a/go/ql/lib/ext/log.model.yml +++ b/go/ql/lib/ext/log.model.yml @@ -1,4 +1,28 @@ extensions: + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["log", "", False, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "", False, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Output", "", "", "Argument[1]", "log-injection", "manual"] + - ["log", "", False, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "", False, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "", False, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "", False, "Println", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Fatal", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Fatalf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "Logger", True, "Fatalln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Output", "", "", "Argument[1]", "log-injection", "manual"] + - ["log", "Logger", True, "Panic", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Panicf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "Logger", True, "Panicln", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Print", "", "", "Argument[0]", "log-injection", "manual"] + - ["log", "Logger", True, "Printf", "", "", "Argument[0..1]", "log-injection", "manual"] + - ["log", "Logger", True, "Println", "", "", "Argument[0]", "log-injection", "manual"] - addsTo: pack: codeql/go-all extensible: summaryModel diff --git a/go/ql/lib/ext/os.model.yml b/go/ql/lib/ext/os.model.yml index 3d87eefe43f7..2c1c64db93ac 100644 --- a/go/ql/lib/ext/os.model.yml +++ b/go/ql/lib/ext/os.model.yml @@ -53,6 +53,7 @@ extensions: - ["os", "", False, "Open", "", "", "ReturnValue[0]", "file", "manual"] - ["os", "", False, "OpenFile", "", "", "ReturnValue[0]", "file", "manual"] - ["os", "", False, "ReadFile", "", "", "ReturnValue[0]", "file", "manual"] + - ["os", "", False, "Stdin", "", "", "", "stdin", "manual"] - ["os", "", False, "UserCacheDir", "", "", "ReturnValue[0]", "environment", "manual"] - ["os", "", False, "UserConfigDir", "", "", "ReturnValue[0]", "environment", "manual"] - ["os", "", False, "UserHomeDir", "", "", "ReturnValue[0]", "environment", "manual"] diff --git a/go/ql/lib/ext/slices.model.yml b/go/ql/lib/ext/slices.model.yml new file mode 100644 index 000000000000..2023aeb3db23 --- /dev/null +++ b/go/ql/lib/ext/slices.model.yml @@ -0,0 +1,31 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: summaryModel + data: + # All should be modeled when we have a way to model iterators + # AppendSec should be modeled when we have a way to model iterators + # Backward should be modeled when we have a way to model iterators + # Chunk should be modeled when we have a way to model iterators + - ["slices", "", False, "Clip", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Clone", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + # Collect should be modeled when we have a way to model iterators + - ["slices", "", False, "Compact", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "CompactFunc", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Concat", "", "", "Argument[0].ArrayElement.ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Delete", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "DeleteFunc", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Grow", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Insert", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Insert", "", "", "Argument[2].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Max", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"] + - ["slices", "", False, "MaxFunc", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"] + - ["slices", "", False, "Min", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"] + - ["slices", "", False, "MinFunc", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"] + - ["slices", "", False, "Repeat", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Replace", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + - ["slices", "", False, "Replace", "", "", "Argument[3].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] + # Sorted should be modeled when we have a way to model iterators + # SortedFunc should be modeled when we have a way to model iterators + # SortedStableFunc should be modeled when we have a way to model iterators + # Values should be modeled when we have a way to model iterators diff --git a/go/ql/lib/ext/xorm.io.xorm.model.yml b/go/ql/lib/ext/xorm.io.xorm.model.yml new file mode 100644 index 000000000000..5cf1ac4f5d73 --- /dev/null +++ b/go/ql/lib/ext/xorm.io.xorm.model.yml @@ -0,0 +1,49 @@ +extensions: + - addsTo: + pack: codeql/go-all + extensible: packageGrouping + data: + - ["xorm", "xorm.io/xorm"] + - ["xorm", "github.com/go-xorm/xorm"] + - addsTo: + pack: codeql/go-all + extensible: sinkModel + data: + - ["group:xorm", "Engine", True, "Alias", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "And", "", "", "Argument[0]", "sql-injection", "manual"] + # Engine.Exec has to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Engine", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "In", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Join", "", "", "Argument[0..2]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "NotIn", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] + # Engine.Query, Engine.QueryInterface and Engine.QueryString have to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Engine", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SetExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SQL", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Sum", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Sums", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SumInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "SumsInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Engine", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Alias", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "And", "", "", "Argument[0]", "sql-injection", "manual"] + # Session.Exec has to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Session", True, "GroupBy", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Having", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "In", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Join", "", "", "Argument[0..2]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "NotIn", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Or", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "OrderBy", "", "", "Argument[0]", "sql-injection", "manual"] + # Session.Query, Session.QueryInterface and Session.QueryString have to be modeled in QL to select only the first syntactic argument + - ["group:xorm", "Session", True, "Select", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SetExpr", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SQL", "", "", "Argument[0]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Sum", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Sums", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SumInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "SumsInt", "", "", "Argument[1]", "sql-injection", "manual"] + - ["group:xorm", "Session", True, "Where", "", "", "Argument[0]", "sql-injection", "manual"] diff --git a/go/ql/lib/semmle/go/Concepts.qll b/go/ql/lib/semmle/go/Concepts.qll index c15d3683b40c..3f0cd0f8885e 100644 --- a/go/ql/lib/semmle/go/Concepts.qll +++ b/go/ql/lib/semmle/go/Concepts.qll @@ -373,6 +373,48 @@ module LoggerCall { } } +private class DefaultLoggerCall extends LoggerCall::Range, DataFlow::CallNode { + DataFlow::ArgumentNode messageComponent; + + DefaultLoggerCall() { + sinkNode(messageComponent, "log-injection") and + this = messageComponent.getCall() + } + + override DataFlow::Node getAMessageComponent() { + not messageComponent instanceof DataFlow::ImplicitVarargsSlice and + result = messageComponent + or + messageComponent instanceof DataFlow::ImplicitVarargsSlice and + result = this.getAnImplicitVarargsArgument() + } +} + +/** + * A call to an interface that looks like a logger. It is common to use a + * locally-defined interface for logging to make it easy to changing logging + * library. + */ +private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode { + HeuristicLoggerCall() { + exists(Method m, string tp, string logFunctionPrefix, string name | + m = this.getTarget() and + m.hasQualifiedName(_, tp, name) and + m.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType + | + tp.regexpMatch(".*[lL]ogger") and + logFunctionPrefix = + [ + "Debug", "Error", "Fatal", "Info", "Log", "Output", "Panic", "Print", "Trace", "Warn", + "With" + ] and + name.matches(logFunctionPrefix + "%") + ) + } + + override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } +} + /** * A function that encodes data into a binary or textual format. * diff --git a/go/ql/lib/semmle/go/Scopes.qll b/go/ql/lib/semmle/go/Scopes.qll index f9b9e3a26b9a..c3671c74b5cd 100644 --- a/go/ql/lib/semmle/go/Scopes.qll +++ b/go/ql/lib/semmle/go/Scopes.qll @@ -472,7 +472,7 @@ class Function extends ValueEntity, @functionobject { /** Gets a parameter of this function. */ Parameter getAParameter() { result = this.getParameter(_) } - /** Gets the `i`th reslt variable of this function. */ + /** Gets the `i`th result variable of this function. */ ResultVariable getResult(int i) { result.isResultOf(this.getFuncDecl(), i) } /** Gets a result variable of this function. */ diff --git a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll index a59c7294e802..5ae7b6a7f0d8 100644 --- a/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/ExternalFlow.qll @@ -38,7 +38,8 @@ * first 6 columns, and the `output` column specifies how data leaves the * element selected by the first 6 columns. An `input` can be either "", * "Argument[n]", or "Argument[n1..n2]": - * - "": Selects a write to the selected element in case this is a field. + * - "": Selects a write to the selected element in case this is a field or + * package-level variable. * - "Argument[n]": Selects an argument in a call to the selected element. * The arguments are zero-indexed, and `receiver` specifies the receiver. * - "Argument[n1..n2]": Similar to "Argument[n]" but selects any argument @@ -47,7 +48,7 @@ * An `output` can be either "", "Argument[n]", "Argument[n1..n2]", "Parameter", * "Parameter[n]", "Parameter[n1..n2]", , "ReturnValue", "ReturnValue[n]", or * "ReturnValue[n1..n2]": - * - "": Selects a read of a selected field. + * - "": Selects a read of a selected field or package-level variable. * - "Argument[n]": Selects the post-update value of an argument in a call to the * selected element. That is, the value of the argument after the call returns. * The arguments are zero-indexed, and `receiver` specifies the receiver. diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index b82039a32fe3..40c68ceb900a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -399,6 +399,13 @@ module SourceSinkInterpretationInput implements c = "" and pragma[only_bind_into](e) = getElementWithQualifier(frn.getField(), frn.getBase()) ) + or + // A package-scope (or universe-scope) variable + exists(Variable v | not v instanceof Field | + c = "" and + n.(DataFlow::ReadNode).reads(v) and + pragma[only_bind_into](e).asEntity() = v + ) ) } @@ -420,6 +427,17 @@ module SourceSinkInterpretationInput implements fw.writesField(base, f, node.asNode()) and pragma[only_bind_into](e) = getElementWithQualifier(f, base) ) + or + // A package-scope (or universe-scope) variable + exists(Node n, SourceOrSinkElement e, DataFlow::Write w, Variable v | + n = node.asNode() and + e = mid.asElement() and + not v instanceof Field + | + c = "" and + w.writes(v, n) and + pragma[only_bind_into](e).asEntity() = v + ) } } diff --git a/go/ql/lib/semmle/go/frameworks/Beego.qll b/go/ql/lib/semmle/go/frameworks/Beego.qll index 9f6ee5980035..a9e296a1f973 100644 --- a/go/ql/lib/semmle/go/frameworks/Beego.qll +++ b/go/ql/lib/semmle/go/frameworks/Beego.qll @@ -33,13 +33,6 @@ module Beego { result = package(v2modulePath(), "server/web/context") } - /** Gets the path for the logs package of beego. */ - string logsPackagePath() { - result = package(v1modulePath(), "logs") - or - result = package(v2modulePath(), "core/logs") - } - /** Gets the path for the utils package of beego. */ string utilsPackagePath() { result = package(v1modulePath(), "utils") @@ -172,36 +165,6 @@ module Beego { override string getAContentType() { none() } } - private string getALogFunctionName() { - result = - [ - "Alert", "Critical", "Debug", "Emergency", "Error", "Info", "Informational", "Notice", - "Trace", "Warn", "Warning" - ] - } - - private class ToplevelBeegoLoggers extends LoggerCall::Range, DataFlow::CallNode { - ToplevelBeegoLoggers() { - this.getTarget().hasQualifiedName([packagePath(), logsPackagePath()], getALogFunctionName()) - } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - - private class BeegoLoggerMethods extends LoggerCall::Range, DataFlow::MethodCallNode { - BeegoLoggerMethods() { - this.getTarget().hasQualifiedName(logsPackagePath(), "BeeLogger", getALogFunctionName()) - } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - - private class UtilLoggers extends LoggerCall::Range, DataFlow::CallNode { - UtilLoggers() { this.getTarget().hasQualifiedName(utilsPackagePath(), "Display") } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - private class HtmlQuoteSanitizer extends SharedXss::Sanitizer { HtmlQuoteSanitizer() { exists(DataFlow::CallNode c | c.getTarget().hasQualifiedName(packagePath(), "Htmlquote") | diff --git a/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll b/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll index c1de0cf42442..925b0f19fa3f 100644 --- a/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll +++ b/go/ql/lib/semmle/go/frameworks/BeegoOrm.qll @@ -14,57 +14,6 @@ module BeegoOrm { /** Gets the package name `github.com/astaxie/beego/orm`. */ string packagePath() { result = package("github.com/astaxie/beego", "orm") } - private class DbSink extends SQL::QueryString::Range { - DbSink() { - exists(Method m, string methodName, int argNum | - m.hasQualifiedName(packagePath(), "DB", methodName) and - ( - methodName = ["Exec", "Prepare", "Query", "QueryRow"] and - argNum = 0 - or - methodName = ["ExecContext", "PrepareContext", "QueryContext", "QueryRowContext"] and - argNum = 1 - ) - | - this = m.getACall().getArgument(argNum) - ) - } - } - - private class QueryBuilderSink extends SQL::QueryString::Range { - // Note this class doesn't do any escaping, unlike the true ORM part of the package - QueryBuilderSink() { - exists(Method impl | impl.implements(packagePath(), "QueryBuilder", _) | - this = impl.getACall().getASyntacticArgument() - ) and - this.getType().getUnderlyingType() instanceof StringType - } - } - - private class OrmerRawSink extends SQL::QueryString::Range { - OrmerRawSink() { - exists(Method impl | impl.implements(packagePath(), "Ormer", "Raw") | - this = impl.getACall().getArgument(0) - ) - } - } - - private class QuerySeterFilterRawSink extends SQL::QueryString::Range { - QuerySeterFilterRawSink() { - exists(Method impl | impl.implements(packagePath(), "QuerySeter", "FilterRaw") | - this = impl.getACall().getArgument(1) - ) - } - } - - private class ConditionRawSink extends SQL::QueryString::Range { - ConditionRawSink() { - exists(Method impl | impl.implements(packagePath(), "Condition", "Raw") | - this = impl.getACall().getArgument(1) - ) - } - } - private class OrmerSource extends StoredXss::Source { OrmerSource() { exists(Method impl | diff --git a/go/ql/lib/semmle/go/frameworks/Couchbase.qll b/go/ql/lib/semmle/go/frameworks/Couchbase.qll index 5eaa4d20c3ad..b5bfbcb22a2d 100644 --- a/go/ql/lib/semmle/go/frameworks/Couchbase.qll +++ b/go/ql/lib/semmle/go/frameworks/Couchbase.qll @@ -5,57 +5,23 @@ import go /** + * DEPRECATED + * * Provides models of commonly used functions in the official Couchbase Go SDK library. */ -module Couchbase { +deprecated module Couchbase { /** + * DEPRECATED + * * Gets a package path for the official Couchbase Go SDK library. * * Note that v1 and v2 have different APIs, but the names are disjoint so there is no need to * distinguish between them. */ - string packagePath() { + deprecated string packagePath() { result = package([ "gopkg.in/couchbase/gocb", "github.com/couchbase/gocb", "github.com/couchbaselabs/gocb" ], "") } - - /** - * A query used in an API function acting on a `Bucket` or `Cluster` struct of v1 of - * the official Couchbase Go library, gocb. - */ - private class CouchbaseV1Query extends NoSql::Query::Range { - CouchbaseV1Query() { - // func (b *Bucket) ExecuteAnalyticsQuery(q *AnalyticsQuery, params interface{}) (AnalyticsResults, error) - // func (b *Bucket) ExecuteN1qlQuery(q *N1qlQuery, params interface{}) (QueryResults, error) - // func (c *Cluster) ExecuteAnalyticsQuery(q *AnalyticsQuery, params interface{}) (AnalyticsResults, error) - // func (c *Cluster) ExecuteN1qlQuery(q *N1qlQuery, params interface{}) (QueryResults, error) - exists(Method meth, string structName, string methodName | - structName in ["Bucket", "Cluster"] and - methodName in ["ExecuteN1qlQuery", "ExecuteAnalyticsQuery"] and - meth.hasQualifiedName(packagePath(), structName, methodName) and - this = meth.getACall().getArgument(0) - ) - } - } - - /** - * A query used in an API function acting on a `Bucket` or `Cluster` struct of v1 of - * the official Couchbase Go library, gocb. - */ - private class CouchbaseV2Query extends NoSql::Query::Range { - CouchbaseV2Query() { - // func (c *Cluster) AnalyticsQuery(statement string, opts *AnalyticsOptions) (*AnalyticsResult, error) - // func (c *Cluster) Query(statement string, opts *QueryOptions) (*QueryResult, error) - // func (s *Scope) AnalyticsQuery(statement string, opts *AnalyticsOptions) (*AnalyticsResult, error) - // func (s *Scope) Query(statement string, opts *QueryOptions) (*QueryResult, error) - exists(Method meth, string structName, string methodName | - structName in ["Cluster", "Scope"] and - methodName in ["AnalyticsQuery", "Query"] and - meth.hasQualifiedName(packagePath(), structName, methodName) and - this = meth.getACall().getArgument(0) - ) - } - } } diff --git a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll index 4d10c8af312d..b1bf4571216a 100644 --- a/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll +++ b/go/ql/lib/semmle/go/frameworks/ElazarlGoproxy.qll @@ -100,10 +100,4 @@ module ElazarlGoproxy { override int getFormatStringIndex() { result = 0 } } - - private class ProxyLog extends LoggerCall::Range, DataFlow::MethodCallNode { - ProxyLog() { this.getTarget() instanceof ProxyLogFunction } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } } diff --git a/go/ql/lib/semmle/go/frameworks/Glog.qll b/go/ql/lib/semmle/go/frameworks/Glog.qll index f9f5c9e3f11f..146b8a4f814b 100644 --- a/go/ql/lib/semmle/go/frameworks/Glog.qll +++ b/go/ql/lib/semmle/go/frameworks/Glog.qll @@ -40,14 +40,4 @@ module Glog { override int getFormatStringIndex() { result = super.getFirstPrintedArg() } } - - private class GlogCall extends LoggerCall::Range, DataFlow::CallNode { - GlogFunction callee; - - GlogCall() { this = callee.getACall() } - - override DataFlow::Node getAMessageComponent() { - result = this.getSyntacticArgument(any(int i | i >= callee.getFirstPrintedArg())) - } - } } diff --git a/go/ql/lib/semmle/go/frameworks/Logrus.qll b/go/ql/lib/semmle/go/frameworks/Logrus.qll index f7de9a75dae8..83278a4cd9e2 100644 --- a/go/ql/lib/semmle/go/frameworks/Logrus.qll +++ b/go/ql/lib/semmle/go/frameworks/Logrus.qll @@ -28,12 +28,6 @@ module Logrus { } } - private class LogCall extends LoggerCall::Range, DataFlow::CallNode { - LogCall() { this = any(LogFunction f).getACall() } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - private class StringFormatters extends StringOps::Formatting::Range instanceof LogFunction { int argOffset; diff --git a/go/ql/lib/semmle/go/frameworks/NoSQL.qll b/go/ql/lib/semmle/go/frameworks/NoSQL.qll index c2469fc02ac1..36932149628e 100644 --- a/go/ql/lib/semmle/go/frameworks/NoSQL.qll +++ b/go/ql/lib/semmle/go/frameworks/NoSQL.qll @@ -31,84 +31,6 @@ module NoSql { ) } } - - /** - * Holds if method `name` of struct `Collection` from package - * [go.mongodb.org/mongo-driver/mongo](https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo) - * interprets parameter `n` as a query. - */ - private predicate mongoDbCollectionMethod(string name, int n) { - // func (coll *Collection) CountDocuments(ctx context.Context, filter interface{}, - // opts ...*options.CountOptions) (int64, error) - name = "CountDocuments" and n = 1 - or - // func (coll *Collection) DeleteMany(ctx context.Context, filter interface{}, - // opts ...*options.DeleteOptions) (*DeleteResult, error) - name = "DeleteMany" and n = 1 - or - // func (coll *Collection) DeleteOne(ctx context.Context, filter interface{}, - // opts ...*options.DeleteOptions) (*DeleteResult, error) - name = "DeleteOne" and n = 1 - or - // func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter interface{}, - // ...) ([]interface{}, error) - name = "Distinct" and n = 2 - or - // func (coll *Collection) Find(ctx context.Context, filter interface{}, - // opts ...*options.FindOptions) (*Cursor, error) - name = "Find" and n = 1 - or - // func (coll *Collection) FindOne(ctx context.Context, filter interface{}, - // opts ...*options.FindOneOptions) *SingleResult - name = "FindOne" and n = 1 - or - // func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{}, ...) - // *SingleResult - name = "FindOneAndDelete" and n = 1 - or - // func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{}, - // replacement interface{}, ...) *SingleResult - name = "FindOneAndReplace" and n = 1 - or - // func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{}, - // update interface{}, ...) *SingleResult - name = "FindOneAndUpdate" and n = 1 - or - // func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{}, - // replacement interface{}, ...) (*UpdateResult, error) - name = "ReplaceOne" and n = 1 - or - // func (coll *Collection) UpdateMany(ctx context.Context, filter interface{}, - // update interface{}, ...) (*UpdateResult, error) - name = "UpdateMany" and n = 1 - or - // func (coll *Collection) UpdateOne(ctx context.Context, filter interface{}, - // update interface{}, ...) (*UpdateResult, error) - name = "UpdateOne" and n = 1 - or - // func (coll *Collection) Watch(ctx context.Context, pipeline interface{}, ...) - // (*ChangeStream, error) - name = "Watch" and n = 1 - or - // func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{}, - // opts ...*options.AggregateOptions) (*Cursor, error) - name = "Aggregate" and n = 1 - } - - /** - * A query used in an API function acting on a `Collection` struct of package - * [go.mongodb.org/mongo-driver/mongo](https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo). - */ - private class MongoDbCollectionQuery extends Range { - MongoDbCollectionQuery() { - exists(Method meth, string methodName, int n | - mongoDbCollectionMethod(methodName, n) and - meth.hasQualifiedName(package("go.mongodb.org/mongo-driver", "mongo"), "Collection", - methodName) and - this = meth.getACall().getArgument(n) - ) - } - } } /** diff --git a/go/ql/lib/semmle/go/frameworks/SQL.qll b/go/ql/lib/semmle/go/frameworks/SQL.qll index 1a6e22807812..a0e80fde1c9f 100644 --- a/go/ql/lib/semmle/go/frameworks/SQL.qll +++ b/go/ql/lib/semmle/go/frameworks/SQL.qll @@ -67,41 +67,34 @@ module SQL { */ abstract class Range extends DataFlow::Node { } + private class DefaultQueryString extends Range { + DefaultQueryString() { + exists(DataFlow::ArgumentNode arg | sinkNode(arg, "sql-injection") | + not arg instanceof DataFlow::ImplicitVarargsSlice and + this = arg + or + arg instanceof DataFlow::ImplicitVarargsSlice and + this = arg.getCall().getAnImplicitVarargsArgument() + ) + } + } + /** * An argument to an API of the squirrel library that is directly interpreted as SQL without * taking syntactic structure into account. */ private class SquirrelQueryString extends Range { SquirrelQueryString() { - exists(Function fn | - exists(string sq | - sq = - package([ - "github.com/Masterminds/squirrel", "gopkg.in/Masterminds/squirrel", - "github.com/lann/squirrel" - ], "") - | - fn.hasQualifiedName(sq, ["Delete", "Expr", "Insert", "Select", "Update"]) - or - exists(Method m, string builder | m = fn | - builder = ["DeleteBuilder", "InsertBuilder", "SelectBuilder", "UpdateBuilder"] and - m.hasQualifiedName(sq, builder, - ["Columns", "From", "Options", "OrderBy", "Prefix", "Suffix", "Where"]) - or - builder = "InsertBuilder" and - m.hasQualifiedName(sq, builder, ["Replace", "Into"]) - or - builder = "SelectBuilder" and - m.hasQualifiedName(sq, builder, - ["CrossJoin", "GroupBy", "InnerJoin", "LeftJoin", "RightJoin"]) - or - builder = "UpdateBuilder" and - m.hasQualifiedName(sq, builder, ["Set", "Table"]) - ) - ) and - this = fn.getACall().getArgument(0) + exists(string sq, Method m, string builder | + FlowExtensions::packageGrouping("squirrel", sq) and + builder = ["DeleteBuilder", "SelectBuilder", "UpdateBuilder"] | - this.getType().getUnderlyingType() instanceof StringType or + m.hasQualifiedName(sq, builder, "Where") and + this = m.getACall().getArgument(0) + ) and + ( + this.getType().getUnderlyingType() instanceof StringType + or this.getType().getUnderlyingType().(SliceType).getElementType() instanceof StringType ) } @@ -113,14 +106,6 @@ module SQL { /** A string that might identify package `go-pg/pg/orm` or a specific version of it. */ private string gopgorm() { result = package("github.com/go-pg/pg", "orm") } - /** A string that might identify package `github.com/rqlite/gorqlite` or `github.com/raindog308/gorqlite` or a specific version of it. */ - private string gorqlite() { - result = package(["github.com/rqlite/gorqlite", "github.com/raindog308/gorqlite"], "") - } - - /** A string that might identify package `github.com/gogf/gf/database/gdb` or a specific version of it. */ - private string gogf() { result = package("github.com/gogf/gf", "database/gdb") } - /** * A string argument to an API of `go-pg/pg` that is directly interpreted as SQL without * taking syntactic structure into account. @@ -185,94 +170,6 @@ module SQL { ) } } - - /** - * A string argument to an API of `github.com/rqlite/gorqlite`, or a specific version of it, that is directly interpreted as SQL without - * taking syntactic structure into account. - */ - private class GorqliteQueryString extends Range { - GorqliteQueryString() { - // func (conn *Connection) Query(sqlStatements []string) (results []QueryResult, err error) - // func (conn *Connection) QueryOne(sqlStatement string) (qr QueryResult, err error) - // func (conn *Connection) Queue(sqlStatements []string) (seq int64, err error) - // func (conn *Connection) QueueOne(sqlStatement string) (seq int64, err error) - // func (conn *Connection) Write(sqlStatements []string) (results []WriteResult, err error) - // func (conn *Connection) WriteOne(sqlStatement string) (wr WriteResult, err error) - exists(Method m, string name | m.hasQualifiedName(gorqlite(), "Connection", name) | - name = ["Query", "QueryOne", "Queue", "QueueOne", "Write", "WriteOne"] and - this = m.getACall().getArgument(0) - ) - } - } - - /** - * A string argument to an API of `github.com/gogf/gf/database/gdb`, or a specific version of it, that is directly interpreted as SQL without - * taking syntactic structure into account. - */ - private class GogfQueryString extends Range { - GogfQueryString() { - exists(Method m, string name | m.implements(gogf(), ["DB", "Core", "TX"], name) | - // func (c *Core) Exec(sql string, args ...interface{}) (result sql.Result, err error) - // func (c *Core) GetAll(sql string, args ...interface{}) (Result, error) - // func (c *Core) GetArray(sql string, args ...interface{}) ([]Value, error) - // func (c *Core) GetCount(sql string, args ...interface{}) (int, error) - // func (c *Core) GetOne(sql string, args ...interface{}) (Record, error) - // func (c *Core) GetValue(sql string, args ...interface{}) (Value, error) - // func (c *Core) Prepare(sql string, execOnMaster ...bool) (*Stmt, error) - // func (c *Core) Query(sql string, args ...interface{}) (rows *sql.Rows, err error) - // func (c *Core) Raw(rawSql string, args ...interface{}) *Model - name = - [ - "Query", "Exec", "Prepare", "GetAll", "GetOne", "GetValue", "GetArray", "GetCount", - "Raw" - ] and - this = m.getACall().getArgument(0) - or - // func (c *Core) GetScan(pointer interface{}, sql string, args ...interface{}) error - // func (c *Core) GetStruct(pointer interface{}, sql string, args ...interface{}) error - // func (c *Core) GetStructs(pointer interface{}, sql string, args ...interface{}) error - name = ["GetScan", "GetStruct", "GetStructs"] and - this = m.getACall().getArgument(1) - or - // func (c *Core) DoCommit(ctx context.Context, link Link, sql string, args []interface{}) (newSql string, newArgs []interface{}, err error) - // func (c *Core) DoExec(ctx context.Context, link Link, sql string, args ...interface{}) (result sql.Result, err error) - // func (c *Core) DoGetAll(ctx context.Context, link Link, sql string, args ...interface{}) (result Result, err error) - // func (c *Core) DoPrepare(ctx context.Context, link Link, sql string) (*Stmt, error) - // func (c *Core) DoQuery(ctx context.Context, link Link, sql string, args ...interface{}) (rows *sql.Rows, err error) - name = ["DoGetAll", "DoQuery", "DoExec", "DoCommit", "DoPrepare"] and - this = m.getACall().getArgument(2) - ) - } - } - } - - /** A model for sinks of GORM. */ - private class GormSink extends SQL::QueryString::Range { - GormSink() { - exists(Method meth, string package, string name | - meth.hasQualifiedName(package, "DB", name) and - this = meth.getACall().getSyntacticArgument(0) and - package = Gorm::packagePath() and - name in [ - "Where", "Raw", "Order", "Not", "Or", "Select", "Table", "Group", "Having", "Joins", - "Exec", "Distinct", "Pluck" - ] - ) - } - } - - /** A model for sinks of github.com/jmoiron/sqlx. */ - private class SqlxSink extends SQL::QueryString::Range { - SqlxSink() { - exists(Method meth, string name, int n | - meth.hasQualifiedName(package("github.com/jmoiron/sqlx", ""), ["DB", "Tx"], name) and - this = meth.getACall().getArgument(n) - | - name = ["Select", "Get"] and n = 1 - or - name = ["MustExec", "Queryx", "NamedExec", "NamedQuery"] and n = 0 - ) - } } } @@ -291,71 +188,25 @@ module Gorm { */ module Xorm { /** Gets the package name for Xorm. */ - string packagePath() { result = package(["xorm.io/xorm", "github.com/go-xorm/xorm"], "") } + string packagePath() { FlowExtensions::packageGrouping("xorm", result) } /** A model for sinks of XORM. */ private class XormSink extends SQL::QueryString::Range { XormSink() { - exists(Method meth, string type, string name, int n | + exists(Method meth, string type, string name | meth.hasQualifiedName(Xorm::packagePath(), type, name) and - this = meth.getACall().getSyntacticArgument(n) and - type = ["Engine", "Session"] + type = ["Engine", "Session"] and + name = ["Exec", "Query", "QueryInterface", "QueryString"] | - name = - [ - "Query", "Exec", "QueryString", "QueryInterface", "SQL", "Where", "And", "Or", "Alias", - "NotIn", "In", "Select", "SetExpr", "OrderBy", "Having", "GroupBy" - ] and - n = 0 - or - name = ["SumInt", "Sum", "Sums", "SumsInt"] and n = 1 - or - name = "Join" and n = [0, 1, 2] + this = meth.getACall().getSyntacticArgument(0) ) } } } /** + * DEPRECATED + * * Provides classes for working with the [Bun](https://bun.uptrace.dev/) package. */ -module Bun { - /** Gets the package name for Bun package. */ - private string packagePath() { result = package("github.com/uptrace/bun", "") } - - /** A model for sinks of Bun. */ - private class BunSink extends SQL::QueryString::Range { - BunSink() { - exists(Function f, string m, int arg | this = f.getACall().getArgument(arg) | - f.hasQualifiedName(packagePath(), m) and - m = "NewRawQuery" and - arg = 1 - ) - or - exists(Method f, string tp, string m, int arg | this = f.getACall().getArgument(arg) | - f.hasQualifiedName(packagePath(), tp, m) and - ( - tp = ["DB", "Conn"] and - m = ["ExecContext", "PrepareContext", "QueryContext", "QueryRowContext"] and - arg = 1 - or - tp = ["DB", "Conn"] and - m = ["Exec", "NewRaw", "Prepare", "Query", "QueryRow", "Raw"] and - arg = 0 - or - tp.matches("%Query") and - m = - [ - "ColumnExpr", "DistinctOn", "For", "GroupExpr", "Having", "ModelTableExpr", - "OrderExpr", "TableExpr", "Where", "WhereOr" - ] and - arg = 0 - or - tp = "RawQuery" and - m = "NewRaw" and - arg = 0 - ) - ) - } - } -} +deprecated module Bun { } diff --git a/go/ql/lib/semmle/go/frameworks/Spew.qll b/go/ql/lib/semmle/go/frameworks/Spew.qll index b12bd0fed815..f49a4aa4d89d 100644 --- a/go/ql/lib/semmle/go/frameworks/Spew.qll +++ b/go/ql/lib/semmle/go/frameworks/Spew.qll @@ -33,16 +33,6 @@ module Spew { override int getFormatStringIndex() { result = super.getFirstPrintedArg() } } - private class SpewCall extends LoggerCall::Range, DataFlow::CallNode { - SpewFunction target; - - SpewCall() { this = target.getACall() } - - override DataFlow::Node getAMessageComponent() { - result = this.getSyntacticArgument(any(int i | i >= target.getFirstPrintedArg())) - } - } - // These are expressed using TaintTracking::FunctionModel because varargs functions don't work with Models-as-Data sumamries yet. /** The `Sprint` function or one of its variants. */ class Sprinter extends TaintTracking::FunctionModel { diff --git a/go/ql/lib/semmle/go/frameworks/Zap.qll b/go/ql/lib/semmle/go/frameworks/Zap.qll index 359f9aba4107..0928d2b0595c 100644 --- a/go/ql/lib/semmle/go/frameworks/Zap.qll +++ b/go/ql/lib/semmle/go/frameworks/Zap.qll @@ -34,18 +34,6 @@ module Zap { override int getFormatStringIndex() { result = 0 } } - /** - * A call to a logger function in Zap. - * - * Functions which add data to be included the next time a direct logging - * function is called are included. - */ - private class ZapCall extends LoggerCall::Range, DataFlow::MethodCallNode { - ZapCall() { this = any(ZapFunction f).getACall() } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - // These are expressed using TaintTracking::FunctionModel because varargs functions don't work with Models-as-Data sumamries yet. /** The function `Fields` that creates an `Option` that can be added to the logger out of `Field`s. */ class FieldsFunction extends TaintTracking::FunctionModel { diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll b/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll index 845225af5bd2..f41326887961 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/DatabaseSql.qll @@ -26,7 +26,7 @@ module DatabaseSql { override DataFlow::Node getAResult() { result = this.getResult(0) } override SQL::QueryString getAQueryString() { - result = this.getAnArgument() + result = this.getASyntacticArgument() or // attempt to resolve a `QueryString` for `Stmt`s using local data flow. t = "Stmt" and @@ -34,24 +34,6 @@ module DatabaseSql { } } - /** A query string used in an API function of the `database/sql` package. */ - private class QueryString extends SQL::QueryString::Range { - QueryString() { - exists(Method meth, string base, string t, string m, int n | - t = ["DB", "Tx", "Conn"] and - meth.hasQualifiedName("database/sql", t, m) and - this = meth.getACall().getArgument(n) - | - base = ["Exec", "Prepare", "Query", "QueryRow"] and - ( - m = base and n = 0 - or - m = base + "Context" and n = 1 - ) - ) - } - } - /** A query in the standard `database/sql/driver` package. */ private class DriverQuery extends SQL::Query::Range, DataFlow::MethodCallNode { DriverQuery() { @@ -78,36 +60,13 @@ module DatabaseSql { override DataFlow::Node getAResult() { result = this.getResult(0) } override SQL::QueryString getAQueryString() { - result = this.getAnArgument() + result = this.getASyntacticArgument() or this.getTarget().hasQualifiedName("database/sql/driver", "Stmt") and result = this.getReceiver().getAPredecessor*().(DataFlow::MethodCallNode).getAnArgument() } } - /** A query string used in an API function of the standard `database/sql/driver` package. */ - private class DriverQueryString extends SQL::QueryString::Range { - DriverQueryString() { - exists(Method meth, int n | - ( - meth.hasQualifiedName("database/sql/driver", "Execer", "Exec") and n = 0 - or - meth.hasQualifiedName("database/sql/driver", "ExecerContext", "ExecContext") and n = 1 - or - meth.hasQualifiedName("database/sql/driver", "Conn", "Prepare") and n = 0 - or - meth.hasQualifiedName("database/sql/driver", "ConnPrepareContext", "PrepareContext") and - n = 1 - or - meth.hasQualifiedName("database/sql/driver", "Queryer", "Query") and n = 0 - or - meth.hasQualifiedName("database/sql/driver", "QueryerContext", "QueryContext") and n = 1 - ) and - this = meth.getACall().getArgument(n) - ) - } - } - // These are expressed using TaintTracking::FunctionModel because varargs functions don't work with Models-as-Data sumamries yet. private class SqlMethodModels extends TaintTracking::FunctionModel, Method { FunctionInput inp; diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll index 54794ea21c9e..6adbd542e9b6 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Fmt.qll @@ -41,13 +41,6 @@ module Fmt { Printer() { this.hasQualifiedName("fmt", ["Print", "Printf", "Println"]) } } - /** A call to `Print` or similar. */ - private class PrintCall extends LoggerCall::Range, DataFlow::CallNode { - PrintCall() { this.getTarget() instanceof Printer } - - override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() } - } - /** The `Fprint` function or one of its variants. */ private class Fprinter extends TaintTracking::FunctionModel { Fprinter() { diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll index 5b402fca1b7e..ca74160bf0df 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Log.qll @@ -32,16 +32,6 @@ module Log { override int getFormatStringIndex() { result = 0 } } - private class LogCall extends LoggerCall::Range, DataFlow::CallNode { - LogFunction target; - - LogCall() { this = target.getACall() } - - override DataFlow::Node getAMessageComponent() { - result = this.getSyntacticArgument(any(int i | i >= target.getFirstPrintedArg())) - } - } - /** A fatal log function, which calls `os.Exit`. */ private class FatalLogFunction extends Function { FatalLogFunction() { this.hasQualifiedName("log", ["Fatal", "Fatalf", "Fatalln"]) } diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll b/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll index fb153451c597..72ea4cc6c573 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/Os.qll @@ -43,12 +43,4 @@ module Os { input = inp and output = outp } } - - private class Stdin extends SourceNode { - Stdin() { - exists(Variable osStdin | osStdin.hasQualifiedName("os", "Stdin") | this = osStdin.getARead()) - } - - override string getThreatModel() { result = "stdin" } - } } diff --git a/go/ql/src/change-notes/2024-11-26-model-slices-package.md b/go/ql/src/change-notes/2024-11-26-model-slices-package.md new file mode 100644 index 000000000000..5a3141c8075a --- /dev/null +++ b/go/ql/src/change-notes/2024-11-26-model-slices-package.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added value flow models for functions in the `slices` package which do not involve the `iter` package. diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/completetest.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/completetest.ext.yml index 79bf9128ef5c..d89a9e04e16a 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/completetest.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/completetest.ext.yml @@ -35,10 +35,12 @@ extensions: pack: codeql/go-all extensible: sourceModel data: + - ["github.com/nonexistent/test", "", False, "SourceVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "A", False, "Src1", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: sinkModel data: + - ["github.com/nonexistent/test", "", False, "SinkVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "Sink1", "", "", "Argument[0]", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "SinkManyArgs", "", "", "Argument[0..2]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.expected index fc9adff8942d..755c3f822791 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.expected @@ -43,3 +43,4 @@ invalidModelRow | test.go:199:17:199:20 | arg1 | qltest | | test.go:199:23:199:26 | arg2 | qltest | | test.go:199:29:199:32 | arg3 | qltest | +| test.go:202:22:202:25 | temp | qltest | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.ext.yml index 426e094c00c3..ec19b822a8c1 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/sinks.ext.yml @@ -3,6 +3,7 @@ extensions: pack: codeql/go-all extensible: sinkModel data: + - ["github.com/nonexistent/test", "", False, "SinkVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "Sink1", "", "", "Argument[0]", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "SinkMethod", "", "", "Argument[receiver]", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "SinkManyArgs", "", "", "Argument[0..2]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected index d63fedba3fdb..bd1525a984b9 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected @@ -21,3 +21,4 @@ invalidModelRow | test.go:183:17:183:24 | call to Src1 | qltest | | test.go:187:24:187:31 | call to Src1 | qltest | | test.go:191:24:191:31 | call to Src1 | qltest | +| test.go:201:10:201:28 | selection of SourceVariable | qltest | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.ext.yml index 5493650132c1..cda2183894ca 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.ext.yml @@ -3,9 +3,10 @@ extensions: pack: codeql/go-all extensible: sourceModel data: + - ["github.com/nonexistent/test", "", False, "SourceVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "A", False, "Src1", "", "", "ReturnValue", "qltest", "manual"] - ["github.com/nonexistent/test", "A", False, "Src2", "", "", "ReturnValue", "qltest", "manual"] - ["github.com/nonexistent/test", "A", True, "Src2", "", "", "ReturnValue", "qltest-w-subtypes", "manual"] - ["github.com/nonexistent/test", "A", False, "SrcArg", "", "", "Argument[0]", "qltest-arg", "manual"] - ["github.com/nonexistent/test", "A", False, "Src3", "", "", "ReturnValue[0]", "qltest", "manual"] - - ["github.com/nonexistent/test", "A", True, "Src3", "", "", "ReturnValue[1]", "qltest-w-subtypes", "manual"] \ No newline at end of file + - ["github.com/nonexistent/test", "A", True, "Src3", "", "", "ReturnValue[1]", "qltest-w-subtypes", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/test.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/test.go index 33e980dac990..29ed066cd50d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/test.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/test.go @@ -197,6 +197,9 @@ func simpleflow() { arg3 := src arg4 := src b.SinkManyArgs(arg1, arg2, arg3, arg4) // $ hasTaintFlow="arg1" hasTaintFlow="arg2" hasTaintFlow="arg3" + + temp := test.SourceVariable + test.SinkVariable = temp // $ hasTaintFlow="temp" } type mapstringstringtype map[string]string diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/vendor/github.com/nonexistent/test/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/vendor/github.com/nonexistent/test/stub.go index 05a5f741d764..72681cf72382 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/vendor/github.com/nonexistent/test/stub.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/vendor/github.com/nonexistent/test/stub.go @@ -72,3 +72,6 @@ func (c C) Get() string { return "" } func (c *C) SetThroughPointer(f string) {} func (c *C) GetThroughPointer() string { return "" } + +var SourceVariable string +var SinkVariable string diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/completetest.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/completetest.ext.yml index 8fbc26ff6cda..924e19a8a73b 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/completetest.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/completetest.ext.yml @@ -35,10 +35,12 @@ extensions: pack: codeql/go-all extensible: sourceModel data: + - ["github.com/nonexistent/test", "", False, "SourceVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "A", False, "Src1", "", "", "ReturnValue", "qltest", "manual"] - addsTo: pack: codeql/go-all extensible: sinkModel data: + - ["github.com/nonexistent/test", "", False, "SinkVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "Sink1", "", "", "Argument[0]", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "SinkManyArgs", "", "", "Argument[0..2]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.expected index 0fe3a614e11f..c9940e181c8c 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.expected @@ -49,3 +49,4 @@ invalidModelRow | test.go:205:10:205:26 | call to min | qltest | | test.go:206:10:206:26 | call to min | qltest | | test.go:207:10:207:26 | call to min | qltest | +| test.go:210:22:210:25 | temp | qltest | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.ext.yml index 426e094c00c3..ec19b822a8c1 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/sinks.ext.yml @@ -3,6 +3,7 @@ extensions: pack: codeql/go-all extensible: sinkModel data: + - ["github.com/nonexistent/test", "", False, "SinkVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "Sink1", "", "", "Argument[0]", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "SinkMethod", "", "", "Argument[receiver]", "qltest", "manual"] - ["github.com/nonexistent/test", "B", False, "SinkManyArgs", "", "", "Argument[0..2]", "qltest", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected index d63fedba3fdb..6fcfcc2a3bcc 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected @@ -21,3 +21,4 @@ invalidModelRow | test.go:183:17:183:24 | call to Src1 | qltest | | test.go:187:24:187:31 | call to Src1 | qltest | | test.go:191:24:191:31 | call to Src1 | qltest | +| test.go:209:10:209:28 | selection of SourceVariable | qltest | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.ext.yml b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.ext.yml index 5493650132c1..cda2183894ca 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.ext.yml +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.ext.yml @@ -3,9 +3,10 @@ extensions: pack: codeql/go-all extensible: sourceModel data: + - ["github.com/nonexistent/test", "", False, "SourceVariable", "", "", "", "qltest", "manual"] - ["github.com/nonexistent/test", "A", False, "Src1", "", "", "ReturnValue", "qltest", "manual"] - ["github.com/nonexistent/test", "A", False, "Src2", "", "", "ReturnValue", "qltest", "manual"] - ["github.com/nonexistent/test", "A", True, "Src2", "", "", "ReturnValue", "qltest-w-subtypes", "manual"] - ["github.com/nonexistent/test", "A", False, "SrcArg", "", "", "Argument[0]", "qltest-arg", "manual"] - ["github.com/nonexistent/test", "A", False, "Src3", "", "", "ReturnValue[0]", "qltest", "manual"] - - ["github.com/nonexistent/test", "A", True, "Src3", "", "", "ReturnValue[1]", "qltest-w-subtypes", "manual"] \ No newline at end of file + - ["github.com/nonexistent/test", "A", True, "Src3", "", "", "ReturnValue[1]", "qltest-w-subtypes", "manual"] diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/test.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/test.go index 82419ae7d595..72c4db352480 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/test.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/test.go @@ -205,6 +205,9 @@ func simpleflow() { b.Sink1(min(srcInt, 0, 1)) // $ hasValueFlow="call to min" b.Sink1(min(0, srcInt, 1)) // $ hasValueFlow="call to min" b.Sink1(min(0, 1, srcInt)) // $ hasValueFlow="call to min" + + temp := test.SourceVariable + test.SinkVariable = temp // $ hasValueFlow="temp" } type mapstringstringtype map[string]string diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/vendor/github.com/nonexistent/test/stub.go b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/vendor/github.com/nonexistent/test/stub.go index 05a5f741d764..72681cf72382 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/vendor/github.com/nonexistent/test/stub.go +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/vendor/github.com/nonexistent/test/stub.go @@ -72,3 +72,6 @@ func (c C) Get() string { return "" } func (c *C) SetThroughPointer(f string) {} func (c *C) GetThroughPointer() string { return "" } + +var SourceVariable string +var SinkVariable string diff --git a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected index 6cc1e09486b7..1198f8d41a9b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/BeegoOrm/SqlInjection.expected @@ -32,40 +32,61 @@ | test.go:59:31:59:39 | untrusted | test.go:57:15:57:41 | call to UserAgent | test.go:59:31:59:39 | untrusted | This query depends on a $@. | test.go:57:15:57:41 | call to UserAgent | user-provided value | | test.go:65:19:65:27 | untrusted | test.go:63:15:63:41 | call to UserAgent | test.go:65:19:65:27 | untrusted | This query depends on a $@. | test.go:63:15:63:41 | call to UserAgent | user-provided value | edges -| test.go:11:15:11:41 | call to UserAgent | test.go:13:11:13:19 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:14:23:14:31 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:15:14:15:22 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:16:26:16:34 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:17:12:17:20 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:18:24:18:32 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:19:15:19:23 | untrusted | provenance | Src:MaD:1 | -| test.go:11:15:11:41 | call to UserAgent | test.go:20:27:20:35 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:28:12:28:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:29:10:29:18 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:31:14:31:22 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:32:15:32:23 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:33:8:33:16 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:34:11:34:19 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:35:9:35:17 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:36:8:36:16 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:37:8:37:16 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:38:13:38:21 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:39:13:39:21 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:40:12:40:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:42:9:42:17 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:44:16:44:24 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:45:12:45:20 | untrusted | provenance | Src:MaD:1 | -| test.go:25:15:25:41 | call to UserAgent | test.go:46:14:46:22 | untrusted | provenance | Src:MaD:1 | -| test.go:26:16:26:42 | call to UserAgent | test.go:44:27:44:36 | untrusted2 | provenance | Src:MaD:1 | -| test.go:26:16:26:42 | call to UserAgent | test.go:46:25:46:34 | untrusted2 | provenance | Src:MaD:1 | -| test.go:50:15:50:41 | call to UserAgent | test.go:52:12:52:20 | untrusted | provenance | Src:MaD:1 | -| test.go:57:15:57:41 | call to UserAgent | test.go:59:31:59:39 | untrusted | provenance | Src:MaD:1 | -| test.go:63:15:63:41 | call to UserAgent | test.go:65:19:65:27 | untrusted | provenance | Src:MaD:1 | +| test.go:11:15:11:41 | call to UserAgent | test.go:13:11:13:19 | untrusted | provenance | Src:MaD:22 Sink:MaD:2 | +| test.go:11:15:11:41 | call to UserAgent | test.go:14:23:14:31 | untrusted | provenance | Src:MaD:22 Sink:MaD:3 | +| test.go:11:15:11:41 | call to UserAgent | test.go:15:14:15:22 | untrusted | provenance | Src:MaD:22 Sink:MaD:4 | +| test.go:11:15:11:41 | call to UserAgent | test.go:16:26:16:34 | untrusted | provenance | Src:MaD:22 Sink:MaD:5 | +| test.go:11:15:11:41 | call to UserAgent | test.go:17:12:17:20 | untrusted | provenance | Src:MaD:22 Sink:MaD:6 | +| test.go:11:15:11:41 | call to UserAgent | test.go:18:24:18:32 | untrusted | provenance | Src:MaD:22 Sink:MaD:7 | +| test.go:11:15:11:41 | call to UserAgent | test.go:19:15:19:23 | untrusted | provenance | Src:MaD:22 Sink:MaD:8 | +| test.go:11:15:11:41 | call to UserAgent | test.go:20:27:20:35 | untrusted | provenance | Src:MaD:22 Sink:MaD:9 | +| test.go:25:15:25:41 | call to UserAgent | test.go:28:12:28:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:29:10:29:18 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:30:15:30:23 | untrusted | provenance | Src:MaD:22 Sink:MaD:13 | +| test.go:25:15:25:41 | call to UserAgent | test.go:31:14:31:22 | untrusted | provenance | Src:MaD:22 Sink:MaD:15 | +| test.go:25:15:25:41 | call to UserAgent | test.go:32:15:32:23 | untrusted | provenance | Src:MaD:22 Sink:MaD:18 | +| test.go:25:15:25:41 | call to UserAgent | test.go:33:8:33:16 | untrusted | provenance | Src:MaD:22 Sink:MaD:16 | +| test.go:25:15:25:41 | call to UserAgent | test.go:34:11:34:19 | untrusted | provenance | Src:MaD:22 Sink:MaD:20 | +| test.go:25:15:25:41 | call to UserAgent | test.go:35:9:35:17 | untrusted | provenance | Src:MaD:22 Sink:MaD:11 | +| test.go:25:15:25:41 | call to UserAgent | test.go:36:8:36:16 | untrusted | provenance | Src:MaD:22 Sink:MaD:17 | +| test.go:25:15:25:41 | call to UserAgent | test.go:37:8:37:16 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:38:13:38:21 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:39:13:39:21 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:40:12:40:20 | untrusted | provenance | Src:MaD:22 Sink:MaD:12 | +| test.go:25:15:25:41 | call to UserAgent | test.go:41:12:41:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:42:9:42:17 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:43:12:43:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:44:16:44:24 | untrusted | provenance | Src:MaD:22 Sink:MaD:14 | +| test.go:25:15:25:41 | call to UserAgent | test.go:45:12:45:20 | untrusted | provenance | Src:MaD:22 | +| test.go:25:15:25:41 | call to UserAgent | test.go:46:14:46:22 | untrusted | provenance | Src:MaD:22 Sink:MaD:19 | +| test.go:26:16:26:42 | call to UserAgent | test.go:44:27:44:36 | untrusted2 | provenance | Src:MaD:22 | +| test.go:26:16:26:42 | call to UserAgent | test.go:46:25:46:34 | untrusted2 | provenance | Src:MaD:22 Sink:MaD:19 | +| test.go:50:15:50:41 | call to UserAgent | test.go:52:12:52:20 | untrusted | provenance | Src:MaD:22 Sink:MaD:10 | +| test.go:57:15:57:41 | call to UserAgent | test.go:59:31:59:39 | untrusted | provenance | Src:MaD:22 Sink:MaD:21 | +| test.go:63:15:63:41 | call to UserAgent | test.go:65:19:65:27 | untrusted | provenance | Src:MaD:22 Sink:MaD:1 | models -| 1 | Source: net/http; Request; true; UserAgent; ; ; ReturnValue; remote; manual | +| 1 | Sink: group:beego-orm; Condition; true; Raw; ; ; Argument[1]; sql-injection; manual | +| 2 | Sink: group:beego-orm; DB; true; Exec; ; ; Argument[0]; sql-injection; manual | +| 3 | Sink: group:beego-orm; DB; true; ExecContext; ; ; Argument[1]; sql-injection; manual | +| 4 | Sink: group:beego-orm; DB; true; Prepare; ; ; Argument[0]; sql-injection; manual | +| 5 | Sink: group:beego-orm; DB; true; PrepareContext; ; ; Argument[1]; sql-injection; manual | +| 6 | Sink: group:beego-orm; DB; true; Query; ; ; Argument[0]; sql-injection; manual | +| 7 | Sink: group:beego-orm; DB; true; QueryContext; ; ; Argument[1]; sql-injection; manual | +| 8 | Sink: group:beego-orm; DB; true; QueryRow; ; ; Argument[0]; sql-injection; manual | +| 9 | Sink: group:beego-orm; DB; true; QueryRowContext; ; ; Argument[1]; sql-injection; manual | +| 10 | Sink: group:beego-orm; Ormer; true; Raw; ; ; Argument[0]; sql-injection; manual | +| 11 | Sink: group:beego-orm; QueryBuilder; true; And; ; ; Argument[0]; sql-injection; manual | +| 12 | Sink: group:beego-orm; QueryBuilder; true; Having; ; ; Argument[0]; sql-injection; manual | +| 13 | Sink: group:beego-orm; QueryBuilder; true; InnerJoin; ; ; Argument[0]; sql-injection; manual | +| 14 | Sink: group:beego-orm; QueryBuilder; true; InsertInto; ; ; Argument[0..1]; sql-injection; manual | +| 15 | Sink: group:beego-orm; QueryBuilder; true; LeftJoin; ; ; Argument[0]; sql-injection; manual | +| 16 | Sink: group:beego-orm; QueryBuilder; true; On; ; ; Argument[0]; sql-injection; manual | +| 17 | Sink: group:beego-orm; QueryBuilder; true; Or; ; ; Argument[0]; sql-injection; manual | +| 18 | Sink: group:beego-orm; QueryBuilder; true; RightJoin; ; ; Argument[0]; sql-injection; manual | +| 19 | Sink: group:beego-orm; QueryBuilder; true; Subquery; ; ; Argument[0..1]; sql-injection; manual | +| 20 | Sink: group:beego-orm; QueryBuilder; true; Where; ; ; Argument[0]; sql-injection; manual | +| 21 | Sink: group:beego-orm; QuerySeter; true; FilterRaw; ; ; Argument[1]; sql-injection; manual | +| 22 | Source: net/http; Request; true; UserAgent; ; ; ReturnValue; remote; manual | nodes | test.go:11:15:11:41 | call to UserAgent | semmle.label | call to UserAgent | | test.go:13:11:13:19 | untrusted | semmle.label | untrusted | diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.expected similarity index 57% rename from java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.expected rename to go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.expected index 8ec8033d086e..db33d6d2504a 100644 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.expected @@ -1,2 +1,3 @@ testFailures +invalidModelRow failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.expected deleted file mode 100644 index ca70ed07c33d..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.expected +++ /dev/null @@ -1,25 +0,0 @@ -| gorm.go:20:12:20:20 | untrusted | github.com/jinzhu/gorm | DB | Where | -| gorm.go:21:10:21:18 | untrusted | github.com/jinzhu/gorm | DB | Raw | -| gorm.go:22:10:22:18 | untrusted | github.com/jinzhu/gorm | DB | Not | -| gorm.go:23:12:23:20 | untrusted | github.com/jinzhu/gorm | DB | Order | -| gorm.go:24:9:24:17 | untrusted | github.com/jinzhu/gorm | DB | Or | -| gorm.go:25:13:25:21 | untrusted | github.com/jinzhu/gorm | DB | Select | -| gorm.go:26:12:26:20 | untrusted | github.com/jinzhu/gorm | DB | Table | -| gorm.go:27:12:27:20 | untrusted | github.com/jinzhu/gorm | DB | Group | -| gorm.go:28:13:28:21 | untrusted | github.com/jinzhu/gorm | DB | Having | -| gorm.go:29:12:29:20 | untrusted | github.com/jinzhu/gorm | DB | Joins | -| gorm.go:30:11:30:19 | untrusted | github.com/jinzhu/gorm | DB | Exec | -| gorm.go:31:12:31:20 | untrusted | github.com/jinzhu/gorm | DB | Pluck | -| gorm.go:34:12:34:20 | untrusted | gorm.io/gorm | DB | Where | -| gorm.go:35:10:35:18 | untrusted | gorm.io/gorm | DB | Raw | -| gorm.go:36:10:36:18 | untrusted | gorm.io/gorm | DB | Not | -| gorm.go:37:12:37:20 | untrusted | gorm.io/gorm | DB | Order | -| gorm.go:38:9:38:17 | untrusted | gorm.io/gorm | DB | Or | -| gorm.go:39:13:39:21 | untrusted | gorm.io/gorm | DB | Select | -| gorm.go:40:12:40:20 | untrusted | gorm.io/gorm | DB | Table | -| gorm.go:41:12:41:20 | untrusted | gorm.io/gorm | DB | Group | -| gorm.go:42:13:42:21 | untrusted | gorm.io/gorm | DB | Having | -| gorm.go:43:12:43:20 | untrusted | gorm.io/gorm | DB | Joins | -| gorm.go:44:11:44:19 | untrusted | gorm.io/gorm | DB | Exec | -| gorm.go:45:15:45:23 | untrusted | gorm.io/gorm | DB | Distinct | -| gorm.go:46:12:46:20 | untrusted | gorm.io/gorm | DB | Pluck | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go index bee8edbf7af8..2d736e2407c9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.go @@ -13,36 +13,35 @@ func getUntrustedString() string { } func main() { - untrusted := getUntrustedString() db1 := gorm1.DB{} - db1.Where(untrusted) - db1.Raw(untrusted) - db1.Not(untrusted) - db1.Order(untrusted) - db1.Or(untrusted) - db1.Select(untrusted) - db1.Table(untrusted) - db1.Group(untrusted) - db1.Having(untrusted) - db1.Joins(untrusted) - db1.Exec(untrusted) - db1.Pluck(untrusted, nil) + db1.Where(untrusted) // $ querystring=untrusted + db1.Raw(untrusted) // $ querystring=untrusted + db1.Not(untrusted) // $ querystring=untrusted + db1.Order(untrusted) // $ querystring=untrusted + db1.Or(untrusted) // $ querystring=untrusted + db1.Select(untrusted) // $ querystring=untrusted + db1.Table(untrusted) // $ querystring=untrusted + db1.Group(untrusted) // $ querystring=untrusted + db1.Having(untrusted) // $ querystring=untrusted + db1.Joins(untrusted) // $ querystring=untrusted + db1.Exec(untrusted) // $ querystring=untrusted + db1.Pluck(untrusted, nil) // $ querystring=untrusted db2 := gorm2.DB{} - db2.Where(untrusted) - db2.Raw(untrusted) - db2.Not(untrusted) - db2.Order(untrusted) - db2.Or(untrusted) - db2.Select(untrusted) - db2.Table(untrusted) - db2.Group(untrusted) - db2.Having(untrusted) - db2.Joins(untrusted) - db2.Exec(untrusted) - db2.Distinct(untrusted) - db2.Pluck(untrusted, nil) + db2.Where(untrusted) // $ querystring=untrusted + db2.Raw(untrusted) // $ querystring=untrusted + db2.Not(untrusted) // $ querystring=untrusted + db2.Order(untrusted) // $ querystring=untrusted + db2.Or(untrusted) // $ querystring=untrusted + db2.Select(untrusted) // $ querystring=untrusted + db2.Table(untrusted) // $ querystring=untrusted + db2.Group(untrusted) // $ querystring=untrusted + db2.Having(untrusted) // $ querystring=untrusted + db2.Joins(untrusted) // $ querystring=untrusted + db2.Exec(untrusted) // $ querystring=untrusted + db2.Distinct(untrusted) // $ querystring=untrusted + db2.Pluck(untrusted, nil) // $ querystring=untrusted } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.ql deleted file mode 100644 index e08b506deaf1..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Gorm/gorm.ql +++ /dev/null @@ -1,5 +0,0 @@ -import go - -from SQL::QueryString qs, Method meth, string a, string b, string c -where meth.hasQualifiedName(a, b, c) and qs = meth.getACall().getSyntacticArgument(0) -select qs, a, b, c diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.expected similarity index 57% rename from java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.expected rename to go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.expected index 8ec8033d086e..db33d6d2504a 100644 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.expected @@ -1,2 +1,3 @@ testFailures +invalidModelRow failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected deleted file mode 100644 index 0540a78fb343..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.expected +++ /dev/null @@ -1,12 +0,0 @@ -| sqlx.go:15:17:15:25 | untrusted | -| sqlx.go:16:14:16:22 | untrusted | -| sqlx.go:17:14:17:22 | untrusted | -| sqlx.go:18:12:18:20 | untrusted | -| sqlx.go:19:15:19:23 | untrusted | -| sqlx.go:20:16:20:24 | untrusted | -| sqlx.go:23:17:23:25 | untrusted | -| sqlx.go:24:14:24:22 | untrusted | -| sqlx.go:25:14:25:22 | untrusted | -| sqlx.go:26:12:26:20 | untrusted | -| sqlx.go:27:15:27:23 | untrusted | -| sqlx.go:28:16:28:24 | untrusted | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go index edc29c4d4eef..e4e8d43395bd 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.go @@ -12,19 +12,19 @@ func main() { db := sqlx.DB{} untrusted := getUntrustedString() - db.Select(nil, untrusted) - db.Get(nil, untrusted) - db.MustExec(untrusted) - db.Queryx(untrusted) - db.NamedExec(untrusted, nil) - db.NamedQuery(untrusted, nil) + db.Select(nil, untrusted) // $ querystring=untrusted + db.Get(nil, untrusted) // $ querystring=untrusted + db.MustExec(untrusted) // $ querystring=untrusted + db.Queryx(untrusted) // $ querystring=untrusted + db.NamedExec(untrusted, nil) // $ querystring=untrusted + db.NamedQuery(untrusted, nil) // $ querystring=untrusted tx := sqlx.Tx{} - tx.Select(nil, untrusted) - tx.Get(nil, untrusted) - tx.MustExec(untrusted) - tx.Queryx(untrusted) - tx.NamedExec(untrusted, nil) - tx.NamedQuery(untrusted, nil) + tx.Select(nil, untrusted) // $ querystring=untrusted + tx.Get(nil, untrusted) // $ querystring=untrusted + tx.MustExec(untrusted) // $ querystring=untrusted + tx.Queryx(untrusted) // $ querystring=untrusted + tx.NamedExec(untrusted, nil) // $ querystring=untrusted + tx.NamedQuery(untrusted, nil) // $ querystring=untrusted } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql deleted file mode 100644 index 7b56fd974419..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/Sqlx/sqlx.ql +++ /dev/null @@ -1,4 +0,0 @@ -import go - -from SQL::QueryString qs -select qs diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.expected new file mode 100644 index 000000000000..105b7026d0c4 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.expected @@ -0,0 +1,3 @@ +failures +invalidModelRow +testFailures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go index 8ce4e5b0826b..44a2e2c2fce4 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/bun/bun.go @@ -22,28 +22,28 @@ func main() { panic(err) } db := bun.NewDB(sqlite, sqlitedialect.New()) - bun.NewRawQuery(db, untrusted) - - db.ExecContext(ctx, untrusted) - db.PrepareContext(ctx, untrusted) - db.QueryContext(ctx, untrusted) - db.QueryRowContext(ctx, untrusted) - - db.Exec(untrusted) - db.NewRaw(untrusted) - db.Prepare(untrusted) - db.Query(untrusted) - db.QueryRow(untrusted) - db.Raw(untrusted) - - db.NewSelect().ColumnExpr(untrusted) - db.NewSelect().DistinctOn(untrusted) - db.NewSelect().For(untrusted) - db.NewSelect().GroupExpr(untrusted) - db.NewSelect().Having(untrusted) - db.NewSelect().ModelTableExpr(untrusted) - db.NewSelect().OrderExpr(untrusted) - db.NewSelect().TableExpr(untrusted) - db.NewSelect().Where(untrusted) - db.NewSelect().WhereOr(untrusted) + bun.NewRawQuery(db, untrusted) // $ querystring=untrusted + + db.ExecContext(ctx, untrusted) // $ querystring=untrusted + db.PrepareContext(ctx, untrusted) // $ querystring=untrusted + db.QueryContext(ctx, untrusted) // $ querystring=untrusted + db.QueryRowContext(ctx, untrusted) // $ querystring=untrusted + + db.Exec(untrusted) // $ querystring=untrusted + db.NewRaw(untrusted) // $ querystring=untrusted + db.Prepare(untrusted) // $ querystring=untrusted + db.Query(untrusted) // $ querystring=untrusted + db.QueryRow(untrusted) // $ querystring=untrusted + db.Raw(untrusted) // $ querystring=untrusted + + db.NewSelect().ColumnExpr(untrusted) // $ querystring=untrusted + db.NewSelect().DistinctOn(untrusted) // $ querystring=untrusted + db.NewSelect().For(untrusted) // $ querystring=untrusted + db.NewSelect().GroupExpr(untrusted) // $ querystring=untrusted + db.NewSelect().Having(untrusted) // $ querystring=untrusted + db.NewSelect().ModelTableExpr(untrusted) // $ querystring=untrusted + db.NewSelect().OrderExpr(untrusted) // $ querystring=untrusted + db.NewSelect().TableExpr(untrusted) // $ querystring=untrusted + db.NewSelect().Where(untrusted) // $ querystring=untrusted + db.NewSelect().WhereOr(untrusted) // $ querystring=untrusted } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.expected deleted file mode 100644 index f4e3e4f15b0a..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.expected +++ /dev/null @@ -1,47 +0,0 @@ -| gogf.go:12:9:12:11 | sql | -| gogf.go:13:11:13:13 | sql | -| gogf.go:14:13:14:15 | sql | -| gogf.go:15:13:15:15 | sql | -| gogf.go:16:11:16:13 | sql | -| gogf.go:17:13:17:15 | sql | -| gogf.go:18:12:18:14 | sql | -| gogf.go:19:10:19:12 | sql | -| gogf.go:20:8:20:10 | sql | -| gogf.go:21:17:21:19 | sql | -| gogf.go:22:19:22:21 | sql | -| gogf.go:23:20:23:22 | sql | -| gogf.go:24:23:24:25 | sql | -| gogf.go:25:21:25:23 | sql | -| gogf.go:26:23:26:25 | sql | -| gogf.go:27:22:27:24 | sql | -| gogf.go:28:24:28:26 | sql | -| gogf.go:32:9:32:11 | sql | -| gogf.go:33:11:33:13 | sql | -| gogf.go:34:13:34:15 | sql | -| gogf.go:35:13:35:15 | sql | -| gogf.go:36:11:36:13 | sql | -| gogf.go:37:13:37:15 | sql | -| gogf.go:38:12:38:14 | sql | -| gogf.go:39:10:39:12 | sql | -| gogf.go:40:8:40:10 | sql | -| gogf.go:41:17:41:19 | sql | -| gogf.go:42:23:42:25 | sql | -| gogf.go:43:21:43:23 | sql | -| gogf.go:44:23:44:25 | sql | -| gogf.go:45:22:45:24 | sql | -| gogf.go:46:24:46:26 | sql | -| gogf.go:51:9:51:11 | sql | -| gogf.go:52:11:52:13 | sql | -| gogf.go:53:13:53:15 | sql | -| gogf.go:54:13:54:15 | sql | -| gogf.go:55:11:55:13 | sql | -| gogf.go:56:13:56:15 | sql | -| gogf.go:57:12:57:14 | sql | -| gogf.go:58:10:58:12 | sql | -| gogf.go:59:8:59:10 | sql | -| gogf.go:60:17:60:19 | sql | -| gogf.go:61:23:61:25 | sql | -| gogf.go:62:21:62:23 | sql | -| gogf.go:63:23:63:25 | sql | -| gogf.go:64:22:64:24 | sql | -| gogf.go:65:24:65:26 | sql | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go index d0eceaf862cf..e2db8016cf0d 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.go @@ -4,11 +4,13 @@ package main //go:generate depstubber -vendor github.com/gogf/gf/database/gdb DB,Core,TX "" import ( + "context" + "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" ) -func gogfCoreTest(sql string, c *gdb.Core) { +func gogfCoreTest(sql string, c *gdb.Core, ctx context.Context) { c.Exec(sql, nil) // $ querystring=sql c.GetAll(sql, nil) // $ querystring=sql c.GetArray(sql, nil) // $ querystring=sql @@ -21,14 +23,14 @@ func gogfCoreTest(sql string, c *gdb.Core) { c.GetScan(nil, sql, nil) // $ querystring=sql c.GetStruct(nil, sql, nil) // $ querystring=sql c.GetStructs(nil, sql, nil) // $ querystring=sql - c.DoCommit(nil, nil, sql, nil) // $ querystring=sql - c.DoExec(nil, nil, sql, nil) // $ querystring=sql - c.DoGetAll(nil, nil, sql, nil) // $ querystring=sql - c.DoQuery(nil, nil, sql, nil) // $ querystring=sql - c.DoPrepare(nil, nil, sql) // $ querystring=sql + c.DoCommit(ctx, nil, sql, nil) // $ querystring=sql + c.DoExec(ctx, nil, sql, nil) // $ querystring=sql + c.DoGetAll(ctx, nil, sql, nil) // $ querystring=sql + c.DoQuery(ctx, nil, sql, nil) // $ querystring=sql + c.DoPrepare(ctx, nil, sql) // $ querystring=sql } -func gogfDbtest(sql string, c gdb.DB) { +func gogfDbtest(sql string, c gdb.DB, ctx context.Context) { c.Exec(sql, nil) // $ querystring=sql c.GetAll(sql, nil) // $ querystring=sql c.GetArray(sql, nil) // $ querystring=sql @@ -39,14 +41,14 @@ func gogfDbtest(sql string, c gdb.DB) { c.Query(sql, nil) // $ querystring=sql c.Raw(sql, nil) // $ querystring=sql c.GetScan(nil, sql, nil) // $ querystring=sql - c.DoCommit(nil, nil, sql, nil) // $ querystring=sql - c.DoExec(nil, nil, sql, nil) // $ querystring=sql - c.DoGetAll(nil, nil, sql, nil) // $ querystring=sql - c.DoQuery(nil, nil, sql, nil) // $ querystring=sql - c.DoPrepare(nil, nil, sql) // $ querystring=sql + c.DoCommit(ctx, nil, sql, nil) // $ querystring=sql + c.DoExec(ctx, nil, sql, nil) // $ querystring=sql + c.DoGetAll(ctx, nil, sql, nil) // $ querystring=sql + c.DoQuery(ctx, nil, sql, nil) // $ querystring=sql + c.DoPrepare(ctx, nil, sql) // $ querystring=sql } -func gogfGTest(sql string) { +func gogfGTest(sql string, ctx context.Context) { c := g.DB("ad") c.Exec(sql, nil) // $ querystring=sql c.GetAll(sql, nil) // $ querystring=sql @@ -58,11 +60,11 @@ func gogfGTest(sql string) { c.Query(sql, nil) // $ querystring=sql c.Raw(sql, nil) // $ querystring=sql c.GetScan(nil, sql, nil) // $ querystring=sql - c.DoCommit(nil, nil, sql, nil) // $ querystring=sql - c.DoExec(nil, nil, sql, nil) // $ querystring=sql - c.DoGetAll(nil, nil, sql, nil) // $ querystring=sql - c.DoQuery(nil, nil, sql, nil) // $ querystring=sql - c.DoPrepare(nil, nil, sql) // $ querystring=sql + c.DoCommit(ctx, nil, sql, nil) // $ querystring=sql + c.DoExec(ctx, nil, sql, nil) // $ querystring=sql + c.DoGetAll(ctx, nil, sql, nil) // $ querystring=sql + c.DoQuery(ctx, nil, sql, nil) // $ querystring=sql + c.DoPrepare(ctx, nil, sql) // $ querystring=sql } func main() { diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.ql deleted file mode 100644 index 7b56fd974419..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gogf/gogf.ql +++ /dev/null @@ -1,4 +0,0 @@ -import go - -from SQL::QueryString qs -select qs diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.expected new file mode 100644 index 000000000000..db33d6d2504a --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.expected @@ -0,0 +1,3 @@ +testFailures +invalidModelRow +failures diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.ql new file mode 100644 index 000000000000..eeb43a82fadd --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/QueryString.ql @@ -0,0 +1,60 @@ +import go +import semmle.go.dataflow.ExternalFlow +import ModelValidation +import TestUtilities.InlineExpectationsTest + +module SqlTest implements TestSig { + string getARelevantTag() { result = "query" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "query" and + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | + q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = q.toString() and + value = qs.toString() + ) + } +} + +module QueryString implements TestSig { + string getARelevantTag() { result = "querystring" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "querystring" and + element = "" and + exists(SQL::QueryString qs | not exists(SQL::Query q | qs = q.getAQueryString()) | + qs.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + value = qs.toString() + ) + } +} + +module Config implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { n.asExpr() instanceof StringLit } + + predicate isSink(DataFlow::Node n) { + n = any(DataFlow::CallNode cn | cn.getTarget().getName() = "sink").getAnArgument() + } +} + +module Flow = TaintTracking::Global; + +module TaintFlow implements TestSig { + string getARelevantTag() { result = "flowfrom" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "flowfrom" and + element = "" and + exists(DataFlow::Node fromNode, DataFlow::Node toNode | + toNode + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + Flow::flow(fromNode, toNode) and + value = fromNode.asExpr().(StringLit).getValue() + ) + } +} + +import MakeTest> diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod index 1f243775658a..826ed0eb1c05 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/go.mod @@ -2,4 +2,4 @@ module main go 1.18 -require github.com/rqlite/gorqlite v0.0.0-20220528150909-c4e99ae96be6 +require github.com/rqlite/gorqlite v0.0.0-20240808172217-12ae7d03ef19 diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.expected b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.expected deleted file mode 100644 index cbd8166ea5e1..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.expected +++ /dev/null @@ -1,6 +0,0 @@ -| gorqlite.go:11:13:11:16 | sqls | -| gorqlite.go:12:13:12:16 | sqls | -| gorqlite.go:13:13:13:16 | sqls | -| gorqlite.go:14:16:14:18 | sql | -| gorqlite.go:15:16:15:18 | sql | -| gorqlite.go:16:16:16:18 | sql | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go index 9b60c6684e67..ebd6e5fd9f3b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.go @@ -1,20 +1,49 @@ package main -//go:generate depstubber -vendor github.com/rqlite/gorqlite Connection Open +//go:generate depstubber -vendor github.com/rqlite/gorqlite Connection,ParameterizedStatement Open import ( + "context" + "github.com/rqlite/gorqlite" ) -func gorqlitetest(sql string, sqls []string) { +func gorqlitetest(sql string, sqls []string, param_sql gorqlite.ParameterizedStatement, param_sqls []gorqlite.ParameterizedStatement, ctx context.Context) { conn, _ := gorqlite.Open("dbUrl") - conn.Query(sqls) // $ querystring=sqls - conn.Queue(sqls) // $ querystring=sqls - conn.Write(sqls) // $ querystring=sqls + + conn.Query(sqls) // $ querystring=sqls + conn.Queue(sqls) // $ querystring=sqls + conn.Write(sqls) // $ querystring=sqls + conn.QueryOne(sql) // $ querystring=sql conn.QueueOne(sql) // $ querystring=sql conn.WriteOne(sql) // $ querystring=sql + + conn.QueryParameterized(param_sqls) // $ querystring=param_sqls + conn.QueueParameterized(param_sqls) // $ querystring=param_sqls + conn.WriteParameterized(param_sqls) // $ querystring=param_sqls + + conn.QueryOneParameterized(param_sql) // $ querystring=param_sql + conn.QueueOneParameterized(param_sql) // $ querystring=param_sql + conn.WriteOneParameterized(param_sql) // $ querystring=param_sql + + conn.QueryContext(ctx, sqls) // $ querystring=sqls + conn.QueueContext(ctx, sqls) // $ querystring=sqls + conn.WriteContext(ctx, sqls) // $ querystring=sqls + + conn.QueryOneContext(ctx, sql) // $ querystring=sql + conn.QueueOneContext(ctx, sql) // $ querystring=sql + conn.WriteOneContext(ctx, sql) // $ querystring=sql + + conn.QueryParameterizedContext(ctx, param_sqls) // $ querystring=param_sqls + conn.QueueParameterizedContext(ctx, param_sqls) // $ querystring=param_sqls + conn.WriteParameterizedContext(ctx, param_sqls) // $ querystring=param_sqls + + conn.QueryOneParameterizedContext(ctx, param_sql) // $ querystring=param_sql + conn.QueueOneParameterizedContext(ctx, param_sql) // $ querystring=param_sql + conn.WriteOneParameterizedContext(ctx, param_sql) // $ querystring=param_sql } + func main() { return } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.ql deleted file mode 100644 index 7b56fd974419..000000000000 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/gorqlite.ql +++ /dev/null @@ -1,4 +0,0 @@ -import go - -from SQL::QueryString qs -select qs diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go index f6f4ca18ec12..0572097582e0 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/github.com/rqlite/gorqlite/stub.go @@ -2,11 +2,15 @@ // This is a simple stub for github.com/rqlite/gorqlite, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/rqlite/gorqlite (exports: Connection; functions: Open) +// Source: github.com/rqlite/gorqlite (exports: Connection,ParameterizedStatement; functions: Open) // Package gorqlite is a stub of github.com/rqlite/gorqlite, generated by depstubber. package gorqlite +import ( + context "context" +) + type Connection struct { ID string } @@ -29,19 +33,83 @@ func (_ *Connection) Query(_ []string) ([]QueryResult, error) { return nil, nil } +func (_ *Connection) QueryContext(_ context.Context, _ []string) ([]QueryResult, error) { + return nil, nil +} + func (_ *Connection) QueryOne(_ string) (QueryResult, error) { return QueryResult{}, nil } +func (_ *Connection) QueryOneContext(_ context.Context, _ string) (QueryResult, error) { + return QueryResult{}, nil +} + +func (_ *Connection) QueryOneParameterized(_ ParameterizedStatement) (QueryResult, error) { + return QueryResult{}, nil +} + +func (_ *Connection) QueryOneParameterizedContext(_ context.Context, _ ParameterizedStatement) (QueryResult, error) { + return QueryResult{}, nil +} + +func (_ *Connection) QueryParameterized(_ []ParameterizedStatement) ([]QueryResult, error) { + return nil, nil +} + +func (_ *Connection) QueryParameterizedContext(_ context.Context, _ []ParameterizedStatement) ([]QueryResult, error) { + return nil, nil +} + func (_ *Connection) Queue(_ []string) (int64, error) { return 0, nil } +func (_ *Connection) QueueContext(_ context.Context, _ []string) (int64, error) { + return 0, nil +} + func (_ *Connection) QueueOne(_ string) (int64, error) { return 0, nil } -func (_ *Connection) SetConsistencyLevel(_ string) error { +func (_ *Connection) QueueOneContext(_ context.Context, _ string) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueOneParameterized(_ ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueOneParameterizedContext(_ context.Context, _ ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueParameterized(_ []ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) QueueParameterizedContext(_ context.Context, _ []ParameterizedStatement) (int64, error) { + return 0, nil +} + +func (_ *Connection) Request(_ []string) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) RequestContext(_ context.Context, _ []string) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) RequestParameterized(_ []ParameterizedStatement) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) RequestParameterizedContext(_ context.Context, _ []ParameterizedStatement) ([]RequestResult, error) { + return nil, nil +} + +func (_ *Connection) SetConsistencyLevel(_ interface{}) error { return nil } @@ -53,12 +121,41 @@ func (_ *Connection) Write(_ []string) ([]WriteResult, error) { return nil, nil } +func (_ *Connection) WriteContext(_ context.Context, _ []string) ([]WriteResult, error) { + return nil, nil +} + func (_ *Connection) WriteOne(_ string) (WriteResult, error) { return WriteResult{}, nil } -func Open(_ string) (Connection, error) { - return Connection{}, nil +func (_ *Connection) WriteOneContext(_ context.Context, _ string) (WriteResult, error) { + return WriteResult{}, nil +} + +func (_ *Connection) WriteOneParameterized(_ ParameterizedStatement) (WriteResult, error) { + return WriteResult{}, nil +} + +func (_ *Connection) WriteOneParameterizedContext(_ context.Context, _ ParameterizedStatement) (WriteResult, error) { + return WriteResult{}, nil +} + +func (_ *Connection) WriteParameterized(_ []ParameterizedStatement) ([]WriteResult, error) { + return nil, nil +} + +func (_ *Connection) WriteParameterizedContext(_ context.Context, _ []ParameterizedStatement) ([]WriteResult, error) { + return nil, nil +} + +func Open(_ string) (*Connection, error) { + return nil, nil +} + +type ParameterizedStatement struct { + Query string + Arguments []interface{} } type QueryResult struct { @@ -90,10 +187,20 @@ func (_ *QueryResult) Scan(_ ...interface{}) error { return nil } +func (_ *QueryResult) Slice() ([]interface{}, error) { + return nil, nil +} + func (_ *QueryResult) Types() []string { return nil } +type RequestResult struct { + Err error + Query *QueryResult + Write *WriteResult +} + type WriteResult struct { Err error Timing float64 diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt index f5e5b9989ede..dafb7c6d1a98 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/gorqlite/vendor/modules.txt @@ -1,3 +1,3 @@ -# github.com/rqlite/gorqlite v0.0.0-20220528150909-c4e99ae96be6 +# github.com/rqlite/gorqlite v0.0.0-20240808172217-12ae7d03ef19 ## explicit github.com/rqlite/gorqlite diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go index 15b687c7ad16..d0350643bb06 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/squirrel.go @@ -1,6 +1,6 @@ package main -//go:generate depstubber -vendor github.com/Masterminds/squirrel DeleteBuilder,InsertBuilder,SelectBuilder,UpdateBuilder Delete,Expr,Insert,Select,Update +//go:generate depstubber -vendor github.com/Masterminds/squirrel DeleteBuilder,Eq,InsertBuilder,SelectBuilder,UpdateBuilder Delete,Expr,Insert,Select,Update import ( "github.com/Masterminds/squirrel" @@ -10,38 +10,44 @@ func squirrelTest(querypart string) { squirrel.Expr(querypart) // $ querystring=querypart deleteBuilder := squirrel.Delete(querypart) // $ querystring=querypart deleteBuilder.From(querypart) // $ querystring=querypart - deleteBuilder.OrderBy(querypart) // $ querystring=[]type{args} + deleteBuilder.OrderBy(querypart) // $ querystring=querypart deleteBuilder.Prefix(querypart) // $ querystring=querypart deleteBuilder.Suffix(querypart) // $ querystring=querypart deleteBuilder.Where(querypart) // $ querystring=querypart insertBuilder := squirrel.Insert(querypart) // $ querystring=querypart - insertBuilder.Columns(querypart) // $ querystring=[]type{args} - insertBuilder.Options(querypart) // $ querystring=[]type{args} + insertBuilder.Columns(querypart) // $ querystring=querypart + insertBuilder.Options(querypart) // $ querystring=querypart insertBuilder.Prefix(querypart) // $ querystring=querypart insertBuilder.Suffix(querypart) // $ querystring=querypart insertBuilder.Into(querypart) // $ querystring=querypart - selectBuilder := squirrel.Select(querypart) // $ querystring=[]type{args} - selectBuilder.Columns(querypart) // $ querystring=[]type{args} + selectBuilder := squirrel.Select(querypart) // $ querystring=querypart + selectBuilder.Columns(querypart) // $ querystring=querypart selectBuilder.From(querypart) // $ querystring=querypart - selectBuilder.Options(querypart) // $ querystring=[]type{args} - selectBuilder.OrderBy(querypart) // $ querystring=[]type{args} + selectBuilder.Options(querypart) // $ querystring=querypart + selectBuilder.OrderBy(querypart) // $ querystring=querypart selectBuilder.Prefix(querypart) // $ querystring=querypart selectBuilder.Suffix(querypart) // $ querystring=querypart selectBuilder.Where(querypart) // $ querystring=querypart selectBuilder.CrossJoin(querypart) // $ querystring=querypart - selectBuilder.GroupBy(querypart) // $ querystring=[]type{args} + selectBuilder.GroupBy(querypart) // $ querystring=querypart selectBuilder.InnerJoin(querypart) // $ querystring=querypart selectBuilder.LeftJoin(querypart) // $ querystring=querypart selectBuilder.RightJoin(querypart) // $ querystring=querypart updateBuilder := squirrel.Update(querypart) // $ querystring=querypart updateBuilder.From(querypart) // $ querystring=querypart - updateBuilder.OrderBy(querypart) // $ querystring=[]type{args} + updateBuilder.OrderBy(querypart) // $ querystring=querypart updateBuilder.Prefix(querypart) // $ querystring=querypart updateBuilder.Suffix(querypart) // $ querystring=querypart updateBuilder.Where(querypart) // $ querystring=querypart updateBuilder.Set(querypart, "") // $ querystring=querypart updateBuilder.Table(querypart) // $ querystring=querypart + + // safe + wrapped := squirrel.Eq{"id": querypart} + deleteBuilder.Where(wrapped) + selectBuilder.Where(wrapped) + updateBuilder.Where(wrapped) } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go index 96a30e49d4ec..1a9e5ca0e9b9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/Masterminds/squirrel/stub.go @@ -2,7 +2,7 @@ // This is a simple stub for github.com/Masterminds/squirrel, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/Masterminds/squirrel (exports: DeleteBuilder,InsertBuilder,SelectBuilder,UpdateBuilder; functions: Delete,Expr,Insert,Select,Update) +// Source: github.com/Masterminds/squirrel (exports: DeleteBuilder,Eq,InsertBuilder,SelectBuilder,UpdateBuilder; functions: Delete,Expr,Insert,Select,Update) // Package squirrel is a stub of github.com/Masterminds/squirrel, generated by depstubber. package squirrel @@ -99,6 +99,12 @@ func (_ DeleteBuilder) Where(_ interface{}, _ ...interface{}) DeleteBuilder { return DeleteBuilder{} } +type Eq map[string]interface{} + +func (_ Eq) ToSql() (string, []interface{}, error) { + return "", nil, nil +} + func Expr(_ string, _ ...interface{}) Sqlizer { return nil } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go b/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go index 6b4dbb116eec..f63b33a0e09b 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go @@ -10,68 +10,73 @@ import ( func xormtest() { query := "UntrustedString" + arg := "arg" engine1 := xorm1.Engine{} - engine1.Query(query) // $ querystring=query - engine1.QueryString(query) // $ querystring=query - engine1.QueryInterface(query) // $ querystring=query - engine1.SQL(query) // $ querystring=query - engine1.Where(query) // $ querystring=query - engine1.Alias(query) // $ querystring=query - engine1.NotIn(query) // $ querystring=query - engine1.In(query) // $ querystring=query - engine1.Select(query) // $ querystring=query - engine1.SetExpr(query, nil) // $ querystring=query - engine1.OrderBy(query) // $ querystring=query - engine1.Having(query) // $ querystring=query - engine1.GroupBy(query) // $ querystring=query + engine1.Query(query, arg) // $ querystring=query + engine1.Exec(query, arg) // $ querystring=query + engine1.QueryString(query, arg) // $ querystring=query + engine1.QueryInterface(query, arg) // $ querystring=query + engine1.SQL(query) // $ querystring=query + engine1.Where(query) // $ querystring=query + engine1.Alias(query) // $ querystring=query + engine1.NotIn(query) // $ querystring=query + engine1.In(query) // $ querystring=query + engine1.Select(query) // $ querystring=query + engine1.SetExpr(query, nil) // $ querystring=query + engine1.OrderBy(query) // $ querystring=query + engine1.Having(query) // $ querystring=query + engine1.GroupBy(query) // $ querystring=query engine2 := xorm2.Engine{} - engine2.Query(query) // $ querystring=query - engine2.QueryString(query) // $ querystring=query - engine2.QueryInterface(query) // $ querystring=query - engine2.SQL(query) // $ querystring=query - engine2.Where(query) // $ querystring=query - engine2.Alias(query) // $ querystring=query - engine2.NotIn(query) // $ querystring=query - engine2.In(query) // $ querystring=query - engine2.Select(query) // $ querystring=query - engine2.SetExpr(query, nil) // $ querystring=query - engine2.OrderBy(query) // $ querystring=query - engine2.Having(query) // $ querystring=query - engine2.GroupBy(query) // $ querystring=query + engine2.Query(query, arg) // $ querystring=query + engine2.Exec(query, arg) // $ querystring=query + engine2.QueryString(query, arg) // $ querystring=query + engine2.QueryInterface(query, arg) // $ querystring=query + engine2.SQL(query) // $ querystring=query + engine2.Where(query) // $ querystring=query + engine2.Alias(query) // $ querystring=query + engine2.NotIn(query) // $ querystring=query + engine2.In(query) // $ querystring=query + engine2.Select(query) // $ querystring=query + engine2.SetExpr(query, nil) // $ querystring=query + engine2.OrderBy(query) // $ querystring=query + engine2.Having(query) // $ querystring=query + engine2.GroupBy(query) // $ querystring=query session1 := xorm1.Session{} - session1.Query(query) // $ querystring=query - session1.QueryString(query) // $ querystring=query - session1.QueryInterface(query) // $ querystring=query - session1.SQL(query) // $ querystring=query - session1.Where(query) // $ querystring=query - session1.Alias(query) // $ querystring=query - session1.NotIn(query) // $ querystring=query - session1.In(query) // $ querystring=query - session1.Select(query) // $ querystring=query - session1.SetExpr(query, nil) // $ querystring=query - session1.OrderBy(query) // $ querystring=query - session1.Having(query) // $ querystring=query - session1.GroupBy(query) // $ querystring=query - session1.And(query) // $ querystring=query - session1.Or(query) // $ querystring=query + session1.Query(query, arg) // $ querystring=query + session1.Exec(query, arg) // $ querystring=query + session1.QueryString(query, arg) // $ querystring=query + session1.QueryInterface(query, arg) // $ querystring=query + session1.SQL(query) // $ querystring=query + session1.Where(query) // $ querystring=query + session1.Alias(query) // $ querystring=query + session1.NotIn(query) // $ querystring=query + session1.In(query) // $ querystring=query + session1.Select(query) // $ querystring=query + session1.SetExpr(query, nil) // $ querystring=query + session1.OrderBy(query) // $ querystring=query + session1.Having(query) // $ querystring=query + session1.GroupBy(query) // $ querystring=query + session1.And(query) // $ querystring=query + session1.Or(query) // $ querystring=query session2 := xorm2.Session{} - session2.Query(query) // $ querystring=query - session2.QueryString(query) // $ querystring=query - session2.QueryInterface(query) // $ querystring=query - session2.SQL(query) // $ querystring=query - session2.Where(query) // $ querystring=query - session2.Alias(query) // $ querystring=query - session2.NotIn(query) // $ querystring=query - session2.In(query) // $ querystring=query - session2.Select(query) // $ querystring=query - session2.SetExpr(query, nil) // $ querystring=query - session2.OrderBy(query) // $ querystring=query - session2.Having(query) // $ querystring=query - session2.GroupBy(query) // $ querystring=query - session2.And(query) // $ querystring=query - session2.Or(query) // $ querystring=query + session2.Query(query, arg) // $ querystring=query + session2.Exec(query, arg) // $ querystring=query + session2.QueryString(query, arg) // $ querystring=query + session2.QueryInterface(query, arg) // $ querystring=query + session2.SQL(query) // $ querystring=query + session2.Where(query) // $ querystring=query + session2.Alias(query) // $ querystring=query + session2.NotIn(query) // $ querystring=query + session2.In(query) // $ querystring=query + session2.Select(query) // $ querystring=query + session2.SetExpr(query, nil) // $ querystring=query + session2.OrderBy(query) // $ querystring=query + session2.Having(query) // $ querystring=query + session2.GroupBy(query) // $ querystring=query + session2.And(query) // $ querystring=query + session2.Or(query) // $ querystring=query } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Slices.go b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Slices.go new file mode 100644 index 000000000000..6ecc98c0a2d3 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Slices.go @@ -0,0 +1,193 @@ +package main + +import ( + "cmp" + "slices" + "strings" +) + +func TaintStepTest_SlicesClip(fromStringSlice []string) []string { + toStringSlice := slices.Clip(fromStringSlice) + return toStringSlice +} + +func TaintStepTest_SlicesClone(fromStringSlice []string) []string { + toStringSlice := slices.Clone(fromStringSlice) + return toStringSlice +} + +func TaintStepTest_SlicesCompact(fromStringSlice []string) []string { + toStringSlice := slices.Compact(fromStringSlice) + return toStringSlice +} + +func TaintStepTest_SlicesCompactFunc(fromStringSlice []string) []string { + toStringSlice := slices.CompactFunc(fromStringSlice, strings.EqualFold) + return toStringSlice +} + +func TaintStepTest_SlicesConcat0(fromStringSlice []string) []string { + toStringSlice := slices.Concat(fromStringSlice, []string{"a", "b", "c"}) + return toStringSlice +} + +func TaintStepTest_SlicesConcat1(fromStringSlice []string) []string { + toStringSlice := slices.Concat([]string{"a", "b", "c"}, fromStringSlice) + return toStringSlice +} + +func TaintStepTest_SlicesDelete(fromStringSlice []string) []string { + toStringSlice := slices.Delete(fromStringSlice, 0, 1) + return toStringSlice +} + +func TaintStepTest_SlicesDeleteFunc(fromStringSlice []string) []string { + deleteEmptyString := func(str string) bool { + return str == "" + } + toStringSlice := slices.DeleteFunc(fromStringSlice, deleteEmptyString) + return toStringSlice +} + +func TaintStepTest_SlicesGrow(fromStringSlice []string) []string { + toStringSlice := slices.Grow(fromStringSlice, 1) + return toStringSlice +} + +func TaintStepTest_SlicesInsert0(fromStringSlice []string) []string { + toStringSlice := slices.Insert(fromStringSlice, 1, "a", "b") + return toStringSlice +} + +func TaintStepTest_SlicesInsert2(fromString string) []string { + toStringSlice := slices.Insert([]string{}, 0, fromString, "b") + return toStringSlice +} + +func TaintStepTest_SlicesMax(fromStringSlice []string) string { + toString := slices.Max(fromStringSlice) + return toString +} + +func TaintStepTest_SlicesMaxFunc(fromStringSlice []string) string { + toString := slices.MaxFunc(fromStringSlice, cmp.Compare) + return toString +} + +func TaintStepTest_SlicesMin(fromStringSlice []string) string { + toString := slices.Min(fromStringSlice) + return toString +} + +func TaintStepTest_SlicesMinFunc(fromStringSlice []string) string { + toString := slices.MinFunc(fromStringSlice, cmp.Compare) + return toString +} + +func TaintStepTest_SlicesRepeat(fromStringSlice []string) []string { + toStringSlice := slices.Repeat(fromStringSlice, 2) + return toStringSlice +} + +func TaintStepTest_SlicesReplace0(fromStringSlice []string) []string { + toStringSlice := slices.Replace(fromStringSlice, 1, 2, "a") + return toStringSlice +} + +func TaintStepTest_SlicesReplace3(fromString string) []string { + toStringSlice := slices.Replace([]string{}, 1, 3, fromString, "b") + return toStringSlice +} + +func RunAllTaints_Slices() { + { + source := []string{newSource(0).(string)} + out := TaintStepTest_SlicesClip(source) + sink(0, out[0]) + } + { + source := []string{newSource(1).(string)} + out := TaintStepTest_SlicesClone(source) + sink(1, out[0]) + } + { + source := []string{newSource(2).(string)} + out := TaintStepTest_SlicesCompact(source) + sink(2, out[0]) + } + { + source := []string{newSource(3).(string)} + out := TaintStepTest_SlicesCompactFunc(source) + sink(3, out[0]) + } + { + source := []string{newSource(4).(string)} + out := TaintStepTest_SlicesConcat0(source) + sink(4, out[0]) + } + { + source := []string{newSource(5).(string)} + out := TaintStepTest_SlicesConcat1(source) + sink(5, out[0]) + } + { + source := []string{newSource(6).(string)} + out := TaintStepTest_SlicesDelete(source) + sink(6, out[0]) + } + { + source := []string{newSource(7).(string)} + out := TaintStepTest_SlicesDeleteFunc(source) + sink(7, out[0]) + } + { + source := []string{newSource(8).(string)} + out := TaintStepTest_SlicesGrow(source) + sink(8, out[0]) + } + { + source := []string{newSource(9).(string)} + out := TaintStepTest_SlicesInsert0(source) + sink(9, out[0]) + } + { + source := newSource(10).(string) + out := TaintStepTest_SlicesInsert2(source) + sink(10, out[0]) + } + { + source := []string{newSource(11).(string)} + out := TaintStepTest_SlicesMax(source) + sink(11, out) + } + { + source := []string{newSource(12).(string)} + out := TaintStepTest_SlicesMaxFunc(source) + sink(12, out) + } + { + source := []string{newSource(13).(string)} + out := TaintStepTest_SlicesMin(source) + sink(13, out) + } + { + source := []string{newSource(14).(string)} + out := TaintStepTest_SlicesMinFunc(source) + sink(14, out) + } + { + source := []string{newSource(15).(string)} + out := TaintStepTest_SlicesRepeat(source) + sink(15, out[0]) + } + { + source := []string{newSource(16).(string)} + out := TaintStepTest_SlicesReplace0(source) + sink(16, out[0]) + } + { + source := newSource(17).(string) + out := TaintStepTest_SlicesReplace3(source) + sink(17, out[0]) + } +} diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/go.mod b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/go.mod index 1481ec9caf63..4168c0a398b9 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/go.mod +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/go.mod @@ -1,6 +1,6 @@ module example.com/m -go 1.20 +go 1.23 require ( golang.org/x/net v0.0.0-20201010224723-4f7140c49acb diff --git a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/vendor/modules.txt b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/vendor/modules.txt index fe5007e8ae12..b11be0ff1d24 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/vendor/modules.txt +++ b/go/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/vendor/modules.txt @@ -1,3 +1,3 @@ # golang.org/x/net v0.0.0-20201010224723-4f7140c49acb -## explicit -golang.org/x/net +## explicit; go 1.11 +golang.org/x/net/context diff --git a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected index c28b1058e7c7..8b2f05c297f8 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/XNetHtml/SqlInjection.expected @@ -1,11 +1,12 @@ #select | test.go:57:11:57:41 | call to EscapeString | test.go:56:2:56:42 | ... := ...[0] | test.go:57:11:57:41 | call to EscapeString | This query depends on a $@. | test.go:56:2:56:42 | ... := ...[0] | user-provided value | edges -| test.go:56:2:56:42 | ... := ...[0] | test.go:57:29:57:40 | selection of Value | provenance | Src:MaD:1 | -| test.go:57:29:57:40 | selection of Value | test.go:57:11:57:41 | call to EscapeString | provenance | MaD:2 | +| test.go:56:2:56:42 | ... := ...[0] | test.go:57:29:57:40 | selection of Value | provenance | Src:MaD:2 | +| test.go:57:29:57:40 | selection of Value | test.go:57:11:57:41 | call to EscapeString | provenance | MaD:3 Sink:MaD:1 | models -| 1 | Source: net/http; Request; true; Cookie; ; ; ReturnValue[0]; remote; manual | -| 2 | Summary: golang.org/x/net/html; ; false; EscapeString; ; ; Argument[0]; ReturnValue; taint; manual | +| 1 | Sink: database/sql; DB; true; Query; ; ; Argument[0]; sql-injection; manual | +| 2 | Source: net/http; Request; true; Cookie; ; ; ReturnValue[0]; remote; manual | +| 3 | Summary: golang.org/x/net/html; ; false; EscapeString; ; ; Argument[0]; ReturnValue; taint; manual | nodes | test.go:56:2:56:42 | ... := ...[0] | semmle.label | ... := ...[0] | | test.go:57:11:57:41 | call to EscapeString | semmle.label | call to EscapeString | diff --git a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index 79d8809e19f9..1ce8c3d1dcf6 100644 --- a/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/go/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -25,53 +25,53 @@ | mongoDB.go:80:22:80:27 | filter | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:80:22:80:27 | filter | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | | mongoDB.go:81:18:81:25 | pipeline | mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:81:18:81:25 | pipeline | This query depends on a $@. | mongoDB.go:40:20:40:30 | call to Referer | user-provided value | edges -| SqlInjection.go:10:7:11:30 | []type{args} [array] | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | MaD:7 | -| SqlInjection.go:10:7:11:30 | call to Sprintf | SqlInjection.go:12:11:12:11 | q | provenance | | -| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query | provenance | Src:MaD:5 MaD:10 | +| SqlInjection.go:10:7:11:30 | []type{args} [array] | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | MaD:23 | +| SqlInjection.go:10:7:11:30 | call to Sprintf | SqlInjection.go:12:11:12:11 | q | provenance | Sink:MaD:1 | +| SqlInjection.go:11:3:11:9 | selection of URL | SqlInjection.go:11:3:11:17 | call to Query | provenance | Src:MaD:21 MaD:26 | | SqlInjection.go:11:3:11:17 | call to Query | SqlInjection.go:11:3:11:29 | index expression | provenance | | | SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | []type{args} [array] | provenance | | | SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | FunctionModel | | issue48.go:17:2:17:33 | ... := ...[0] | issue48.go:18:17:18:17 | b | provenance | | -| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:1 MaD:8 | -| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... | provenance | MaD:6 | +| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:17 MaD:24 | +| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... | provenance | MaD:22 | | issue48.go:18:20:18:39 | &... | issue48.go:21:3:21:33 | index expression | provenance | | -| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:7 | -| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 | provenance | | +| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:23 | +| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 | provenance | Sink:MaD:1 | | issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | []type{args} [array] | provenance | | | issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | call to Sprintf | provenance | FunctionModel | | issue48.go:27:2:27:34 | ... := ...[0] | issue48.go:28:17:28:18 | b2 | provenance | | -| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:1 MaD:8 | -| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... | provenance | MaD:6 | +| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:17 MaD:24 | +| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... | provenance | MaD:22 | | issue48.go:28:21:28:41 | &... | issue48.go:31:3:31:31 | selection of Category | provenance | | -| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:7 | -| issue48.go:30:8:31:32 | call to Sprintf | issue48.go:32:11:32:12 | q4 | provenance | | +| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:23 | +| issue48.go:30:8:31:32 | call to Sprintf | issue48.go:32:11:32:12 | q4 | provenance | Sink:MaD:1 | | issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | []type{args} [array] | provenance | | | issue48.go:31:3:31:31 | selection of Category | issue48.go:30:8:31:32 | call to Sprintf | provenance | FunctionModel | -| issue48.go:37:17:37:50 | type conversion | issue48.go:37:53:37:73 | &... | provenance | MaD:6 | -| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query | provenance | Src:MaD:5 MaD:10 | +| issue48.go:37:17:37:50 | type conversion | issue48.go:37:53:37:73 | &... | provenance | MaD:22 | +| issue48.go:37:24:37:30 | selection of URL | issue48.go:37:24:37:38 | call to Query | provenance | Src:MaD:21 MaD:26 | | issue48.go:37:24:37:38 | call to Query | issue48.go:37:17:37:50 | type conversion | provenance | | | issue48.go:37:53:37:73 | &... | issue48.go:40:3:40:31 | selection of Category | provenance | | -| issue48.go:39:8:40:32 | []type{args} [array] | issue48.go:39:8:40:32 | call to Sprintf | provenance | MaD:7 | -| issue48.go:39:8:40:32 | call to Sprintf | issue48.go:41:11:41:12 | q5 | provenance | | +| issue48.go:39:8:40:32 | []type{args} [array] | issue48.go:39:8:40:32 | call to Sprintf | provenance | MaD:23 | +| issue48.go:39:8:40:32 | call to Sprintf | issue48.go:41:11:41:12 | q5 | provenance | Sink:MaD:1 | | issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | []type{args} [array] | provenance | | | issue48.go:40:3:40:31 | selection of Category | issue48.go:39:8:40:32 | call to Sprintf | provenance | FunctionModel | -| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression | provenance | Src:MaD:2 | -| main.go:15:11:15:84 | []type{args} [array] | main.go:15:11:15:84 | call to Sprintf | provenance | MaD:7 | -| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:11:11:11:16 | selection of Form | main.go:11:11:11:28 | index expression | provenance | Src:MaD:18 Sink:MaD:1 | +| main.go:15:11:15:84 | []type{args} [array] | main.go:15:11:15:84 | call to Sprintf | provenance | MaD:23 Sink:MaD:2 | +| main.go:15:63:15:67 | selection of URL | main.go:15:63:15:75 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:15:63:15:75 | call to Query | main.go:15:63:15:83 | index expression | provenance | | | main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | []type{args} [array] | provenance | | -| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | call to Sprintf | provenance | FunctionModel | -| main.go:16:11:16:85 | []type{args} [array] | main.go:16:11:16:85 | call to Sprintf | provenance | MaD:7 | -| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get | provenance | Src:MaD:3 MaD:9 | +| main.go:15:63:15:83 | index expression | main.go:15:11:15:84 | call to Sprintf | provenance | FunctionModel Sink:MaD:2 | +| main.go:16:11:16:85 | []type{args} [array] | main.go:16:11:16:85 | call to Sprintf | provenance | MaD:23 Sink:MaD:2 | +| main.go:16:63:16:70 | selection of Header | main.go:16:63:16:84 | call to Get | provenance | Src:MaD:19 MaD:25 | | main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | []type{args} [array] | provenance | | -| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | call to Sprintf | provenance | FunctionModel | +| main.go:16:63:16:84 | call to Get | main.go:16:11:16:85 | call to Sprintf | provenance | FunctionModel Sink:MaD:2 | | main.go:28:17:31:2 | &... [pointer, Category] | main.go:34:3:34:13 | RequestData [pointer, Category] | provenance | | | main.go:28:18:31:2 | struct literal [Category] | main.go:28:17:31:2 | &... [pointer, Category] | provenance | | -| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:30:13:30:19 | selection of URL | main.go:30:13:30:27 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:30:13:30:27 | call to Query | main.go:30:13:30:39 | index expression | provenance | | | main.go:30:13:30:39 | index expression | main.go:28:18:31:2 | struct literal [Category] | provenance | | -| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:7 | -| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q | provenance | | +| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:23 | +| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q | provenance | Sink:MaD:1 | | main.go:34:3:34:13 | RequestData [pointer, Category] | main.go:34:3:34:13 | implicit dereference [Category] | provenance | | | main.go:34:3:34:13 | implicit dereference [Category] | main.go:34:3:34:22 | selection of Category | provenance | | | main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | []type{args} [array] | provenance | | @@ -80,11 +80,11 @@ edges | main.go:39:2:39:12 | definition of RequestData [pointer, Category] | main.go:43:3:43:13 | RequestData [pointer, Category] | provenance | | | main.go:40:2:40:12 | RequestData [pointer, Category] | main.go:40:2:40:12 | implicit dereference [Category] | provenance | | | main.go:40:2:40:12 | implicit dereference [Category] | main.go:39:2:39:12 | definition of RequestData [pointer, Category] | provenance | | -| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:40:25:40:39 | call to Query | main.go:40:25:40:51 | index expression | provenance | | | main.go:40:25:40:51 | index expression | main.go:40:2:40:12 | implicit dereference [Category] | provenance | | -| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:7 | -| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q | provenance | | +| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:23 | +| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q | provenance | Sink:MaD:1 | | main.go:43:3:43:13 | RequestData [pointer, Category] | main.go:43:3:43:13 | implicit dereference [Category] | provenance | | | main.go:43:3:43:13 | implicit dereference [Category] | main.go:43:3:43:22 | selection of Category | provenance | | | main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | []type{args} [array] | provenance | | @@ -93,11 +93,11 @@ edges | main.go:48:2:48:12 | definition of RequestData [pointer, Category] | main.go:52:3:52:13 | RequestData [pointer, Category] | provenance | | | main.go:49:3:49:14 | star expression [Category] | main.go:48:2:48:12 | definition of RequestData [pointer, Category] | provenance | | | main.go:49:4:49:14 | RequestData [pointer, Category] | main.go:49:3:49:14 | star expression [Category] | provenance | | -| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:49:28:49:34 | selection of URL | main.go:49:28:49:42 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:49:28:49:42 | call to Query | main.go:49:28:49:54 | index expression | provenance | | | main.go:49:28:49:54 | index expression | main.go:49:3:49:14 | star expression [Category] | provenance | | -| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:7 | -| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q | provenance | | +| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:23 | +| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q | provenance | Sink:MaD:1 | | main.go:52:3:52:13 | RequestData [pointer, Category] | main.go:52:3:52:13 | implicit dereference [Category] | provenance | | | main.go:52:3:52:13 | implicit dereference [Category] | main.go:52:3:52:22 | selection of Category | provenance | | | main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | []type{args} [array] | provenance | | @@ -106,44 +106,60 @@ edges | main.go:57:2:57:12 | definition of RequestData [pointer, Category] | main.go:61:5:61:15 | RequestData [pointer, Category] | provenance | | | main.go:58:3:58:14 | star expression [Category] | main.go:57:2:57:12 | definition of RequestData [pointer, Category] | provenance | | | main.go:58:4:58:14 | RequestData [pointer, Category] | main.go:58:3:58:14 | star expression [Category] | provenance | | -| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query | provenance | Src:MaD:5 MaD:10 | +| main.go:58:28:58:34 | selection of URL | main.go:58:28:58:42 | call to Query | provenance | Src:MaD:21 MaD:26 | | main.go:58:28:58:42 | call to Query | main.go:58:28:58:54 | index expression | provenance | | | main.go:58:28:58:54 | index expression | main.go:58:3:58:14 | star expression [Category] | provenance | | -| main.go:60:7:61:26 | []type{args} [array] | main.go:60:7:61:26 | call to Sprintf | provenance | MaD:7 | -| main.go:60:7:61:26 | call to Sprintf | main.go:62:11:62:11 | q | provenance | | +| main.go:60:7:61:26 | []type{args} [array] | main.go:60:7:61:26 | call to Sprintf | provenance | MaD:23 | +| main.go:60:7:61:26 | call to Sprintf | main.go:62:11:62:11 | q | provenance | Sink:MaD:1 | | main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | []type{args} [array] | provenance | | | main.go:61:3:61:25 | selection of Category | main.go:60:7:61:26 | call to Sprintf | provenance | FunctionModel | | main.go:61:4:61:15 | star expression [Category] | main.go:61:3:61:25 | selection of Category | provenance | | | main.go:61:5:61:15 | RequestData [pointer, Category] | main.go:61:4:61:15 | star expression [Category] | provenance | | -| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:42:28:42:41 | untrustedInput | provenance | Src:MaD:4 | +| mongoDB.go:40:20:40:30 | call to Referer | mongoDB.go:42:28:42:41 | untrustedInput | provenance | Src:MaD:20 | | mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:50:34:50:39 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:61:27:61:32 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:63:23:63:28 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:64:22:64:27 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:66:32:66:37 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:69:17:69:22 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:70:20:70:25 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:71:29:71:34 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:72:30:72:35 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:73:29:73:34 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:78:23:78:28 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:79:23:79:28 | filter | provenance | | -| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:80:22:80:27 | filter | provenance | | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:61:27:61:32 | filter | provenance | Sink:MaD:4 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:63:23:63:28 | filter | provenance | Sink:MaD:5 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:64:22:64:27 | filter | provenance | Sink:MaD:6 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:66:32:66:37 | filter | provenance | Sink:MaD:7 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:69:17:69:22 | filter | provenance | Sink:MaD:8 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:70:20:70:25 | filter | provenance | Sink:MaD:9 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:71:29:71:34 | filter | provenance | Sink:MaD:10 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:72:30:72:35 | filter | provenance | Sink:MaD:11 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:73:29:73:34 | filter | provenance | Sink:MaD:12 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:78:23:78:28 | filter | provenance | Sink:MaD:13 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:79:23:79:28 | filter | provenance | Sink:MaD:14 | +| mongoDB.go:42:19:42:42 | struct literal | mongoDB.go:80:22:80:27 | filter | provenance | Sink:MaD:15 | | mongoDB.go:42:28:42:41 | untrustedInput | mongoDB.go:42:19:42:42 | struct literal | provenance | Config | -| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:57:22:57:29 | pipeline | provenance | | -| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:81:18:81:25 | pipeline | provenance | | +| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:57:22:57:29 | pipeline | provenance | Sink:MaD:3 | +| mongoDB.go:50:23:50:40 | struct literal | mongoDB.go:81:18:81:25 | pipeline | provenance | Sink:MaD:16 | | mongoDB.go:50:34:50:39 | filter | mongoDB.go:50:23:50:40 | struct literal | provenance | Config | models -| 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual | -| 2 | Source: net/http; Request; true; Form; ; ; ; remote; manual | -| 3 | Source: net/http; Request; true; Header; ; ; ; remote; manual | -| 4 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual | -| 5 | Source: net/http; Request; true; URL; ; ; ; remote; manual | -| 6 | Summary: encoding/json; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual | -| 7 | Summary: fmt; ; false; Sprintf; ; ; Argument[1].ArrayElement; ReturnValue; taint; manual | -| 8 | Summary: io/ioutil; ; false; ReadAll; ; ; Argument[0]; ReturnValue[0]; taint; manual | -| 9 | Summary: net/http; Header; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | -| 10 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual | +| 1 | Sink: database/sql; DB; true; Query; ; ; Argument[0]; sql-injection; manual | +| 2 | Sink: database/sql; Tx; true; Query; ; ; Argument[0]; sql-injection; manual | +| 3 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Aggregate; ; ; Argument[1]; nosql-injection; manual | +| 4 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; CountDocuments; ; ; Argument[1]; nosql-injection; manual | +| 5 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; DeleteMany; ; ; Argument[1]; nosql-injection; manual | +| 6 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; DeleteOne; ; ; Argument[1]; nosql-injection; manual | +| 7 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Distinct; ; ; Argument[2]; nosql-injection; manual | +| 8 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Find; ; ; Argument[1]; nosql-injection; manual | +| 9 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOne; ; ; Argument[1]; nosql-injection; manual | +| 10 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOneAndDelete; ; ; Argument[1]; nosql-injection; manual | +| 11 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOneAndReplace; ; ; Argument[1]; nosql-injection; manual | +| 12 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; FindOneAndUpdate; ; ; Argument[1]; nosql-injection; manual | +| 13 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; ReplaceOne; ; ; Argument[1]; nosql-injection; manual | +| 14 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; UpdateMany; ; ; Argument[1]; nosql-injection; manual | +| 15 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; UpdateOne; ; ; Argument[1]; nosql-injection; manual | +| 16 | Sink: go.mongodb.org/mongo-driver/mongo; Collection; true; Watch; ; ; Argument[1]; nosql-injection; manual | +| 17 | Source: net/http; Request; true; Body; ; ; ; remote; manual | +| 18 | Source: net/http; Request; true; Form; ; ; ; remote; manual | +| 19 | Source: net/http; Request; true; Header; ; ; ; remote; manual | +| 20 | Source: net/http; Request; true; Referer; ; ; ReturnValue; remote; manual | +| 21 | Source: net/http; Request; true; URL; ; ; ; remote; manual | +| 22 | Summary: encoding/json; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual | +| 23 | Summary: fmt; ; false; Sprintf; ; ; Argument[1].ArrayElement; ReturnValue; taint; manual | +| 24 | Summary: io/ioutil; ; false; ReadAll; ; ; Argument[0]; ReturnValue[0]; taint; manual | +| 25 | Summary: net/http; Header; true; Get; ; ; Argument[receiver]; ReturnValue; taint; manual | +| 26 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual | nodes | SqlInjection.go:10:7:11:30 | []type{args} [array] | semmle.label | []type{args} [array] | | SqlInjection.go:10:7:11:30 | call to Sprintf | semmle.label | call to Sprintf | diff --git a/go/ql/test/query-tests/Security/CWE-117/LogInjection.go b/go/ql/test/query-tests/Security/CWE-117/LogInjection.go index 4f02cc9aef83..6fb628c4cc38 100644 --- a/go/ql/test/query-tests/Security/CWE-117/LogInjection.go +++ b/go/ql/test/query-tests/Security/CWE-117/LogInjection.go @@ -7,7 +7,7 @@ package main //go:generate depstubber -vendor github.com/davecgh/go-spew/spew "" Dump,Errorf,Print,Printf,Println,Fdump,Fprint,Fprintf,Fprintln //go:generate depstubber -vendor github.com/elazarl/goproxy ProxyCtx "" //go:generate depstubber -vendor github.com/golang/glog Level,Verbose Info,InfoDepth,Infof,Infoln,Error,ErrorDepth,Errorf,Errorln,Fatal,FatalDepth,Fatalf,Fatalln,Exit,ExitDepth,Exitf,Exitln,V -//go:generate depstubber -vendor github.com/sirupsen/logrus Fields,Entry,Logger,Level Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithFields,WithField +//go:generate depstubber -vendor github.com/sirupsen/logrus FieldLogger,Fields,Entry,Logger,Level Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,New,NewEntry,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithError,WithFields,WithField //go:generate depstubber -vendor go.uber.org/zap Logger,SugaredLogger NewProduction import ( @@ -30,6 +30,7 @@ import ( func handler(req *http.Request, ctx *goproxy.ProxyCtx) { username := req.URL.Query()["username"][0] + slice := []any{"username", username} testFlag := req.URL.Query()["testFlag"][0] { @@ -170,129 +171,180 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) { } // sirupsen/logrus { - logrus.Debug(username) // $ hasTaintFlow="username" - logrus.Debugf(username, "") // $ hasTaintFlow="username" - logrus.Debugf("", username) // $ hasTaintFlow="username" - logrus.Debugln(username) // $ hasTaintFlow="username" - logrus.Error(username) // $ hasTaintFlow="username" - logrus.Errorf(username, "") // $ hasTaintFlow="username" - logrus.Errorf("", username) // $ hasTaintFlow="username" - logrus.Errorln(username) // $ hasTaintFlow="username" - logrus.Fatal(username) // $ hasTaintFlow="username" - logrus.Fatalf(username, "") // $ hasTaintFlow="username" - logrus.Fatalf("", username) // $ hasTaintFlow="username" - logrus.Fatalln(username) // $ hasTaintFlow="username" - logrus.Info(username) // $ hasTaintFlow="username" - logrus.Infof(username, "") // $ hasTaintFlow="username" - logrus.Infof("", username) // $ hasTaintFlow="username" - logrus.Infoln(username) // $ hasTaintFlow="username" - logrus.Panic(username) // $ hasTaintFlow="username" - logrus.Panicf(username, "") // $ hasTaintFlow="username" - logrus.Panicf("", username) // $ hasTaintFlow="username" - logrus.Panicln(username) // $ hasTaintFlow="username" - logrus.Print(username) // $ hasTaintFlow="username" - logrus.Printf(username, "") // $ hasTaintFlow="username" - logrus.Printf("", username) // $ hasTaintFlow="username" - logrus.Println(username) // $ hasTaintFlow="username" - logrus.Trace(username) // $ hasTaintFlow="username" - logrus.Tracef(username, "") // $ hasTaintFlow="username" - logrus.Tracef("", username) // $ hasTaintFlow="username" - logrus.Traceln(username) // $ hasTaintFlow="username" - logrus.Warn(username) // $ hasTaintFlow="username" - logrus.Warnf(username, "") // $ hasTaintFlow="username" - logrus.Warnf("", username) // $ hasTaintFlow="username" - logrus.Warnln(username) // $ hasTaintFlow="username" - logrus.Warning(username) // $ hasTaintFlow="username" - logrus.Warningf(username, "") // $ hasTaintFlow="username" - logrus.Warningf("", username) // $ hasTaintFlow="username" - logrus.Warningln(username) // $ hasTaintFlow="username" - + err := fmt.Errorf("error: %s", username) fields := make(logrus.Fields) fields["username"] = username - entry := logrus.WithFields(fields) // $ hasTaintFlow="fields" - entry = logrus.WithField("username", username) // $ hasTaintFlow="username" - entry.Debug(username) // $ hasTaintFlow="username" - entry.Debugf(username, "") // $ hasTaintFlow="username" - entry.Debugf("", username) // $ hasTaintFlow="username" - entry.Debugln(username) // $ hasTaintFlow="username" - entry.Error(username) // $ hasTaintFlow="username" - entry.Errorf(username, "") // $ hasTaintFlow="username" - entry.Errorf("", username) // $ hasTaintFlow="username" - entry.Errorln(username) // $ hasTaintFlow="username" - entry.Fatal(username) // $ hasTaintFlow="username" - entry.Fatalf(username, "") // $ hasTaintFlow="username" - entry.Fatalf("", username) // $ hasTaintFlow="username" - entry.Fatalln(username) // $ hasTaintFlow="username" - entry.Info(username) // $ hasTaintFlow="username" - entry.Infof(username, "") // $ hasTaintFlow="username" - entry.Infof("", username) // $ hasTaintFlow="username" - entry.Infoln(username) // $ hasTaintFlow="username" - entry.Log(0, username) // $ hasTaintFlow="username" - entry.Logf(0, username, "") // $ hasTaintFlow="username" - entry.Logf(0, "", username) // $ hasTaintFlow="username" - entry.Logln(0, username) // $ hasTaintFlow="username" - entry.Panic(username) // $ hasTaintFlow="username" - entry.Panicf(username, "") // $ hasTaintFlow="username" - entry.Panicf("", username) // $ hasTaintFlow="username" - entry.Panicln(username) // $ hasTaintFlow="username" - entry.Print(username) // $ hasTaintFlow="username" - entry.Printf(username, "") // $ hasTaintFlow="username" - entry.Printf("", username) // $ hasTaintFlow="username" - entry.Println(username) // $ hasTaintFlow="username" - entry.Trace(username) // $ hasTaintFlow="username" - entry.Tracef(username, "") // $ hasTaintFlow="username" - entry.Tracef("", username) // $ hasTaintFlow="username" - entry.Traceln(username) // $ hasTaintFlow="username" - entry.Warn(username) // $ hasTaintFlow="username" - entry.Warnf(username, "") // $ hasTaintFlow="username" - entry.Warnf("", username) // $ hasTaintFlow="username" - entry.Warnln(username) // $ hasTaintFlow="username" - entry.Warning(username) // $ hasTaintFlow="username" - entry.Warningf(username, "") // $ hasTaintFlow="username" - entry.Warningf("", username) // $ hasTaintFlow="username" - entry.Warningln(username) // $ hasTaintFlow="username" - - logger := entry.Logger - logger.Debug(username) // $ hasTaintFlow="username" - logger.Debugf(username, "") // $ hasTaintFlow="username" - logger.Debugf("", username) // $ hasTaintFlow="username" - logger.Debugln(username) // $ hasTaintFlow="username" - logger.Error(username) // $ hasTaintFlow="username" - logger.Errorf(username, "") // $ hasTaintFlow="username" - logger.Errorf("", username) // $ hasTaintFlow="username" - logger.Errorln(username) // $ hasTaintFlow="username" - logger.Fatal(username) // $ hasTaintFlow="username" - logger.Fatalf(username, "") // $ hasTaintFlow="username" - logger.Fatalf("", username) // $ hasTaintFlow="username" - logger.Fatalln(username) // $ hasTaintFlow="username" - logger.Info(username) // $ hasTaintFlow="username" - logger.Infof(username, "") // $ hasTaintFlow="username" - logger.Infof("", username) // $ hasTaintFlow="username" - logger.Infoln(username) // $ hasTaintFlow="username" - logger.Log(0, username) // $ hasTaintFlow="username" - logger.Logf(0, username, "") // $ hasTaintFlow="username" - logger.Logf(0, "", username) // $ hasTaintFlow="username" - logger.Logln(0, username) // $ hasTaintFlow="username" - logger.Panic(username) // $ hasTaintFlow="username" - logger.Panicf(username, "") // $ hasTaintFlow="username" - logger.Panicf("", username) // $ hasTaintFlow="username" - logger.Panicln(username) // $ hasTaintFlow="username" - logger.Print(username) // $ hasTaintFlow="username" - logger.Printf(username, "") // $ hasTaintFlow="username" - logger.Printf("", username) // $ hasTaintFlow="username" - logger.Println(username) // $ hasTaintFlow="username" - logger.Trace(username) // $ hasTaintFlow="username" - logger.Tracef(username, "") // $ hasTaintFlow="username" - logger.Tracef("", username) // $ hasTaintFlow="username" - logger.Traceln(username) // $ hasTaintFlow="username" - logger.Warn(username) // $ hasTaintFlow="username" - logger.Warnf(username, "") // $ hasTaintFlow="username" - logger.Warnf("", username) // $ hasTaintFlow="username" - logger.Warnln(username) // $ hasTaintFlow="username" - logger.Warning(username) // $ hasTaintFlow="username" - logger.Warningf(username, "") // $ hasTaintFlow="username" - logger.Warningf("", username) // $ hasTaintFlow="username" - logger.Warningln(username) // $ hasTaintFlow="username" + logger := logrus.New() + entry := logrus.NewEntry(logger) + + logrus.Debug(username) // $ hasTaintFlow="username" + logrus.Debugf(username, "") // $ hasTaintFlow="username" + logrus.Debugf("", username) // $ hasTaintFlow="username" + logrus.Debugln(username) // $ hasTaintFlow="username" + logrus.Error(username) // $ hasTaintFlow="username" + logrus.Errorf(username, "") // $ hasTaintFlow="username" + logrus.Errorf("", username) // $ hasTaintFlow="username" + logrus.Errorln(username) // $ hasTaintFlow="username" + logrus.Fatal(username) // $ hasTaintFlow="username" + logrus.Fatalf(username, "") // $ hasTaintFlow="username" + logrus.Fatalf("", username) // $ hasTaintFlow="username" + logrus.Fatalln(username) // $ hasTaintFlow="username" + logrus.Info(username) // $ hasTaintFlow="username" + logrus.Infof(username, "") // $ hasTaintFlow="username" + logrus.Infof("", username) // $ hasTaintFlow="username" + logrus.Infoln(username) // $ hasTaintFlow="username" + logrus.Panic(username) // $ hasTaintFlow="username" + logrus.Panicf(username, "") // $ hasTaintFlow="username" + logrus.Panicf("", username) // $ hasTaintFlow="username" + logrus.Panicln(username) // $ hasTaintFlow="username" + logrus.Print(username) // $ hasTaintFlow="username" + logrus.Printf(username, "") // $ hasTaintFlow="username" + logrus.Printf("", username) // $ hasTaintFlow="username" + logrus.Println(username) // $ hasTaintFlow="username" + logrus.Trace(username) // $ hasTaintFlow="username" + logrus.Tracef(username, "") // $ hasTaintFlow="username" + logrus.Tracef("", username) // $ hasTaintFlow="username" + logrus.Traceln(username) // $ hasTaintFlow="username" + logrus.Warn(username) // $ hasTaintFlow="username" + logrus.Warnf(username, "") // $ hasTaintFlow="username" + logrus.Warnf("", username) // $ hasTaintFlow="username" + logrus.Warnln(username) // $ hasTaintFlow="username" + logrus.Warning(username) // $ hasTaintFlow="username" + logrus.Warningf(username, "") // $ hasTaintFlow="username" + logrus.Warningf("", username) // $ hasTaintFlow="username" + logrus.Warningln(username) // $ hasTaintFlow="username" + logrus.WithError(err) // $ hasTaintFlow="err" + logrus.WithField(username, "") // $ hasTaintFlow="username" + logrus.WithField("", username) // $ hasTaintFlow="username" + logrus.WithFields(fields) // $ hasTaintFlow="fields" + + entry.Debug(username) // $ hasTaintFlow="username" + entry.Debugf(username, "") // $ hasTaintFlow="username" + entry.Debugf("", username) // $ hasTaintFlow="username" + entry.Debugln(username) // $ hasTaintFlow="username" + entry.Error(username) // $ hasTaintFlow="username" + entry.Errorf(username, "") // $ hasTaintFlow="username" + entry.Errorf("", username) // $ hasTaintFlow="username" + entry.Errorln(username) // $ hasTaintFlow="username" + entry.Fatal(username) // $ hasTaintFlow="username" + entry.Fatalf(username, "") // $ hasTaintFlow="username" + entry.Fatalf("", username) // $ hasTaintFlow="username" + entry.Fatalln(username) // $ hasTaintFlow="username" + entry.Info(username) // $ hasTaintFlow="username" + entry.Infof(username, "") // $ hasTaintFlow="username" + entry.Infof("", username) // $ hasTaintFlow="username" + entry.Infoln(username) // $ hasTaintFlow="username" + entry.Log(0, username) // $ hasTaintFlow="username" + entry.Logf(0, username, "") // $ hasTaintFlow="username" + entry.Logf(0, "", username) // $ hasTaintFlow="username" + entry.Logln(0, username) // $ hasTaintFlow="username" + entry.Panic(username) // $ hasTaintFlow="username" + entry.Panicf(username, "") // $ hasTaintFlow="username" + entry.Panicf("", username) // $ hasTaintFlow="username" + entry.Panicln(username) // $ hasTaintFlow="username" + entry.Print(username) // $ hasTaintFlow="username" + entry.Printf(username, "") // $ hasTaintFlow="username" + entry.Printf("", username) // $ hasTaintFlow="username" + entry.Println(username) // $ hasTaintFlow="username" + entry.Trace(username) // $ hasTaintFlow="username" + entry.Tracef(username, "") // $ hasTaintFlow="username" + entry.Tracef("", username) // $ hasTaintFlow="username" + entry.Traceln(username) // $ hasTaintFlow="username" + entry.Warn(username) // $ hasTaintFlow="username" + entry.Warnf(username, "") // $ hasTaintFlow="username" + entry.Warnf("", username) // $ hasTaintFlow="username" + entry.Warnln(username) // $ hasTaintFlow="username" + entry.Warning(username) // $ hasTaintFlow="username" + entry.Warningf(username, "") // $ hasTaintFlow="username" + entry.Warningf("", username) // $ hasTaintFlow="username" + entry.Warningln(username) // $ hasTaintFlow="username" + entry.WithError(err) // $ hasTaintFlow="err" + entry.WithField(username, "") // $ hasTaintFlow="username" + entry.WithField("", username) // $ hasTaintFlow="username" + entry.WithFields(fields) // $ hasTaintFlow="fields" + + logger.Debug(username) // $ hasTaintFlow="username" + logger.Debugf(username, "") // $ hasTaintFlow="username" + logger.Debugf("", username) // $ hasTaintFlow="username" + logger.Debugln(username) // $ hasTaintFlow="username" + logger.Error(username) // $ hasTaintFlow="username" + logger.Errorf(username, "") // $ hasTaintFlow="username" + logger.Errorf("", username) // $ hasTaintFlow="username" + logger.Errorln(username) // $ hasTaintFlow="username" + logger.Fatal(username) // $ hasTaintFlow="username" + logger.Fatalf(username, "") // $ hasTaintFlow="username" + logger.Fatalf("", username) // $ hasTaintFlow="username" + logger.Fatalln(username) // $ hasTaintFlow="username" + logger.Info(username) // $ hasTaintFlow="username" + logger.Infof(username, "") // $ hasTaintFlow="username" + logger.Infof("", username) // $ hasTaintFlow="username" + logger.Infoln(username) // $ hasTaintFlow="username" + logger.Log(0, username) // $ hasTaintFlow="username" + logger.Logf(0, username, "") // $ hasTaintFlow="username" + logger.Logf(0, "", username) // $ hasTaintFlow="username" + logger.Logln(0, username) // $ hasTaintFlow="username" + logger.Panic(username) // $ hasTaintFlow="username" + logger.Panicf(username, "") // $ hasTaintFlow="username" + logger.Panicf("", username) // $ hasTaintFlow="username" + logger.Panicln(username) // $ hasTaintFlow="username" + logger.Print(username) // $ hasTaintFlow="username" + logger.Printf(username, "") // $ hasTaintFlow="username" + logger.Printf("", username) // $ hasTaintFlow="username" + logger.Println(username) // $ hasTaintFlow="username" + logger.Trace(username) // $ hasTaintFlow="username" + logger.Tracef(username, "") // $ hasTaintFlow="username" + logger.Tracef("", username) // $ hasTaintFlow="username" + logger.Traceln(username) // $ hasTaintFlow="username" + logger.Warn(username) // $ hasTaintFlow="username" + logger.Warnf(username, "") // $ hasTaintFlow="username" + logger.Warnf("", username) // $ hasTaintFlow="username" + logger.Warnln(username) // $ hasTaintFlow="username" + logger.Warning(username) // $ hasTaintFlow="username" + logger.Warningf(username, "") // $ hasTaintFlow="username" + logger.Warningf("", username) // $ hasTaintFlow="username" + logger.Warningln(username) // $ hasTaintFlow="username" + logger.WithError(err) // $ hasTaintFlow="err" + logger.WithField(username, "") // $ hasTaintFlow="username" + logger.WithField("", username) // $ hasTaintFlow="username" + logger.WithFields(fields) // $ hasTaintFlow="fields" + + var fieldlogger logrus.FieldLogger = entry + fieldlogger.Debug(username) // $ hasTaintFlow="username" + fieldlogger.Debugf(username, "") // $ hasTaintFlow="username" + fieldlogger.Debugf("", username) // $ hasTaintFlow="username" + fieldlogger.Debugln(username) // $ hasTaintFlow="username" + fieldlogger.Error(username) // $ hasTaintFlow="username" + fieldlogger.Errorf(username, "") // $ hasTaintFlow="username" + fieldlogger.Errorf("", username) // $ hasTaintFlow="username" + fieldlogger.Errorln(username) // $ hasTaintFlow="username" + fieldlogger.Fatal(username) // $ hasTaintFlow="username" + fieldlogger.Fatalf(username, "") // $ hasTaintFlow="username" + fieldlogger.Fatalf("", username) // $ hasTaintFlow="username" + fieldlogger.Fatalln(username) // $ hasTaintFlow="username" + fieldlogger.Info(username) // $ hasTaintFlow="username" + fieldlogger.Infof(username, "") // $ hasTaintFlow="username" + fieldlogger.Infof("", username) // $ hasTaintFlow="username" + fieldlogger.Infoln(username) // $ hasTaintFlow="username" + fieldlogger.Panic(username) // $ hasTaintFlow="username" + fieldlogger.Panicf(username, "") // $ hasTaintFlow="username" + fieldlogger.Panicf("", username) // $ hasTaintFlow="username" + fieldlogger.Panicln(username) // $ hasTaintFlow="username" + fieldlogger.Print(username) // $ hasTaintFlow="username" + fieldlogger.Printf(username, "") // $ hasTaintFlow="username" + fieldlogger.Printf("", username) // $ hasTaintFlow="username" + fieldlogger.Println(username) // $ hasTaintFlow="username" + fieldlogger.Warn(username) // $ hasTaintFlow="username" + fieldlogger.Warnf(username, "") // $ hasTaintFlow="username" + fieldlogger.Warnf("", username) // $ hasTaintFlow="username" + fieldlogger.Warnln(username) // $ hasTaintFlow="username" + fieldlogger.Warning(username) // $ hasTaintFlow="username" + fieldlogger.Warningf(username, "") // $ hasTaintFlow="username" + fieldlogger.Warningf("", username) // $ hasTaintFlow="username" + fieldlogger.Warningln(username) // $ hasTaintFlow="username" + fieldlogger.WithError(err) // $ hasTaintFlow="err" + fieldlogger.WithField(username, "") // $ hasTaintFlow="username" + fieldlogger.WithField("", username) // $ hasTaintFlow="username" + fieldlogger.WithFields(fields) // $ hasTaintFlow="fields" } // davecgh/go-spew/spew { @@ -361,8 +413,34 @@ func handler(req *http.Request, ctx *goproxy.ProxyCtx) { sLogger.Named(username) // $ hasTaintFlow="username" sLogger.With(username) // $ hasTaintFlow="username" } + // heuristic logger interface + { + logger.Printf(username) // $ hasTaintFlow="username" + logger.Printf("%s", username) // $ hasTaintFlow="username" + simpleLogger.Tracew(username) // $ hasTaintFlow="username" + simpleLogger.Tracew("%s", username) // $ hasTaintFlow="username" + simpleLogger.Debugw("%s %s", slice...) // $ hasTaintFlow="slice" + } + } +type Logger interface { + Printf(string, ...interface{}) +} + +type SimpleLogger interface { + Debugw(msg string, keysAndValues ...any) + Infow(msg string, keysAndValues ...any) + Warnw(msg string, keysAndValues ...any) + Errorw(msg string, keysAndValues ...any) + Tracew(msg string, keysAndValues ...any) +} + +var ( + logger Logger + simpleLogger SimpleLogger +) + // GOOD: The user-provided value is escaped before being written to the log. func handlerGood(req *http.Request) { username := req.URL.Query()["username"][0] @@ -598,5 +676,4 @@ func handlerGood4(req *http.Request, ctx *goproxy.ProxyCtx) { } sLogger.Warnf("user %#q logged in.\n", username) // $ hasTaintFlow="username" } - } diff --git a/go/ql/test/query-tests/Security/CWE-117/go.mod b/go/ql/test/query-tests/Security/CWE-117/go.mod index 57b2077a4ed1..906d90f31b66 100644 --- a/go/ql/test/query-tests/Security/CWE-117/go.mod +++ b/go/ql/test/query-tests/Security/CWE-117/go.mod @@ -1,14 +1,33 @@ module main -go 1.14 +go 1.23 require ( github.com/astaxie/beego v1.12.3 + github.com/davecgh/go-spew v1.1.1 github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/kr/text v0.2.0 // indirect github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.6.0 // indirect - golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + go.uber.org/zap v1.27.0 k8s.io/klog v1.0.0 ) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/golang/protobuf v1.4.2 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/prometheus/client_golang v1.7.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.10.0 // indirect + github.com/prometheus/procfs v0.1.3 // indirect + github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect + golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + golang.org/x/text v0.3.0 // indirect + google.golang.org/protobuf v1.23.0 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect +) diff --git a/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go b/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go index e8f7bccc4465..497d85559bb2 100644 --- a/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go +++ b/go/ql/test/query-tests/Security/CWE-117/vendor/github.com/sirupsen/logrus/stub.go @@ -2,7 +2,7 @@ // This is a simple stub for github.com/sirupsen/logrus, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/sirupsen/logrus (exports: Fields,Entry,Logger,Level; functions: Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithFields,WithField) +// Source: github.com/sirupsen/logrus (exports: FieldLogger,Fields,Entry,Logger,Level; functions: Debug,Debugf,Debugln,Error,Errorf,Errorln,Fatal,Fatalf,Fatalln,Info,Infof,Infoln,New,NewEntry,Panic,Panicf,Panicln,Print,Printf,Println,Trace,Tracef,Traceln,Warn,Warnf,Warnln,Warning,Warningf,Warningln,WithError,WithFields,WithField) // Package logrus is a stub of github.com/sirupsen/logrus, generated by depstubber. package logrus @@ -148,6 +148,36 @@ func Fatalf(_ string, _ ...interface{}) {} func Fatalln(_ ...interface{}) {} +type FieldLogger interface { + Debug(_ ...interface{}) + Debugf(_ string, _ ...interface{}) + Debugln(_ ...interface{}) + Error(_ ...interface{}) + Errorf(_ string, _ ...interface{}) + Errorln(_ ...interface{}) + Fatal(_ ...interface{}) + Fatalf(_ string, _ ...interface{}) + Fatalln(_ ...interface{}) + Info(_ ...interface{}) + Infof(_ string, _ ...interface{}) + Infoln(_ ...interface{}) + Panic(_ ...interface{}) + Panicf(_ string, _ ...interface{}) + Panicln(_ ...interface{}) + Print(_ ...interface{}) + Printf(_ string, _ ...interface{}) + Println(_ ...interface{}) + Warn(_ ...interface{}) + Warnf(_ string, _ ...interface{}) + Warning(_ ...interface{}) + Warningf(_ string, _ ...interface{}) + Warningln(_ ...interface{}) + Warnln(_ ...interface{}) + WithError(_ error) *Entry + WithField(_ string, _ interface{}) *Entry + WithFields(_ Fields) *Entry +} + type Fields map[string]interface{} type Formatter interface { @@ -332,6 +362,14 @@ func (_ *Logger) WriterLevel(_ Level) *io.PipeWriter { return nil } +func New() *Logger { + return nil +} + +func NewEntry(_ *Logger) *Entry { + return nil +} + func Panic(_ ...interface{}) {} func Panicf(_ string, _ ...interface{}) {} @@ -362,6 +400,10 @@ func Warningln(_ ...interface{}) {} func Warnln(_ ...interface{}) {} +func WithError(_ error) *Entry { + return nil +} + func WithField(_ string, _ interface{}) *Entry { return nil } diff --git a/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt b/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt index a6227c09a936..fa7cb0a9a823 100644 --- a/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt +++ b/go/ql/test/query-tests/Security/CWE-117/vendor/modules.txt @@ -1,24 +1,134 @@ # github.com/astaxie/beego v1.12.3 -## explicit +## explicit; go 1.13 github.com/astaxie/beego +github.com/astaxie/beego/config +github.com/astaxie/beego/context +github.com/astaxie/beego/context/param +github.com/astaxie/beego/grace +github.com/astaxie/beego/logs +github.com/astaxie/beego/session +github.com/astaxie/beego/toolbox +github.com/astaxie/beego/utils +# github.com/beorn7/perks v1.0.1 +## explicit; go 1.11 +github.com/beorn7/perks/quantile +# github.com/cespare/xxhash/v2 v2.1.1 +## explicit; go 1.11 +github.com/cespare/xxhash/v2 +# github.com/davecgh/go-spew v1.1.1 +## explicit +github.com/davecgh/go-spew/spew # github.com/elazarl/goproxy v0.0.0-20211114080932-d06c3be7c11b ## explicit github.com/elazarl/goproxy # github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b ## explicit github.com/golang/glog -# github.com/kr/text v0.2.0 +# github.com/golang/protobuf v1.4.2 +## explicit; go 1.9 +github.com/golang/protobuf/proto +github.com/golang/protobuf/ptypes +github.com/golang/protobuf/ptypes/any +github.com/golang/protobuf/ptypes/duration +github.com/golang/protobuf/ptypes/timestamp +# github.com/hashicorp/golang-lru v0.5.4 +## explicit; go 1.12 +github.com/hashicorp/golang-lru +github.com/hashicorp/golang-lru/simplelru +# github.com/matttproud/golang_protobuf_extensions v1.0.1 ## explicit -github.com/kr/text -# github.com/sirupsen/logrus v1.8.1 +github.com/matttproud/golang_protobuf_extensions/pbutil +# github.com/prometheus/client_golang v1.7.0 +## explicit; go 1.11 +github.com/prometheus/client_golang/prometheus +github.com/prometheus/client_golang/prometheus/internal +github.com/prometheus/client_golang/prometheus/promhttp +# github.com/prometheus/client_model v0.2.0 +## explicit; go 1.9 +github.com/prometheus/client_model/go +# github.com/prometheus/common v0.10.0 +## explicit; go 1.11 +github.com/prometheus/common/expfmt +github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg +github.com/prometheus/common/model +# github.com/prometheus/procfs v0.1.3 +## explicit; go 1.12 +github.com/prometheus/procfs +github.com/prometheus/procfs/internal/fs +github.com/prometheus/procfs/internal/util +# github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 ## explicit +github.com/shiena/ansicolor +# github.com/sirupsen/logrus v1.8.1 +## explicit; go 1.13 github.com/sirupsen/logrus -# github.com/stretchr/testify v1.6.0 +# go.uber.org/multierr v1.10.0 +## explicit; go 1.19 +go.uber.org/multierr +# go.uber.org/zap v1.27.0 +## explicit; go 1.19 +go.uber.org/zap +go.uber.org/zap/buffer +go.uber.org/zap/internal +go.uber.org/zap/internal/bufferpool +go.uber.org/zap/internal/color +go.uber.org/zap/internal/exit +go.uber.org/zap/internal/pool +go.uber.org/zap/internal/stacktrace +go.uber.org/zap/zapcore +# golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 ## explicit -github.com/stretchr/testify +golang.org/x/crypto/acme +golang.org/x/crypto/acme/autocert +# golang.org/x/net v0.0.0-20190620200207-3b0461eec859 +## explicit; go 1.11 +golang.org/x/net/idna # golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f +## explicit; go 1.12 +golang.org/x/sys/internal/unsafeheader +golang.org/x/sys/unix +golang.org/x/sys/windows +# golang.org/x/text v0.3.0 ## explicit -golang.org/x/sys -# k8s.io/klog v1.0.0 +golang.org/x/text/secure/bidirule +golang.org/x/text/transform +golang.org/x/text/unicode/bidi +golang.org/x/text/unicode/norm +# google.golang.org/protobuf v1.23.0 +## explicit; go 1.9 +google.golang.org/protobuf/encoding/prototext +google.golang.org/protobuf/encoding/protowire +google.golang.org/protobuf/internal/descfmt +google.golang.org/protobuf/internal/descopts +google.golang.org/protobuf/internal/detrand +google.golang.org/protobuf/internal/encoding/defval +google.golang.org/protobuf/internal/encoding/messageset +google.golang.org/protobuf/internal/encoding/tag +google.golang.org/protobuf/internal/encoding/text +google.golang.org/protobuf/internal/errors +google.golang.org/protobuf/internal/fieldnum +google.golang.org/protobuf/internal/fieldsort +google.golang.org/protobuf/internal/filedesc +google.golang.org/protobuf/internal/filetype +google.golang.org/protobuf/internal/flags +google.golang.org/protobuf/internal/genname +google.golang.org/protobuf/internal/impl +google.golang.org/protobuf/internal/mapsort +google.golang.org/protobuf/internal/pragma +google.golang.org/protobuf/internal/set +google.golang.org/protobuf/internal/strs +google.golang.org/protobuf/internal/version +google.golang.org/protobuf/proto +google.golang.org/protobuf/reflect/protoreflect +google.golang.org/protobuf/reflect/protoregistry +google.golang.org/protobuf/runtime/protoiface +google.golang.org/protobuf/runtime/protoimpl +google.golang.org/protobuf/types/known/anypb +google.golang.org/protobuf/types/known/durationpb +google.golang.org/protobuf/types/known/timestamppb +# gopkg.in/yaml.v2 v2.2.8 ## explicit +gopkg.in/yaml.v2 +# k8s.io/klog v1.0.0 +## explicit; go 1.12 k8s.io/klog diff --git a/java/ql/automodel/publish.sh b/java/ql/automodel/publish.sh deleted file mode 100755 index 7304f0da1809..000000000000 --- a/java/ql/automodel/publish.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash -set -e - -help="Usage: ./publish [--override-release] [--dry-run] -Publish the automodel query pack. - -If no arguments are provided, publish the version of the codeql repo specified by the latest official release of the codeml-automodel repo. -If the --override-release argument is provided, your current local HEAD is used (for unofficial releases or patching). -If the --dry-run argument is provided, the release is not published (for testing purposes)." - -# Echo the help message -if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then - echo "$help" - exit 0 -fi - -# Check the number of arguments are valid -if [ $# -gt 2 ]; then - echo "Error: Invalid arguments provided" - echo "$help" - exit 1 -fi - -OVERRIDE_RELEASE=0 -DRY_RUN=0 -for arg in "$@" -do - case $arg in - --override-release) - OVERRIDE_RELEASE=1 - shift # Remove --override-release from processing - ;; - --dry-run) - DRY_RUN=1 - shift # Remove --dry-run from processing - ;; - *) - echo "Error: Invalid argument provided: $arg" - echo "$help" - exit 1 - ;; - esac -done - -# Describe what we're about to do based on the command-line arguments -if [ $OVERRIDE_RELEASE = 1 ]; then - echo "Publishing the current HEAD of the automodel repo" -else - echo "Publishing the version of the automodel repo specified by the latest official release of the codeml-automodel repo" -fi -if [ $DRY_RUN = 1 ]; then - echo "Dry run: we will step through the process but we won't publish the query pack" -else - echo "Not a dry run! Publishing the query pack" -fi - -# If we're publishing the codeml-automodel release then we will checkout the sha specified in the release. -# So we need to check that there are no uncommitted changes in the local branch. -# And, if we're publishing the current HEAD, it's cleaner to ensure that there are no uncommitted changes. -if ! git diff --quiet; then - echo "Error: Uncommitted changes exist. Please commit or stash your changes before publishing." - exit 1 -fi - -# Check the above environment variables are set -if [ -z "${GITHUB_TOKEN}" ]; then - echo "Error: GITHUB_TOKEN environment variable not set. Please set this to a token with package:write permissions to codeql." - exit 1 -fi -if [ -z "${GH_TOKEN}" ]; then - echo "Error: GH_TOKEN environment variable not set. Please set this to a token with repo permissions to github/codeml-automodel." - exit 1 -fi - -# Get the sha of the previous release, i.e. the last commit to the main branch that updated the query pack version -PREVIOUS_RELEASE_SHA=$(git rev-list -n 1 main -- ./src/qlpack.yml) -if [ -z "$PREVIOUS_RELEASE_SHA" ]; then - echo "Error: Could not get the sha of the previous release of codeml-automodel query pack" - exit 1 -else - echo "Previous query-pack release sha: $PREVIOUS_RELEASE_SHA" -fi - -CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) -CURRENT_SHA=$(git rev-parse HEAD) - -if [ $OVERRIDE_RELEASE = 1 ]; then - # Check that the current HEAD is downstream from PREVIOUS_RELEASE_SHA - if ! git merge-base --is-ancestor "$PREVIOUS_RELEASE_SHA" "$CURRENT_SHA"; then - echo "Error: The current HEAD is not downstream from the previous release" - exit 1 - fi -else - # Get the latest release of codeml-automodel - TAG_NAME=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/github/codeml-automodel/releases/latest | jq -r .tag_name) - # Check TAG_NAME is not empty - if [ -z "$TAG_NAME" ]; then - echo "Error: Could not get latest release of codeml-automodel" - exit 1 - fi - echo "Updating to latest automodel release: $TAG_NAME" - # Before downloading, delete any existing release.zip, and ignore failure if not present - rm release.zip || true - gh release download $TAG_NAME -A zip -O release.zip --repo 'https://github.com/github/codeml-automodel' - # Before unzipping, delete any existing release directory, and ignore failure if not present - rm -rf release || true - unzip -o release.zip -d release - REVISION=$(jq -r '.["codeql-sha"]' release/codeml-automodel*/codeml-automodel-release.json) - echo "The latest codeml-automodel release specifies the codeql sha $REVISION" - # Check that REVISION is downstream from PREVIOUS_RELEASE_SHA - if ! git merge-base --is-ancestor "$PREVIOUS_RELEASE_SHA" "$REVISION"; then - echo "Error: The codeql version $REVISION is not downstream of the query-pack version $PREVIOUS_RELEASE_SHA" - exit 1 - fi - # Get the version of the codeql code specified by the codeml-automodel release - git checkout "$REVISION" -fi - -# Get the absolute path of the automodel repo -AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")" -# Get the absolute path of the workspace root -WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.." -# Specify the groups of queries to test and publish -GRPS="automodel,-test" - -# Install the codeql gh extension -gh extensions install github/gh-codeql - -pushd "$AUTOMODEL_ROOT" -echo Testing automodel queries -gh codeql test run test -popd - -pushd "$WORKSPACE_ROOT" -echo "Preparing the release" -gh codeql pack release --groups $GRPS -v - -if [ $DRY_RUN = 1 ]; then - echo "Dry run: not publishing the query pack" - gh codeql pack publish --groups $GRPS --dry-run -v -else - echo "Not a dry run! Publishing the query pack" - gh codeql pack publish --groups $GRPS -v -fi - -echo "Bumping versions" -gh codeql pack post-release --groups $GRPS -v -popd - -# The above commands update -# ./src/CHANGELOG.md -# ./src/codeql-pack.release.yml -# ./src/qlpack.yml -# and add a new file -# ./src/change-notes/released/.md - -# Get the filename of the most recently created file in ./src/change-notes/released/*.md -# This will be the file for the new release -NEW_CHANGE_NOTES_FILE=$(ls -t ./src/change-notes/released/*.md | head -n 1) - -# Make a copy of the modified files -mv ./src/CHANGELOG.md ./src/CHANGELOG.md.dry-run -mv ./src/codeql-pack.release.yml ./src/codeql-pack.release.yml.dry-run -mv ./src/qlpack.yml ./src/qlpack.yml.dry-run -mv "$NEW_CHANGE_NOTES_FILE" ./src/change-notes/released.md.dry-run - -if [ $OVERRIDE_RELEASE = 1 ]; then - # Restore the original files - git checkout ./src/CHANGELOG.md - git checkout ./src/codeql-pack.release.yml - git checkout ./src/qlpack.yml -else - # Restore the original files - git checkout "$CURRENT_BRANCH" --force -fi - -if [ $DRY_RUN = 1 ]; then - echo "Inspect the updated dry-run version files:" - ls -l ./src/*.dry-run - ls -l ./src/change-notes/*.dry-run -else - # Add the updated files to the current branch - echo "Adding the version changes" - mv -f ./src/CHANGELOG.md.dry-run ./src/CHANGELOG.md - mv -f ./src/codeql-pack.release.yml.dry-run ./src/codeql-pack.release.yml - mv -f ./src/qlpack.yml.dry-run ./src/qlpack.yml - mv -f ./src/change-notes/released.md.dry-run "$NEW_CHANGE_NOTES_FILE" - git add ./src/CHANGELOG.md - git add ./src/codeql-pack.release.yml - git add ./src/qlpack.yml - git add "$NEW_CHANGE_NOTES_FILE" - echo "Added the following updated version files to the current branch:" - git status -s - echo "To complete the release, please commit these files and merge to the main branch" -fi - -echo "Done" \ No newline at end of file diff --git a/java/ql/automodel/src/AutomodelAlertSinkUtil.qll b/java/ql/automodel/src/AutomodelAlertSinkUtil.qll deleted file mode 100644 index f20c8e57b6cc..000000000000 --- a/java/ql/automodel/src/AutomodelAlertSinkUtil.qll +++ /dev/null @@ -1,183 +0,0 @@ -private import java -private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow -private import semmle.code.java.dataflow.TaintTracking -private import semmle.code.java.security.RequestForgeryConfig -private import semmle.code.java.security.CommandLineQuery -private import semmle.code.java.security.SqlConcatenatedQuery -private import semmle.code.java.security.SqlInjectionQuery -private import semmle.code.java.security.UrlRedirectQuery -private import semmle.code.java.security.TaintedPathQuery -private import semmle.code.java.security.SqlInjectionQuery -private import AutomodelJavaUtil - -private newtype TSinkModel = - MkSinkModel( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input, string kind, string provenance - ) { - ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance, - _) - } - -class SinkModel extends TSinkModel { - string package; - string type; - boolean subtypes; - string name; - string signature; - string ext; - string input; - string kind; - string provenance; - - SinkModel() { - this = MkSinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) - } - - /** Gets the package for this sink model. */ - string getPackage() { result = package } - - /** Gets the type for this sink model. */ - string getType() { result = type } - - /** Gets whether this sink model considers subtypes. */ - boolean getSubtypes() { result = subtypes } - - /** Gets the name for this sink model. */ - string getName() { result = name } - - /** Gets the signature for this sink model. */ - string getSignature() { result = signature } - - /** Gets the input for this sink model. */ - string getInput() { result = input } - - /** Gets the extension for this sink model. */ - string getExt() { result = ext } - - /** Gets the kind for this sink model. */ - string getKind() { result = kind } - - /** Gets the provenance for this sink model. */ - string getProvenance() { result = provenance } - - /** Gets the number of instances of this sink model. */ - int getInstanceCount() { result = count(PotentialSinkModelExpr p | p.getSinkModel() = this) } - - /** Gets a string representation of this sink model. */ - string toString() { - result = - "SinkModel(" + package + ", " + type + ", " + subtypes + ", " + name + ", " + signature + ", " - + ext + ", " + input + ", " + kind + ", " + provenance + ")" - } - - /** Gets a string representation of this sink model as it would appear in a Models-as-Data file. */ - string getRepr() { - result = - "\"" + package + "\", \"" + type + "\", " + pyBool(subtypes) + ", \"" + name + "\", \"" + - signature + "\", \"" + ext + "\", \"" + input + "\", \"" + kind + "\", \"" + provenance + - "\"" - } -} - -/** An expression that may correspond to a sink model. */ -class PotentialSinkModelExpr extends Expr { - /** - * Holds if this expression has the given signature. The signature should contain enough - * information to determine a corresponding sink model, if one exists. - */ - pragma[nomagic] - predicate hasSignature( - string package, string type, boolean subtypes, string name, string signature, string input - ) { - exists(Call call, Callable callable, int argIdx | - call.getCallee().getSourceDeclaration() = callable and - ( - this = call.getArgument(argIdx) - or - this = call.getQualifier() and argIdx = -1 - ) and - (if argIdx = -1 then input = "Argument[this]" else input = "Argument[" + argIdx + "]") and - package = callable.getDeclaringType().getPackage().getName() and - type = callable.getDeclaringType().getErasure().(RefType).getNestedName() and - subtypes = considerSubtypes(callable) and - name = callable.getName() and - signature = ExternalFlow::paramsString(callable) - ) - } - - /** Gets a sink model that corresponds to this expression. */ - SinkModel getSinkModel() { - this.hasSignature(result.getPackage(), result.getType(), result.getSubtypes(), result.getName(), - result.getSignature(), result.getInput()) - } -} - -private string pyBool(boolean b) { - b = true and result = "True" - or - b = false and result = "False" -} - -/** - * Gets a string representation of the existing sink model at the expression `e`, in the format in - * which it would appear in a Models-as-Data file. Also restricts the provenance of the sink model - * to be `ai-generated`. - */ -string getSinkModelRepr(PotentialSinkModelExpr e) { - result = e.getSinkModel().getRepr() and - e.getSinkModel().getProvenance() = "ai-generated" -} - -/** - * Gets the string representation of a sink model in a format suitable for appending to an alert - * message. - */ -string getSinkModelQueryRepr(PotentialSinkModelExpr e) { - result = "\nsinkModel: " + getSinkModelRepr(e) -} - -/** - * A parameterised module that takes a dataflow config, and exposes a predicate for counting the - * number of AI-generated sink models that appear in alerts for that query. - */ -private module SinkTallier { - module ConfigFlow = TaintTracking::Global; - - predicate getSinkModelCount(int c, SinkModel s) { - s = any(ConfigFlow::PathNode sink).getNode().asExpr().(PotentialSinkModelExpr).getSinkModel() and - c = - strictcount(ConfigFlow::PathNode sink | - ConfigFlow::flowPath(_, sink) and - s = sink.getNode().asExpr().(PotentialSinkModelExpr).getSinkModel() - ) - } -} - -predicate sinkModelTallyPerQuery(string queryName, int alertCount, SinkModel sinkModel) { - queryName = "java/request-forgery" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) - or - queryName = "java/command-line-injection" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) - or - queryName = "java/concatenated-sql-query" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) - or - queryName = "java/ssrf" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) - or - queryName = "java/path-injection" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) - or - queryName = "java/unvalidated-url-redirection" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) - or - queryName = "java/sql-injection" and - SinkTallier::getSinkModelCount(alertCount, sinkModel) -} - -predicate sinkModelTally(int alertCount, SinkModel sinkModel) { - sinkModelTallyPerQuery(_, _, sinkModel) and - alertCount = sum(int c | sinkModelTallyPerQuery(_, c, sinkModel)) -} diff --git a/java/ql/automodel/src/AutomodelAlertSinks.ql b/java/ql/automodel/src/AutomodelAlertSinks.ql deleted file mode 100644 index e9af51b4d637..000000000000 --- a/java/ql/automodel/src/AutomodelAlertSinks.ql +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @name Number of alerts per sink model - * @description Counts the number of alerts using `ai-generated` sink models. - * @kind table - * @id java/ml/metrics-count-alerts-per-sink-model - * @tags internal automodel metrics - */ - -private import java -private import AutomodelAlertSinkUtil - -from int alertCount, SinkModel s -where sinkModelTally(alertCount, s) and s.getProvenance() = "ai-generated" -select alertCount, s.getPackage() as package, s.getType() as type, s.getSubtypes() as subtypes, - s.getName() as name, s.getSignature() as signature, s.getInput() as input, s.getExt() as ext, - s.getKind() as kind, s.getProvenance() as provenance order by alertCount desc diff --git a/java/ql/automodel/src/AutomodelAlertSinksPerQuery.ql b/java/ql/automodel/src/AutomodelAlertSinksPerQuery.ql deleted file mode 100644 index 64a5038d1166..000000000000 --- a/java/ql/automodel/src/AutomodelAlertSinksPerQuery.ql +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @name Number of alerts per sink model and query - * @description Counts the number of alerts per query using `ai-generated` sink models. - * @kind table - * @id java/ml/metrics-count-alerts-per-sink-model-and-query - * @tags internal automodel metrics - */ - -private import java -private import AutomodelAlertSinkUtil - -from string queryId, int alertCount, SinkModel s -where - sinkModelTallyPerQuery(queryId, alertCount, s) and - s.getProvenance() = "ai-generated" -select queryId, alertCount, s.getPackage() as package, s.getType() as type, - s.getSubtypes() as subtypes, s.getName() as name, s.getSignature() as signature, - s.getInput() as input, s.getExt() as ext, s.getKind() as kind, s.getProvenance() as provenance - order by queryId, alertCount desc diff --git a/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll b/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll deleted file mode 100644 index 750d776891f3..000000000000 --- a/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll +++ /dev/null @@ -1,677 +0,0 @@ -/** - * For internal use only. - */ - -private import java -private import semmle.code.Location as Location -private import semmle.code.java.dataflow.DataFlow -private import semmle.code.java.dataflow.TaintTracking -private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow -private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl -private import semmle.code.java.security.ExternalAPIs as ExternalAPIs -private import semmle.code.java.Expr as Expr -private import semmle.code.java.security.QueryInjection -private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions -private import AutomodelJavaUtil as AutomodelJavaUtil -private import semmle.code.java.security.PathSanitizer as PathSanitizer -import AutomodelSharedCharacteristics as SharedCharacteristics -import AutomodelEndpointTypes as AutomodelEndpointTypes - -newtype JavaRelatedLocationType = - CallContext() or - MethodDoc() or - ClassDoc() - -newtype TApplicationModeEndpoint = - TExplicitArgument(Call call, DataFlow::Node arg) { - AutomodelJavaUtil::isFromSource(call) and - exists(Argument argExpr | - arg.asExpr() = argExpr and call = argExpr.getCall() and not argExpr.isVararg() - ) and - not AutomodelJavaUtil::isUnexploitableType(arg.getType()) - } or - TInstanceArgument(Call call, DataFlow::Node arg) { - AutomodelJavaUtil::isFromSource(call) and - arg = DataFlow::getInstanceArgument(call) and - not call instanceof ConstructorCall and - not AutomodelJavaUtil::isUnexploitableType(arg.getType()) - } or - TImplicitVarargsArray(Call call, DataFlow::ImplicitVarargsArray arg, int idx) { - AutomodelJavaUtil::isFromSource(call) and - call = arg.getCall() and - idx = call.getCallee().getVaragsParameterIndex() and - not AutomodelJavaUtil::isUnexploitableType(arg.getType()) - } or - TMethodReturnValue(MethodCall call) { - AutomodelJavaUtil::isFromSource(call) and - not AutomodelJavaUtil::isUnexploitableType(call.getType()) - } or - TOverriddenParameter(Parameter p, Method overriddenMethod) { - AutomodelJavaUtil::isFromSource(p) and - p.getCallable().(Method).overrides(overriddenMethod) - } - -/** - * An endpoint is a node that is a candidate for modeling. - */ -abstract private class ApplicationModeEndpoint extends TApplicationModeEndpoint { - /** - * Gets the callable to be modeled that this endpoint represents. - */ - abstract Callable getCallable(); - - /** - * Gets the input (if any) for this endpoint, eg.: `Argument[0]`. - * - * For endpoints that are source candidates, this will be `none()`. - */ - abstract string getMaDInput(); - - /** - * Gets the output (if any) for this endpoint, eg.: `ReturnValue`. - * - * For endpoints that are sink candidates, this will be `none()`. - */ - abstract string getMaDOutput(); - - abstract Top asTop(); - - /** - * Converts the endpoint to a node that can be used in a data flow graph. - */ - abstract DataFlow::Node asNode(); - - string getExtensibleType() { - if not exists(this.getMaDInput()) and exists(this.getMaDOutput()) - then result = "sourceModel" - else - if exists(this.getMaDInput()) and not exists(this.getMaDOutput()) - then result = "sinkModel" - else none() // if both exist, it would be a summaryModel (not yet supported) - } - - abstract string toString(); -} - -class TCallArgument = TExplicitArgument or TInstanceArgument or TImplicitVarargsArray; - -/** - * An endpoint that represents an "argument" to a call in a broad sense, including - * both explicit arguments and the instance argument. - */ -abstract class CallArgument extends ApplicationModeEndpoint, TCallArgument { - Call call; - DataFlow::Node arg; - - override Callable getCallable() { result = call.getCallee().getSourceDeclaration() } - - override string getMaDOutput() { none() } - - override DataFlow::Node asNode() { result = arg } - - Call getCall() { result = call } - - override string toString() { result = arg.toString() } -} - -/** - * An endpoint that represents an explicit argument to a call. - */ -class ExplicitArgument extends CallArgument, TExplicitArgument { - ExplicitArgument() { this = TExplicitArgument(call, arg) } - - private int getArgIndex() { this.asTop() = call.getArgument(result) } - - override string getMaDInput() { result = "Argument[" + this.getArgIndex() + "]" } - - override Top asTop() { result = arg.asExpr() } -} - -/** - * An endpoint that represents the instance argument to a call. - */ -class InstanceArgument extends CallArgument, TInstanceArgument { - InstanceArgument() { this = TInstanceArgument(call, arg) } - - override string getMaDInput() { result = "Argument[this]" } - - override Top asTop() { if exists(arg.asExpr()) then result = arg.asExpr() else result = call } - - override string toString() { result = arg.toString() } -} - -/** - * An endpoint that represents an implicit varargs array. - * We choose to represent the varargs array as a single endpoint, rather than as multiple endpoints. - * - * This avoids the problem of having to deal with redundant endpoints downstream. - * - * In order to be able to distinguish between varargs endpoints and regular endpoints, we export the `isVarargsArray` - * meta data field in the extraction queries. - */ -class ImplicitVarargsArray extends CallArgument, TImplicitVarargsArray { - int idx; - - ImplicitVarargsArray() { this = TImplicitVarargsArray(call, arg, idx) } - - override string getMaDInput() { result = "Argument[" + idx + "]" } - - override Top asTop() { result = call } -} - -/** - * An endpoint that represents a method call. The `ReturnValue` of a method call - * may be a source. - */ -class MethodReturnValue extends ApplicationModeEndpoint, TMethodReturnValue { - MethodCall call; - - MethodReturnValue() { this = TMethodReturnValue(call) } - - override Callable getCallable() { result = call.getCallee().getSourceDeclaration() } - - override string getMaDInput() { none() } - - override string getMaDOutput() { result = "ReturnValue" } - - override Top asTop() { result = call } - - override DataFlow::Node asNode() { result.asExpr() = call } - - override string toString() { result = call.toString() } -} - -/** - * An endpoint that represents a parameter of an overridden method that may be - * a source. - */ -class OverriddenParameter extends ApplicationModeEndpoint, TOverriddenParameter { - Parameter p; - Method overriddenMethod; - - OverriddenParameter() { this = TOverriddenParameter(p, overriddenMethod) } - - override Callable getCallable() { - // NB: we're returning the overridden callable here. This means that the - // candidate model will be about the overridden method, not the overriding - // method. This is a more general model, that also applies to other - // subclasses of the overridden class. - result = overriddenMethod.getSourceDeclaration() - } - - private int getArgIndex() { p.getCallable().getParameter(result) = p } - - override string getMaDInput() { none() } - - override string getMaDOutput() { result = "Parameter[" + this.getArgIndex() + "]" } - - override Top asTop() { result = p } - - override DataFlow::Node asNode() { result.(DataFlow::ParameterNode).asParameter() = p } - - override string toString() { result = p.toString() } -} - -/** - * A candidates implementation. - * - * Some important notes: - * - This mode is using arguments as endpoints. - * - We use the `CallContext` (the surrounding call expression) as related location. - */ -module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig { - // for documentation of the implementations here, see the QLDoc in the CandidateSig signature module. - class Endpoint = ApplicationModeEndpoint; - - class EndpointType = AutomodelEndpointTypes::EndpointType; - - class SinkType = AutomodelEndpointTypes::SinkType; - - class SourceType = AutomodelEndpointTypes::SourceType; - - class RelatedLocation = Location::Top; - - class RelatedLocationType = JavaRelatedLocationType; - - // Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact. - predicate isSanitizer(Endpoint e, EndpointType t) { - exists(t) and - AutomodelJavaUtil::isUnexploitableType([ - // for most endpoints, we can get the type from the node - e.asNode().getType(), - // but not for calls to void methods, where we need to go via the AST - e.asTop().(Expr).getType() - ]) - or - t instanceof AutomodelEndpointTypes::PathInjectionSinkType and - e.asNode() instanceof PathSanitizer::PathInjectionSanitizer - } - - RelatedLocation asLocation(Endpoint e) { result = e.asTop() } - - predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2; - - predicate isSink(Endpoint e, string kind, string provenance) { - exists( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input - | - sinkSpec(e, package, type, subtypes, name, signature, ext, input) and - ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind, - provenance, _) - ) - or - isCustomSink(e, kind) and provenance = "custom-sink" - } - - predicate isSource(Endpoint e, string kind, string provenance) { - exists( - string package, string type, boolean subtypes, string name, string signature, string ext, - string output - | - sourceSpec(e, package, type, subtypes, name, signature, ext, output) and - ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind, - provenance, _) - ) - } - - predicate isNeutral(Endpoint e) { - exists(string package, string type, string name, string signature, string endpointType | - sinkSpec(e, package, type, _, name, signature, _, _) and - endpointType = "sink" - or - sourceSpec(e, package, type, _, name, signature, _, _) and - endpointType = "source" - | - ExternalFlow::neutralModel(package, type, name, [signature, ""], endpointType, _) - ) - } - - /** - * Holds if the endpoint concerns a callable with the given package, type, name and signature. - * - * If `subtypes` is `false`, only the exact callable is considered. If `true`, the callable and - * all its overrides are considered. - */ - additional predicate endpointCallable( - Endpoint e, string package, string type, boolean subtypes, string name, string signature - ) { - exists(Callable c | - c = e.getCallable() and subtypes in [true, false] - or - e.getCallable().(Method).getSourceDeclaration().overrides+(c) and subtypes = true - | - c.hasQualifiedName(package, type, name) and - signature = ExternalFlow::paramsString(c) - ) - } - - additional predicate sinkSpec( - Endpoint e, string package, string type, boolean subtypes, string name, string signature, - string ext, string input - ) { - endpointCallable(e, package, type, subtypes, name, signature) and - ext = "" and - input = e.getMaDInput() - } - - additional predicate sourceSpec( - Endpoint e, string package, string type, boolean subtypes, string name, string signature, - string ext, string output - ) { - endpointCallable(e, package, type, subtypes, name, signature) and - ext = "" and - output = e.getMaDOutput() - } - - /** - * Gets the related location for the given endpoint. - * - * The only related location we model is the the call expression surrounding to - * which the endpoint is either argument or qualifier (known as the call context). - */ - RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) { - type = CallContext() and - result = e.(CallArgument).getCall() - or - type = MethodDoc() and - result = e.getCallable().(Documentable).getJavadoc() - or - type = ClassDoc() and - result = e.getCallable().getDeclaringType().(Documentable).getJavadoc() - } -} - -/** - * Contains endpoints that are defined in QL code rather than as a MaD model. Ideally this predicate - * should be empty. - */ -private predicate isCustomSink(Endpoint e, string kind) { - e.asNode() instanceof QueryInjectionSink and kind = "sql" -} - -module CharacteristicsImpl = - SharedCharacteristics::SharedCharacteristics; - -class EndpointCharacteristic = CharacteristicsImpl::EndpointCharacteristic; - -class Endpoint = ApplicationCandidatesImpl::Endpoint; - -/* - * Predicates that are used to surface prompt examples and candidates for classification with an ML model. - */ - -/** - * A MetadataExtractor that extracts metadata for application mode. - */ -class ApplicationModeMetadataExtractor extends string { - ApplicationModeMetadataExtractor() { this = "ApplicationModeMetadataExtractor" } - - predicate hasMetadata( - Endpoint e, string package, string type, string subtypes, string name, string signature, - string input, string output, string isVarargsArray, string alreadyAiModeled, - string extensibleType - ) { - exists(Callable callable | e.getCallable() = callable | - (if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and - (if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and - package = callable.getDeclaringType().getPackage().getName() and - // we're using the erased types because the MaD convention is to not specify type parameters. - // Whether something is or isn't a sink doesn't usually depend on the type parameters. - type = callable.getDeclaringType().getErasure().(RefType).getNestedName() and - subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and - name = callable.getName() and - signature = ExternalFlow::paramsString(callable) and - ( - if e instanceof ImplicitVarargsArray - then isVarargsArray = "true" - else isVarargsArray = "false" - ) and - extensibleType = e.getExtensibleType() - ) and - ( - not CharacteristicsImpl::isModeled(e, _, extensibleType, _) and alreadyAiModeled = "" - or - CharacteristicsImpl::isModeled(e, _, extensibleType, alreadyAiModeled) - ) - } -} - -/** - * Holds if the given `endpoint` should be considered a candidate for the `extensibleType`. - * - * The other parameters record various other properties of interest. - */ -predicate isCandidate( - Endpoint endpoint, string package, string type, string subtypes, string name, string signature, - string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled -) { - CharacteristicsImpl::isCandidate(endpoint, _) and - not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | - u.appliesToEndpoint(endpoint) - ) and - any(ApplicationModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargs, - alreadyAiModeled, extensibleType) and - // If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a - // candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's - // already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We - // assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink - // types, and we don't need to reexamine it. - alreadyAiModeled.matches(["", "%ai-%"]) and - AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature) -} - -/** - * Holds if the given `endpoint` is a negative example for the `extensibleType` - * because of the `characteristic`. - * - * The other parameters record various other properties of interest. - */ -predicate isNegativeExample( - Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package, - string type, string subtypes, string name, string signature, string input, string output, - string isVarargsArray, string extensibleType -) { - characteristic.appliesToEndpoint(endpoint) and - // the node is known not to be an endpoint of any appropriate type - forall(AutomodelEndpointTypes::EndpointType tp | - tp = CharacteristicsImpl::getAPotentialType(endpoint) - | - characteristic.hasImplications(tp, false, _) - ) and - // the lowest confidence across all endpoint types should be at least highConfidence - confidence = - min(float c | - characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c) - ) and - confidence >= SharedCharacteristics::highConfidence() and - any(ApplicationModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, - isVarargsArray, _, extensibleType) and - // It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes - // as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here. - not exists(EndpointCharacteristic characteristic2, float confidence2 | - characteristic2 != characteristic - | - characteristic2.appliesToEndpoint(endpoint) and - confidence2 >= SharedCharacteristics::maximalConfidence() and - characteristic2 - .hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2) - ) -} - -/** - * Holds if the given `endpoint` is a positive example for the `endpointType`. - * - * The other parameters record various other properties of interest. - */ -predicate isPositiveExample( - Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name, - string signature, string input, string output, string isVarargsArray, string extensibleType -) { - any(ApplicationModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, - isVarargsArray, _, extensibleType) and - CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) and - exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext())) -} - -/* - * EndpointCharacteristic classes that are specific to Automodel for Java. - */ - -/** - * A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks. - * - * A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return - * type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does - * the dangerous/interesting thing, so we want the latter to be modeled as the sink. - * - * TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks - */ -private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic { - UnexploitableIsCharacteristic() { this = "argument of is-style boolean method" } - - override predicate appliesToEndpoint(Endpoint e) { - e.getCallable().getName().matches("is%") and - e.getCallable().getReturnType() instanceof BooleanType and - not ApplicationCandidatesImpl::isSink(e, _, _) - } -} - -/** - * A negative characteristic that indicates that parameters of an existence-checking boolean method should not be - * considered sinks. - * - * A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a - * boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the - * dangerous/interesting thing, so we want the latter to be modeled as the sink. - */ -private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic { - UnexploitableExistsCharacteristic() { this = "argument of existence-checking boolean method" } - - override predicate appliesToEndpoint(Endpoint e) { - exists(Callable callable | callable = e.getCallable() | - callable.getName().toLowerCase() = ["exists", "notexists"] and - callable.getReturnType() instanceof BooleanType - ) - } -} - -/** - * A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks, - * and its return value should not be considered a source. - */ -private class ExceptionCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic -{ - ExceptionCharacteristic() { this = "argument/result of exception-related method" } - - override predicate appliesToEndpoint(Endpoint e) { - e.getCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable and - ( - e.getExtensibleType() = "sinkModel" and - not ApplicationCandidatesImpl::isSink(e, _, _) - or - e.getExtensibleType() = "sourceModel" and - not ApplicationCandidatesImpl::isSource(e, _, _) and - e.getMaDOutput() = "ReturnValue" - ) - } -} - -/** - * A negative characteristic that indicates that an endpoint is a MaD taint step. MaD modeled taint steps are global, - * so they are not sinks for any query. Non-MaD taint steps might be specific to a particular query, so we don't - * filter those out. - */ -private class IsMaDTaintStepCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic { - IsMaDTaintStepCharacteristic() { this = "taint step" } - - override predicate appliesToEndpoint(Endpoint e) { - FlowSummaryImpl::Private::Steps::summaryThroughStepValue(e.asNode(), _, _) - or - FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(e.asNode(), _, _) - or - FlowSummaryImpl::Private::Steps::summaryGetterStep(e.asNode(), _, _, _) - or - FlowSummaryImpl::Private::Steps::summarySetterStep(e.asNode(), _, _, _) - } -} - -/** - * A call to a method that's known locally will not be considered as a candidate to model. - * - * The reason is that we would expect data/taint flow into the method implementation to uncover - * any sinks that are present there. - */ -private class LocalCall extends CharacteristicsImpl::UninterestingToModelCharacteristic { - LocalCall() { this = "local call" } - - override predicate appliesToEndpoint(Endpoint e) { - e.(CallArgument).getCallable().fromSource() - or - e.(MethodReturnValue).getCallable().fromSource() - } -} - -/** - * A characteristic that marks endpoints as uninteresting to model, according to the Java ModelExclusions module. - */ -private class ExcludedFromModeling extends CharacteristicsImpl::UninterestingToModelCharacteristic { - ExcludedFromModeling() { this = "excluded from modeling" } - - override predicate appliesToEndpoint(Endpoint e) { - ModelExclusions::isUninterestingForModels(e.getCallable()) - } -} - -/** - * A negative characteristic that filters out non-public methods. Non-public methods are not interesting to include in - * the standard Java modeling, because they cannot be called from outside the package. - */ -private class NonPublicMethodCharacteristic extends CharacteristicsImpl::UninterestingToModelCharacteristic -{ - NonPublicMethodCharacteristic() { this = "non-public method" } - - override predicate appliesToEndpoint(Endpoint e) { - exists(Callable c | c = e.getCallable() | not c.isPublic()) - } -} - -/** - * A negative characteristic that indicates that an endpoint is a non-sink argument to a method whose sinks have already - * been modeled _manually_. This is restricted to manual sinks only, because only during the manual process do we have - * the expectation that all sinks present in a method have been considered. - * - * WARNING: These endpoints should not be used as negative samples for training, because some sinks may have been missed - * when the method was modeled. Specifically, as we start using ATM to merge in new declarations, we can be less sure - * that a method with one argument modeled as a MaD sink has also had its remaining arguments manually reviewed. The - * ML model might have predicted argument 0 of some method to be a sink but not argument 1, when in fact argument 1 is - * also a sink. - */ -private class OtherArgumentToModeledMethodCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic -{ - OtherArgumentToModeledMethodCharacteristic() { - this = "other argument to a method that has already been modeled manually" - } - - override predicate appliesToEndpoint(Endpoint e) { - not ApplicationCandidatesImpl::isSink(e, _, _) and - exists(CallArgument otherSink | - ApplicationCandidatesImpl::isSink(otherSink, _, "manual") and - e.(CallArgument).getCall() = otherSink.getCall() and - e != otherSink - ) - } -} - -/** - * Holds if the type of the given expression is annotated with `@FunctionalInterface`. - */ -predicate hasFunctionalInterfaceType(Expr e) { - exists(RefType tp | tp = e.getType().getErasure() | - tp.getAnAssociatedAnnotation().getType().hasQualifiedName("java.lang", "FunctionalInterface") - ) -} - -/** - * A characteristic that marks functional expression as likely not sinks. - * - * These expressions may well _contain_ sinks, but rarely are sinks themselves. - */ -private class FunctionValueCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic { - FunctionValueCharacteristic() { this = "function value" } - - override predicate appliesToEndpoint(Endpoint e) { - exists(Expr expr | expr = e.asNode().asExpr() | - expr instanceof FunctionalExpr or hasFunctionalInterfaceType(expr) - ) - } -} - -/** - * A negative characteristic that indicates that an endpoint is not a `to` node for any known taint step. Such a node - * cannot be tainted, because taint can't flow into it. - * - * WARNING: These endpoints should not be used as negative samples for training, because they may include sinks for - * which our taint tracking modeling is incomplete. - */ -private class CannotBeTaintedCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic -{ - CannotBeTaintedCharacteristic() { this = "cannot be tainted" } - - override predicate appliesToEndpoint(Endpoint e) { not this.isKnownOutNodeForStep(e) } - - /** - * Holds if the node `n` is known as the predecessor in a modeled flow step. - */ - private predicate isKnownOutNodeForStep(Endpoint e) { - e.asNode().asExpr() instanceof Call or // we just assume flow in that case - TaintTracking::localTaintStep(_, e.asNode()) or - FlowSummaryImpl::Private::Steps::summaryThroughStepValue(_, e.asNode(), _) or - FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(_, e.asNode(), _) or - FlowSummaryImpl::Private::Steps::summaryGetterStep(_, _, e.asNode(), _) or - FlowSummaryImpl::Private::Steps::summarySetterStep(_, _, e.asNode(), _) - } -} diff --git a/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql deleted file mode 100644 index a3fa8b9b46fa..000000000000 --- a/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Surfaces the endpoints that are not already known to be sinks, and are therefore used as candidates for - * classification with an ML model. - * - * Note: This query does not actually classify the endpoints using the model. - * - * @name Automodel candidates (application mode) - * @description A query to extract automodel candidates in application mode. - * @kind problem - * @problem.severity recommendation - * @id java/ml/extract-automodel-application-candidates - * @tags internal extract automodel application-mode candidates - */ - -import java -private import AutomodelApplicationModeCharacteristics -private import AutomodelJavaUtil - -/** - * Gets a sample of endpoints (of at most `limit` samples) with the given method signature. - * - * The main purpose of this helper predicate is to avoid selecting too many candidates, as this may - * cause the SARIF file to exceed the maximum size limit. - */ -bindingset[limit] -private Endpoint getSampleForSignature( - int limit, string package, string type, string subtypes, string name, string signature, - string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled -) { - exists(int n, int num_endpoints, ApplicationModeMetadataExtractor meta | - num_endpoints = - count(Endpoint e | - meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs, - alreadyAiModeled, extensibleType) - ) - | - result = - rank[n](Endpoint e, Location loc | - loc = e.asTop().getLocation() and - meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs, - alreadyAiModeled, extensibleType) - | - e - order by - loc.getFile().getAbsolutePath(), loc.getStartLine(), loc.getStartColumn(), - loc.getEndLine(), loc.getEndColumn() - ) and - // To avoid selecting samples that are too close together (as the ranking above goes by file - // path first), we select `limit` evenly spaced samples from the ranked list of endpoints. By - // default this would always include the first sample, so we add a random-chosen prime offset - // to the first sample index, and reduce modulo the number of endpoints. - // Finally, we add 1 to the result, as ranking results in a 1-indexed relation. - n = 1 + (([0 .. limit - 1] * (num_endpoints / limit).floor() + 46337) % num_endpoints) - ) -} - -from - Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes, - DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output, - DollarAtString isVarargsArray, DollarAtString alreadyAiModeled, DollarAtString extensibleType -where - isCandidate(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray, - extensibleType, alreadyAiModeled) and - endpoint = - getSampleForSignature(9, package, type, subtypes, name, signature, input, output, - isVarargsArray, extensibleType, alreadyAiModeled) -select endpoint.asNode(), - "Related locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // - package, "package", // - type, "type", // - subtypes, "subtypes", // - name, "name", // method name - signature, "signature", // - input, "input", // - output, "output", // - isVarargsArray, "isVarargsArray", // - alreadyAiModeled, "alreadyAiModeled", // - extensibleType, "extensibleType" diff --git a/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql deleted file mode 100644 index a399c413fa4a..000000000000 --- a/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Surfaces endpoints that are non-sinks with high confidence, for use as negative examples in the prompt. - * - * @name Negative examples (application mode) - * @kind problem - * @problem.severity recommendation - * @id java/ml/extract-automodel-application-negative-examples - * @tags internal extract automodel application-mode negative examples - */ - -private import java -private import AutomodelApplicationModeCharacteristics -private import AutomodelEndpointTypes -private import AutomodelJavaUtil - -/** - * Gets a sample of endpoints (of at most `limit` samples) for which the given characteristic applies. - * - * The main purpose of this helper predicate is to avoid selecting too many samples, as this may - * cause the SARIF file to exceed the maximum size limit. - */ -bindingset[limit] -Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) { - exists(int n, int num_endpoints | num_endpoints = count(Endpoint e | c.appliesToEndpoint(e)) | - result = - rank[n](Endpoint e, Location loc | - loc = e.asTop().getLocation() and c.appliesToEndpoint(e) - | - e - order by - loc.getFile().getAbsolutePath(), loc.getStartLine(), loc.getStartColumn(), - loc.getEndLine(), loc.getEndColumn() - ) and - // To avoid selecting samples that are too close together (as the ranking above goes by file - // path first), we select `limit` evenly spaced samples from the ranked list of endpoints. By - // default this would always include the first sample, so we add a random-chosen prime offset - // to the first sample index, and reduce modulo the number of endpoints. - // Finally, we add 1 to the result, as ranking results in a 1-indexed relation. - n = 1 + (([0 .. limit - 1] * (num_endpoints / limit).floor() + 46337) % num_endpoints) - ) -} - -from - Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message, - DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, - DollarAtString signature, DollarAtString input, DollarAtString output, - DollarAtString isVarargsArray, DollarAtString extensibleType -where - endpoint = getSampleForCharacteristic(characteristic, 100) and - isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature, - input, output, isVarargsArray, extensibleType) and - message = characteristic -select endpoint.asNode(), - message + "\nrelated locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // - package, "package", // - type, "type", // - subtypes, "subtypes", // - name, "name", // - signature, "signature", // - input, "input", // - output, "output", // - isVarargsArray, "isVarargsArray", // - extensibleType, "extensibleType" diff --git a/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql b/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql deleted file mode 100644 index faf49b73fc14..000000000000 --- a/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Surfaces endpoints that are sinks with high confidence, for use as positive examples in the prompt. - * - * @name Positive examples (application mode) - * @kind problem - * @problem.severity recommendation - * @id java/ml/extract-automodel-application-positive-examples - * @tags internal extract automodel application-mode positive examples - */ - -private import AutomodelApplicationModeCharacteristics -private import AutomodelEndpointTypes -private import AutomodelJavaUtil - -from - Endpoint endpoint, EndpointType endpointType, ApplicationModeMetadataExtractor meta, - DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, - DollarAtString signature, DollarAtString input, DollarAtString output, - DollarAtString isVarargsArray, DollarAtString extensibleType -where - isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output, - isVarargsArray, extensibleType) -select endpoint.asNode(), - endpointType + "\nrelated locations: $@, $@, $@." + - "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // - package, "package", // - type, "type", // - subtypes, "subtypes", // - name, "name", // - signature, "signature", // - input, "input", // - output, "output", // - isVarargsArray, "isVarargsArray", // - extensibleType, "extensibleType" diff --git a/java/ql/automodel/src/AutomodelCandidateFilter.yml b/java/ql/automodel/src/AutomodelCandidateFilter.yml deleted file mode 100644 index c945ae3206fe..000000000000 --- a/java/ql/automodel/src/AutomodelCandidateFilter.yml +++ /dev/null @@ -1,5 +0,0 @@ -extensions: - - addsTo: - pack: codeql/java-automodel-queries - extensible: automodelCandidateFilter - data: [] diff --git a/java/ql/automodel/src/AutomodelCountGeneratedSinks.ql b/java/ql/automodel/src/AutomodelCountGeneratedSinks.ql deleted file mode 100644 index 475e3753810b..000000000000 --- a/java/ql/automodel/src/AutomodelCountGeneratedSinks.ql +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @name Number of instances of each sink model - * @description Counts the number of instances of `ai-generated` sink models. - * @kind table - * @id java/ml/metrics-count-instances-per-sink-model - * @tags internal automodel metrics - */ - -private import java -private import AutomodelAlertSinkUtil - -from int instanceCount, SinkModel s -where - instanceCount = s.getInstanceCount() and - instanceCount > 0 and - s.getProvenance() = "ai-generated" -select instanceCount, s.getPackage() as package, s.getType() as type, s.getSubtypes() as subtypes, - s.getName() as name, s.getSignature() as signature, s.getInput() as input, s.getExt() as ext, - s.getKind() as kind, s.getProvenance() as provenance order by instanceCount desc diff --git a/java/ql/automodel/src/AutomodelEndpointTypes.qll b/java/ql/automodel/src/AutomodelEndpointTypes.qll deleted file mode 100644 index f4f7bc8eb7b0..000000000000 --- a/java/ql/automodel/src/AutomodelEndpointTypes.qll +++ /dev/null @@ -1,82 +0,0 @@ -/** - * For internal use only. - * - * Defines the set of classes that endpoint scoring models can predict. Endpoint scoring models must - * only predict classes defined within this file. This file is the source of truth for the integer - * representation of each of these classes. - */ - -/** A class that can be predicted by a classifier. */ -abstract class EndpointType extends string { - /** - * Holds when the string matches the name of the sink / source type. - */ - bindingset[this] - EndpointType() { any() } - - /** - * Gets the name of the sink/source kind for this endpoint type as used in models-as-data. - * - * See https://github.com/github/codeql/blob/44213f0144fdd54bb679ca48d68b28dcf820f7a8/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll#LL353C11-L357C31 - * for sink types, and https://github.com/github/codeql/blob/44213f0144fdd54bb679ca48d68b28dcf820f7a8/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll#L365 - * for source types. - */ - final string getKind() { result = this } -} - -/** A class for sink types that can be predicted by a classifier. */ -abstract class SinkType extends EndpointType { - bindingset[this] - SinkType() { any() } -} - -/** A sink relevant to the SQL injection query */ -class SqlInjectionSinkType extends SinkType { - SqlInjectionSinkType() { this = "sql-injection" } -} - -/** A sink relevant to the tainted path injection query. */ -class PathInjectionSinkType extends SinkType { - PathInjectionSinkType() { this = "path-injection" } -} - -/** A sink relevant to the SSRF query. */ -class RequestForgerySinkType extends SinkType { - RequestForgerySinkType() { this = "request-forgery" } -} - -/** A sink relevant to the command injection query. */ -class CommandInjectionSinkType extends SinkType { - CommandInjectionSinkType() { this = "command-injection" } -} - -/** A sink relevant to file storage. */ -class FileContentStoreSinkType extends SinkType { - FileContentStoreSinkType() { this = "file-content-store" } -} - -/** A sink relevant to HTML injection. */ -class HtmlInjectionSinkType extends SinkType { - HtmlInjectionSinkType() { this = "html-injection" } -} - -/** A sink relevant to LDAP injection. */ -class LdapInjectionSinkType extends SinkType { - LdapInjectionSinkType() { this = "ldap-injection" } -} - -/** A sink relevant to URL redirection. */ -class UrlRedirectionSinkType extends SinkType { - UrlRedirectionSinkType() { this = "url-redirection" } -} - -/** A class for source types that can be predicted by a classifier. */ -abstract class SourceType extends EndpointType { - bindingset[this] - SourceType() { any() } -} - -/** A source of remote data. */ -class RemoteSourceType extends SourceType { - RemoteSourceType() { this = "remote" } -} diff --git a/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll b/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll deleted file mode 100644 index 7f385a41d1ea..000000000000 --- a/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll +++ /dev/null @@ -1,507 +0,0 @@ -/** - * For internal use only. - */ - -private import java -private import semmle.code.Location as Location -private import semmle.code.java.dataflow.DataFlow -private import semmle.code.java.dataflow.TaintTracking -private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow -private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl -private import semmle.code.java.security.ExternalAPIs as ExternalAPIs -private import semmle.code.java.Expr as Expr -private import semmle.code.java.security.QueryInjection -private import semmle.code.java.security.RequestForgery -private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions -private import AutomodelJavaUtil as AutomodelJavaUtil -import AutomodelSharedCharacteristics as SharedCharacteristics -import AutomodelEndpointTypes as AutomodelEndpointTypes - -newtype JavaRelatedLocationType = - MethodDoc() or - ClassDoc() - -newtype TFrameworkModeEndpoint = - TExplicitParameter(Parameter p) { - AutomodelJavaUtil::isFromSource(p) and - not AutomodelJavaUtil::isUnexploitableType(p.getType()) - } or - TQualifier(Callable c) { AutomodelJavaUtil::isFromSource(c) and not c instanceof Constructor } or - TReturnValue(Callable c) { - AutomodelJavaUtil::isFromSource(c) and - c instanceof Constructor - or - AutomodelJavaUtil::isFromSource(c) and - c instanceof Method and - not AutomodelJavaUtil::isUnexploitableType(c.getReturnType()) - } or - TOverridableParameter(Method m, Parameter p) { - AutomodelJavaUtil::isFromSource(p) and - not AutomodelJavaUtil::isUnexploitableType(p.getType()) and - p.getCallable() = m and - m instanceof ModelExclusions::ModelApi and - AutomodelJavaUtil::isOverridable(m) - } or - TOverridableQualifier(Method m) { - AutomodelJavaUtil::isFromSource(m) and - m instanceof ModelExclusions::ModelApi and - AutomodelJavaUtil::isOverridable(m) - } - -/** - * A framework mode endpoint. - */ -abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint { - /** - * Gets the input (if any) for this endpoint, eg.: `Argument[0]`. - * - * For endpoints that are source candidates, this will be `none()`. - */ - abstract string getMaDInput(); - - /** - * Gets the output (if any) for this endpoint, eg.: `ReturnValue`. - * - * For endpoints that are sink candidates, this will be `none()`. - */ - abstract string getMaDOutput(); - - /** - * Returns the name of the parameter of the endpoint. - */ - abstract string getParamName(); - - /** - * Returns the callable that contains the endpoint. - */ - abstract Callable getCallable(); - - abstract Top asTop(); - - abstract string getExtensibleType(); - - string toString() { result = this.asTop().toString() } - - Location getLocation() { result = this.asTop().getLocation() } -} - -class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParameter { - Parameter param; - - ExplicitParameterEndpoint() { this = TExplicitParameter(param) and param.fromSource() } - - override string getMaDInput() { result = "Argument[" + param.getPosition() + "]" } - - override string getMaDOutput() { none() } - - override string getParamName() { result = param.getName() } - - override Callable getCallable() { result = param.getCallable() } - - override Top asTop() { result = param } - - override string getExtensibleType() { result = "sinkModel" } -} - -class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier { - Callable callable; - - QualifierEndpoint() { - this = TQualifier(callable) and not callable.isStatic() and callable.fromSource() - } - - override string getMaDInput() { result = "Argument[this]" } - - override string getMaDOutput() { none() } - - override string getParamName() { result = "this" } - - override Callable getCallable() { result = callable } - - override Top asTop() { result = callable } - - override string getExtensibleType() { result = "sinkModel" } -} - -class ReturnValue extends FrameworkModeEndpoint, TReturnValue { - Callable callable; - - ReturnValue() { this = TReturnValue(callable) and callable.fromSource() } - - override string getMaDInput() { none() } - - override string getMaDOutput() { result = "ReturnValue" } - - override string getParamName() { none() } - - override Callable getCallable() { result = callable } - - override Top asTop() { result = callable } - - override string getExtensibleType() { result = "sourceModel" } -} - -class OverridableParameter extends FrameworkModeEndpoint, TOverridableParameter { - Method method; - Parameter param; - - OverridableParameter() { this = TOverridableParameter(method, param) } - - override string getMaDInput() { none() } - - override string getMaDOutput() { result = "Parameter[" + param.getPosition() + "]" } - - override string getParamName() { result = param.getName() } - - override Callable getCallable() { result = method } - - override Top asTop() { result = param } - - override string getExtensibleType() { result = "sourceModel" } -} - -class OverridableQualifier extends FrameworkModeEndpoint, TOverridableQualifier { - Method m; - - OverridableQualifier() { this = TOverridableQualifier(m) } - - override string getMaDInput() { none() } - - override string getMaDOutput() { result = "Parameter[this]" } - - override string getParamName() { result = "this" } - - override Callable getCallable() { result = m } - - override Top asTop() { result = m } - - override string getExtensibleType() { result = "sourceModel" } -} - -/** - * A candidates implementation for framework mode. - * - * Some important notes: - * - This mode is using parameters as endpoints. - * - Sink- and neutral-information is being used from MaD models. - * - When available, we use method- and class-java-docs as related locations. - */ -module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig { - // for documentation of the implementations here, see the QLDoc in the CandidateSig signature module. - class Endpoint = FrameworkModeEndpoint; - - class EndpointType = AutomodelEndpointTypes::EndpointType; - - class SinkType = AutomodelEndpointTypes::SinkType; - - class SourceType = AutomodelEndpointTypes::SourceType; - - class RelatedLocation = Location::Top; - - class RelatedLocationType = JavaRelatedLocationType; - - // Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact. - predicate isSanitizer(Endpoint e, EndpointType t) { none() } - - RelatedLocation asLocation(Endpoint e) { result = e.asTop() } - - predicate isKnownKind = AutomodelJavaUtil::isKnownKind/2; - - predicate isSink(Endpoint e, string kind, string provenance) { - exists( - string package, string type, boolean subtypes, string name, string signature, string ext, - string input - | - sinkSpec(e, package, type, subtypes, name, signature, ext, input) and - ExternalFlow::sinkModel(package, type, subtypes, name, [signature, ""], ext, input, kind, - provenance, _) - ) - } - - predicate isSource(Endpoint e, string kind, string provenance) { - exists( - string package, string type, boolean subtypes, string name, string signature, string ext, - string output - | - sourceSpec(e, package, type, subtypes, name, signature, ext, output) and - ExternalFlow::sourceModel(package, type, subtypes, name, [signature, ""], ext, output, kind, - provenance, _) - ) - } - - predicate isNeutral(Endpoint e) { - exists(string package, string type, string name, string signature, string endpointType | - sinkSpec(e, package, type, _, name, signature, _, _) and - endpointType = "sink" - or - sourceSpec(e, package, type, _, name, signature, _, _) and - endpointType = "source" - | - ExternalFlow::neutralModel(package, type, name, [signature, ""], endpointType, _) - ) - } - - /** - * Holds if the endpoint concerns a callable with the given package, type, name and signature. - * - * If `subtypes` is `false`, only the exact callable is considered. If `true`, the callable and - * all its overrides are considered. - */ - additional predicate endpointCallable( - Endpoint e, string package, string type, boolean subtypes, string name, string signature - ) { - exists(Callable c | - c = e.getCallable() and subtypes in [true, false] - or - e.getCallable().(Method).getSourceDeclaration().overrides+(c) and subtypes = true - | - c.hasQualifiedName(package, type, name) and - signature = ExternalFlow::paramsString(c) - ) - } - - additional predicate sinkSpec( - Endpoint e, string package, string type, boolean subtypes, string name, string signature, - string ext, string input - ) { - endpointCallable(e, package, type, subtypes, name, signature) and - ext = "" and - input = e.getMaDInput() - } - - additional predicate sourceSpec( - Endpoint e, string package, string type, boolean subtypes, string name, string signature, - string ext, string output - ) { - endpointCallable(e, package, type, subtypes, name, signature) and - ext = "" and - output = e.getMaDOutput() - } - - /** - * Gets the related location for the given endpoint. - * - * Related locations can be JavaDoc comments of the class or the method. - */ - RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) { - type = MethodDoc() and - result = e.getCallable().(Documentable).getJavadoc() - or - type = ClassDoc() and - result = e.getCallable().getDeclaringType().(Documentable).getJavadoc() - } -} - -module CharacteristicsImpl = SharedCharacteristics::SharedCharacteristics; - -class EndpointCharacteristic = CharacteristicsImpl::EndpointCharacteristic; - -class Endpoint = FrameworkCandidatesImpl::Endpoint; - -/* - * Predicates that are used to surface prompt examples and candidates for classification with an ML model. - */ - -/** - * A MetadataExtractor that extracts metadata for framework mode. - */ -class FrameworkModeMetadataExtractor extends string { - FrameworkModeMetadataExtractor() { this = "FrameworkModeMetadataExtractor" } - - predicate hasMetadata( - Endpoint e, string package, string type, string subtypes, string name, string signature, - string input, string output, string parameterName, string alreadyAiModeled, - string extensibleType - ) { - exists(Callable callable | e.getCallable() = callable | - (if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and - (if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and - package = callable.getDeclaringType().getPackage().getName() and - // we're using the erased types because the MaD convention is to not specify type parameters. - // Whether something is or isn't a sink doesn't usually depend on the type parameters. - type = callable.getDeclaringType().getErasure().(RefType).getNestedName() and - subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and - name = callable.getName() and - signature = ExternalFlow::paramsString(callable) and - (if exists(e.getParamName()) then parameterName = e.getParamName() else parameterName = "") and - e.getExtensibleType() = extensibleType - ) and - ( - not CharacteristicsImpl::isModeled(e, _, extensibleType, _) and alreadyAiModeled = "" - or - CharacteristicsImpl::isModeled(e, _, extensibleType, alreadyAiModeled) - ) - } -} - -/** - * Holds if the given `endpoint` should be considered a candidate for the `extensibleType`. - * - * The other parameters record various other properties of interest. - */ -predicate isCandidate( - Endpoint endpoint, string package, string type, string subtypes, string name, string signature, - string input, string output, string parameterName, string extensibleType, string alreadyAiModeled -) { - CharacteristicsImpl::isCandidate(endpoint, _) and - not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u | - u.appliesToEndpoint(endpoint) - ) and - any(FrameworkModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - alreadyAiModeled, extensibleType) and - // If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a - // candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's - // already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We - // assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink - // types, and we don't need to reexamine it. - alreadyAiModeled.matches(["", "%ai-%"]) and - AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature) -} - -/** - * Holds if the given `endpoint` is a negative example for the `extensibleType` - * because of the `characteristic`. - * - * The other parameters record various other properties of interest. - */ -predicate isNegativeExample( - Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package, - string type, string subtypes, string name, string signature, string input, string output, - string parameterName, string extensibleType -) { - characteristic.appliesToEndpoint(endpoint) and - // the node is known not to be an endpoint of any appropriate type - forall(AutomodelEndpointTypes::EndpointType tp | - tp = CharacteristicsImpl::getAPotentialType(endpoint) - | - characteristic.hasImplications(tp, false, _) - ) and - // the lowest confidence across all endpoint types should be at least highConfidence - confidence = - min(float c | - characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c) - ) and - confidence >= SharedCharacteristics::highConfidence() and - any(FrameworkModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - _, extensibleType) and - // It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes - // as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here. - not exists(EndpointCharacteristic characteristic2, float confidence2 | - characteristic2 != characteristic - | - characteristic2.appliesToEndpoint(endpoint) and - confidence2 >= SharedCharacteristics::maximalConfidence() and - characteristic2 - .hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2) - ) -} - -/** - * Holds if the given `endpoint` is a positive example for the `endpointType`. - * - * The other parameters record various other properties of interest. - */ -predicate isPositiveExample( - Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name, - string signature, string input, string output, string parameterName, string extensibleType -) { - any(FrameworkModeMetadataExtractor meta) - .hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - _, extensibleType) and - CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) -} - -/* - * EndpointCharacteristic classes that are specific to Automodel for Java. - */ - -/** - * A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks, - * and its return value should not be considered a source. - * - * A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return - * type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does - * the dangerous/interesting thing, so we want the latter to be modeled as the sink. - * - * TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks - */ -private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic -{ - UnexploitableIsCharacteristic() { this = "argument of is-style boolean method" } - - override predicate appliesToEndpoint(Endpoint e) { - e.getCallable().getName().matches("is%") and - e.getCallable().getReturnType() instanceof BooleanType and - ( - e.getExtensibleType() = "sinkModel" and - not FrameworkCandidatesImpl::isSink(e, _, _) - or - e.getExtensibleType() = "sourceModel" and - not FrameworkCandidatesImpl::isSource(e, _, _) and - e.getMaDOutput() = "ReturnValue" - ) - } -} - -/** - * A negative characteristic that indicates that parameters of an existence-checking boolean method should not be - * considered sinks, and its return value should not be considered a source. - * - * A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a - * boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the - * dangerous/interesting thing, so we want the latter to be modeled as the sink. - */ -private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic -{ - UnexploitableExistsCharacteristic() { this = "argument of existence-checking boolean method" } - - override predicate appliesToEndpoint(Endpoint e) { - exists(Callable callable | - callable = e.getCallable() and - callable.getName().toLowerCase() = ["exists", "notexists"] and - callable.getReturnType() instanceof BooleanType - | - e.getExtensibleType() = "sinkModel" and - not FrameworkCandidatesImpl::isSink(e, _, _) - or - e.getExtensibleType() = "sourceModel" and - not FrameworkCandidatesImpl::isSource(e, _, _) and - e.getMaDOutput() = "ReturnValue" - ) - } -} - -/** - * A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks, - * and its return value should not be considered a source. - */ -private class ExceptionCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic -{ - ExceptionCharacteristic() { this = "argument/result of exception-related method" } - - override predicate appliesToEndpoint(Endpoint e) { - e.getCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable and - ( - e.getExtensibleType() = "sinkModel" and - not FrameworkCandidatesImpl::isSink(e, _, _) - or - e.getExtensibleType() = "sourceModel" and - not FrameworkCandidatesImpl::isSource(e, _, _) and - e.getMaDOutput() = "ReturnValue" - ) - } -} - -/** - * A characteristic that limits candidates to parameters of methods that are recognized as `ModelApi`, iow., APIs that - * are considered worth modeling. - */ -private class NotAModelApi extends CharacteristicsImpl::UninterestingToModelCharacteristic { - NotAModelApi() { this = "not a model API" } - - override predicate appliesToEndpoint(Endpoint e) { - not e.getCallable() instanceof ModelExclusions::ModelApi - } -} diff --git a/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql deleted file mode 100644 index 83683b4e78f5..000000000000 --- a/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Surfaces the endpoints that are not already known to be sinks, and are therefore used as candidates for - * classification with an ML model. - * - * Note: This query does not actually classify the endpoints using the model. - * - * @name Automodel candidates (framework mode) - * @description A query to extract automodel candidates in framework mode. - * @kind problem - * @problem.severity recommendation - * @id java/ml/extract-automodel-framework-candidates - * @tags internal extract automodel framework-mode candidates - */ - -private import AutomodelFrameworkModeCharacteristics -private import AutomodelJavaUtil - -from - Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes, - DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output, - DollarAtString parameterName, DollarAtString alreadyAiModeled, DollarAtString extensibleType -where - isCandidate(endpoint, package, type, subtypes, name, signature, input, output, parameterName, - extensibleType, alreadyAiModeled) -select endpoint, - "Related locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // - package, "package", // - type, "type", // - subtypes, "subtypes", // - name, "name", // - signature, "signature", // - input, "input", // - output, "output", // - parameterName, "parameterName", // - alreadyAiModeled, "alreadyAiModeled", // - extensibleType, "extensibleType" diff --git a/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql deleted file mode 100644 index 05e5951b0610..000000000000 --- a/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Surfaces endpoints that are non-sinks with high confidence, for use as negative examples in the prompt. - * - * @name Negative examples (framework mode) - * @kind problem - * @problem.severity recommendation - * @id java/ml/extract-automodel-framework-negative-examples - * @tags internal extract automodel framework-mode negative examples - */ - -private import AutomodelFrameworkModeCharacteristics -private import AutomodelEndpointTypes -private import AutomodelJavaUtil - -from - Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, - DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name, - DollarAtString signature, DollarAtString input, DollarAtString output, - DollarAtString parameterName, DollarAtString extensibleType -where - isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature, - input, output, parameterName, extensibleType) -select endpoint, - characteristic + "\nrelated locations: $@, $@." + - "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // - package, "package", // - type, "type", // - subtypes, "subtypes", // - name, "name", // - signature, "signature", // - input, "input", // - output, "output", // - parameterName, "parameterName", // - extensibleType, "extensibleType" diff --git a/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql b/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql deleted file mode 100644 index 7cb023949ed9..000000000000 --- a/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Surfaces endpoints that are sinks with high confidence, for use as positive examples in the prompt. - * - * @name Positive examples (framework mode) - * @kind problem - * @problem.severity recommendation - * @id java/ml/extract-automodel-framework-positive-examples - * @tags internal extract automodel framework-mode positive examples - */ - -private import AutomodelFrameworkModeCharacteristics -private import AutomodelEndpointTypes -private import AutomodelJavaUtil - -from - Endpoint endpoint, EndpointType endpointType, DollarAtString package, DollarAtString type, - DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input, - DollarAtString output, DollarAtString parameterName, DollarAtString extensibleType -where - isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output, - parameterName, extensibleType) -select endpoint, - endpointType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", // - CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", // - package, "package", // - type, "type", // - subtypes, "subtypes", // - name, "name", // - signature, "signature", // - input, "input", // - output, "output", // - parameterName, "parameterName", // - extensibleType, "extensibleType" diff --git a/java/ql/automodel/src/AutomodelJavaUtil.qll b/java/ql/automodel/src/AutomodelJavaUtil.qll deleted file mode 100644 index 368fb172483b..000000000000 --- a/java/ql/automodel/src/AutomodelJavaUtil.qll +++ /dev/null @@ -1,111 +0,0 @@ -private import java -private import AutomodelEndpointTypes as AutomodelEndpointTypes - -/** - * A helper class to represent a string value that can be returned by a query using $@ notation. - * - * It extends `string`, but adds a mock `hasLocationInfo` method that returns the string itself as the file name. - * - * Use this, when you want to return a string value from a query using $@ notation - the string value - * will be included in the sarif file. - * - * - * Background information on `hasLocationInfo`: - * https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-location-information - */ -class DollarAtString extends string { - bindingset[this] - DollarAtString() { any() } - - bindingset[this] - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - path = this and sl = 1 and sc = 1 and el = 1 and ec = 1 - } -} - -/** - * Holds for all combinations of MaD kinds (`kind`) and their human readable - * descriptions. - */ -predicate isKnownKind(string kind, AutomodelEndpointTypes::EndpointType type) { - kind = type.getKind() -} - -/** - * By convention, the subtypes property of the MaD declaration should only be - * true when there _can_ exist any subtypes with a different implementation. - * - * It would technically be ok to always use the value 'true', but this would - * break convention. - */ -pragma[nomagic] -boolean considerSubtypes(Callable callable) { - if - callable.isStatic() or - callable.getDeclaringType().isStatic() or - callable.isFinal() or - callable.getDeclaringType().isFinal() - then result = false - else result = true -} - -/** - * Holds if the given package, type, name and signature is a candidate for automodeling. - * - * This predicate is extensible, so that different endpoints can be selected at runtime. - */ -extensible predicate automodelCandidateFilter( - string package, string type, string name, string signature -); - -/** - * Holds if the given package, type, name and signature is a candidate for automodeling. - * - * This relies on an extensible predicate, and if that is not supplied then - * all endpoints are considered candidates. - */ -bindingset[package, type, name, signature] -predicate includeAutomodelCandidate(string package, string type, string name, string signature) { - not automodelCandidateFilter(_, _, _, _) or - automodelCandidateFilter(package, type, name, signature) -} - -/** - * Holds if the given program element corresponds to a piece of source code, - * that is, it is not compiler-generated. - * - * Note: This is a stricter check than `Element::fromSource`, which simply - * checks whether the element is in a source file as opposed to a JAR file. - * There can be compiler-generated elements in source files (especially for - * Kotlin), which we also want to exclude. - */ -predicate isFromSource(Element e) { - // from a source file (not a JAR) - e.fromSource() and - // not explicitly marked as compiler-generated - not e.isCompilerGenerated() and - // does not have a dummy location - not e.hasLocationInfo(_, 0, 0, 0, 0) -} - -/** - * Holds if taint cannot flow through the given type (because it is a numeric - * type or some other type with a fixed set of values). - */ -predicate isUnexploitableType(Type tp) { - tp instanceof PrimitiveType or - tp instanceof BoxedType or - tp instanceof NumberType or - tp instanceof VoidType -} - -/** - * Holds if the given method can be overridden, that is, it is not final, - * static, or private. - */ -predicate isOverridable(Method m) { - not m.getDeclaringType().isFinal() and - not m.isFinal() and - not m.isStatic() and - not m.isPrivate() -} diff --git a/java/ql/automodel/src/AutomodelSharedCharacteristics.qll b/java/ql/automodel/src/AutomodelSharedCharacteristics.qll deleted file mode 100644 index 273c5d30dec9..000000000000 --- a/java/ql/automodel/src/AutomodelSharedCharacteristics.qll +++ /dev/null @@ -1,412 +0,0 @@ -float maximalConfidence() { result = 1.0 } - -float highConfidence() { result = 0.9 } - -float mediumConfidence() { result = 0.6 } - -/** - * A specification of how to instantiate the shared characteristics for a given candidate class. - * - * The `CandidateSig` implementation specifies a type to use for Endpoints (eg., `ParameterNode`), as well as a type - * to label endpoint classes (the `EndpointType`). One of the endpoint classes needs to be a 'negative' class, meaning - * "not any of the other known endpoint types". - */ -signature module CandidateSig { - /** - * An endpoint is a potential candidate for modeling. This will typically be bound to the language's - * DataFlow node class, or a subtype thereof. - */ - class Endpoint { - /** - * Gets the kind of this endpoint, either "sourceModel" or "sinkModel". - */ - string getExtensibleType(); - - /** - * Gets a string representation of this endpoint. - */ - string toString(); - } - - /** - * A related location for an endpoint. This will typically be bound to the supertype of all AST nodes (eg., `Top`). - */ - class RelatedLocation; - - /** - * A label for a related location. - * - * Eg., method-doc, class-doc, etc. - */ - class RelatedLocationType; - - /** - * An endpoint type considered by this specification. - */ - class EndpointType extends string; - - /** - * A sink endpoint type considered by this specification. - */ - class SinkType extends EndpointType; - - /** - * A source endpoint type considered by this specification. - */ - class SourceType extends EndpointType; - - /** - * Gets the endpoint as a location. - * - * This is a utility function to convert an endpoint to its corresponding location. - */ - RelatedLocation asLocation(Endpoint e); - - /** - * Defines what MaD kinds are known, and what endpoint type they correspond to. - */ - predicate isKnownKind(string kind, EndpointType type); - - /** - * Holds if `e` is a flow sanitizer, and has type `t`. - */ - predicate isSanitizer(Endpoint e, EndpointType t); - - /** - * Holds if `e` is a sink with the label `kind`, and provenance `provenance`. - */ - predicate isSink(Endpoint e, string kind, string provenance); - - /** - * Holds if `e` is a source with the label `kind`, and provenance `provenance`. - */ - predicate isSource(Endpoint e, string kind, string provenance); - - /** - * Holds if `e` is not a source or sink of any kind. - */ - predicate isNeutral(Endpoint e); - - /** - * Gets a related location. - * - * A related location is a source code location that may hold extra information about an endpoint that can be useful - * to the machine learning model. - * - * For example, a related location for a method call may be the documentation comment of a method. - */ - RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType name); -} - -/** - * A set of shared characteristics for a given candidate class. - * - * This module is language-agnostic, although the `CandidateSig` module will be language-specific. - * - * The language specific implementation can also further extend the behavior of this module by adding additional - * implementations of endpoint characteristics exported by this module. - */ -module SharedCharacteristics { - predicate isSink = Candidate::isSink/3; - - predicate isNeutral = Candidate::isNeutral/1; - - predicate isModeled(Candidate::Endpoint e, string kind, string extensibleKind, string provenance) { - Candidate::isSink(e, kind, provenance) and extensibleKind = "sinkModel" - or - Candidate::isSource(e, kind, provenance) and extensibleKind = "sourceModel" - } - - /** - * Holds if `endpoint` is modeled as `endpointType`. - */ - predicate isKnownAs( - Candidate::Endpoint endpoint, Candidate::EndpointType endpointType, - EndpointCharacteristic characteristic - ) { - // If the list of characteristics includes positive indicators with maximal confidence for this class, then it's a - // known sink for the class. - characteristic.appliesToEndpoint(endpoint) and - characteristic.hasImplications(endpointType, true, maximalConfidence()) - } - - /** - * Gets a potential type of this endpoint to make sure that sources are - * associated with source types and sinks with sink types. - */ - Candidate::EndpointType getAPotentialType(Candidate::Endpoint endpoint) { - endpoint.getExtensibleType() = "sourceModel" and - result instanceof Candidate::SourceType - or - endpoint.getExtensibleType() = "sinkModel" and - result instanceof Candidate::SinkType - } - - /** - * Holds if the given `endpoint` should be considered as a candidate for type `endpointType`, - * and classified by the ML model. - * - * A candidate is an endpoint that cannot be excluded from `endpointType` based on its characteristics. - */ - predicate isCandidate(Candidate::Endpoint endpoint, Candidate::EndpointType endpointType) { - endpointType = getAPotentialType(endpoint) and - not exists(getAnExcludingCharacteristic(endpoint, endpointType)) - } - - /** - * Gets the related location of `e` with name `name`, if it exists. - * Otherwise, gets the candidate itself. - */ - Candidate::RelatedLocation getRelatedLocationOrCandidate( - Candidate::Endpoint e, Candidate::RelatedLocationType type - ) { - if exists(Candidate::getRelatedLocation(e, type)) - then result = Candidate::getRelatedLocation(e, type) - else result = Candidate::asLocation(e) - } - - /** - * Gets a characteristics that disbar `endpoint` from being a candidate for `endpointType` - * with at least medium confidence. - */ - EndpointCharacteristic getAnExcludingCharacteristic( - Candidate::Endpoint endpoint, Candidate::EndpointType endpointType - ) { - result.appliesToEndpoint(endpoint) and - exists(float confidence | - confidence >= mediumConfidence() and - result.hasImplications(endpointType, false, confidence) - ) - } - - /** - * A set of characteristics that a particular endpoint might have. This set of characteristics is used to make decisions - * about whether to include the endpoint in the training set and with what kind, as well as whether to score the - * endpoint at inference time. - */ - abstract class EndpointCharacteristic extends string { - /** - * Holds for the string that is the name of the characteristic. This should describe some property of an endpoint - * that is meaningful for determining whether it's a sink, and if so, of which sink type. - */ - bindingset[this] - EndpointCharacteristic() { any() } - - /** - * Holds for endpoints that have this characteristic. - */ - abstract predicate appliesToEndpoint(Candidate::Endpoint n); - - /** - * This predicate describes what the characteristic tells us about an endpoint. - * - * Params: - * endpointType: The sink/source type. - * isPositiveIndicator: If true, this characteristic indicates that this endpoint _is_ a member of the class; if - * false, it indicates that it _isn't_ a member of the class. - * confidence: A float in [0, 1], which tells us how strong an indicator this characteristic is for the endpoint - * belonging / not belonging to the given class. A confidence near zero means this characteristic is a very weak - * indicator of whether or not the endpoint belongs to the class. A confidence of 1 means that all endpoints with - * this characteristic definitively do/don't belong to the class. - */ - abstract predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ); - - /** Indicators with confidence at or above this threshold are considered to be high-confidence indicators. */ - final float getHighConfidenceThreshold() { result = 0.8 } - } - - /** - * A high-confidence characteristic that indicates that an endpoint is a sink of a specified type. These endpoints can - * be used as positive samples for training or for a few-shot prompt. - */ - abstract class SinkCharacteristic extends EndpointCharacteristic { - bindingset[this] - SinkCharacteristic() { any() } - - abstract Candidate::EndpointType getSinkType(); - - final override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - endpointType = this.getSinkType() and - isPositiveIndicator = true and - confidence = maximalConfidence() - } - } - - /** - * A high-confidence characteristic that indicates that an endpoint is a source of a specified type. These endpoints can - * be used as positive samples for training or for a few-shot prompt. - */ - abstract class SourceCharacteristic extends EndpointCharacteristic { - bindingset[this] - SourceCharacteristic() { any() } - - abstract Candidate::EndpointType getSourceType(); - - final override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - endpointType = this.getSourceType() and - isPositiveIndicator = true and - confidence = maximalConfidence() - } - } - - /** - * A high-confidence characteristic that indicates that an endpoint is not a sink of any type. These endpoints can be - * used as negative samples for training or for a few-shot prompt. - */ - abstract class NotASinkCharacteristic extends EndpointCharacteristic { - bindingset[this] - NotASinkCharacteristic() { any() } - - override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - endpointType instanceof Candidate::SinkType and - isPositiveIndicator = false and - confidence = highConfidence() - } - } - - /** - * A high-confidence characteristic that indicates that an endpoint is not a source of any type. These endpoints can be - * used as negative samples for training or for a few-shot prompt. - */ - abstract class NotASourceCharacteristic extends EndpointCharacteristic { - bindingset[this] - NotASourceCharacteristic() { any() } - - override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - endpointType instanceof Candidate::SourceType and - isPositiveIndicator = false and - confidence = highConfidence() - } - } - - /** - * A high-confidence characteristic that indicates that an endpoint is neither a source nor a sink of any type. - */ - abstract class NeitherSourceNorSinkCharacteristic extends NotASinkCharacteristic, - NotASourceCharacteristic - { - bindingset[this] - NeitherSourceNorSinkCharacteristic() { any() } - - final override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - NotASinkCharacteristic.super.hasImplications(endpointType, isPositiveIndicator, confidence) or - NotASourceCharacteristic.super.hasImplications(endpointType, isPositiveIndicator, confidence) - } - } - - /** - * A medium-confidence characteristic that indicates that an endpoint is unlikely to be a sink of any type. These - * endpoints can be excluded from scoring at inference time, both to save time and to avoid false positives. They should - * not, however, be used as negative samples for training or for a few-shot prompt, because they may include a small - * number of sinks. - */ - abstract class LikelyNotASinkCharacteristic extends EndpointCharacteristic { - bindingset[this] - LikelyNotASinkCharacteristic() { any() } - - override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - endpointType instanceof Candidate::SinkType and - isPositiveIndicator = false and - confidence = mediumConfidence() - } - } - - /** - * A characteristic that indicates not necessarily that an endpoint is not a sink, but rather that it is not a sink - * that's interesting to model in the standard Java libraries. These filters should be removed when extracting sink - * candidates within a user's codebase for customized modeling. - * - * These endpoints should not be used as negative samples for training or for a few-shot prompt, because they are not - * necessarily non-sinks. - */ - abstract class UninterestingToModelCharacteristic extends EndpointCharacteristic { - bindingset[this] - UninterestingToModelCharacteristic() { any() } - - override predicate hasImplications( - Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence - ) { - endpointType instanceof Candidate::SinkType and - isPositiveIndicator = false and - confidence = mediumConfidence() - } - } - - /** - * Contains default implementations that are derived solely from the `CandidateSig` implementation. - */ - private module DefaultCharacteristicImplementations { - /** - * Endpoints identified as sinks by the `CandidateSig` implementation are sinks with maximal confidence. - */ - private class KnownSinkCharacteristic extends SinkCharacteristic { - string madKind; - Candidate::EndpointType endpointType; - string provenance; - - KnownSinkCharacteristic() { - Candidate::isKnownKind(madKind, endpointType) and - // bind "this" to a unique string differing from that of the SinkType classes - this = madKind + "_" + provenance + "_characteristic" and - Candidate::isSink(_, madKind, provenance) - } - - override predicate appliesToEndpoint(Candidate::Endpoint e) { - Candidate::isSink(e, madKind, provenance) - } - - override Candidate::EndpointType getSinkType() { result = endpointType } - } - - private class KnownSourceCharacteristic extends SourceCharacteristic { - string madKind; - Candidate::EndpointType endpointType; - string provenance; - - KnownSourceCharacteristic() { - Candidate::isKnownKind(madKind, endpointType) and - // bind "this" to a unique string differing from that of the SinkType classes - this = madKind + "_" + provenance + "_characteristic" and - Candidate::isSource(_, madKind, provenance) - } - - override predicate appliesToEndpoint(Candidate::Endpoint e) { - Candidate::isSource(e, madKind, provenance) - } - - override Candidate::EndpointType getSourceType() { result = endpointType } - } - - /** - * A negative characteristic that indicates that an endpoint was manually modeled as a neutral model. - */ - private class NeutralModelCharacteristic extends NeitherSourceNorSinkCharacteristic { - NeutralModelCharacteristic() { this = "known non-sink" } - - override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isNeutral(e) } - } - - /** - * A negative characteristic that indicates that an endpoint is a sanitizer, and thus not a source. - */ - private class IsSanitizerCharacteristic extends NotASourceCharacteristic { - IsSanitizerCharacteristic() { this = "known sanitizer" } - - override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isSanitizer(e, _) } - } - } -} diff --git a/java/ql/automodel/src/AutomodelSinkModelMrvaQueries.ql b/java/ql/automodel/src/AutomodelSinkModelMrvaQueries.ql deleted file mode 100644 index ed61ccfbbfdc..000000000000 --- a/java/ql/automodel/src/AutomodelSinkModelMrvaQueries.ql +++ /dev/null @@ -1,62 +0,0 @@ -/** - * This file contains query predicates for use when gathering metrics at scale using Multi Repo - * Variant Analysis. - */ - -private import java -private import AutomodelAlertSinkUtil - -/** - * Holds if `alertCount` is the number of alerts for the query with ID `queryId` for which the - * sinks correspond to the given `ai-generated` sink model. - */ -query predicate sinkModelCountPerQuery( - string queryId, int alertCount, string package, string type, boolean subtypes, string name, - string signature, string input, string ext, string kind, string provenance -) { - exists(SinkModel s | - sinkModelTallyPerQuery(queryId, alertCount, s) and - s.getProvenance() = "ai-generated" and - s.getPackage() = package and - s.getType() = type and - s.getSubtypes() = subtypes and - s.getName() = name and - s.getSignature() = signature and - s.getInput() = input and - s.getExt() = ext and - s.getKind() = kind and - s.getProvenance() = provenance - ) -} - -/** - * Holds if `instanceCount` is the number of instances corresponding to the given `ai-generated` - * sink model (as identified by the `package`, `name`, `input`, etc.). - */ -query predicate instanceCount( - int instanceCount, string package, string type, boolean subtypes, string name, string signature, - string input, string ext, string kind, string provenance -) { - exists(SinkModel s | - instanceCount = s.getInstanceCount() and - instanceCount > 0 and - s.getProvenance() = "ai-generated" and - s.getPackage() = package and - s.getType() = type and - s.getSubtypes() = subtypes and - s.getName() = name and - s.getSignature() = signature and - s.getInput() = input and - s.getExt() = ext and - s.getKind() = kind and - s.getProvenance() = provenance - ) -} - -// MRVA requires a select clause, so we repurpose it to tell us which query predicates had results. -from string hadResults -where - sinkModelCountPerQuery(_, _, _, _, _, _, _, _, _, _, _) and hadResults = "sinkModelCountPerQuery" - or - instanceCount(_, _, _, _, _, _, _, _, _, _) and hadResults = "instanceCount" -select hadResults diff --git a/java/ql/automodel/src/change-notes/2024-11-19-drop-automodel.md b/java/ql/automodel/src/change-notes/2024-11-19-drop-automodel.md new file mode 100644 index 000000000000..2b554d6de204 --- /dev/null +++ b/java/ql/automodel/src/change-notes/2024-11-19-drop-automodel.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* Dropped the Java Automodel queries. diff --git a/java/ql/automodel/src/codeql-pack.release.yml b/java/ql/automodel/src/codeql-pack.release.yml deleted file mode 100644 index 56a2fb388725..000000000000 --- a/java/ql/automodel/src/codeql-pack.release.yml +++ /dev/null @@ -1,2 +0,0 @@ ---- -lastReleaseVersion: 1.0.11 diff --git a/java/ql/automodel/src/qlpack.yml b/java/ql/automodel/src/qlpack.yml deleted file mode 100644 index 4acf2219db30..000000000000 --- a/java/ql/automodel/src/qlpack.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: codeql/java-automodel-queries -version: 1.0.12-dev -groups: - - java - - automodel -dependencies: - codeql/java-all: ${workspace} -dataExtensions: - - AutomodelCandidateFilter.yml -warnOnImplicitThis: true \ No newline at end of file diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.ql b/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.ql deleted file mode 100644 index b7e1efc45325..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/AutomodelApplicationModeExtractionTests.ql +++ /dev/null @@ -1,35 +0,0 @@ -import java -import AutomodelApplicationModeCharacteristics as Characteristics -import AutomodelExtractionTests - -module TestHelper implements TestHelperSig { - Location getEndpointLocation(Characteristics::Endpoint endpoint) { - result = endpoint.asTop().getLocation() - } - - predicate isCandidate( - Characteristics::Endpoint endpoint, string name, string signature, string input, string output, - string extensibleType - ) { - Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _, - extensibleType, _) - } - - predicate isPositiveExample( - Characteristics::Endpoint endpoint, string endpointType, string name, string signature, - string input, string output, string extensibleType - ) { - Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input, - output, _, extensibleType) - } - - predicate isNegativeExample( - Characteristics::Endpoint endpoint, string name, string signature, string input, string output, - string extensibleType - ) { - Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _, - extensibleType) - } -} - -import MakeTest> diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java b/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java deleted file mode 100644 index b0f3482a7322..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/PluginImpl.java +++ /dev/null @@ -1,8 +0,0 @@ -import hudson.Plugin; - -public class PluginImpl extends Plugin { - @Override - public void configure(String name, String value) { // $ sourceModelCandidate=configure(String,String):Parameter[0] sourceModelCandidate=configure(String,String):Parameter[1] - // ... - } -} diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java b/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java deleted file mode 100644 index 9691cf86c150..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/Test.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.github.codeql.test; - -import java.io.InputStream; -import java.io.PrintWriter; -import java.nio.file.CopyOption; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; -import java.io.File; -import java.io.FileFilter; -import java.nio.file.FileVisitOption; -import java.net.URLConnection; -import java.util.concurrent.FutureTask; - -class Test { - public static void main(String[] args) throws Exception { - AtomicReference reference = new AtomicReference<>(); // uninteresting (parameterless constructor) - reference.set( // $ sinkModelCandidate=set(Object):Argument[this] - args[0] // $ negativeSinkExample=set(Object):Argument[0] // modeled as a flow step - ); // not a source candidate (return type is void) - } - - public static void callSupplier(Supplier supplier) { - supplier.get(); // not a source candidate (lambda flow) - } - - public static void copyFiles(Path source, Path target, CopyOption option) throws Exception { - Files.copy( - source, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[0](path-injection) - target, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[1](path-injection) - option // no candidate (not modeled, but source and target are modeled) - ); // $ sourceModelCandidate=copy(Path,Path,CopyOption[]):ReturnValue - } - - public static InputStream getInputStream(Path openPath) throws Exception { - return Files.newInputStream( - openPath // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) // sink candidate because "only" ai-modeled, and useful as a candidate in regression testing - ); // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue - } - - public static InputStream getInputStream(String openPath, String otherPath) throws Exception { - return Test.getInputStream( // the call is not a source candidate (argument to local call) - Paths.get( - openPath, // $ negativeSinkExample=get(String,String[]):Argument[0] // modeled as a flow step - otherPath - ) // $ sourceModelCandidate=get(String,String[]):ReturnValue negativeSinkExample=get(String,String[]):Argument[1] - ); - } - - public static int compareFiles(File f1, File f2) { - return f1.compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] - f2 // $ negativeSinkExample=compareTo(File):Argument[0] // modeled as not a sink - ); // not a source candidate (return type is int) - } - - public static void FilesWalkExample(Path p, FileVisitOption o) throws Exception { - Files.walk( - p, // $ negativeSinkExample=walk(Path,FileVisitOption[]):Argument[0] // modeled as a flow step - o, // the implicit varargs array is a candidate, annotated on the last line of the call - o // not a candidate (only the first arg corresponding to a varargs array - // is extracted) - ); // $ sourceModelCandidate=walk(Path,FileVisitOption[]):ReturnValue sinkModelCandidate=walk(Path,FileVisitOption[]):Argument[1] - } - - public static void WebSocketExample(URLConnection c) throws Exception { - c.getInputStream(); // $ sinkModelCandidate=getInputStream():Argument[this] positiveSourceExample=getInputStream():ReturnValue(remote) // not a source candidate (manual modeling) - c.connect(); // $ sinkModelCandidate=connect():Argument[this] // not a source candidate (return type is void) - } - - public static void fileFilterExample(File f, FileFilter ff) { - f.listFiles( // $ sinkModelCandidate=listFiles(FileFilter):Argument[this] - ff - ); // $ sourceModelCandidate=listFiles(FileFilter):ReturnValue - } -} - -class OverrideTest extends Exception { - public void printStackTrace(PrintWriter writer) { // $ sourceModelCandidate=printStackTrace(PrintWriter):Parameter[0] - return; - } - -} - -class TaskUtils { - public FutureTask getTask() { - FutureTask ft = new FutureTask(() -> { - // ^-- no sink candidate for the `this` qualifier of a constructor - return 42; - }); - return ft; - } -} - -class MoreTests { - public static void FilesListExample(Path p) throws Exception { - Files.list( - Files.createDirectories( - p // $ positiveSinkExample=createDirectories(Path,FileAttribute[]):Argument[0](path-injection) - ) // $ sourceModelCandidate=createDirectories(Path,FileAttribute[]):ReturnValue negativeSinkExample=list(Path):Argument[0] // modeled as a flow step - ); // $ sourceModelCandidate=list(Path):ReturnValue - - Files.delete( - p // $ sinkModelCandidate=delete(Path):Argument[0] positiveSinkExample=delete(Path):Argument[0](path-injection) - ); // not a source candidate (return type is void) - - Files.deleteIfExists( - p // $ sinkModelCandidate=deleteIfExists(Path):Argument[0] positiveSinkExample=deleteIfExists(Path):Argument[0](path-injection) - ); // not a source candidate (return type is boolean) - } -} \ No newline at end of file diff --git a/java/ql/automodel/test/AutomodelApplicationModeExtraction/hudson/Plugin.java b/java/ql/automodel/test/AutomodelApplicationModeExtraction/hudson/Plugin.java deleted file mode 100644 index 3ad79abb8df1..000000000000 --- a/java/ql/automodel/test/AutomodelApplicationModeExtraction/hudson/Plugin.java +++ /dev/null @@ -1,7 +0,0 @@ -package hudson; - -/** Plugin doc */ -public class Plugin { - /** Configure method doc */ - public void configure(String name, String value) {} -} diff --git a/java/ql/automodel/test/AutomodelExtractionTests.qll b/java/ql/automodel/test/AutomodelExtractionTests.qll deleted file mode 100644 index fbc407c67f05..000000000000 --- a/java/ql/automodel/test/AutomodelExtractionTests.qll +++ /dev/null @@ -1,77 +0,0 @@ -import java -import TestUtilities.InlineExpectationsTest -import AutomodelSharedCharacteristics - -signature module TestHelperSig { - Location getEndpointLocation(Candidate::Endpoint e); - - predicate isCandidate( - Candidate::Endpoint e, string name, string signature, string input, string output, - string extensibleType - ); - - predicate isPositiveExample( - Candidate::Endpoint e, string endpointType, string name, string signature, string input, - string output, string extensibleType - ); - - predicate isNegativeExample( - Candidate::Endpoint e, string name, string signature, string input, string output, - string extensibleType - ); -} - -module Extraction TestHelper> implements TestSig { - string getARelevantTag() { - result in [ - "sourceModelCandidate", "sinkModelCandidate", // a candidate source/sink - "positiveSourceExample", "positiveSinkExample", // a known source/sink - "negativeSourceExample", "negativeSinkExample" // a known non-source/non-sink - ] - } - - /** - * If `extensibleType` is `sourceModel` then the result is `ifSource`, if it - * is `sinkModel` then the result is `ifSink`. - */ - bindingset[extensibleType, ifSource, ifSink] - private string ifSource(string extensibleType, string ifSource, string ifSink) { - extensibleType = "sourceModel" and result = ifSource - or - extensibleType = "sinkModel" and result = ifSink - } - - additional predicate selectEndpoint( - Candidate::Endpoint endpoint, string name, string signature, string input, string output, - string extensibleType, string tag, string suffix - ) { - TestHelper::isCandidate(endpoint, name, signature, input, output, extensibleType) and - tag = ifSource(extensibleType, "sourceModelCandidate", "sinkModelCandidate") and - suffix = "" - or - TestHelper::isNegativeExample(endpoint, name, signature, input, output, extensibleType) and - tag = "negative" + ifSource(extensibleType, "Source", "Sink") + "Example" and - suffix = "" - or - exists(string endpointType | - TestHelper::isPositiveExample(endpoint, endpointType, name, signature, input, output, - extensibleType) and - tag = "positive" + ifSource(extensibleType, "Source", "Sink") + "Example" and - suffix = "(" + endpointType + ")" - ) - } - - predicate hasActualResult(Location location, string element, string tag, string value) { - exists( - Candidate::Endpoint endpoint, string name, string signature, string input, string output, - string extensibleType, string suffix - | - selectEndpoint(endpoint, name, signature, input, output, extensibleType, tag, suffix) - | - TestHelper::getEndpointLocation(endpoint) = location and - endpoint.toString() = element and - // for source models only the output is relevant, and vice versa for sink models - value = name + signature + ":" + ifSource(extensibleType, output, input) + suffix - ) - } -} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.ql b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.ql deleted file mode 100644 index 0d5e86118705..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/AutomodelFrameworkModeExtractionTests.ql +++ /dev/null @@ -1,35 +0,0 @@ -import java -import AutomodelFrameworkModeCharacteristics as Characteristics -import AutomodelExtractionTests - -module TestHelper implements TestHelperSig { - Location getEndpointLocation(Characteristics::Endpoint endpoint) { - result = endpoint.asTop().getLocation() - } - - predicate isCandidate( - Characteristics::Endpoint endpoint, string name, string signature, string input, string output, - string extensibleType - ) { - Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _, - extensibleType, _) - } - - predicate isPositiveExample( - Characteristics::Endpoint endpoint, string endpointType, string name, string signature, - string input, string output, string extensibleType - ) { - Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input, - output, _, extensibleType) - } - - predicate isNegativeExample( - Characteristics::Endpoint endpoint, string name, string signature, string input, string output, - string extensibleType - ) { - Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _, - extensibleType) - } -} - -import MakeTest> diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/MyWriter.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/MyWriter.java deleted file mode 100644 index 62bd773cc2e2..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/MyWriter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.codeql.test; - -public class MyWriter extends java.io.Writer { - @Override - public void write(char[] cbuf, int off, int len) { // $ sinkModelCandidate=write(char[],int,int):Argument[this] positiveSinkExample=write(char[],int,int):Argument[0](file-content-store) sourceModelCandidate=write(char[],int,int):Parameter[this] sourceModelCandidate=write(char[],int,int):Parameter[0] - } - - @Override - public void close() { // $ sinkModelCandidate=close():Argument[this] sourceModelCandidate=close():Parameter[this] - } - - @Override - public void flush() { // $ sinkModelCandidate=flush():Argument[this] sourceModelCandidate=flush():Parameter[this] - } -} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java deleted file mode 100644 index b106d3da5940..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/NonPublicClass.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.github.codeql.test; - -/** - * No candidates in this class, as it's not public! - */ -class NonPublicClass { - public void noCandidates(String here) { - System.out.println(here); - } -} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java deleted file mode 100644 index 79fabff0664b..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicClass.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.github.codeql.test; - -public class PublicClass { - public void stuff(String arg) { // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // source candidates because it is an overrideable method - System.out.println(arg); - } - - public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // `arg` is not a source candidate (not overrideabe); `this` is not a candidate (static method) - System.out.println(arg); - } - - protected void nonPublicStuff(String arg) { // $ sinkModelCandidate=nonPublicStuff(String):Argument[this] sourceModelCandidate=nonPublicStuff(String):Parameter[this] sinkModelCandidate=nonPublicStuff(String):Argument[0] sourceModelCandidate=nonPublicStuff(String):Parameter[0] - System.out.println(arg); - } - - void packagePrivateStuff(String arg) { // no candidates because the method is not public - System.out.println(arg); - } - - public PublicClass(Object input) { // $ sourceModelCandidate=PublicClass(Object):ReturnValue sinkModelCandidate=PublicClass(Object):Argument[0] // `this` is not a candidate because it is a constructor - } - - // `input` and `input` are source candidates, but not sink candidates (is-style method) - public Boolean isIgnored(Object input) { // $ negativeSinkExample=isIgnored(Object):Argument[this] sourceModelCandidate=isIgnored(Object):Parameter[this] negativeSinkExample=isIgnored(Object):Argument[0] sourceModelCandidate=isIgnored(Object):Parameter[0] - return false; - } -} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java deleted file mode 100644 index d4f80b3c6988..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/com/github/codeql/test/PublicInterface.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.codeql.test; - -public interface PublicInterface { - public int stuff(String arg); // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // result is _not_ a source candidate source (primitive return type) - - public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // not a source candidate (static method) - System.out.println(arg); - } -} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java deleted file mode 100644 index 8bfe83e23397..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/io/File.java +++ /dev/null @@ -1,13 +0,0 @@ -package java.io; - -public class File { - public int compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] sourceModelCandidate=compareTo(File):Parameter[this] // modeled as neutral for sinks - File pathname // $ negativeSinkExample=compareTo(File):Argument[0] sourceModelCandidate=compareTo(File):Parameter[0] // modeled as neutral for sinks - ) { - return 0; - } - - public boolean setLastModified(long time) { // $ sinkModelCandidate=setLastModified(long):Argument[this] sourceModelCandidate=setLastModified(long):Parameter[this] // time is not a candidate (primitive type) - return false; - } // return value is not a source candidate because it's a primitive -} diff --git a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java b/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java deleted file mode 100644 index a833ba5f6e20..000000000000 --- a/java/ql/automodel/test/AutomodelFrameworkModeExtraction/java/nio/file/Files.java +++ /dev/null @@ -1,31 +0,0 @@ -package java.nio.file; - -import java.io.InputStream; -import java.io.FileInputStream; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.file.OpenOption; - -public class Files { - public static void copy( // method result is not a candidate source (void) - Path source, // $ positiveSinkExample=copy(Path,OutputStream):Argument[0](path-injection) // manual model exists - OutputStream out // $ sinkModelCandidate=copy(Path,OutputStream):Argument[1] - /* NB: may be worthwhile to implement the - same behavior as in application mode where out would not be a - candidate because there already is a model for another parameter of - the same method and we assume that methods are always modeled - completely. - */ - ) throws IOException { - // ... - } - - public static InputStream newInputStream( // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue - Path openPath, // $ positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] // known sink, but still a candidate (ai-modeled, and useful as a candidate in regression testing) - OpenOption... options // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[1] - ) throws IOException { - return new FileInputStream(openPath.toFile()); - } -} diff --git a/java/ql/automodel/test/change-notes/2024-05-23-Version1.md b/java/ql/automodel/test/change-notes/2024-05-23-Version1.md deleted file mode 100644 index 5840e51017be..000000000000 --- a/java/ql/automodel/test/change-notes/2024-05-23-Version1.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: breaking ---- -* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0. diff --git a/java/ql/automodel/test/qlpack.yml b/java/ql/automodel/test/qlpack.yml deleted file mode 100644 index 46138d9435c0..000000000000 --- a/java/ql/automodel/test/qlpack.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: codeql/java-automodel-tests -version: 1.0.0-dev -groups: - - java - - automodel - - test -dependencies: - codeql/java-all: ${workspace} - codeql/java-automodel-queries: ${workspace} - codeql/java-tests: ${workspace} -extractor: java -tests: . -warnOnImplicitThis: true \ No newline at end of file diff --git a/java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md b/java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md new file mode 100644 index 000000000000..dea1e7ff81e1 --- /dev/null +++ b/java/ql/lib/change-notes/2024-11-04-list-of-constants-sanitizer.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Calling `coll.contains(x)` is now a taint sanitizer (for any query) for the value `x`, where `coll` is a collection of constants. diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll index e7d34d166b12..c931817e00b4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSteps.qll @@ -28,6 +28,7 @@ private module Frameworks { private import semmle.code.java.frameworks.ThreadLocal private import semmle.code.java.frameworks.ratpack.RatpackExec private import semmle.code.java.frameworks.stapler.Stapler + private import semmle.code.java.security.ListOfConstantsSanitizer } /** @@ -189,3 +190,8 @@ private class NumberTaintPreservingCallable extends TaintPreservingCallable { * map-key and map-value content, so that e.g. a tainted `Map` is assumed to have tainted keys and values. */ abstract class TaintInheritingContent extends DataFlow::Content { } + +/** + * A sanitizer in all global taint flow configurations but not in local taint. + */ +abstract class DefaultTaintSanitizer extends DataFlow::Node { } diff --git a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll index c548c5db38be..9e05b69db4ad 100644 --- a/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll @@ -13,24 +13,27 @@ private import semmle.code.java.dispatch.VirtualDispatch private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.controlflow.Guards private import codeql.typeflow.TypeFlow +private import codeql.typeflow.UniversalFlow as UniversalFlow -private module Input implements TypeFlowInput { - private newtype TTypeFlowNode = +/** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */ +private RefType boxIfNeeded(J::Type t) { + t.(PrimitiveType).getBoxedType() = result or + result = t +} + +/** Provides the input types and predicates for instantiation of `UniversalFlow`. */ +module FlowStepsInput implements UniversalFlow::UniversalFlowInput { + private newtype TFlowNode = TField(Field f) { not f.getType() instanceof PrimitiveType } or TSsa(BaseSsaVariable ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or TExpr(Expr e) or TMethod(Method m) { not m.getReturnType() instanceof PrimitiveType } - /** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */ - private RefType boxIfNeeded(J::Type t) { - t.(PrimitiveType).getBoxedType() = result or - result = t - } - /** * A `Field`, `BaseSsaVariable`, `Expr`, or `Method`. */ - class TypeFlowNode extends TTypeFlowNode { + class FlowNode extends TFlowNode { + /** Gets a textual representation of this element. */ string toString() { result = this.asField().toString() or result = this.asSsa().toString() or @@ -38,6 +41,7 @@ private module Input implements TypeFlowInput { result = this.asMethod().toString() } + /** Gets the source location for this element. */ Location getLocation() { result = this.asField().getLocation() or result = this.asSsa().getLocation() or @@ -45,14 +49,19 @@ private module Input implements TypeFlowInput { result = this.asMethod().getLocation() } + /** Gets the field corresponding to this node, if any. */ Field asField() { this = TField(result) } + /** Gets the SSA variable corresponding to this node, if any. */ BaseSsaVariable asSsa() { this = TSsa(result) } + /** Gets the expression corresponding to this node, if any. */ Expr asExpr() { this = TExpr(result) } + /** Gets the method corresponding to this node, if any. */ Method asMethod() { this = TMethod(result) } + /** Gets the type of this node. */ RefType getType() { result = this.asField().getType() or result = this.asSsa().getSourceVariable().getType() or @@ -61,8 +70,6 @@ private module Input implements TypeFlowInput { } } - class Type = RefType; - private SrcCallable viableCallable_v1(Call c) { result = viableImpl_v1(c) or @@ -88,7 +95,7 @@ private module Input implements TypeFlowInput { * * For a given `n2`, this predicate must include all possible `n1` that can flow to `n2`. */ - predicate step(TypeFlowNode n1, TypeFlowNode n2) { + predicate step(FlowNode n1, FlowNode n2) { n2.asExpr().(ChooseExpr).getAResultExpr() = n1.asExpr() or exists(Field f, Expr e | @@ -134,7 +141,7 @@ private module Input implements TypeFlowInput { /** * Holds if `null` is the only value that flows to `n`. */ - predicate isNullValue(TypeFlowNode n) { + predicate isNullValue(FlowNode n) { n.asExpr() instanceof NullLiteral or exists(LocalVariableDeclExpr decl | @@ -144,11 +151,21 @@ private module Input implements TypeFlowInput { ) } - predicate isExcludedFromNullAnalysis(TypeFlowNode n) { + predicate isExcludedFromNullAnalysis(FlowNode n) { // Fields that are never assigned a non-null value are probably set by // reflection and are thus not always null. exists(n.asField()) } +} + +private module Input implements TypeFlowInput { + import FlowStepsInput + + class TypeFlowNode = FlowNode; + + predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1; + + class Type = RefType; predicate exactTypeBase(TypeFlowNode n, RefType t) { exists(ClassInstanceExpr e | 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 f33a6d7195f0..79f12e57f6a2 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/BaseSSA.qll @@ -38,6 +38,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable { /** Gets the `Callable` in which this `BaseSsaSourceVariable` is defined. */ Callable getEnclosingCallable() { this = TLocalVar(result, _) } + /** Gets a textual representation of this element. */ string toString() { exists(LocalScopeVariable v, Callable c | this = TLocalVar(c, v) | if c = v.getCallable() @@ -46,6 +47,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable { ) } + /** Gets the source location for this element. */ Location getLocation() { exists(LocalScopeVariable v | this = TLocalVar(_, v) and result = v.getLocation()) } @@ -482,8 +484,10 @@ class BaseSsaVariable extends TBaseSsaVariable { this = TSsaEntryDef(_, result) } + /** Gets a textual representation of this element. */ string toString() { none() } + /** Gets the source location for this element. */ Location getLocation() { result = this.getCfgNode().getLocation() } /** Gets the `BasicBlock` in which this SSA variable is defined. */ diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll index ad770b75a3eb..1c7db851a2cc 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/TaintTrackingUtil.qll @@ -161,6 +161,7 @@ private module Cached { */ cached predicate defaultTaintSanitizer(DataFlow::Node node) { + node instanceof DefaultTaintSanitizer or // Ignore paths through test code. node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or node.asExpr() instanceof ValidatedVariableAccess diff --git a/java/ql/lib/semmle/code/java/security/Encryption.qll b/java/ql/lib/semmle/code/java/security/Encryption.qll index 6fc7f6b7d16a..7c9c5ec60dbf 100644 --- a/java/ql/lib/semmle/code/java/security/Encryption.qll +++ b/java/ql/lib/semmle/code/java/security/Encryption.qll @@ -223,10 +223,7 @@ string getAnInsecureHashAlgorithmName() { } private string rankedInsecureAlgorithm(int i) { - // In this case we know these are being used for encryption, so we want to match - // weak hash algorithms too. - result = - rank[i](string s | s = getAnInsecureAlgorithmName() or s = getAnInsecureHashAlgorithmName()) + result = rank[i](string s | s = getAnInsecureAlgorithmName()) } private string insecureAlgorithmString(int i) { @@ -249,8 +246,8 @@ string getInsecureAlgorithmRegex() { string getASecureAlgorithmName() { result = [ - "RSA", "SHA-?256", "SHA-?512", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))", - "Blowfish", "ECIES" + "RSA", "SHA-?(256|384|512)", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))", + "Blowfish", "ECIES", "SHA3-(256|384|512)" ] } diff --git a/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll b/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll new file mode 100644 index 000000000000..cc57fbce648d --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ListOfConstantsSanitizer.qll @@ -0,0 +1,263 @@ +/** + * Provides a default taint sanitizer identifying comparisons against lists of + * compile-time constants. + */ + +import java +private import codeql.typeflow.UniversalFlow as UniversalFlow +private import semmle.code.java.Collections +private import semmle.code.java.controlflow.Guards +private import semmle.code.java.dataflow.internal.BaseSSA +private import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.dataflow.TypeFlow +private import semmle.code.java.dispatch.VirtualDispatch + +private class FlowNode = FlowStepsInput::FlowNode; + +/** + * Holds if `n2` is an unmodifiable collection constructed from input `n1`, + * which is either another collection or a number of elements. + */ +private predicate unmodifiableCollectionStep(FlowNode n1, FlowNode n2) { + exists(Call c, Callable tgt | + n2.asExpr() = c and + n1.asExpr() = c.getAnArgument() and + c.getCallee().getSourceDeclaration() = tgt + | + tgt.hasQualifiedName("java.util", "Collections", + ["unmodifiableCollection", "unmodifiableList", "unmodifiableSet"]) + or + tgt.hasQualifiedName("java.util", ["List", "Set"], ["copyOf", "of"]) + or + tgt.hasQualifiedName("com.google.common.collect", ["ImmutableList", "ImmutableSet"], + ["copyOf", "of"]) + ) +} + +/** + * Holds if `n2` is a collection or array constructed from input `n1`, which is + * either a collection, an array, or a number of elements. + */ +private predicate collectionStep(FlowNode n1, FlowNode n2) { + n2.asExpr().(ArrayInit).getAnInit() = n1.asExpr() + or + n2.asExpr().(ArrayCreationExpr).getInit() = n1.asExpr() + or + unmodifiableCollectionStep(n1, n2) + or + exists(Call c, Callable tgt | + n2.asExpr() = c and + n1.asExpr() = c.getAnArgument() and + c.getCallee().getSourceDeclaration() = tgt + | + tgt.hasQualifiedName("java.util", "Arrays", "asList") + or + tgt.isStatic() and + tgt.hasName(["copyOf", "of"]) and + tgt.getDeclaringType().getASourceSupertype+().hasQualifiedName("java.util", "Collection") + or + tgt instanceof Constructor and + tgt.getNumberOfParameters() = 1 and + tgt.getParameterType(0) instanceof CollectionType and + tgt.getDeclaringType() instanceof CollectionType + ) +} + +private module BaseUniversalFlow = UniversalFlow::Make; + +private module UnmodifiableProp implements BaseUniversalFlow::NullaryPropertySig { + predicate hasPropertyBase(FlowNode n) { unmodifiableCollectionStep(_, n) } +} + +/** Holds if the given node is an unmodifiable collection. */ +private predicate unmodifiableCollection = + BaseUniversalFlow::FlowNullary::hasProperty/1; + +/** + * Holds if `v` is a collection or array with an access, `coll`, at which the + * element `e` gets added. + */ +private predicate collectionAddition(Variable v, VarAccess coll, Expr e) { + exists(MethodCall mc, Method m, int arg | + mc.getMethod().getSourceDeclaration().overridesOrInstantiates*(m) and + mc.getQualifier() = coll and + v.getAnAccess() = coll and + mc.getArgument(arg) = e + | + m.hasQualifiedName("java.util", "Collection", ["add", "addAll"]) and + m.getNumberOfParameters() = 1 and + arg = 0 + or + m.hasQualifiedName("java.util", "List", ["add", "addAll"]) and + m.getNumberOfParameters() = 2 and + arg = 1 + or + m.hasQualifiedName("java.util", "SequencedCollection", ["addFirst", "addLast"]) and + m.getNumberOfParameters() = 1 and + arg = 0 + ) + or + v.getAnAccess() = coll and + exists(Assignment assign | assign.getSource() = e | + coll = assign.getDest().(ArrayAccess).getArray() + ) +} + +/** + * Holds if `n` represents a definition of `v` and `v` is a collection or + * array that has additions occurring as side-effects after its definition. + */ +private predicate nodeWithAddition(FlowNode n, Variable v) { + collectionAddition(v, _, _) and + ( + n.asField() = v + or + n.asSsa().getSourceVariable().getVariable() = v and + (n.asSsa() instanceof BaseSsaUpdate or n.asSsa().(BaseSsaImplicitInit).isParameterDefinition(_)) + ) +} + +/** Holds if `c` does not add elements to the given collection. */ +private predicate safeCallable(Callable c) { + c instanceof CollectionQueryMethod + or + c instanceof CollectionMethod and + c.hasName(["clear", "remove", "removeAll", "stream", "iterator", "toArray"]) + or + c.hasQualifiedName("org.apache.commons.lang3", "StringUtils", "join") +} + +/** + * Holds if `n` might be mutated in ways that adds elements that are not + * tracked by the `collectionAddition` predicate. + */ +private predicate collectionWithPossibleMutation(FlowNode n) { + not unmodifiableCollection(n) and + ( + exists(Expr e | + n.asExpr() = e and + (e.getType() instanceof CollectionType or e.getType() instanceof Array) and + not collectionAddition(_, e, _) and + not collectionStep(n, _) + | + exists(ArrayAccess aa | e = aa.getArray()) + or + exists(Call c, Callable tgt | c.getAnArgument() = e or c.getQualifier() = e | + tgt = c.getCallee().getSourceDeclaration() and + not safeCallable(tgt) + ) + ) + or + exists(FlowNode mid | + FlowStepsInput::step(n, mid) and + collectionWithPossibleMutation(mid) + ) + ) +} + +/** + * A collection constructor that constructs an empty mutable collection. + */ +private class EmptyCollectionConstructor extends Constructor { + EmptyCollectionConstructor() { + this.getDeclaringType() instanceof CollectionType and + forall(Type t | t = this.getAParamType() | t instanceof PrimitiveType) + } +} + +private module CollectionFlowStepsInput implements UniversalFlow::UniversalFlowInput { + import FlowStepsInput + + /** + * Holds if `n2` is a collection/array/constant whose value(s) are + * determined completely from the range of `n1` nodes. + */ + predicate step(FlowNode n1, FlowNode n2) { + // Exclude the regular input constraints for those nodes that are covered + // completely by `collectionStep`. + FlowStepsInput::step(n1, n2) and + not collectionStep(_, n2) + or + // For collections with side-effects in the form of additions, we add the + // sources of those additions as additional input that need to originate + // from constants. + exists(Variable v | + nodeWithAddition(n2, v) and + collectionAddition(v, _, n1.asExpr()) + ) + or + // Include various forms of collection transformation. + collectionStep(n1, n2) + } + + predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1; +} + +private module CollectionUniversalFlow = UniversalFlow::Make; + +private module ConstantCollectionProp implements CollectionUniversalFlow::NullaryPropertySig { + /** + * Holds if `n` forms the base case for finding collections of constants. + * These are individual constants and empty collections. + */ + predicate hasPropertyBase(FlowNode n) { + n.asExpr().isCompileTimeConstant() or + n.asExpr().(ConstructorCall).getConstructor() instanceof EmptyCollectionConstructor + } + + predicate barrier = collectionWithPossibleMutation/1; +} + +/** + * Holds if the given node is either a constant or a collection/array of + * constants. + */ +private predicate constantCollection = + CollectionUniversalFlow::FlowNullary::hasProperty/1; + +/** Gets the result of a case normalization call of `arg`. */ +private MethodCall normalizeCaseCall(Expr arg) { + exists(Method changecase | result.getMethod() = changecase | + changecase.hasName(["toUpperCase", "toLowerCase"]) and + changecase.getDeclaringType() instanceof TypeString and + arg = result.getQualifier() + or + changecase + .hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "StringUtils", + ["lowerCase", "upperCase"]) and + arg = result.getArgument(0) + or + changecase + .hasQualifiedName("org.apache.hadoop.util", "StringUtils", ["toLowerCase", "toUpperCase"]) and + arg = result.getArgument(0) + ) +} + +/** + * Holds if the guard `g` ensures that the expression `e` is one of a set of + * known constants upon evaluating to `branch`. + */ +private predicate constantCollectionContainsCheck(Guard g, Expr e, boolean branch) { + exists(MethodCall mc, Method m, FlowNode n, Expr checked | + g = mc and + mc.getMethod().getSourceDeclaration().overridesOrInstantiates*(m) and + m.hasQualifiedName("java.util", "Collection", "contains") and + n.asExpr() = mc.getQualifier() and + constantCollection(n) and + checked = mc.getAnArgument() and + branch = true + | + checked = e or + checked = normalizeCaseCall(e) + ) +} + +/** + * A comparison against a list of compile-time constants, sanitizing taint by + * restricting to a set of known values. + */ +private class ListOfConstantsComparisonSanitizerGuard extends TaintTracking::DefaultTaintSanitizer { + ListOfConstantsComparisonSanitizerGuard() { + this = DataFlow::BarrierGuard::getABarrierNode() + } +} diff --git a/java/ql/lib/semmle/code/java/security/MaybeBrokenCryptoAlgorithmQuery.qll b/java/ql/lib/semmle/code/java/security/MaybeBrokenCryptoAlgorithmQuery.qll index 1533b61dd5e4..060a30f87e6a 100644 --- a/java/ql/lib/semmle/code/java/security/MaybeBrokenCryptoAlgorithmQuery.qll +++ b/java/ql/lib/semmle/code/java/security/MaybeBrokenCryptoAlgorithmQuery.qll @@ -30,7 +30,11 @@ class InsecureAlgoLiteral extends InsecureAlgorithm, ShortStringLiteral { s.length() > 1 and not s.regexpMatch(getSecureAlgorithmRegex()) and // Exclude results covered by another query. - not s.regexpMatch(getInsecureAlgorithmRegex()) + not s.regexpMatch(getInsecureAlgorithmRegex()) and + // Exclude results covered by `InsecureAlgoProperty`. + // This removes duplicates when a string literal is a default value for the property, + // such as "MD5" in the following: `props.getProperty("hashAlg2", "MD5")`. + not exists(InsecureAlgoProperty insecAlgoProp | this = insecAlgoProp.getAnArgument()) ) } diff --git a/java/ql/src/change-notes/2024-10-29-weak-crypto-hash.md b/java/ql/src/change-notes/2024-10-29-weak-crypto-hash.md new file mode 100644 index 000000000000..b4ac88bcdc6a --- /dev/null +++ b/java/ql/src/change-notes/2024-10-29-weak-crypto-hash.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `java/weak-cryptographic-algorithm` query has been updated to no longer report uses of hash functions such as `MD5` and `SHA1` even if they are known to be weak. These hash algorithms are used very often in non-sensitive contexts, making the query too imprecise in practice. The `java/potentially-weak-cryptographic-algorithm` query has been updated to report these uses instead. diff --git a/java/ql/src/change-notes/2024-11-22-sha3.md b/java/ql/src/change-notes/2024-11-22-sha3.md new file mode 100644 index 000000000000..61dbc35162e1 --- /dev/null +++ b/java/ql/src/change-notes/2024-11-22-sha3.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added SHA3 to the list of secure hashing algorithms. As a result the `java/potentially-weak-cryptographic-algorithm` query should no longer flag up uses of SHA3. diff --git a/java/ql/src/change-notes/2024-11-24-sha2.md b/java/ql/src/change-notes/2024-11-24-sha2.md new file mode 100644 index 000000000000..395ea04b782e --- /dev/null +++ b/java/ql/src/change-notes/2024-11-24-sha2.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added SHA-384 to the list of secure hashing algorithms. As a result the `java/potentially-weak-cryptographic-algorithm` query should no longer flag up uses of SHA-384. diff --git a/java/ql/test/library-tests/dataflow/getter/getter.expected b/java/ql/test/library-tests/dataflow/getter/getter.expected index b5af3f91a593..9a36107f1983 100644 --- a/java/ql/test/library-tests/dataflow/getter/getter.expected +++ b/java/ql/test/library-tests/dataflow/getter/getter.expected @@ -1,6 +1,5 @@ | A.java:5:12:5:15 | this | A.java:5:12:5:19 | this.foo | A.java:2:7:2:9 | foo | | A.java:21:13:21:13 | a | A.java:21:13:21:22 | getFoo(...) | A.java:2:7:2:9 | foo | | A.java:23:9:23:9 | a | A.java:23:9:23:19 | aGetter(...) | A.java:2:7:2:9 | foo | -| A.java:24:9:24:10 | a2 | A.java:24:9:24:23 | notAGetter(...) | A.java:2:7:2:9 | foo | | A.java:45:12:45:38 | maybeIdWrap(...) | A.java:45:12:45:42 | maybeIdWrap(...).foo | A.java:2:7:2:9 | foo | | A.java:49:12:49:38 | maybeIdWrap(...) | A.java:49:12:49:42 | maybeIdWrap(...).foo | A.java:2:7:2:9 | foo | diff --git a/java/ql/test/library-tests/dataflow/range-analysis-inline/B.java b/java/ql/test/library-tests/dataflow/range-analysis-inline/B.java new file mode 100644 index 000000000000..01c8656deead --- /dev/null +++ b/java/ql/test/library-tests/dataflow/range-analysis-inline/B.java @@ -0,0 +1,158 @@ +public class B { + + // Use this method to mark non-integer bounds + // that should also be annotated. + static void bound(int b) { } + + public int forLoop() { + int result = 0; + for (int i = 0; + i < 10; // $ bound="i in [0..10]" + i++) { // $ bound="i in [0..9]" + result = i; // $ bound="i in [0..9]" + } + return result; // $ bound="result in [0..9]" + } + + public int forLoopExit() { + int result = 0; + for (; result < 10;) { // $ bound="result in [0..10]" + result += 1; // $ bound="result in [0..9]" + } + return result; // $ bound="result = 10" + } + + public int forLoopExitStep() { + int result = 0; + for (; result < 10;) { // $ bound="result in [0..12]" + result += 3; // $ bound="result in [0..9]" + } + return result; // $ bound="result = 12" + } + + public int forLoopExitUpd() { + int result = 0; + for (; result < 10; // $ bound="result in [0..10]" + result++) { // $ bound="result in [0..9]" + } + return result; // $ bound="result = 10" + } + + public int forLoopExitNested() { + int result = 0; + for (; result < 10;) { + int i = 0; + for (; i < 3;) { // $ bound="i in [0..3]" + i += 1; // $ bound="i in [0..2]" + } + result += i; // $ bound="result in [0..9]" bound="i = 3" + } + return result; // $ MISSING:bound="result = 12" + } + + public int emptyForLoop() { + int result = 0; + for (int i = 0; i < 0; // $ bound="i = 0" + i++) { // $ bound="i in [0..-1]" + result = i; // $ bound="i in [0..-1]" + } + return result; // $ bound="result = 0" + } + + public int noLoop() { + int result = 0; + result += 1; // $ bound="result = 0" + return result; // $ bound="result = 1" + } + + public int foreachLoop() { + int result = 0; + for (int i : new int[] {1, 2, 3, 4, 5}) { + result = i; + } + return result; + } + + public int emptyForeachLoop() { + int result = 0; + for (int i : new int[] {}) { + result = i; + } + return result; + } + + public int whileLoop() { + int result = 100; + while (result > 5) { // $ bound="result in [4..100]" + result = result - 2; // $ bound="result in [6..100]" + } + return result; // $ bound="result = 4" + } + + public int oddWhileLoop() { + int result = 101; + while (result > 5) { // $ bound="result in [5..101]" + result = result - 2; // $ bound="result in [7..101]" + } + return result; // $ bound="result = 5" + } + + static void arrayLength(int[] arr) { + bound(arr.length); + for (int i = 0; + i < arr.length; + i++) { // $ bound="i <= arr.length - 1" + arr[i]++; // $ bound="i <= arr.length - 1" + } + } + + static int varBound(int b) { + bound(b); + int result = 0; + for (int i = 0; + i < b; + i++) { // $ bound="i <= b - 1" + result = i; // $ bound="i <= b - 1" + } + return result; // We cannot conclude anything here, since we do not know that b > 0 + } + + static int varBoundPositiveGuard(int b) { + bound(b); + if (b > 0) { + int result = 0; + for (int i = 0; + i < b; + i++) { // $ bound="i <= b - 1" + result = i; // $ bound="i <= b - 1" + } + return result; // $ MISSING: bound="result <= b - 1" + } else { + return 0; + } + } + + static int varBoundPositiveGuardEarlyReturn(int b) { + bound(b); + if (b <= 0) return 0; + int result = 0; + for (int i = 0; + i < b; + i++) { // $ bound="i <= b - 1" + result = i; // $ bound="i <= b - 1" + } + return result; // $ MISSING: bound="result <= b - 1" + } + + static int varBoundPositiveAssert(int b) { + bound(b); + assert b > 0; + int result = 0; + for (int i = 0; + i < b; + i++) { // $ bound="i <= b - 1" + result = i; // $ bound="i <= b - 1" + } + return result; // $ MISSING: bound="result <= b - 1" + } +} \ No newline at end of file diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.expected b/java/ql/test/library-tests/dataflow/range-analysis-inline/range.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.expected rename to java/ql/test/library-tests/dataflow/range-analysis-inline/range.expected diff --git a/java/ql/test/library-tests/dataflow/range-analysis-inline/range.ql b/java/ql/test/library-tests/dataflow/range-analysis-inline/range.ql new file mode 100644 index 000000000000..b0fcc1710d44 --- /dev/null +++ b/java/ql/test/library-tests/dataflow/range-analysis-inline/range.ql @@ -0,0 +1,71 @@ +/** + * Inline range analysis tests for Java. + * See `shared/util/codeql/dataflow/test/InlineFlowTest.qll` + */ + +import java +import semmle.code.java.dataflow.RangeAnalysis +private import TestUtilities.InlineExpectationsTest as IET + +module RangeTest implements IET::TestSig { + string getARelevantTag() { result = "bound" } + + predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "bound" and + ( + // simple integer bounds (`ZeroBound`s) + exists(Expr e, int lower, int upper | + constrained(e, lower, upper) and + e instanceof VarRead and + e.getCompilationUnit().fromSource() + | + location = e.getLocation() and + element = e.toString() and + if lower = upper + then value = "\"" + e.toString() + " = " + lower.toString() + "\"" + else + value = "\"" + e.toString() + " in [" + lower.toString() + ".." + upper.toString() + "]\"" + ) + or + // advanced bounds + exists(Expr e, int delta, string deltaStr, boolean upper, string cmp, Expr boundExpr | + annotatedBound(e, _, boundExpr, delta, upper) and + e instanceof VarRead and + e.getCompilationUnit().fromSource() and + ( + if delta = 0 + then deltaStr = "" + else + if delta > 0 + then deltaStr = " + " + delta.toString() + else deltaStr = " - " + delta.abs().toString() + ) and + if upper = true then cmp = "<=" else cmp = ">=" + | + location = e.getLocation() and + element = e.toString() and + value = "\"" + e.toString() + " " + cmp + " " + boundExpr.toString() + deltaStr + "\"" + ) + ) + } + + private predicate constrained(Expr e, int lower, int upper) { + bounded(e, any(ZeroBound z), lower, false, _) and + bounded(e, any(ZeroBound z), upper, true, _) + } + + private predicate annotatedBound(Expr e, Bound b, Expr boundExpr, int delta, boolean upper) { + bounded(e, b, delta, upper, _) and + // the expression for the bound is explicitly requested as being annotated + // via a call such as + // ```java + // bound(expr); + // ``` + boundExpr = b.getExpr() and + exists(Call c | c.getCallee().getName() = "bound" and c.getArgument(0) = boundExpr) and + // non-trivial bound + not e = b.getExpr() + } +} + +import IET::MakeTest diff --git a/java/ql/test/library-tests/listofconstants/A.java b/java/ql/test/library-tests/listofconstants/A.java new file mode 100644 index 000000000000..74129692d71d --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/A.java @@ -0,0 +1,35 @@ +import java.util.*; + +public class A { + private static final Set SEPARATORS = + Collections.unmodifiableSet( + new HashSet<>(Arrays.asList("\t", "\n", ";"))); + + public static void sink(String s) { } + + private void checkSeparator(String separator) { + if (SEPARATORS.contains(separator)) { + sink(separator); + } + } + + public static final String URI1 = "yarn.io/gpu"; + public static final String URI2 = "yarn.io/fpga"; + + public static final Set SCHEMAS = Set.of(URI1, URI2, "s3a", "wasb"); + + private void checkSchema(String schema) { + if (SCHEMAS.contains(schema)) { + sink(schema); + } + } + + private void testAdd(String inp) { + Set s = new HashSet<>(); + s.add("AA"); + s.add("BB"); + if (s.contains(inp.toUpperCase())) { + sink(inp); + } + } +} diff --git a/java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected b/java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected new file mode 100644 index 000000000000..1ea902154a6e --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/CONSISTENCY/typeParametersInScope.expected @@ -0,0 +1 @@ +| Type A uses out-of-scope type variable E. Note the Java extractor is known to sometimes do this; the Kotlin extractor should not. | diff --git a/java/ql/test/library-tests/listofconstants/test.expected b/java/ql/test/library-tests/listofconstants/test.expected new file mode 100644 index 000000000000..203d64cd46dd --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/test.expected @@ -0,0 +1,3 @@ +| A.java:12:12:12:20 | separator | +| A.java:23:12:23:17 | schema | +| A.java:32:12:32:14 | inp | diff --git a/java/ql/test/library-tests/listofconstants/test.ql b/java/ql/test/library-tests/listofconstants/test.ql new file mode 100644 index 000000000000..f56dfc0f11f4 --- /dev/null +++ b/java/ql/test/library-tests/listofconstants/test.ql @@ -0,0 +1,5 @@ +import java +import semmle.code.java.dataflow.FlowSteps + +from DefaultTaintSanitizer e +select e diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java new file mode 100644 index 000000000000..285f9bc49cb2 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilList.java @@ -0,0 +1,306 @@ +// Test cases for CWE-089 (SQL injection and Java Persistence query injection) +// http://cwe.mitre.org/data/definitions/89.html +package test.cwe089.semmle.tests; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +class AllowListSanitizerWithJavaUtilList { + public static Connection connection; + public static final List goodAllowList1 = List.of("allowed1", "allowed2", "allowed3"); + public static final List goodAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1")); + public static final List goodAllowList3; + public static final List goodAllowList4; + public static final List goodAllowList5; + public static final List badAllowList1 = List.of("allowed1", "allowed2", getNonConstantString()); + public static final List badAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString())); + public static final List badAllowList3; + public static final List badAllowList4; + public static List badAllowList6 = List.of("allowed1", "allowed2", "allowed3"); + public final List goodAllowList7 = List.of("allowed1", "allowed2", "allowed3"); + + static { + goodAllowList3 = List.of("allowed1", "allowed2", "allowed3"); + goodAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2")); + badAllowList3 = List.of(getNonConstantString(), "allowed2", "allowed3"); + badAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString())); + goodAllowList5 = new ArrayList(); + goodAllowList5.add("allowed1"); + goodAllowList5.add("allowed2"); + goodAllowList5.add("allowed3"); + } + + public static String getNonConstantString() { + return String.valueOf(System.currentTimeMillis()); + } + + public static void main(String[] args) throws IOException, SQLException { + badAllowList6 = List.of("allowed1", getNonConstantString(), "allowed3"); + testStaticFields(args); + testLocal(args); + var x = new AllowListSanitizerWithJavaUtilList(); + x.testNonStaticFields(args); + testMultipleSources(args); + testEscape(args); + } + + private static void testStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + if(goodAllowList1.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList2.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList1.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList2.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList5.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: the allowlist is in a non-final field + if(badAllowList6.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private void testNonStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[0]; + // GOOD: the allowlist is in a non-static field + if(goodAllowList7.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private static void testLocal(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + { + List allowlist = List.of("allowed1", "allowed2", "allowed3"); + if(allowlist.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + List allowlist = List.of("allowed1", "allowed2", args[2]); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + List allowlist = List.of(allowedArray); + if(allowlist.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + List allowlist = List.of(allowedArray); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + List allowlist = Collections.unmodifiableList(Arrays.asList("allowed1")); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + List allowlist = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2", args[2])); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + List allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray)); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + List allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray)); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant string + { + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + allowlist.add("allowed2"); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + allowlist.add(getNonConstantString()); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but it contains a non-compile-time constant element + { + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + addNonConstantStringDirectly(allowlist); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testMultipleSources(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which might contain constant strings + List allowlist = new ArrayList(); + allowlist.add("allowed1"); + if (b) { + allowlist.add(getNonConstantString()); + } + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + List allowlist = b ? goodAllowList1 : badAllowList1; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + List allowlist = b ? goodAllowList1 : List.of("allowed1", "allowed2", args[2]);; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testEscape(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which contains constant strings + List allowlist = new ArrayList(); + addNonConstantStringViaLambda(e -> allowlist.add(e)); + if(allowlist.contains(tainted)){ // missing result + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void addNonConstantStringDirectly(List list) { + list.add(getNonConstantString()); + } + + private static void addNonConstantStringViaLambda(Consumer adder) { + adder.accept(getNonConstantString()); + } + +} diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java new file mode 100644 index 000000000000..e1a5f889c6fa --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/AllowListSanitizerWithJavaUtilSet.java @@ -0,0 +1,305 @@ +// Test cases for CWE-089 (SQL injection and Java Persistence query injection) +// http://cwe.mitre.org/data/definitions/89.html +package test.cwe089.semmle.tests; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; +import java.util.function.Consumer; + +class AllowListSanitizerWithJavaUtilSet { + public static Connection connection; + public static final Set goodAllowList1 = Set.of("allowed1", "allowed2", "allowed3"); + public static final Set goodAllowList2 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1","allowed2"))); + public static final Set goodAllowList3; + public static final Set goodAllowList4; + public static final Set goodAllowList5; + public static final Set badAllowList1 = Set.of("allowed1", "allowed2", getNonConstantString()); + public static final Set badAllowList2 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", getNonConstantString()))); + public static final Set badAllowList3; + public static final Set badAllowList4; + public static Set badAllowList6 = Set.of("allowed1", "allowed2", "allowed3"); + public final Set goodAllowList7 = Set.of("allowed1", "allowed2", "allowed3"); + + static { + goodAllowList3 = Set.of("allowed1", "allowed2", "allowed3"); + goodAllowList4 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", "allowed2"))); + badAllowList3 = Set.of(getNonConstantString(), "allowed2", "allowed3"); + badAllowList4 = Collections.unmodifiableSet(new HashSet(Arrays.asList("allowed1", getNonConstantString()))); + goodAllowList5 = new HashSet(); + goodAllowList5.add("allowed1"); + goodAllowList5.add("allowed2"); + goodAllowList5.add("allowed3"); + } + + public static String getNonConstantString() { + return String.valueOf(System.currentTimeMillis()); + } + + public static void main(String[] args) throws IOException, SQLException { + badAllowList6 = Set.of("allowed1", getNonConstantString(), "allowed3"); + testStaticFields(args); + testLocal(args); + var x = new AllowListSanitizerWithJavaUtilSet(); + x.testNonStaticFields(args); + testMultipleSources(args); + testEscape(args); + } + + private static void testStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + if(goodAllowList1.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList2.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList1.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList2.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList3.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: an allowlist is used with constant strings + if(badAllowList4.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // GOOD: an allowlist is used with constant strings + if(goodAllowList5.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + // BAD: the allowlist is in a non-final field + if(badAllowList6.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private void testNonStaticFields(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: the allowlist is in a non-static field + if(goodAllowList7.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + + private static void testLocal(String[] args) throws IOException, SQLException { + String tainted = args[1]; + // GOOD: an allowlist is used with constant strings + { + Set allowlist = Set.of("allowed1", "allowed2", "allowed3"); + if(allowlist.contains(tainted.toLowerCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + Set allowlist = Set.of("allowed1", "allowed2", args[2]); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + Set allowlist = Set.of(allowedArray); + if(allowlist.contains(tainted.toUpperCase())){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + Set allowlist = Set.of(allowedArray); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1"))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1", "allowed2", args[2]))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant strings + { + String[] allowedArray = {"allowed1", "allowed2", "allowed3"}; + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + String[] allowedArray = {"allowed1", "allowed2", args[2]}; + Set allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray))); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // GOOD: an allowlist is used with constant string + { + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + allowlist.add("allowed2"); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but one of the entries is not a compile-time constant + { + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + allowlist.add(getNonConstantString()); + allowlist.add("allowed3"); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + // BAD: an allowlist is used but it contains a non-compile-time constant element + { + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + addNonConstantStringDirectly(allowlist); + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testMultipleSources(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which might contain constant strings + Set allowlist = new HashSet(); + allowlist.add("allowed1"); + if (b) { + allowlist.add(getNonConstantString()); + } + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + Set allowlist = b ? goodAllowList1 : badAllowList1; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + { + // BAD: an allowlist is used which might contain constant strings + Set allowlist = b ? goodAllowList1 : Set.of("allowed1", "allowed2", args[2]);; + if(allowlist.contains(tainted)){ + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void testEscape(String[] args) throws IOException, SQLException { + String tainted = args[1]; + boolean b = args[2] == "True"; + { + // BAD: an allowlist is used which contains constant strings + Set allowlist = new HashSet(); + addNonConstantStringViaLambda(e -> allowlist.add(e)); + if(allowlist.contains(tainted)){ // missing result + String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + + tainted + "' ORDER BY PRICE"; + ResultSet results = connection.createStatement().executeQuery(query); + } + } + } + + private static void addNonConstantStringDirectly(Set set) { + set.add(getNonConstantString()); + } + + private static void addNonConstantStringViaLambda(Consumer adder) { + adder.accept(getNonConstantString()); + } + +} diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected new file mode 100644 index 000000000000..1f8028eff60e --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/CONSISTENCY/typeParametersInScope.expected @@ -0,0 +1 @@ +| Type AllowListSanitizerWithJavaUtilSet uses out-of-scope type variable E. Note the Java extractor is known to sometimes do this; the Kotlin extractor should not. | diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected index fc1d87f06b17..1e560f03c3b9 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlConcatenated.expected @@ -1,3 +1,55 @@ +| AllowListSanitizerWithJavaUtilList.java:64:66:64:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:63:8:63:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:70:66:70:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:69:8:69:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:76:66:76:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:75:8:75:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:82:66:82:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:81:8:81:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:87:8:87:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:93:8:93:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:99:8:99:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:105:8:105:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:111:8:111:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:117:8:117:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:127:8:127:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:140:67:140:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:139:9:139:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:148:9:148:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:159:67:159:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:158:9:158:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:168:9:168:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:178:67:178:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:177:9:177:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:186:9:186:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:197:67:197:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:196:9:196:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:206:9:206:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:219:67:219:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:218:9:218:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:230:9:230:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:241:9:241:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:259:9:259:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:268:9:268:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:277:9:277:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:292:9:292:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:63:66:63:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:62:8:62:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:69:66:69:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:68:8:68:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:75:66:75:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:74:8:74:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:81:66:81:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:80:8:80:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:86:8:86:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:92:8:92:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:98:8:98:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:104:8:104:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:110:8:110:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:116:8:116:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:126:8:126:14 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:139:67:139:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:138:9:138:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:147:9:147:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:158:67:158:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:157:9:157:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:167:9:167:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:177:67:177:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:176:9:176:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:185:9:185:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:196:67:196:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:195:9:195:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:205:9:205:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:218:67:218:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:217:9:217:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:229:9:229:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:240:9:240:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:258:9:258:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:267:9:267:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:276:9:276:15 | tainted | this expression | +| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:291:9:291:15 | tainted | this expression | | Test.java:36:47:36:52 | query1 | Query built by concatenation with $@, which may be untrusted. | Test.java:35:8:35:15 | category | this expression | | Test.java:42:57:42:62 | query2 | Query built by concatenation with $@, which may be untrusted. | Test.java:41:51:41:52 | id | this expression | | Test.java:50:62:50:67 | query3 | Query built by concatenation with $@, which may be untrusted. | Test.java:49:8:49:15 | category | this expression | diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected index d54bbdaec05d..a45f58bd54d6 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/SqlTainted.expected @@ -1,4 +1,34 @@ #select +| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | +| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value | | Mongo.java:17:45:17:67 | parse(...) | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:45:17:67 | parse(...) | This query depends on a $@. | Mongo.java:10:29:10:41 | args | user-provided value | | Mongo.java:21:49:21:52 | json | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | This query depends on a $@. | Mongo.java:10:29:10:41 | args | user-provided value | | Test.java:36:47:36:52 | query1 | Test.java:227:26:227:38 | args : String[] | Test.java:36:47:36:52 | query1 | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value | @@ -10,6 +40,52 @@ | Test.java:209:47:209:68 | queryWithUserTableName | Test.java:227:26:227:38 | args : String[] | Test.java:209:47:209:68 | queryWithUserTableName | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value | | Test.java:221:81:221:111 | ... + ... | Test.java:227:26:227:38 | args : String[] | Test.java:221:81:221:111 | ... + ... | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value | edges +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | provenance | | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | provenance | Sink:MaD:4 | +| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | provenance | Sink:MaD:4 | | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:56:17:66 | stringQuery : String | provenance | | | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | provenance | | | Mongo.java:17:56:17:66 | stringQuery : String | Mongo.java:17:45:17:67 | parse(...) | provenance | Config | @@ -40,6 +116,54 @@ models | 6 | Summary: java.lang; AbstractStringBuilder; true; append; ; ; Argument[0]; Argument[this]; taint; manual | | 7 | Summary: java.lang; CharSequence; true; toString; ; ; Argument[this]; ReturnValue; taint; manual | nodes +| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | semmle.label | query | +| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | semmle.label | args : String[] | +| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | semmle.label | query | | Mongo.java:10:29:10:41 | args : String[] | semmle.label | args : String[] | | Mongo.java:17:45:17:67 | parse(...) | semmle.label | parse(...) | | Mongo.java:17:56:17:66 | stringQuery : String | semmle.label | stringQuery : String | diff --git a/java/ql/test/query-tests/security/CWE-327/semmle/tests/BrokenCryptoAlgorithm.expected b/java/ql/test/query-tests/security/CWE-327/semmle/tests/BrokenCryptoAlgorithm.expected index 612e1c730544..94719b477391 100644 --- a/java/ql/test/query-tests/security/CWE-327/semmle/tests/BrokenCryptoAlgorithm.expected +++ b/java/ql/test/query-tests/security/CWE-327/semmle/tests/BrokenCryptoAlgorithm.expected @@ -1,14 +1,8 @@ #select | Test.java:19:20:19:50 | getInstance(...) | Test.java:19:45:19:49 | "DES" | Test.java:19:45:19:49 | "DES" | Cryptographic algorithm $@ is weak and should not be used. | Test.java:19:45:19:49 | "DES" | DES | | Test.java:42:14:42:38 | getInstance(...) | Test.java:42:33:42:37 | "RC2" | Test.java:42:33:42:37 | "RC2" | Cryptographic algorithm $@ is weak and should not be used. | Test.java:42:33:42:37 | "RC2" | RC2 | -| WeakHashing.java:21:30:21:92 | getInstance(...) | WeakHashing.java:21:86:21:90 | "MD5" : String | WeakHashing.java:21:56:21:91 | getProperty(...) | Cryptographic algorithm $@ is weak and should not be used. | WeakHashing.java:21:86:21:90 | "MD5" | MD5 | edges -| WeakHashing.java:21:86:21:90 | "MD5" : String | WeakHashing.java:21:56:21:91 | getProperty(...) | provenance | MaD:1 | -models -| 1 | Summary: java.util; Properties; true; getProperty; (String,String); ; Argument[1]; ReturnValue; value; manual | nodes | Test.java:19:45:19:49 | "DES" | semmle.label | "DES" | | Test.java:42:33:42:37 | "RC2" | semmle.label | "RC2" | -| WeakHashing.java:21:56:21:91 | getProperty(...) | semmle.label | getProperty(...) | -| WeakHashing.java:21:86:21:90 | "MD5" : String | semmle.label | "MD5" : String | subpaths diff --git a/java/ql/test/query-tests/security/CWE-327/semmle/tests/WeakHashing.java b/java/ql/test/query-tests/security/CWE-327/semmle/tests/WeakHashing.java index 6a3565fc1412..c79c025a41c8 100644 --- a/java/ql/test/query-tests/security/CWE-327/semmle/tests/WeakHashing.java +++ b/java/ql/test/query-tests/security/CWE-327/semmle/tests/WeakHashing.java @@ -19,11 +19,17 @@ void hashing() throws NoSuchAlgorithmException, IOException { // BAD: Using a strong hashing algorithm but with a weak default MessageDigest bad3 = MessageDigest.getInstance(props.getProperty("hashAlg2", "MD5")); - + // GOOD: Using a strong hashing algorithm MessageDigest ok = MessageDigest.getInstance(props.getProperty("hashAlg2")); // OK: Property does not exist and default is secure MessageDigest ok2 = MessageDigest.getInstance(props.getProperty("hashAlg3", "SHA-256")); + + // GOOD: Using a strong hashing algorithm + MessageDigest ok3 = MessageDigest.getInstance("SHA3-512"); + + // GOOD: Using a strong hashing algorithm + MessageDigest ok4 = MessageDigest.getInstance("SHA384"); } -} \ No newline at end of file +} diff --git a/javascript/extractor/lib/typescript/package-lock.json b/javascript/extractor/lib/typescript/package-lock.json index 50a9e0a66caa..1978e3963246 100644 --- a/javascript/extractor/lib/typescript/package-lock.json +++ b/javascript/extractor/lib/typescript/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "typescript-parser-wrapper", "dependencies": { - "typescript": "^5.6.2" + "typescript": "^5.7.2" }, "devDependencies": { "@types/node": "18.15.3" @@ -20,9 +20,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index bf650ec457a4..9d77f4ab740a 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -2,7 +2,7 @@ "name": "typescript-parser-wrapper", "private": true, "dependencies": { - "typescript": "5.6.2" + "typescript": "^5.7.2" }, "scripts": { "build": "tsc --project tsconfig.json", diff --git a/javascript/ql/integration-tests/diagnostics/internal-error/src/my_failure.ts b/javascript/ql/integration-tests/diagnostics/internal-error/src/my_failure.ts index 29e78b136e82..f2a1644e18ff 100644 --- a/javascript/ql/integration-tests/diagnostics/internal-error/src/my_failure.ts +++ b/javascript/ql/integration-tests/diagnostics/internal-error/src/my_failure.ts @@ -1,17 +1,3022 @@ -type Output = { - (...args: S): any; -}; - -declare function createThing( - type: K, - fn: (...args: S) => any -): Output; - -const one = createThing("one", () => ({})); - -const two = createThing("two", () => ({})); - -const three = createThing("three", (cursor: string) => null); -const four = createThing("four", (error: number) => null); - -type Events = Array; +console.log( + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 + + 1 +); diff --git a/javascript/ql/lib/change-notes/2024-11-18-ES2022-find-functions.md b/javascript/ql/lib/change-notes/2024-11-18-ES2022-find-functions.md new file mode 100644 index 000000000000..e3fe3b6aef25 --- /dev/null +++ b/javascript/ql/lib/change-notes/2024-11-18-ES2022-find-functions.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- +* Added taint-steps for `Array.prototype.findLast` +* Added taint-steps for `Array.prototype.findLastIndex` diff --git a/javascript/ql/lib/change-notes/2024-11-20-ES2023-string-protytpe-toWellFormed.md b/javascript/ql/lib/change-notes/2024-11-20-ES2023-string-protytpe-toWellFormed.md new file mode 100644 index 000000000000..dda4d8787605 --- /dev/null +++ b/javascript/ql/lib/change-notes/2024-11-20-ES2023-string-protytpe-toWellFormed.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added taint-steps for `String.prototype.toWellFormed`. diff --git a/javascript/ql/lib/change-notes/2024-11-20-ES2024-group-functions.md b/javascript/ql/lib/change-notes/2024-11-20-ES2024-group-functions.md new file mode 100644 index 000000000000..8511727f8e77 --- /dev/null +++ b/javascript/ql/lib/change-notes/2024-11-20-ES2024-group-functions.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added taint-steps for `Map.groupBy` and `Object.groupBy`. diff --git a/javascript/ql/lib/semmle/javascript/Arrays.qll b/javascript/ql/lib/semmle/javascript/Arrays.qll index 7ce37130996a..bec711b835a7 100644 --- a/javascript/ql/lib/semmle/javascript/Arrays.qll +++ b/javascript/ql/lib/semmle/javascript/Arrays.qll @@ -384,10 +384,10 @@ private module ArrayLibraries { } /** - * Gets a call to `Array.prototype.find` or a polyfill implementing the same functionality. + * Gets a call to `Array.prototype.find` or `Array.prototype.findLast` or a polyfill implementing the same functionality. */ DataFlow::CallNode arrayFindCall(DataFlow::Node array) { - result.(DataFlow::MethodCallNode).getMethodName() = "find" and + result.(DataFlow::MethodCallNode).getMethodName() in ["find", "findLast"] and array = result.getReceiver() or result = DataFlow::moduleImport(["array.prototype.find", "array-find"]).getACall() and @@ -483,4 +483,31 @@ private module ArrayLibraries { ) } } + + /** + * Defines a data flow step that tracks the flow of data through callback functions in arrays. + */ + private class ArrayCallBackDataFlowStep extends PreCallGraphStep { + override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) { + exists(DataFlow::MethodCallNode call | + call.getMethodName() = ["findLast", "find", "findLastIndex"] and + prop = arrayLikeElement() and + obj = call.getReceiver() and + element = call.getCallback(0).getParameter(0) + ) + } + } + + /** + * This step models the propagation of data from the array to the callback function's parameter. + */ + private class ArrayCallBackDataTaintStep extends TaintTracking::SharedTaintStep { + override predicate step(DataFlow::Node obj, DataFlow::Node element) { + exists(DataFlow::MethodCallNode call | + call.getMethodName() = ["findLast", "find", "findLastIndex"] and + obj = call.getReceiver() and + element = call.getCallback(0).getParameter(0) + ) + } + } } diff --git a/javascript/ql/lib/semmle/javascript/Collections.qll b/javascript/ql/lib/semmle/javascript/Collections.qll index a0e251554ff7..028c3abe4b3b 100644 --- a/javascript/ql/lib/semmle/javascript/Collections.qll +++ b/javascript/ql/lib/semmle/javascript/Collections.qll @@ -151,4 +151,32 @@ private module CollectionDataFlow { ) } } + + /** + * A step for a call to `groupBy` on an iterable object. + */ + private class GroupByTaintStep extends TaintTracking::SharedTaintStep { + override predicate heapStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(DataFlow::MethodCallNode call | + call = DataFlow::globalVarRef(["Map", "Object"]).getAMemberCall("groupBy") and + pred = call.getArgument(0) and + (succ = call.getCallback(1).getParameter(0) or succ = call) + ) + } + } + + /** + * A step for handling data flow and taint tracking for the groupBy method on iterable objects. + * Ensures propagation of taint and data flow through the groupBy operation. + */ + private class GroupByDataFlowStep extends PreCallGraphStep { + override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { + exists(DataFlow::MethodCallNode call | + call = DataFlow::globalVarRef("Map").getAMemberCall("groupBy") and + pred = call.getArgument(0) and + succ = call and + prop = mapValueUnknownKey() + ) + } + } } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index a19691e94480..6b6fc9c4b07d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -612,7 +612,7 @@ module TaintTracking { "italics", "link", "padEnd", "padStart", "repeat", "replace", "replaceAll", "slice", "small", "split", "strike", "sub", "substr", "substring", "sup", "toLocaleLowerCase", "toLocaleUpperCase", "toLowerCase", "toUpperCase", "trim", - "trimLeft", "trimRight" + "trimLeft", "trimRight", "toWellFormed" ] or // sorted, interesting, properties of Object.prototype diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index ea5f2fb97558..818f0d922d48 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -114,7 +114,7 @@ predicate hasNonVoidCallbackMethod(string name) { name = [ "every", "filter", "find", "findIndex", "flatMap", "map", "reduce", "reduceRight", "some", - "sort" + "sort", "findLastIndex", "findLast" ] } diff --git a/javascript/ql/test/library-tests/Arrays/DataFlow.expected b/javascript/ql/test/library-tests/Arrays/DataFlow.expected index 4332f14c45e2..07fabfb7270c 100644 --- a/javascript/ql/test/library-tests/Arrays/DataFlow.expected +++ b/javascript/ql/test/library-tests/Arrays/DataFlow.expected @@ -14,6 +14,7 @@ | arrays.js:2:16:2:23 | "source" | arrays.js:90:10:90:10 | x | | arrays.js:2:16:2:23 | "source" | arrays.js:93:8:93:17 | arr.at(-1) | | arrays.js:2:16:2:23 | "source" | arrays.js:109:8:109:24 | arr8_spread.pop() | +| arrays.js:2:16:2:23 | "source" | arrays.js:111:8:111:33 | arr.fin ... llback) | | arrays.js:18:22:18:29 | "source" | arrays.js:18:50:18:50 | e | | arrays.js:22:15:22:22 | "source" | arrays.js:23:8:23:17 | arr2.pop() | | arrays.js:25:15:25:22 | "source" | arrays.js:26:8:26:17 | arr3.pop() | @@ -25,3 +26,8 @@ | arrays.js:53:4:53:11 | "source" | arrays.js:54:10:54:18 | ary.pop() | | arrays.js:99:31:99:38 | "source" | arrays.js:100:8:100:17 | arr8.pop() | | arrays.js:103:55:103:62 | "source" | arrays.js:105:8:105:25 | arr8_variant.pop() | +| arrays.js:114:19:114:26 | "source" | arrays.js:115:50:115:53 | item | +| arrays.js:114:19:114:26 | "source" | arrays.js:116:10:116:16 | element | +| arrays.js:120:19:120:26 | "source" | arrays.js:121:46:121:49 | item | +| arrays.js:120:19:120:26 | "source" | arrays.js:122:10:122:16 | element | +| arrays.js:126:19:126:26 | "source" | arrays.js:127:55:127:58 | item | diff --git a/javascript/ql/test/library-tests/Arrays/DataFlow.ql b/javascript/ql/test/library-tests/Arrays/DataFlow.ql index 80c9f068a10f..5c5f4a0d10e6 100644 --- a/javascript/ql/test/library-tests/Arrays/DataFlow.ql +++ b/javascript/ql/test/library-tests/Arrays/DataFlow.ql @@ -3,7 +3,10 @@ import javascript class ArrayFlowConfig extends DataFlow::Configuration { ArrayFlowConfig() { this = "ArrayFlowConfig" } - override predicate isSource(DataFlow::Node source) { source.asExpr().getStringValue() = "source" } + override predicate isSource(DataFlow::Node source) { + source.asExpr().getStringValue() = "source" or + source.(DataFlow::CallNode).getCalleeName() = "source" + } override predicate isSink(DataFlow::Node sink) { sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument() diff --git a/javascript/ql/test/library-tests/Arrays/TaintFlow.expected b/javascript/ql/test/library-tests/Arrays/TaintFlow.expected index a531715bfb6b..246a52e803b2 100644 --- a/javascript/ql/test/library-tests/Arrays/TaintFlow.expected +++ b/javascript/ql/test/library-tests/Arrays/TaintFlow.expected @@ -15,6 +15,7 @@ | arrays.js:2:16:2:23 | "source" | arrays.js:90:10:90:10 | x | | arrays.js:2:16:2:23 | "source" | arrays.js:93:8:93:17 | arr.at(-1) | | arrays.js:2:16:2:23 | "source" | arrays.js:109:8:109:24 | arr8_spread.pop() | +| arrays.js:2:16:2:23 | "source" | arrays.js:111:8:111:33 | arr.fin ... llback) | | arrays.js:18:22:18:29 | "source" | arrays.js:18:50:18:50 | e | | arrays.js:22:15:22:22 | "source" | arrays.js:23:8:23:17 | arr2.pop() | | arrays.js:25:15:25:22 | "source" | arrays.js:26:8:26:17 | arr3.pop() | @@ -29,3 +30,13 @@ | arrays.js:96:9:96:16 | "source" | arrays.js:96:8:96:36 | ["sourc ... => !!x) | | arrays.js:99:31:99:38 | "source" | arrays.js:100:8:100:17 | arr8.pop() | | arrays.js:103:55:103:62 | "source" | arrays.js:105:8:105:25 | arr8_variant.pop() | +| arrays.js:114:19:114:26 | "source" | arrays.js:115:50:115:53 | item | +| arrays.js:114:19:114:26 | "source" | arrays.js:116:10:116:16 | element | +| arrays.js:120:19:120:26 | "source" | arrays.js:121:46:121:49 | item | +| arrays.js:120:19:120:26 | "source" | arrays.js:122:10:122:16 | element | +| arrays.js:126:19:126:26 | "source" | arrays.js:127:55:127:58 | item | +| arrays.js:131:17:131:24 | source() | arrays.js:132:46:132:49 | item | +| arrays.js:131:17:131:24 | source() | arrays.js:133:10:133:17 | element1 | +| arrays.js:137:17:137:24 | source() | arrays.js:138:50:138:53 | item | +| arrays.js:137:17:137:24 | source() | arrays.js:139:10:139:17 | element1 | +| arrays.js:143:17:143:24 | source() | arrays.js:144:55:144:58 | item | diff --git a/javascript/ql/test/library-tests/Arrays/TaintFlow.ql b/javascript/ql/test/library-tests/Arrays/TaintFlow.ql index cee2f294a349..d8f187591624 100644 --- a/javascript/ql/test/library-tests/Arrays/TaintFlow.ql +++ b/javascript/ql/test/library-tests/Arrays/TaintFlow.ql @@ -3,7 +3,10 @@ import javascript class ArrayTaintFlowConfig extends TaintTracking::Configuration { ArrayTaintFlowConfig() { this = "ArrayTaintFlowConfig" } - override predicate isSource(DataFlow::Node source) { source.asExpr().getStringValue() = "source" } + override predicate isSource(DataFlow::Node source) { + source.asExpr().getStringValue() = "source" or + source.(DataFlow::CallNode).getCalleeName() = "source" + } override predicate isSink(DataFlow::Node sink) { sink = any(DataFlow::CallNode call | call.getCalleeName() = "sink").getAnArgument() diff --git a/javascript/ql/test/library-tests/Arrays/arrays.js b/javascript/ql/test/library-tests/Arrays/arrays.js index 579741fa3aac..deedf29f6f67 100644 --- a/javascript/ql/test/library-tests/Arrays/arrays.js +++ b/javascript/ql/test/library-tests/Arrays/arrays.js @@ -107,4 +107,41 @@ var arr8_spread = []; arr8_spread = arr8_spread.toSpliced(0, 0, ...arr); sink(arr8_spread.pop()); // NOT OK + + sink(arr.findLast(someCallback)); // NOT OK + + { // Test for findLast function + const list = ["source"]; + const element = list.findLast((item) => sink(item)); // NOT OK + sink(element); // NOT OK + } + + { // Test for find function + const list = ["source"]; + const element = list.find((item) => sink(item)); // NOT OK + sink(element); // NOT OK + } + + { // Test for findLastIndex function + const list = ["source"]; + const element = list.findLastIndex((item) => sink(item)); // NOT OK + sink(element); // OK + } + { + const arr = source(); + const element1 = arr.find((item) => sink(item)); // NOT OK + sink(element1); // NOT OK + } + + { + const arr = source(); + const element1 = arr.findLast((item) => sink(item)); // NOT OK + sink(element1); // NOT OK + } + + { + const arr = source(); + const element1 = arr.findLastIndex((item) => sink(item)); // NOT OK + sink(element1); // OK + } }); diff --git a/javascript/ql/test/library-tests/Arrays/printAst.expected b/javascript/ql/test/library-tests/Arrays/printAst.expected index a7333b294853..a825b12f3fbd 100644 --- a/javascript/ql/test/library-tests/Arrays/printAst.expected +++ b/javascript/ql/test/library-tests/Arrays/printAst.expected @@ -1,9 +1,9 @@ nodes -| arrays.js:1:1:110:2 | [ParExpr] (functi ... T OK }) | semmle.label | [ParExpr] (functi ... T OK }) | -| arrays.js:1:1:110:3 | [ExprStmt] (functi ... OK }); | semmle.label | [ExprStmt] (functi ... OK }); | -| arrays.js:1:1:110:3 | [ExprStmt] (functi ... OK }); | semmle.order | 1 | -| arrays.js:1:2:110:1 | [FunctionExpr] functio ... OT OK } | semmle.label | [FunctionExpr] functio ... OT OK } | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | semmle.label | [BlockStmt] { let ... OT OK } | +| arrays.js:1:1:147:2 | [ParExpr] (functi ... } }) | semmle.label | [ParExpr] (functi ... } }) | +| arrays.js:1:1:147:3 | [ExprStmt] (functi ... } }); | semmle.label | [ExprStmt] (functi ... } }); | +| arrays.js:1:1:147:3 | [ExprStmt] (functi ... } }); | semmle.order | 1 | +| arrays.js:1:2:147:1 | [FunctionExpr] functio ... K } } | semmle.label | [FunctionExpr] functio ... K } } | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | semmle.label | [BlockStmt] { let ... K } } | | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | [DeclStmt] let source = ... | | arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | [VarDecl] source | | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | [VariableDeclarator] source = "source" | @@ -487,6 +487,146 @@ nodes | arrays.js:109:8:109:22 | [DotExpr] arr8_spread.pop | semmle.label | [DotExpr] arr8_spread.pop | | arrays.js:109:8:109:24 | [MethodCallExpr] arr8_spread.pop() | semmle.label | [MethodCallExpr] arr8_spread.pop() | | arrays.js:109:20:109:22 | [Label] pop | semmle.label | [Label] pop | +| arrays.js:111:3:111:6 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | semmle.label | [CallExpr] sink(ar ... lback)) | +| arrays.js:111:3:111:35 | [ExprStmt] sink(ar ... back)); | semmle.label | [ExprStmt] sink(ar ... back)); | +| arrays.js:111:8:111:10 | [VarRef] arr | semmle.label | [VarRef] arr | +| arrays.js:111:8:111:19 | [DotExpr] arr.findLast | semmle.label | [DotExpr] arr.findLast | +| arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | semmle.label | [MethodCallExpr] arr.fin ... llback) | +| arrays.js:111:12:111:19 | [Label] findLast | semmle.label | [Label] findLast | +| arrays.js:111:21:111:32 | [VarRef] someCallback | semmle.label | [VarRef] someCallback | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | semmle.label | [BlockStmt] { // T ... OK } | +| arrays.js:114:5:114:28 | [DeclStmt] const list = ... | semmle.label | [DeclStmt] const list = ... | +| arrays.js:114:11:114:14 | [VarDecl] list | semmle.label | [VarDecl] list | +| arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | semmle.label | [VariableDeclarator] list = ["source"] | +| arrays.js:114:18:114:27 | [ArrayExpr] ["source"] | semmle.label | [ArrayExpr] ["source"] | +| arrays.js:114:19:114:26 | [Literal] "source" | semmle.label | [Literal] "source" | +| arrays.js:115:5:115:56 | [DeclStmt] const element = ... | semmle.label | [DeclStmt] const element = ... | +| arrays.js:115:11:115:17 | [VarDecl] element | semmle.label | [VarDecl] element | +| arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | semmle.label | [VariableDeclarator] element ... (item)) | +| arrays.js:115:21:115:24 | [VarRef] list | semmle.label | [VarRef] list | +| arrays.js:115:21:115:33 | [DotExpr] list.findLast | semmle.label | [DotExpr] list.findLast | +| arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | semmle.label | [MethodCallExpr] list.fi ... (item)) | +| arrays.js:115:26:115:33 | [Label] findLast | semmle.label | [Label] findLast | +| arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | [ArrowFunctionExpr] (item) => sink(item) | +| arrays.js:115:36:115:39 | [SimpleParameter] item | semmle.label | [SimpleParameter] item | +| arrays.js:115:45:115:48 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:115:45:115:54 | [CallExpr] sink(item) | semmle.label | [CallExpr] sink(item) | +| arrays.js:115:50:115:53 | [VarRef] item | semmle.label | [VarRef] item | +| arrays.js:116:5:116:8 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:116:5:116:17 | [CallExpr] sink(element) | semmle.label | [CallExpr] sink(element) | +| arrays.js:116:5:116:18 | [ExprStmt] sink(element); | semmle.label | [ExprStmt] sink(element); | +| arrays.js:116:10:116:16 | [VarRef] element | semmle.label | [VarRef] element | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | semmle.label | [BlockStmt] { // T ... OK } | +| arrays.js:120:5:120:28 | [DeclStmt] const list = ... | semmle.label | [DeclStmt] const list = ... | +| arrays.js:120:11:120:14 | [VarDecl] list | semmle.label | [VarDecl] list | +| arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | semmle.label | [VariableDeclarator] list = ["source"] | +| arrays.js:120:18:120:27 | [ArrayExpr] ["source"] | semmle.label | [ArrayExpr] ["source"] | +| arrays.js:120:19:120:26 | [Literal] "source" | semmle.label | [Literal] "source" | +| arrays.js:121:5:121:52 | [DeclStmt] const element = ... | semmle.label | [DeclStmt] const element = ... | +| arrays.js:121:11:121:17 | [VarDecl] element | semmle.label | [VarDecl] element | +| arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | semmle.label | [VariableDeclarator] element ... (item)) | +| arrays.js:121:21:121:24 | [VarRef] list | semmle.label | [VarRef] list | +| arrays.js:121:21:121:29 | [DotExpr] list.find | semmle.label | [DotExpr] list.find | +| arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | semmle.label | [MethodCallExpr] list.fi ... (item)) | +| arrays.js:121:26:121:29 | [Label] find | semmle.label | [Label] find | +| arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | [ArrowFunctionExpr] (item) => sink(item) | +| arrays.js:121:32:121:35 | [SimpleParameter] item | semmle.label | [SimpleParameter] item | +| arrays.js:121:41:121:44 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:121:41:121:50 | [CallExpr] sink(item) | semmle.label | [CallExpr] sink(item) | +| arrays.js:121:46:121:49 | [VarRef] item | semmle.label | [VarRef] item | +| arrays.js:122:5:122:8 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:122:5:122:17 | [CallExpr] sink(element) | semmle.label | [CallExpr] sink(element) | +| arrays.js:122:5:122:18 | [ExprStmt] sink(element); | semmle.label | [ExprStmt] sink(element); | +| arrays.js:122:10:122:16 | [VarRef] element | semmle.label | [VarRef] element | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | semmle.label | [BlockStmt] { // T ... OK } | +| arrays.js:126:5:126:28 | [DeclStmt] const list = ... | semmle.label | [DeclStmt] const list = ... | +| arrays.js:126:11:126:14 | [VarDecl] list | semmle.label | [VarDecl] list | +| arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | semmle.label | [VariableDeclarator] list = ["source"] | +| arrays.js:126:18:126:27 | [ArrayExpr] ["source"] | semmle.label | [ArrayExpr] ["source"] | +| arrays.js:126:19:126:26 | [Literal] "source" | semmle.label | [Literal] "source" | +| arrays.js:127:5:127:61 | [DeclStmt] const element = ... | semmle.label | [DeclStmt] const element = ... | +| arrays.js:127:11:127:17 | [VarDecl] element | semmle.label | [VarDecl] element | +| arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | semmle.label | [VariableDeclarator] element ... (item)) | +| arrays.js:127:21:127:24 | [VarRef] list | semmle.label | [VarRef] list | +| arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | semmle.label | [DotExpr] list.findLastIndex | +| arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | semmle.label | [MethodCallExpr] list.fi ... (item)) | +| arrays.js:127:26:127:38 | [Label] findLastIndex | semmle.label | [Label] findLastIndex | +| arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | [ArrowFunctionExpr] (item) => sink(item) | +| arrays.js:127:41:127:44 | [SimpleParameter] item | semmle.label | [SimpleParameter] item | +| arrays.js:127:50:127:53 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:127:50:127:59 | [CallExpr] sink(item) | semmle.label | [CallExpr] sink(item) | +| arrays.js:127:55:127:58 | [VarRef] item | semmle.label | [VarRef] item | +| arrays.js:128:5:128:8 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:128:5:128:17 | [CallExpr] sink(element) | semmle.label | [CallExpr] sink(element) | +| arrays.js:128:5:128:18 | [ExprStmt] sink(element); | semmle.label | [ExprStmt] sink(element); | +| arrays.js:128:10:128:16 | [VarRef] element | semmle.label | [VarRef] element | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | semmle.label | [BlockStmt] { c ... OK } | +| arrays.js:131:5:131:25 | [DeclStmt] const arr = ... | semmle.label | [DeclStmt] const arr = ... | +| arrays.js:131:11:131:13 | [VarDecl] arr | semmle.label | [VarDecl] arr | +| arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | semmle.label | [VariableDeclarator] arr = source() | +| arrays.js:131:17:131:22 | [VarRef] source | semmle.label | [VarRef] source | +| arrays.js:131:17:131:24 | [CallExpr] source() | semmle.label | [CallExpr] source() | +| arrays.js:132:5:132:52 | [DeclStmt] const element1 = ... | semmle.label | [DeclStmt] const element1 = ... | +| arrays.js:132:11:132:18 | [VarDecl] element1 | semmle.label | [VarDecl] element1 | +| arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | semmle.label | [VariableDeclarator] element ... (item)) | +| arrays.js:132:22:132:24 | [VarRef] arr | semmle.label | [VarRef] arr | +| arrays.js:132:22:132:29 | [DotExpr] arr.find | semmle.label | [DotExpr] arr.find | +| arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | semmle.label | [MethodCallExpr] arr.fin ... (item)) | +| arrays.js:132:26:132:29 | [Label] find | semmle.label | [Label] find | +| arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | [ArrowFunctionExpr] (item) => sink(item) | +| arrays.js:132:32:132:35 | [SimpleParameter] item | semmle.label | [SimpleParameter] item | +| arrays.js:132:41:132:44 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:132:41:132:50 | [CallExpr] sink(item) | semmle.label | [CallExpr] sink(item) | +| arrays.js:132:46:132:49 | [VarRef] item | semmle.label | [VarRef] item | +| arrays.js:133:5:133:8 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:133:5:133:18 | [CallExpr] sink(element1) | semmle.label | [CallExpr] sink(element1) | +| arrays.js:133:5:133:19 | [ExprStmt] sink(element1); | semmle.label | [ExprStmt] sink(element1); | +| arrays.js:133:10:133:17 | [VarRef] element1 | semmle.label | [VarRef] element1 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | semmle.label | [BlockStmt] { c ... OK } | +| arrays.js:137:5:137:25 | [DeclStmt] const arr = ... | semmle.label | [DeclStmt] const arr = ... | +| arrays.js:137:11:137:13 | [VarDecl] arr | semmle.label | [VarDecl] arr | +| arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | semmle.label | [VariableDeclarator] arr = source() | +| arrays.js:137:17:137:22 | [VarRef] source | semmle.label | [VarRef] source | +| arrays.js:137:17:137:24 | [CallExpr] source() | semmle.label | [CallExpr] source() | +| arrays.js:138:5:138:56 | [DeclStmt] const element1 = ... | semmle.label | [DeclStmt] const element1 = ... | +| arrays.js:138:11:138:18 | [VarDecl] element1 | semmle.label | [VarDecl] element1 | +| arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | semmle.label | [VariableDeclarator] element ... (item)) | +| arrays.js:138:22:138:24 | [VarRef] arr | semmle.label | [VarRef] arr | +| arrays.js:138:22:138:33 | [DotExpr] arr.findLast | semmle.label | [DotExpr] arr.findLast | +| arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | semmle.label | [MethodCallExpr] arr.fin ... (item)) | +| arrays.js:138:26:138:33 | [Label] findLast | semmle.label | [Label] findLast | +| arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | [ArrowFunctionExpr] (item) => sink(item) | +| arrays.js:138:36:138:39 | [SimpleParameter] item | semmle.label | [SimpleParameter] item | +| arrays.js:138:45:138:48 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:138:45:138:54 | [CallExpr] sink(item) | semmle.label | [CallExpr] sink(item) | +| arrays.js:138:50:138:53 | [VarRef] item | semmle.label | [VarRef] item | +| arrays.js:139:5:139:8 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:139:5:139:18 | [CallExpr] sink(element1) | semmle.label | [CallExpr] sink(element1) | +| arrays.js:139:5:139:19 | [ExprStmt] sink(element1); | semmle.label | [ExprStmt] sink(element1); | +| arrays.js:139:10:139:17 | [VarRef] element1 | semmle.label | [VarRef] element1 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | semmle.label | [BlockStmt] { c ... OK } | +| arrays.js:143:5:143:25 | [DeclStmt] const arr = ... | semmle.label | [DeclStmt] const arr = ... | +| arrays.js:143:11:143:13 | [VarDecl] arr | semmle.label | [VarDecl] arr | +| arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | semmle.label | [VariableDeclarator] arr = source() | +| arrays.js:143:17:143:22 | [VarRef] source | semmle.label | [VarRef] source | +| arrays.js:143:17:143:24 | [CallExpr] source() | semmle.label | [CallExpr] source() | +| arrays.js:144:5:144:61 | [DeclStmt] const element1 = ... | semmle.label | [DeclStmt] const element1 = ... | +| arrays.js:144:11:144:18 | [VarDecl] element1 | semmle.label | [VarDecl] element1 | +| arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | semmle.label | [VariableDeclarator] element ... (item)) | +| arrays.js:144:22:144:24 | [VarRef] arr | semmle.label | [VarRef] arr | +| arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | semmle.label | [DotExpr] arr.findLastIndex | +| arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | semmle.label | [MethodCallExpr] arr.fin ... (item)) | +| arrays.js:144:26:144:38 | [Label] findLastIndex | semmle.label | [Label] findLastIndex | +| arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | [ArrowFunctionExpr] (item) => sink(item) | +| arrays.js:144:41:144:44 | [SimpleParameter] item | semmle.label | [SimpleParameter] item | +| arrays.js:144:50:144:53 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:144:50:144:59 | [CallExpr] sink(item) | semmle.label | [CallExpr] sink(item) | +| arrays.js:144:55:144:58 | [VarRef] item | semmle.label | [VarRef] item | +| arrays.js:145:5:145:8 | [VarRef] sink | semmle.label | [VarRef] sink | +| arrays.js:145:5:145:18 | [CallExpr] sink(element1) | semmle.label | [CallExpr] sink(element1) | +| arrays.js:145:5:145:19 | [ExprStmt] sink(element1); | semmle.label | [ExprStmt] sink(element1); | +| arrays.js:145:10:145:17 | [VarRef] element1 | semmle.label | [VarRef] element1 | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | @@ -544,6 +684,32 @@ nodes | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | @@ -552,128 +718,142 @@ nodes | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | edges -| arrays.js:1:1:110:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:110:1 | [FunctionExpr] functio ... OT OK } | semmle.label | 1 | -| arrays.js:1:1:110:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:110:1 | [FunctionExpr] functio ... OT OK } | semmle.order | 1 | -| arrays.js:1:1:110:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:110:2 | [ParExpr] (functi ... T OK }) | semmle.label | 1 | -| arrays.js:1:1:110:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:110:2 | [ParExpr] (functi ... T OK }) | semmle.order | 1 | -| arrays.js:1:2:110:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | semmle.label | 5 | -| arrays.js:1:2:110:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | semmle.order | 5 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:24 | [DeclStmt] var arr4_variant = ... | semmle.label | 18 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:24 | [DeclStmt] var arr4_variant = ... | semmle.order | 18 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:46 | [ExprStmt] arr4_va ... urce"); | semmle.label | 19 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:46 | [ExprStmt] arr4_va ... urce"); | semmle.order | 19 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:34:3:34:21 | [ExprStmt] arr4_variant.pop(); | semmle.label | 20 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:34:3:34:21 | [ExprStmt] arr4_variant.pop(); | semmle.order | 20 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:27 | [ExprStmt] sink(ar ... pop()); | semmle.label | 21 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:27 | [ExprStmt] sink(ar ... pop()); | semmle.order | 21 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:23 | [DeclStmt] var arr4_spread = ... | semmle.label | 22 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:23 | [DeclStmt] var arr4_spread = ... | semmle.order | 22 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:38:35 | [ExprStmt] arr4_sp ... ..arr); | semmle.label | 23 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:38:35 | [ExprStmt] arr4_sp ... ..arr); | semmle.order | 23 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:39:3:39:26 | [ExprStmt] sink(ar ... pop()); | semmle.label | 24 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:39:3:39:26 | [ExprStmt] sink(ar ... pop()); | semmle.order | 24 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:29 | [DeclStmt] var arr5 = ... | semmle.label | 25 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:29 | [DeclStmt] var arr5 = ... | semmle.order | 25 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:42:3:42:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 26 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:42:3:42:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 26 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:44:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 27 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:44:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 27 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:46:3:46:16 | [DeclStmt] var arr6 = ... | semmle.label | 28 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:46:3:46:16 | [DeclStmt] var arr6 = ... | semmle.order | 28 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:47:3:49:3 | [ForStmt] for (va ... i]; } | semmle.label | 29 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:47:3:49:3 | [ForStmt] for (va ... i]; } | semmle.order | 29 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:50:3:50:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 30 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:50:3:50:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 30 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:53:3:56:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 31 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:53:3:56:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 31 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:58:3:58:15 | [ExprStmt] sink(arr[0]); | semmle.label | 32 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:58:3:58:15 | [ExprStmt] sink(arr[0]); | semmle.order | 32 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:60:3:62:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:60:3:62:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:66:3 | [ForOfStmt] for (co ... OK } | semmle.label | 34 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:66:3 | [ForOfStmt] for (co ... OK } | semmle.order | 34 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:68:3:70:3 | [ForOfStmt] for (co ... OK } | semmle.label | 35 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:68:3:70:3 | [ForOfStmt] for (co ... OK } | semmle.order | 35 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:72:3:72:16 | [DeclStmt] var arr7 = ... | semmle.label | 36 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:72:3:72:16 | [DeclStmt] var arr7 = ... | semmle.order | 36 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:73:3:73:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 37 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:73:3:73:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 37 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:76:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:76:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:78:3:78:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 39 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:78:3:78:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 39 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:81:3 | [ForOfStmt] for (co ... OK } | semmle.label | 40 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:81:3 | [ForOfStmt] for (co ... OK } | semmle.order | 40 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:83:3:83:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 41 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:83:3:83:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 41 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:85:3:85:42 | [DeclStmt] const arrayFind = ... | semmle.label | 42 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:85:3:85:42 | [DeclStmt] const arrayFind = ... | semmle.order | 42 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:86:3:86:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 43 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:86:3:86:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 43 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:88:3:88:31 | [DeclStmt] const uniq = ... | semmle.label | 44 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:88:3:88:31 | [DeclStmt] const uniq = ... | semmle.order | 44 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:89:3:91:3 | [ForOfStmt] for (co ... OK } | semmle.label | 45 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:89:3:91:3 | [ForOfStmt] for (co ... OK } | semmle.order | 45 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:93:3:93:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | 46 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:93:3:93:19 | [ExprStmt] sink(arr.at(-1)); | semmle.order | 46 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:95:3:95:36 | [ExprStmt] sink([" ... => x)); | semmle.label | 47 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:95:3:95:36 | [ExprStmt] sink([" ... => x)); | semmle.order | 47 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:96:3:96:38 | [ExprStmt] sink([" ... !!x)); | semmle.label | 48 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:96:3:96:38 | [ExprStmt] sink([" ... !!x)); | semmle.order | 48 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:98:3:98:16 | [DeclStmt] var arr8 = ... | semmle.label | 49 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:98:3:98:16 | [DeclStmt] var arr8 = ... | semmle.order | 49 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:99:3:99:40 | [ExprStmt] arr8 = ... urce"); | semmle.label | 50 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:99:3:99:40 | [ExprStmt] arr8 = ... urce"); | semmle.order | 50 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:100:3:100:19 | [ExprStmt] sink(arr8.pop()); | semmle.label | 51 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:100:3:100:19 | [ExprStmt] sink(arr8.pop()); | semmle.order | 51 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:102:3:102:24 | [DeclStmt] var arr8_variant = ... | semmle.label | 52 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:102:3:102:24 | [DeclStmt] var arr8_variant = ... | semmle.order | 52 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:103:3:103:64 | [ExprStmt] arr8_va ... urce"); | semmle.label | 53 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:103:3:103:64 | [ExprStmt] arr8_va ... urce"); | semmle.order | 53 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:104:3:104:21 | [ExprStmt] arr8_variant.pop(); | semmle.label | 54 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:104:3:104:21 | [ExprStmt] arr8_variant.pop(); | semmle.order | 54 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:105:3:105:27 | [ExprStmt] sink(ar ... pop()); | semmle.label | 55 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:105:3:105:27 | [ExprStmt] sink(ar ... pop()); | semmle.order | 55 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:107:3:107:23 | [DeclStmt] var arr8_spread = ... | semmle.label | 56 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:107:3:107:23 | [DeclStmt] var arr8_spread = ... | semmle.order | 56 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:108:3:108:52 | [ExprStmt] arr8_sp ... ..arr); | semmle.label | 57 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:108:3:108:52 | [ExprStmt] arr8_sp ... ..arr); | semmle.order | 57 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:109:3:109:26 | [ExprStmt] sink(ar ... pop()); | semmle.label | 58 | -| arrays.js:1:14:110:1 | [BlockStmt] { let ... OT OK } | arrays.js:109:3:109:26 | [ExprStmt] sink(ar ... pop()); | semmle.order | 58 | +| arrays.js:1:1:147:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:147:1 | [FunctionExpr] functio ... K } } | semmle.label | 1 | +| arrays.js:1:1:147:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:147:1 | [FunctionExpr] functio ... K } } | semmle.order | 1 | +| arrays.js:1:1:147:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:147:2 | [ParExpr] (functi ... } }) | semmle.label | 1 | +| arrays.js:1:1:147:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:147:2 | [ParExpr] (functi ... } }) | semmle.order | 1 | +| arrays.js:1:2:147:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | semmle.label | 5 | +| arrays.js:1:2:147:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | semmle.order | 5 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:24 | [DeclStmt] var arr4_variant = ... | semmle.label | 18 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:24 | [DeclStmt] var arr4_variant = ... | semmle.order | 18 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:46 | [ExprStmt] arr4_va ... urce"); | semmle.label | 19 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:46 | [ExprStmt] arr4_va ... urce"); | semmle.order | 19 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:34:3:34:21 | [ExprStmt] arr4_variant.pop(); | semmle.label | 20 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:34:3:34:21 | [ExprStmt] arr4_variant.pop(); | semmle.order | 20 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:27 | [ExprStmt] sink(ar ... pop()); | semmle.label | 21 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:27 | [ExprStmt] sink(ar ... pop()); | semmle.order | 21 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:23 | [DeclStmt] var arr4_spread = ... | semmle.label | 22 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:23 | [DeclStmt] var arr4_spread = ... | semmle.order | 22 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:38:35 | [ExprStmt] arr4_sp ... ..arr); | semmle.label | 23 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:38:35 | [ExprStmt] arr4_sp ... ..arr); | semmle.order | 23 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:39:3:39:26 | [ExprStmt] sink(ar ... pop()); | semmle.label | 24 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:39:3:39:26 | [ExprStmt] sink(ar ... pop()); | semmle.order | 24 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:29 | [DeclStmt] var arr5 = ... | semmle.label | 25 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:29 | [DeclStmt] var arr5 = ... | semmle.order | 25 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:42:3:42:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 26 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:42:3:42:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 26 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:44:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 27 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:44:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 27 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:46:3:46:16 | [DeclStmt] var arr6 = ... | semmle.label | 28 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:46:3:46:16 | [DeclStmt] var arr6 = ... | semmle.order | 28 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:47:3:49:3 | [ForStmt] for (va ... i]; } | semmle.label | 29 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:47:3:49:3 | [ForStmt] for (va ... i]; } | semmle.order | 29 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:50:3:50:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 30 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:50:3:50:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 30 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:53:3:56:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 31 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:53:3:56:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 31 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:58:3:58:15 | [ExprStmt] sink(arr[0]); | semmle.label | 32 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:58:3:58:15 | [ExprStmt] sink(arr[0]); | semmle.order | 32 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:60:3:62:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:60:3:62:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:66:3 | [ForOfStmt] for (co ... OK } | semmle.label | 34 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:66:3 | [ForOfStmt] for (co ... OK } | semmle.order | 34 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:68:3:70:3 | [ForOfStmt] for (co ... OK } | semmle.label | 35 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:68:3:70:3 | [ForOfStmt] for (co ... OK } | semmle.order | 35 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:72:3:72:16 | [DeclStmt] var arr7 = ... | semmle.label | 36 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:72:3:72:16 | [DeclStmt] var arr7 = ... | semmle.order | 36 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:73:3:73:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 37 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:73:3:73:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 37 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:76:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:76:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:78:3:78:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 39 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:78:3:78:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 39 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:81:3 | [ForOfStmt] for (co ... OK } | semmle.label | 40 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:81:3 | [ForOfStmt] for (co ... OK } | semmle.order | 40 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:83:3:83:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 41 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:83:3:83:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 41 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:85:3:85:42 | [DeclStmt] const arrayFind = ... | semmle.label | 42 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:85:3:85:42 | [DeclStmt] const arrayFind = ... | semmle.order | 42 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:86:3:86:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 43 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:86:3:86:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 43 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:88:3:88:31 | [DeclStmt] const uniq = ... | semmle.label | 44 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:88:3:88:31 | [DeclStmt] const uniq = ... | semmle.order | 44 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:89:3:91:3 | [ForOfStmt] for (co ... OK } | semmle.label | 45 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:89:3:91:3 | [ForOfStmt] for (co ... OK } | semmle.order | 45 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:93:3:93:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | 46 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:93:3:93:19 | [ExprStmt] sink(arr.at(-1)); | semmle.order | 46 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:95:3:95:36 | [ExprStmt] sink([" ... => x)); | semmle.label | 47 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:95:3:95:36 | [ExprStmt] sink([" ... => x)); | semmle.order | 47 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:96:3:96:38 | [ExprStmt] sink([" ... !!x)); | semmle.label | 48 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:96:3:96:38 | [ExprStmt] sink([" ... !!x)); | semmle.order | 48 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:98:3:98:16 | [DeclStmt] var arr8 = ... | semmle.label | 49 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:98:3:98:16 | [DeclStmt] var arr8 = ... | semmle.order | 49 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:99:3:99:40 | [ExprStmt] arr8 = ... urce"); | semmle.label | 50 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:99:3:99:40 | [ExprStmt] arr8 = ... urce"); | semmle.order | 50 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:100:3:100:19 | [ExprStmt] sink(arr8.pop()); | semmle.label | 51 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:100:3:100:19 | [ExprStmt] sink(arr8.pop()); | semmle.order | 51 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:102:3:102:24 | [DeclStmt] var arr8_variant = ... | semmle.label | 52 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:102:3:102:24 | [DeclStmt] var arr8_variant = ... | semmle.order | 52 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:103:3:103:64 | [ExprStmt] arr8_va ... urce"); | semmle.label | 53 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:103:3:103:64 | [ExprStmt] arr8_va ... urce"); | semmle.order | 53 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:104:3:104:21 | [ExprStmt] arr8_variant.pop(); | semmle.label | 54 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:104:3:104:21 | [ExprStmt] arr8_variant.pop(); | semmle.order | 54 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:105:3:105:27 | [ExprStmt] sink(ar ... pop()); | semmle.label | 55 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:105:3:105:27 | [ExprStmt] sink(ar ... pop()); | semmle.order | 55 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:107:3:107:23 | [DeclStmt] var arr8_spread = ... | semmle.label | 56 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:107:3:107:23 | [DeclStmt] var arr8_spread = ... | semmle.order | 56 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:108:3:108:52 | [ExprStmt] arr8_sp ... ..arr); | semmle.label | 57 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:108:3:108:52 | [ExprStmt] arr8_sp ... ..arr); | semmle.order | 57 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:109:3:109:26 | [ExprStmt] sink(ar ... pop()); | semmle.label | 58 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:109:3:109:26 | [ExprStmt] sink(ar ... pop()); | semmle.order | 58 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:111:3:111:35 | [ExprStmt] sink(ar ... back)); | semmle.label | 59 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:111:3:111:35 | [ExprStmt] sink(ar ... back)); | semmle.order | 59 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | semmle.label | 60 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | semmle.order | 60 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | semmle.label | 61 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | semmle.order | 61 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | semmle.label | 62 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | semmle.order | 62 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | semmle.label | 63 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | semmle.order | 63 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | semmle.label | 64 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | semmle.order | 64 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | semmle.label | 65 | +| arrays.js:1:14:147:1 | [BlockStmt] { let ... K } } | arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | semmle.order | 65 | | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | 1 | | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.order | 1 | | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | 1 | @@ -1490,6 +1670,272 @@ edges | arrays.js:109:8:109:22 | [DotExpr] arr8_spread.pop | arrays.js:109:20:109:22 | [Label] pop | semmle.order | 2 | | arrays.js:109:8:109:24 | [MethodCallExpr] arr8_spread.pop() | arrays.js:109:8:109:22 | [DotExpr] arr8_spread.pop | semmle.label | 0 | | arrays.js:109:8:109:24 | [MethodCallExpr] arr8_spread.pop() | arrays.js:109:8:109:22 | [DotExpr] arr8_spread.pop | semmle.order | 0 | +| arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | arrays.js:111:3:111:6 | [VarRef] sink | semmle.label | 0 | +| arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | arrays.js:111:3:111:6 | [VarRef] sink | semmle.order | 0 | +| arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:111:3:111:35 | [ExprStmt] sink(ar ... back)); | arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | semmle.label | 1 | +| arrays.js:111:3:111:35 | [ExprStmt] sink(ar ... back)); | arrays.js:111:3:111:34 | [CallExpr] sink(ar ... lback)) | semmle.order | 1 | +| arrays.js:111:8:111:19 | [DotExpr] arr.findLast | arrays.js:111:8:111:10 | [VarRef] arr | semmle.label | 1 | +| arrays.js:111:8:111:19 | [DotExpr] arr.findLast | arrays.js:111:8:111:10 | [VarRef] arr | semmle.order | 1 | +| arrays.js:111:8:111:19 | [DotExpr] arr.findLast | arrays.js:111:12:111:19 | [Label] findLast | semmle.label | 2 | +| arrays.js:111:8:111:19 | [DotExpr] arr.findLast | arrays.js:111:12:111:19 | [Label] findLast | semmle.order | 2 | +| arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | arrays.js:111:8:111:19 | [DotExpr] arr.findLast | semmle.label | 0 | +| arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | arrays.js:111:8:111:19 | [DotExpr] arr.findLast | semmle.order | 0 | +| arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | arrays.js:114:5:114:28 | [DeclStmt] const list = ... | semmle.label | 1 | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | arrays.js:114:5:114:28 | [DeclStmt] const list = ... | semmle.order | 1 | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | arrays.js:115:5:115:56 | [DeclStmt] const element = ... | semmle.label | 2 | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | arrays.js:115:5:115:56 | [DeclStmt] const element = ... | semmle.order | 2 | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | arrays.js:116:5:116:18 | [ExprStmt] sink(element); | semmle.label | 3 | +| arrays.js:113:3:117:3 | [BlockStmt] { // T ... OK } | arrays.js:116:5:116:18 | [ExprStmt] sink(element); | semmle.order | 3 | +| arrays.js:114:5:114:28 | [DeclStmt] const list = ... | arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | semmle.label | 1 | +| arrays.js:114:5:114:28 | [DeclStmt] const list = ... | arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | semmle.order | 1 | +| arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | arrays.js:114:11:114:14 | [VarDecl] list | semmle.label | 1 | +| arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | arrays.js:114:11:114:14 | [VarDecl] list | semmle.order | 1 | +| arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | arrays.js:114:18:114:27 | [ArrayExpr] ["source"] | semmle.label | 2 | +| arrays.js:114:11:114:27 | [VariableDeclarator] list = ["source"] | arrays.js:114:18:114:27 | [ArrayExpr] ["source"] | semmle.order | 2 | +| arrays.js:114:18:114:27 | [ArrayExpr] ["source"] | arrays.js:114:19:114:26 | [Literal] "source" | semmle.label | 1 | +| arrays.js:114:18:114:27 | [ArrayExpr] ["source"] | arrays.js:114:19:114:26 | [Literal] "source" | semmle.order | 1 | +| arrays.js:115:5:115:56 | [DeclStmt] const element = ... | arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | semmle.label | 1 | +| arrays.js:115:5:115:56 | [DeclStmt] const element = ... | arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | semmle.order | 1 | +| arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | arrays.js:115:11:115:17 | [VarDecl] element | semmle.label | 1 | +| arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | arrays.js:115:11:115:17 | [VarDecl] element | semmle.order | 1 | +| arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | semmle.label | 2 | +| arrays.js:115:11:115:55 | [VariableDeclarator] element ... (item)) | arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | semmle.order | 2 | +| arrays.js:115:21:115:33 | [DotExpr] list.findLast | arrays.js:115:21:115:24 | [VarRef] list | semmle.label | 1 | +| arrays.js:115:21:115:33 | [DotExpr] list.findLast | arrays.js:115:21:115:24 | [VarRef] list | semmle.order | 1 | +| arrays.js:115:21:115:33 | [DotExpr] list.findLast | arrays.js:115:26:115:33 | [Label] findLast | semmle.label | 2 | +| arrays.js:115:21:115:33 | [DotExpr] list.findLast | arrays.js:115:26:115:33 | [Label] findLast | semmle.order | 2 | +| arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | arrays.js:115:21:115:33 | [DotExpr] list.findLast | semmle.label | 0 | +| arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | arrays.js:115:21:115:33 | [DotExpr] list.findLast | semmle.order | 0 | +| arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:115:21:115:55 | [MethodCallExpr] list.fi ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:115:45:115:54 | [CallExpr] sink(item) | semmle.label | 5 | +| arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:115:45:115:54 | [CallExpr] sink(item) | semmle.order | 5 | +| arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| arrays.js:115:45:115:54 | [CallExpr] sink(item) | arrays.js:115:45:115:48 | [VarRef] sink | semmle.label | 0 | +| arrays.js:115:45:115:54 | [CallExpr] sink(item) | arrays.js:115:45:115:48 | [VarRef] sink | semmle.order | 0 | +| arrays.js:115:45:115:54 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:115:45:115:54 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:116:5:116:17 | [CallExpr] sink(element) | arrays.js:116:5:116:8 | [VarRef] sink | semmle.label | 0 | +| arrays.js:116:5:116:17 | [CallExpr] sink(element) | arrays.js:116:5:116:8 | [VarRef] sink | semmle.order | 0 | +| arrays.js:116:5:116:17 | [CallExpr] sink(element) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:116:5:116:17 | [CallExpr] sink(element) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:116:5:116:18 | [ExprStmt] sink(element); | arrays.js:116:5:116:17 | [CallExpr] sink(element) | semmle.label | 1 | +| arrays.js:116:5:116:18 | [ExprStmt] sink(element); | arrays.js:116:5:116:17 | [CallExpr] sink(element) | semmle.order | 1 | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | arrays.js:120:5:120:28 | [DeclStmt] const list = ... | semmle.label | 1 | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | arrays.js:120:5:120:28 | [DeclStmt] const list = ... | semmle.order | 1 | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | arrays.js:121:5:121:52 | [DeclStmt] const element = ... | semmle.label | 2 | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | arrays.js:121:5:121:52 | [DeclStmt] const element = ... | semmle.order | 2 | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | arrays.js:122:5:122:18 | [ExprStmt] sink(element); | semmle.label | 3 | +| arrays.js:119:3:123:3 | [BlockStmt] { // T ... OK } | arrays.js:122:5:122:18 | [ExprStmt] sink(element); | semmle.order | 3 | +| arrays.js:120:5:120:28 | [DeclStmt] const list = ... | arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | semmle.label | 1 | +| arrays.js:120:5:120:28 | [DeclStmt] const list = ... | arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | semmle.order | 1 | +| arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | arrays.js:120:11:120:14 | [VarDecl] list | semmle.label | 1 | +| arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | arrays.js:120:11:120:14 | [VarDecl] list | semmle.order | 1 | +| arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | arrays.js:120:18:120:27 | [ArrayExpr] ["source"] | semmle.label | 2 | +| arrays.js:120:11:120:27 | [VariableDeclarator] list = ["source"] | arrays.js:120:18:120:27 | [ArrayExpr] ["source"] | semmle.order | 2 | +| arrays.js:120:18:120:27 | [ArrayExpr] ["source"] | arrays.js:120:19:120:26 | [Literal] "source" | semmle.label | 1 | +| arrays.js:120:18:120:27 | [ArrayExpr] ["source"] | arrays.js:120:19:120:26 | [Literal] "source" | semmle.order | 1 | +| arrays.js:121:5:121:52 | [DeclStmt] const element = ... | arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | semmle.label | 1 | +| arrays.js:121:5:121:52 | [DeclStmt] const element = ... | arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | semmle.order | 1 | +| arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | arrays.js:121:11:121:17 | [VarDecl] element | semmle.label | 1 | +| arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | arrays.js:121:11:121:17 | [VarDecl] element | semmle.order | 1 | +| arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | semmle.label | 2 | +| arrays.js:121:11:121:51 | [VariableDeclarator] element ... (item)) | arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | semmle.order | 2 | +| arrays.js:121:21:121:29 | [DotExpr] list.find | arrays.js:121:21:121:24 | [VarRef] list | semmle.label | 1 | +| arrays.js:121:21:121:29 | [DotExpr] list.find | arrays.js:121:21:121:24 | [VarRef] list | semmle.order | 1 | +| arrays.js:121:21:121:29 | [DotExpr] list.find | arrays.js:121:26:121:29 | [Label] find | semmle.label | 2 | +| arrays.js:121:21:121:29 | [DotExpr] list.find | arrays.js:121:26:121:29 | [Label] find | semmle.order | 2 | +| arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | arrays.js:121:21:121:29 | [DotExpr] list.find | semmle.label | 0 | +| arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | arrays.js:121:21:121:29 | [DotExpr] list.find | semmle.order | 0 | +| arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:121:21:121:51 | [MethodCallExpr] list.fi ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:121:41:121:50 | [CallExpr] sink(item) | semmle.label | 5 | +| arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:121:41:121:50 | [CallExpr] sink(item) | semmle.order | 5 | +| arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| arrays.js:121:41:121:50 | [CallExpr] sink(item) | arrays.js:121:41:121:44 | [VarRef] sink | semmle.label | 0 | +| arrays.js:121:41:121:50 | [CallExpr] sink(item) | arrays.js:121:41:121:44 | [VarRef] sink | semmle.order | 0 | +| arrays.js:121:41:121:50 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:121:41:121:50 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:122:5:122:17 | [CallExpr] sink(element) | arrays.js:122:5:122:8 | [VarRef] sink | semmle.label | 0 | +| arrays.js:122:5:122:17 | [CallExpr] sink(element) | arrays.js:122:5:122:8 | [VarRef] sink | semmle.order | 0 | +| arrays.js:122:5:122:17 | [CallExpr] sink(element) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:122:5:122:17 | [CallExpr] sink(element) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:122:5:122:18 | [ExprStmt] sink(element); | arrays.js:122:5:122:17 | [CallExpr] sink(element) | semmle.label | 1 | +| arrays.js:122:5:122:18 | [ExprStmt] sink(element); | arrays.js:122:5:122:17 | [CallExpr] sink(element) | semmle.order | 1 | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | arrays.js:126:5:126:28 | [DeclStmt] const list = ... | semmle.label | 1 | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | arrays.js:126:5:126:28 | [DeclStmt] const list = ... | semmle.order | 1 | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | arrays.js:127:5:127:61 | [DeclStmt] const element = ... | semmle.label | 2 | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | arrays.js:127:5:127:61 | [DeclStmt] const element = ... | semmle.order | 2 | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | arrays.js:128:5:128:18 | [ExprStmt] sink(element); | semmle.label | 3 | +| arrays.js:125:3:129:3 | [BlockStmt] { // T ... OK } | arrays.js:128:5:128:18 | [ExprStmt] sink(element); | semmle.order | 3 | +| arrays.js:126:5:126:28 | [DeclStmt] const list = ... | arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | semmle.label | 1 | +| arrays.js:126:5:126:28 | [DeclStmt] const list = ... | arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | semmle.order | 1 | +| arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | arrays.js:126:11:126:14 | [VarDecl] list | semmle.label | 1 | +| arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | arrays.js:126:11:126:14 | [VarDecl] list | semmle.order | 1 | +| arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | arrays.js:126:18:126:27 | [ArrayExpr] ["source"] | semmle.label | 2 | +| arrays.js:126:11:126:27 | [VariableDeclarator] list = ["source"] | arrays.js:126:18:126:27 | [ArrayExpr] ["source"] | semmle.order | 2 | +| arrays.js:126:18:126:27 | [ArrayExpr] ["source"] | arrays.js:126:19:126:26 | [Literal] "source" | semmle.label | 1 | +| arrays.js:126:18:126:27 | [ArrayExpr] ["source"] | arrays.js:126:19:126:26 | [Literal] "source" | semmle.order | 1 | +| arrays.js:127:5:127:61 | [DeclStmt] const element = ... | arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | semmle.label | 1 | +| arrays.js:127:5:127:61 | [DeclStmt] const element = ... | arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | semmle.order | 1 | +| arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | arrays.js:127:11:127:17 | [VarDecl] element | semmle.label | 1 | +| arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | arrays.js:127:11:127:17 | [VarDecl] element | semmle.order | 1 | +| arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | semmle.label | 2 | +| arrays.js:127:11:127:60 | [VariableDeclarator] element ... (item)) | arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | semmle.order | 2 | +| arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | arrays.js:127:21:127:24 | [VarRef] list | semmle.label | 1 | +| arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | arrays.js:127:21:127:24 | [VarRef] list | semmle.order | 1 | +| arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | arrays.js:127:26:127:38 | [Label] findLastIndex | semmle.label | 2 | +| arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | arrays.js:127:26:127:38 | [Label] findLastIndex | semmle.order | 2 | +| arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | semmle.label | 0 | +| arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | arrays.js:127:21:127:38 | [DotExpr] list.findLastIndex | semmle.order | 0 | +| arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:127:21:127:60 | [MethodCallExpr] list.fi ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:127:50:127:59 | [CallExpr] sink(item) | semmle.label | 5 | +| arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:127:50:127:59 | [CallExpr] sink(item) | semmle.order | 5 | +| arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| arrays.js:127:50:127:59 | [CallExpr] sink(item) | arrays.js:127:50:127:53 | [VarRef] sink | semmle.label | 0 | +| arrays.js:127:50:127:59 | [CallExpr] sink(item) | arrays.js:127:50:127:53 | [VarRef] sink | semmle.order | 0 | +| arrays.js:127:50:127:59 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:127:50:127:59 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:128:5:128:17 | [CallExpr] sink(element) | arrays.js:128:5:128:8 | [VarRef] sink | semmle.label | 0 | +| arrays.js:128:5:128:17 | [CallExpr] sink(element) | arrays.js:128:5:128:8 | [VarRef] sink | semmle.order | 0 | +| arrays.js:128:5:128:17 | [CallExpr] sink(element) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:128:5:128:17 | [CallExpr] sink(element) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:128:5:128:18 | [ExprStmt] sink(element); | arrays.js:128:5:128:17 | [CallExpr] sink(element) | semmle.label | 1 | +| arrays.js:128:5:128:18 | [ExprStmt] sink(element); | arrays.js:128:5:128:17 | [CallExpr] sink(element) | semmle.order | 1 | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | arrays.js:131:5:131:25 | [DeclStmt] const arr = ... | semmle.label | 1 | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | arrays.js:131:5:131:25 | [DeclStmt] const arr = ... | semmle.order | 1 | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | arrays.js:132:5:132:52 | [DeclStmt] const element1 = ... | semmle.label | 2 | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | arrays.js:132:5:132:52 | [DeclStmt] const element1 = ... | semmle.order | 2 | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | arrays.js:133:5:133:19 | [ExprStmt] sink(element1); | semmle.label | 3 | +| arrays.js:130:3:134:3 | [BlockStmt] { c ... OK } | arrays.js:133:5:133:19 | [ExprStmt] sink(element1); | semmle.order | 3 | +| arrays.js:131:5:131:25 | [DeclStmt] const arr = ... | arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | semmle.label | 1 | +| arrays.js:131:5:131:25 | [DeclStmt] const arr = ... | arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | semmle.order | 1 | +| arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | arrays.js:131:11:131:13 | [VarDecl] arr | semmle.label | 1 | +| arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | arrays.js:131:11:131:13 | [VarDecl] arr | semmle.order | 1 | +| arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | arrays.js:131:17:131:24 | [CallExpr] source() | semmle.label | 2 | +| arrays.js:131:11:131:24 | [VariableDeclarator] arr = source() | arrays.js:131:17:131:24 | [CallExpr] source() | semmle.order | 2 | +| arrays.js:131:17:131:24 | [CallExpr] source() | arrays.js:131:17:131:22 | [VarRef] source | semmle.label | 0 | +| arrays.js:131:17:131:24 | [CallExpr] source() | arrays.js:131:17:131:22 | [VarRef] source | semmle.order | 0 | +| arrays.js:132:5:132:52 | [DeclStmt] const element1 = ... | arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | semmle.label | 1 | +| arrays.js:132:5:132:52 | [DeclStmt] const element1 = ... | arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | semmle.order | 1 | +| arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | arrays.js:132:11:132:18 | [VarDecl] element1 | semmle.label | 1 | +| arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | arrays.js:132:11:132:18 | [VarDecl] element1 | semmle.order | 1 | +| arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | semmle.label | 2 | +| arrays.js:132:11:132:51 | [VariableDeclarator] element ... (item)) | arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | semmle.order | 2 | +| arrays.js:132:22:132:29 | [DotExpr] arr.find | arrays.js:132:22:132:24 | [VarRef] arr | semmle.label | 1 | +| arrays.js:132:22:132:29 | [DotExpr] arr.find | arrays.js:132:22:132:24 | [VarRef] arr | semmle.order | 1 | +| arrays.js:132:22:132:29 | [DotExpr] arr.find | arrays.js:132:26:132:29 | [Label] find | semmle.label | 2 | +| arrays.js:132:22:132:29 | [DotExpr] arr.find | arrays.js:132:26:132:29 | [Label] find | semmle.order | 2 | +| arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | arrays.js:132:22:132:29 | [DotExpr] arr.find | semmle.label | 0 | +| arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | arrays.js:132:22:132:29 | [DotExpr] arr.find | semmle.order | 0 | +| arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:132:22:132:51 | [MethodCallExpr] arr.fin ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:132:41:132:50 | [CallExpr] sink(item) | semmle.label | 5 | +| arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:132:41:132:50 | [CallExpr] sink(item) | semmle.order | 5 | +| arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| arrays.js:132:41:132:50 | [CallExpr] sink(item) | arrays.js:132:41:132:44 | [VarRef] sink | semmle.label | 0 | +| arrays.js:132:41:132:50 | [CallExpr] sink(item) | arrays.js:132:41:132:44 | [VarRef] sink | semmle.order | 0 | +| arrays.js:132:41:132:50 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:132:41:132:50 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:133:5:133:18 | [CallExpr] sink(element1) | arrays.js:133:5:133:8 | [VarRef] sink | semmle.label | 0 | +| arrays.js:133:5:133:18 | [CallExpr] sink(element1) | arrays.js:133:5:133:8 | [VarRef] sink | semmle.order | 0 | +| arrays.js:133:5:133:18 | [CallExpr] sink(element1) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:133:5:133:18 | [CallExpr] sink(element1) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:133:5:133:19 | [ExprStmt] sink(element1); | arrays.js:133:5:133:18 | [CallExpr] sink(element1) | semmle.label | 1 | +| arrays.js:133:5:133:19 | [ExprStmt] sink(element1); | arrays.js:133:5:133:18 | [CallExpr] sink(element1) | semmle.order | 1 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | arrays.js:137:5:137:25 | [DeclStmt] const arr = ... | semmle.label | 1 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | arrays.js:137:5:137:25 | [DeclStmt] const arr = ... | semmle.order | 1 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | arrays.js:138:5:138:56 | [DeclStmt] const element1 = ... | semmle.label | 2 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | arrays.js:138:5:138:56 | [DeclStmt] const element1 = ... | semmle.order | 2 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | arrays.js:139:5:139:19 | [ExprStmt] sink(element1); | semmle.label | 3 | +| arrays.js:136:3:140:3 | [BlockStmt] { c ... OK } | arrays.js:139:5:139:19 | [ExprStmt] sink(element1); | semmle.order | 3 | +| arrays.js:137:5:137:25 | [DeclStmt] const arr = ... | arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | semmle.label | 1 | +| arrays.js:137:5:137:25 | [DeclStmt] const arr = ... | arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | semmle.order | 1 | +| arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | arrays.js:137:11:137:13 | [VarDecl] arr | semmle.label | 1 | +| arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | arrays.js:137:11:137:13 | [VarDecl] arr | semmle.order | 1 | +| arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | arrays.js:137:17:137:24 | [CallExpr] source() | semmle.label | 2 | +| arrays.js:137:11:137:24 | [VariableDeclarator] arr = source() | arrays.js:137:17:137:24 | [CallExpr] source() | semmle.order | 2 | +| arrays.js:137:17:137:24 | [CallExpr] source() | arrays.js:137:17:137:22 | [VarRef] source | semmle.label | 0 | +| arrays.js:137:17:137:24 | [CallExpr] source() | arrays.js:137:17:137:22 | [VarRef] source | semmle.order | 0 | +| arrays.js:138:5:138:56 | [DeclStmt] const element1 = ... | arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | semmle.label | 1 | +| arrays.js:138:5:138:56 | [DeclStmt] const element1 = ... | arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | semmle.order | 1 | +| arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | arrays.js:138:11:138:18 | [VarDecl] element1 | semmle.label | 1 | +| arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | arrays.js:138:11:138:18 | [VarDecl] element1 | semmle.order | 1 | +| arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | semmle.label | 2 | +| arrays.js:138:11:138:55 | [VariableDeclarator] element ... (item)) | arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | semmle.order | 2 | +| arrays.js:138:22:138:33 | [DotExpr] arr.findLast | arrays.js:138:22:138:24 | [VarRef] arr | semmle.label | 1 | +| arrays.js:138:22:138:33 | [DotExpr] arr.findLast | arrays.js:138:22:138:24 | [VarRef] arr | semmle.order | 1 | +| arrays.js:138:22:138:33 | [DotExpr] arr.findLast | arrays.js:138:26:138:33 | [Label] findLast | semmle.label | 2 | +| arrays.js:138:22:138:33 | [DotExpr] arr.findLast | arrays.js:138:26:138:33 | [Label] findLast | semmle.order | 2 | +| arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | arrays.js:138:22:138:33 | [DotExpr] arr.findLast | semmle.label | 0 | +| arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | arrays.js:138:22:138:33 | [DotExpr] arr.findLast | semmle.order | 0 | +| arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:138:22:138:55 | [MethodCallExpr] arr.fin ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:138:45:138:54 | [CallExpr] sink(item) | semmle.label | 5 | +| arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:138:45:138:54 | [CallExpr] sink(item) | semmle.order | 5 | +| arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| arrays.js:138:45:138:54 | [CallExpr] sink(item) | arrays.js:138:45:138:48 | [VarRef] sink | semmle.label | 0 | +| arrays.js:138:45:138:54 | [CallExpr] sink(item) | arrays.js:138:45:138:48 | [VarRef] sink | semmle.order | 0 | +| arrays.js:138:45:138:54 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:138:45:138:54 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:139:5:139:18 | [CallExpr] sink(element1) | arrays.js:139:5:139:8 | [VarRef] sink | semmle.label | 0 | +| arrays.js:139:5:139:18 | [CallExpr] sink(element1) | arrays.js:139:5:139:8 | [VarRef] sink | semmle.order | 0 | +| arrays.js:139:5:139:18 | [CallExpr] sink(element1) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:139:5:139:18 | [CallExpr] sink(element1) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:139:5:139:19 | [ExprStmt] sink(element1); | arrays.js:139:5:139:18 | [CallExpr] sink(element1) | semmle.label | 1 | +| arrays.js:139:5:139:19 | [ExprStmt] sink(element1); | arrays.js:139:5:139:18 | [CallExpr] sink(element1) | semmle.order | 1 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | arrays.js:143:5:143:25 | [DeclStmt] const arr = ... | semmle.label | 1 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | arrays.js:143:5:143:25 | [DeclStmt] const arr = ... | semmle.order | 1 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | arrays.js:144:5:144:61 | [DeclStmt] const element1 = ... | semmle.label | 2 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | arrays.js:144:5:144:61 | [DeclStmt] const element1 = ... | semmle.order | 2 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | arrays.js:145:5:145:19 | [ExprStmt] sink(element1); | semmle.label | 3 | +| arrays.js:142:3:146:3 | [BlockStmt] { c ... OK } | arrays.js:145:5:145:19 | [ExprStmt] sink(element1); | semmle.order | 3 | +| arrays.js:143:5:143:25 | [DeclStmt] const arr = ... | arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | semmle.label | 1 | +| arrays.js:143:5:143:25 | [DeclStmt] const arr = ... | arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | semmle.order | 1 | +| arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | arrays.js:143:11:143:13 | [VarDecl] arr | semmle.label | 1 | +| arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | arrays.js:143:11:143:13 | [VarDecl] arr | semmle.order | 1 | +| arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | arrays.js:143:17:143:24 | [CallExpr] source() | semmle.label | 2 | +| arrays.js:143:11:143:24 | [VariableDeclarator] arr = source() | arrays.js:143:17:143:24 | [CallExpr] source() | semmle.order | 2 | +| arrays.js:143:17:143:24 | [CallExpr] source() | arrays.js:143:17:143:22 | [VarRef] source | semmle.label | 0 | +| arrays.js:143:17:143:24 | [CallExpr] source() | arrays.js:143:17:143:22 | [VarRef] source | semmle.order | 0 | +| arrays.js:144:5:144:61 | [DeclStmt] const element1 = ... | arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | semmle.label | 1 | +| arrays.js:144:5:144:61 | [DeclStmt] const element1 = ... | arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | semmle.order | 1 | +| arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | arrays.js:144:11:144:18 | [VarDecl] element1 | semmle.label | 1 | +| arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | arrays.js:144:11:144:18 | [VarDecl] element1 | semmle.order | 1 | +| arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | semmle.label | 2 | +| arrays.js:144:11:144:60 | [VariableDeclarator] element ... (item)) | arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | semmle.order | 2 | +| arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | arrays.js:144:22:144:24 | [VarRef] arr | semmle.label | 1 | +| arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | arrays.js:144:22:144:24 | [VarRef] arr | semmle.order | 1 | +| arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | arrays.js:144:26:144:38 | [Label] findLastIndex | semmle.label | 2 | +| arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | arrays.js:144:26:144:38 | [Label] findLastIndex | semmle.order | 2 | +| arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | semmle.label | 0 | +| arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | arrays.js:144:22:144:38 | [DotExpr] arr.findLastIndex | semmle.order | 0 | +| arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:144:22:144:60 | [MethodCallExpr] arr.fin ... (item)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:144:50:144:59 | [CallExpr] sink(item) | semmle.label | 5 | +| arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | arrays.js:144:50:144:59 | [CallExpr] sink(item) | semmle.order | 5 | +| arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| arrays.js:144:50:144:59 | [CallExpr] sink(item) | arrays.js:144:50:144:53 | [VarRef] sink | semmle.label | 0 | +| arrays.js:144:50:144:59 | [CallExpr] sink(item) | arrays.js:144:50:144:53 | [VarRef] sink | semmle.order | 0 | +| arrays.js:144:50:144:59 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:144:50:144:59 | [CallExpr] sink(item) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:145:5:145:18 | [CallExpr] sink(element1) | arrays.js:145:5:145:8 | [VarRef] sink | semmle.label | 0 | +| arrays.js:145:5:145:18 | [CallExpr] sink(element1) | arrays.js:145:5:145:8 | [VarRef] sink | semmle.order | 0 | +| arrays.js:145:5:145:18 | [CallExpr] sink(element1) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| arrays.js:145:5:145:18 | [CallExpr] sink(element1) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| arrays.js:145:5:145:19 | [ExprStmt] sink(element1); | arrays.js:145:5:145:18 | [CallExpr] sink(element1) | semmle.label | 1 | +| arrays.js:145:5:145:19 | [ExprStmt] sink(element1); | arrays.js:145:5:145:18 | [CallExpr] sink(element1) | semmle.order | 1 | | file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.label | 0 | | file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.order | 0 | | file://:0:0:0:0 | (Arguments) | arrays.js:8:12:8:17 | [VarRef] source | semmle.label | 0 | @@ -1634,6 +2080,46 @@ edges | file://:0:0:0:0 | (Arguments) | arrays.js:108:45:108:50 | [SpreadElement] ...arr | semmle.order | 2 | | file://:0:0:0:0 | (Arguments) | arrays.js:109:8:109:24 | [MethodCallExpr] arr8_spread.pop() | semmle.label | 0 | | file://:0:0:0:0 | (Arguments) | arrays.js:109:8:109:24 | [MethodCallExpr] arr8_spread.pop() | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:111:8:111:33 | [MethodCallExpr] arr.fin ... llback) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:111:21:111:32 | [VarRef] someCallback | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:111:21:111:32 | [VarRef] someCallback | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:115:35:115:54 | [ArrowFunctionExpr] (item) => sink(item) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:115:50:115:53 | [VarRef] item | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:115:50:115:53 | [VarRef] item | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:116:10:116:16 | [VarRef] element | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:116:10:116:16 | [VarRef] element | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:121:31:121:50 | [ArrowFunctionExpr] (item) => sink(item) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:121:46:121:49 | [VarRef] item | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:121:46:121:49 | [VarRef] item | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:122:10:122:16 | [VarRef] element | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:122:10:122:16 | [VarRef] element | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:127:40:127:59 | [ArrowFunctionExpr] (item) => sink(item) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:127:55:127:58 | [VarRef] item | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:127:55:127:58 | [VarRef] item | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:128:10:128:16 | [VarRef] element | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:128:10:128:16 | [VarRef] element | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:132:31:132:50 | [ArrowFunctionExpr] (item) => sink(item) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:132:46:132:49 | [VarRef] item | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:132:46:132:49 | [VarRef] item | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:133:10:133:17 | [VarRef] element1 | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:133:10:133:17 | [VarRef] element1 | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:138:35:138:54 | [ArrowFunctionExpr] (item) => sink(item) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:138:50:138:53 | [VarRef] item | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:138:50:138:53 | [VarRef] item | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:139:10:139:17 | [VarRef] element1 | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:139:10:139:17 | [VarRef] element1 | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:144:40:144:59 | [ArrowFunctionExpr] (item) => sink(item) | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:144:55:144:58 | [VarRef] item | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:144:55:144:58 | [VarRef] item | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:145:10:145:17 | [VarRef] element1 | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | arrays.js:145:10:145:17 | [VarRef] element1 | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.label | 0 | | file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | arrays.js:16:12:16:12 | [SimpleParameter] e | semmle.label | 0 | @@ -1652,5 +2138,17 @@ edges | file://:0:0:0:0 | (Parameters) | arrays.js:95:27:95:27 | [SimpleParameter] x | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | arrays.js:96:27:96:27 | [SimpleParameter] x | semmle.label | 0 | | file://:0:0:0:0 | (Parameters) | arrays.js:96:27:96:27 | [SimpleParameter] x | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:115:36:115:39 | [SimpleParameter] item | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:115:36:115:39 | [SimpleParameter] item | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:121:32:121:35 | [SimpleParameter] item | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:121:32:121:35 | [SimpleParameter] item | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:127:41:127:44 | [SimpleParameter] item | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:127:41:127:44 | [SimpleParameter] item | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:132:32:132:35 | [SimpleParameter] item | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:132:32:132:35 | [SimpleParameter] item | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:138:36:138:39 | [SimpleParameter] item | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:138:36:138:39 | [SimpleParameter] item | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:144:41:144:44 | [SimpleParameter] item | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | arrays.js:144:41:144:44 | [SimpleParameter] item | semmle.order | 0 | graphProperties | semmle.graphKind | tree | diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index f81405a32a2f..b6d5ab1e435c 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -209,6 +209,10 @@ typeInferenceMismatch | static-capture-groups.js:2:17:2:24 | source() | static-capture-groups.js:27:14:27:22 | RegExp.$1 | | static-capture-groups.js:32:17:32:24 | source() | static-capture-groups.js:38:10:38:18 | RegExp.$1 | | static-capture-groups.js:42:12:42:19 | source() | static-capture-groups.js:43:14:43:22 | RegExp.$1 | +| string-immutable-operations.js:2:13:2:20 | source() | string-immutable-operations.js:3:10:3:25 | x.toWellFormed() | +| string-immutable-operations.js:2:13:2:20 | source() | string-immutable-operations.js:6:10:6:20 | wellFormedX | +| string-immutable-operations.js:2:13:2:20 | source() | string-immutable-operations.js:9:10:9:26 | concatWellFormedX | +| string-immutable-operations.js:11:10:11:17 | source() | string-immutable-operations.js:11:10:11:32 | source( ... ormed() | | string-replace.js:3:13:3:20 | source() | string-replace.js:14:10:14:13 | data | | string-replace.js:3:13:3:20 | source() | string-replace.js:18:10:18:13 | data | | string-replace.js:3:13:3:20 | source() | string-replace.js:21:6:21:41 | safe(). ... taint) | @@ -244,8 +248,19 @@ typeInferenceMismatch | tst.js:2:13:2:20 | source() | tst.js:66:10:66:16 | xSorted | | tst.js:2:13:2:20 | source() | tst.js:68:10:68:23 | x.toReversed() | | tst.js:2:13:2:20 | source() | tst.js:70:10:70:18 | xReversed | -| tst.js:2:13:2:20 | source() | tst.js:72:10:72:17 | x.with() | -| tst.js:2:13:2:20 | source() | tst.js:74:10:74:14 | xWith | +| tst.js:2:13:2:20 | source() | tst.js:72:10:72:31 | Map.gro ... z => z) | +| tst.js:2:13:2:20 | source() | tst.js:74:10:74:34 | Object. ... z => z) | +| tst.js:2:13:2:20 | source() | tst.js:78:55:78:58 | item | +| tst.js:2:13:2:20 | source() | tst.js:79:14:79:20 | grouped | +| tst.js:2:13:2:20 | source() | tst.js:100:10:100:17 | x.with() | +| tst.js:2:13:2:20 | source() | tst.js:102:10:102:14 | xWith | +| tst.js:75:22:75:29 | source() | tst.js:75:10:75:52 | Map.gro ... (item)) | +| tst.js:75:22:75:29 | source() | tst.js:75:47:75:50 | item | +| tst.js:82:23:82:30 | source() | tst.js:83:58:83:61 | item | +| tst.js:82:23:82:30 | source() | tst.js:84:14:84:20 | grouped | +| tst.js:87:22:87:29 | source() | tst.js:90:14:90:25 | taintedValue | +| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue | +| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) | | xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text | | xml.js:12:17:12:24 | source() | xml.js:13:14:13:19 | result | | xml.js:23:18:23:25 | source() | xml.js:20:14:20:17 | attr | diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index 33a27661ecd1..3b89229b2d7f 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -112,3 +112,5 @@ | thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 | | tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x | | tst.js:2:13:2:20 | source() | tst.js:54:14:54:19 | unsafe | +| tst.js:93:22:93:29 | source() | tst.js:96:14:96:25 | taintedValue | +| tst.js:93:22:93:29 | source() | tst.js:97:14:97:26 | map.get(true) | diff --git a/javascript/ql/test/library-tests/TaintTracking/string-immutable-operations.js b/javascript/ql/test/library-tests/TaintTracking/string-immutable-operations.js new file mode 100644 index 000000000000..79e93fab0025 --- /dev/null +++ b/javascript/ql/test/library-tests/TaintTracking/string-immutable-operations.js @@ -0,0 +1,12 @@ +function test() { + let x = source(); + sink(x.toWellFormed()); // NOT OK + + const wellFormedX = x.toWellFormed(); + sink(wellFormedX); // NOT OK + + const concatWellFormedX = "/" + wellFormedX + "!"; + sink(concatWellFormedX); // NOT OK + + sink(source().toWellFormed()); // NOT OK +} diff --git a/javascript/ql/test/library-tests/TaintTracking/tst.js b/javascript/ql/test/library-tests/TaintTracking/tst.js index 13b4ea48d8dd..8fbc5e525bd7 100644 --- a/javascript/ql/test/library-tests/TaintTracking/tst.js +++ b/javascript/ql/test/library-tests/TaintTracking/tst.js @@ -69,6 +69,34 @@ function test() { const xReversed = x.toReversed(); sink(xReversed) // NOT OK + sink(Map.groupBy(x, z => z)); // NOT OK + sink(Custom.groupBy(x, z => z)); // OK + sink(Object.groupBy(x, z => z)); // NOT OK + sink(Map.groupBy(source(), (item) => sink(item))); // NOT OK + + { + const grouped = Map.groupBy(x, (item) => sink(item)); // NOT OK + sink(grouped); // NOT OK + } + { + const list = [source()]; + const grouped = Map.groupBy(list, (item) => sink(item)); // NOT OK + sink(grouped); // NOT OK + } + { + const data = source(); + const result = Object.groupBy(data, item => item); + const taintedValue = result[notDefined()]; + sink(taintedValue); // NOT OK + } + { + const data = source(); + const map = Map.groupBy(data, item => item); + const taintedValue = map.get(true); + sink(taintedValue); // NOT OK + sink(map.get(true)); // NOT OK + } + sink(x.with()) // NOT OK const xWith = x.with(); sink(xWith) // NOT OK diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected index 3061a6ba1f04..df304b899bb0 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected @@ -1877,8 +1877,35 @@ nodes | tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | semmle.label | [MethodCallExpr] obj[key ... rCase() | | tst.ts:508:21:508:23 | [VarRef] key | semmle.label | [VarRef] key | | tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.label | [Label] toUpperCase | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.label | [NamespaceDeclaration] namespa ... type. } | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | semmle.order | 92 | +| tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.label | [VarDecl] TS57 | +| tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.label | [DeclStmt] const a = ... | +| tst.ts:514:17:514:17 | [VarDecl] a | semmle.label | [VarDecl] a | +| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | semmle.label | [VariableDeclarator] a: symbol | +| tst.ts:514:20:514:25 | [KeywordTypeExpr] symbol | semmle.label | [KeywordTypeExpr] symbol | +| tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | semmle.label | [ExportDeclaration] export ... }; } | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | semmle.label | [ClassDefinition,TypeDefinition] class A ... }; } | +| tst.ts:515:16:515:16 | [VarDecl] A | semmle.label | [VarDecl] A | +| tst.ts:515:18:515:17 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | +| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} | +| tst.ts:515:18:515:17 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} | +| tst.ts:515:18:515:17 | [Label] constructor | semmle.label | [Label] constructor | +| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | semmle.label | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | +| tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | semmle.label | [FunctionExpr] [a]() { return 1 } | +| tst.ts:516:8:516:8 | [VarRef] a | semmle.label | [VarRef] a | +| tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | semmle.label | [BlockStmt] { return 1 } | +| tst.ts:516:15:516:22 | [ReturnStmt] return 1 | semmle.label | [ReturnStmt] return 1 | +| tst.ts:516:22:516:22 | [Literal] 1 | semmle.label | [Literal] 1 | +| tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | semmle.label | [DeclStmt] const e1 = ... | +| tst.ts:519:17:519:18 | [VarDecl] e1 | semmle.label | [VarDecl] e1 | +| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | semmle.label | [VariableDeclarator] e1: A[typeof a] | +| tst.ts:519:21:519:21 | [LocalTypeAccess] A | semmle.label | [LocalTypeAccess] A | +| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | semmle.label | [IndexedAccessTypeExpr] A[typeof a] | +| tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.label | [TypeofTypeExpr] typeof a | +| tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.label | [LocalVarTypeAccess] a | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } | -| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 92 | +| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 93 | | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } | | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS | | tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' | @@ -1896,7 +1923,7 @@ nodes | tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' | | tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } | -| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 93 | +| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 94 | | tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } | | tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES | | tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' | @@ -1914,7 +1941,7 @@ nodes | tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' | | tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 94 | +| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 | | tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' | @@ -1922,7 +1949,7 @@ nodes | tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; | | tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' | | tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 95 | +| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 | | tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | @@ -1930,7 +1957,7 @@ nodes | tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; | | tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' | | tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 96 | +| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 97 | | tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' | @@ -1938,16 +1965,16 @@ nodes | tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; | | tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | -| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 97 | +| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 98 | | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B | | type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean | | type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... | -| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 98 | +| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 99 | | type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b | | type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B | | type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B | | type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | -| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 99 | +| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 100 | | type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray | | type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T | | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T | @@ -1959,14 +1986,14 @@ nodes | type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... | -| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 100 | +| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 101 | | type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> | | type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray | | type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | -| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 101 | +| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 102 | | type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json | | type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] | | type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -1982,12 +2009,12 @@ nodes | type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] | | type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... | -| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 102 | +| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 103 | | type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json | | type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json | | type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | -| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 103 | +| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 104 | | type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode | | type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] | | type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -2003,7 +2030,7 @@ nodes | type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | | type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] | | type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... | -| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 104 | +| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 105 | | type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode | | type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] | | type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | @@ -2028,12 +2055,12 @@ nodes | type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" | | type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" | | type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 105 | +| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 106 | | type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} | -| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 106 | +| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 107 | | type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} | | type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | @@ -2041,36 +2068,36 @@ nodes | type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} | | type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor | | type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... | -| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 107 | +| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 108 | | type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj | | type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C | | type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C | | type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} | -| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 108 | +| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 109 | | type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} | | type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E | | type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... | -| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 109 | +| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 110 | | type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj | | type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E | | type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E | | type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} | -| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 110 | +| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 111 | | type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} | | type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N | | type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; | | type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... | -| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 111 | +| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 112 | | type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj | | type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N | | type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N | | type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 112 | +| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 113 | | type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | -| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 113 | +| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 114 | | type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I | | type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S | | type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S | @@ -2078,14 +2105,14 @@ nodes | type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; | | type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S | | type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... | -| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 114 | +| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 115 | | type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i | | type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I | | type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I | | type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I | semmle.label | [GenericTypeExpr] I | | type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } | -| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 115 | +| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 116 | | type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} | @@ -2097,14 +2124,14 @@ nodes | type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T | | type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... | -| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 116 | +| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 117 | | type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C | semmle.label | [VariableDeclarator] c: C | | type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C | | type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C | semmle.label | [GenericTypeExpr] C | | type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } | -| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 117 | +| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 118 | | type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color | | type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red | | type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red | @@ -2113,29 +2140,29 @@ nodes | type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue | | type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue | | type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... | -| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 118 | +| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 119 | | type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color | | type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color | | type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color | | type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } | -| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 119 | +| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 120 | | type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember | | type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member | | type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member | | type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... | -| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 120 | +| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 121 | | type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e | | type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember | | type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember | | type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | -| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 121 | +| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 122 | | type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias | | type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T | | type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T | | type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] | | type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... | -| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 122 | +| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 123 | | type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray | | type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> | | type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias | @@ -5534,6 +5561,56 @@ edges | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | tst.ts:508:26:508:36 | [Label] toUpperCase | semmle.order | 2 | | tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.label | 0 | | tst.ts:508:17:508:38 | [MethodCallExpr] obj[key ... rCase() | tst.ts:508:17:508:36 | [DotExpr] obj[key].toUpperCase | semmle.order | 0 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.label | 1 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:513:11:513:14 | [VarDecl] TS57 | semmle.order | 1 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.label | 2 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:514:3:514:26 | [DeclStmt] const a = ... | semmle.order | 2 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | semmle.label | 3 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | semmle.order | 3 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | semmle.label | 4 | +| tst.ts:513:1:520:1 | [NamespaceDeclaration] namespa ... type. } | tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | semmle.order | 4 | +| tst.ts:514:3:514:26 | [DeclStmt] const a = ... | tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | semmle.label | 1 | +| tst.ts:514:3:514:26 | [DeclStmt] const a = ... | tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | semmle.order | 1 | +| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:17:514:17 | [VarDecl] a | semmle.label | 1 | +| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:17:514:17 | [VarDecl] a | semmle.order | 1 | +| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:20:514:25 | [KeywordTypeExpr] symbol | semmle.label | 2 | +| tst.ts:514:17:514:25 | [VariableDeclarator] a: symbol | tst.ts:514:20:514:25 | [KeywordTypeExpr] symbol | semmle.order | 2 | +| tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | semmle.label | 1 | +| tst.ts:515:3:517:3 | [ExportDeclaration] export ... }; } | tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | semmle.order | 1 | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:16:515:16 | [VarDecl] A | semmle.label | 1 | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:16:515:16 | [VarDecl] A | semmle.order | 1 | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | 2 | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.order | 2 | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | semmle.label | 3 | +| tst.ts:515:10:517:3 | [ClassDefinition,TypeDefinition] class A ... }; } | tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | semmle.order | 3 | +| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [FunctionExpr] () {} | semmle.label | 2 | +| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [FunctionExpr] () {} | semmle.order | 2 | +| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [Label] constructor | semmle.label | 1 | +| tst.ts:515:18:515:17 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | tst.ts:515:18:515:17 | [Label] constructor | semmle.order | 1 | +| tst.ts:515:18:515:17 | [FunctionExpr] () {} | tst.ts:515:18:515:17 | [BlockStmt] {} | semmle.label | 5 | +| tst.ts:515:18:515:17 | [FunctionExpr] () {} | tst.ts:515:18:515:17 | [BlockStmt] {} | semmle.order | 5 | +| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | semmle.label | 1 | +| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | semmle.order | 1 | +| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:8:516:8 | [VarRef] a | semmle.label | 2 | +| tst.ts:516:7:516:24 | [ClassInitializedMember,MethodDefinition] [a]() { return 1 } | tst.ts:516:8:516:8 | [VarRef] a | semmle.order | 2 | +| tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | semmle.label | 5 | +| tst.ts:516:7:516:24 | [FunctionExpr] [a]() { return 1 } | tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | semmle.order | 5 | +| tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | tst.ts:516:15:516:22 | [ReturnStmt] return 1 | semmle.label | 1 | +| tst.ts:516:13:516:24 | [BlockStmt] { return 1 } | tst.ts:516:15:516:22 | [ReturnStmt] return 1 | semmle.order | 1 | +| tst.ts:516:15:516:22 | [ReturnStmt] return 1 | tst.ts:516:22:516:22 | [Literal] 1 | semmle.label | 1 | +| tst.ts:516:15:516:22 | [ReturnStmt] return 1 | tst.ts:516:22:516:22 | [Literal] 1 | semmle.order | 1 | +| tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | semmle.label | 1 | +| tst.ts:519:3:519:32 | [DeclStmt] const e1 = ... | tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | semmle.order | 1 | +| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:17:519:18 | [VarDecl] e1 | semmle.label | 1 | +| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:17:519:18 | [VarDecl] e1 | semmle.order | 1 | +| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | semmle.label | 2 | +| tst.ts:519:17:519:31 | [VariableDeclarator] e1: A[typeof a] | tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | semmle.order | 2 | +| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:21:519:21 | [LocalTypeAccess] A | semmle.label | 1 | +| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:21:519:21 | [LocalTypeAccess] A | semmle.order | 1 | +| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.label | 2 | +| tst.ts:519:21:519:31 | [IndexedAccessTypeExpr] A[typeof a] | tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | semmle.order | 2 | +| tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.label | 1 | +| tst.ts:519:23:519:30 | [TypeofTypeExpr] typeof a | tst.ts:519:30:519:30 | [LocalVarTypeAccess] a | semmle.order | 1 | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | 1 | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.order | 1 | | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | 0 | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected index b786fae3713e..150ce1867248 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected @@ -728,6 +728,13 @@ getExprType | tst.ts:508:17:508:38 | obj[key ... rCase() | string | | tst.ts:508:21:508:23 | key | string | | tst.ts:508:26:508:36 | toUpperCase | () => string | +| tst.ts:513:11:513:14 | TS57 | typeof TS57 in tst.ts | +| tst.ts:514:17:514:17 | a | symbol | +| tst.ts:515:16:515:16 | A | A | +| tst.ts:516:7:516:24 | [a]() { return 1 } | () => number | +| tst.ts:516:8:516:8 | a | symbol | +| tst.ts:516:22:516:22 | 1 | 1 | +| tst.ts:519:17:519:18 | e1 | () => number | | tstModuleCJS.cts:1:17:1:28 | tstModuleCJS | () => "a" \| "b" | | tstModuleCJS.cts:2:12:2:15 | Math | Math | | tstModuleCJS.cts:2:12:2:22 | Math.random | () => number | @@ -843,6 +850,7 @@ getTypeDefinitionType | tst.ts:447:5:458:5 | class P ... }\\n } | Person | | tst.ts:473:5:476:5 | class S ... ;\\n } | SomeClass | | tst.ts:481:5:481:34 | type Pa ... T, T]; | Pair3 | +| tst.ts:515:10:517:3 | class A ... };\\n } | A | | type_alias.ts:1:1:1:17 | type B = boolean; | boolean | | type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray | | type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json | @@ -1219,6 +1227,11 @@ getTypeExprType | tst.ts:506:27:506:32 | string | string | | tst.ts:506:35:506:41 | unknown | unknown | | tst.ts:506:50:506:55 | string | string | +| tst.ts:514:20:514:25 | symbol | symbol | +| tst.ts:519:21:519:21 | A | A | +| tst.ts:519:21:519:31 | A[typeof a] | () => number | +| tst.ts:519:23:519:30 | typeof a | symbol | +| tst.ts:519:30:519:30 | a | symbol | | tstModuleCJS.cts:1:33:1:35 | 'a' | "a" | | tstModuleCJS.cts:1:33:1:41 | 'a' \| 'b' | "a" \| "b" | | tstModuleCJS.cts:1:39:1:41 | 'b' | "b" | @@ -1290,6 +1303,7 @@ getTypeExprType missingToString referenceDefinition | A | badTypes.ts:5:1:5:29 | interfa ... is.B {} | +| A | tst.ts:515:10:517:3 | class A ... };\\n } | | Action | tst.ts:252:3:254:50 | type Ac ... ring }; | | Alias | type_definitions.ts:21:1:21:20 | type Alias = T[]; | | Alias | type_definitions.ts:21:1:21:20 | type Alias = T[]; | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts index 4c29465b5645..87f876be9d0f 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts @@ -508,4 +508,13 @@ module TS55 { var str = obj[key].toUpperCase(); // Now okay, previously was error } } -} \ No newline at end of file +} + +namespace TS57{ + declare const a: symbol; + export class A { + [a]() { return 1 }; + } + + declare const e1: A[typeof a]; // Now okay, previously was compilation error TS2538: Type 'symbol' cannot be used as an index type. +} diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 1cbbd9faa5a3..dec3eea044d1 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -7,3 +7,5 @@ | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 | | tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | | tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | +| tst.js:114:12:114:56 | [1,2,3] ... 3); }) | the $@ does not return anything, yet the return value from the call to findLastIndex is used. | tst.js:114:34:114:55 | n => { ... , 3); } | callback function | +| tst.js:117:12:117:51 | [1,2,3] ... 3); }) | the $@ does not return anything, yet the return value from the call to findLast is used. | tst.js:117:29:117:50 | n => { ... , 3); } | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index dbedb3dee3cc..7b9968115f5e 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -107,3 +107,13 @@ class Bar extends Foo { console.log(super()); // OK. } } + +() => { + let equals = (x, y) => { return x === y; }; + + var foo = [1,2,3].findLastIndex(n => { equals(n, 3); }) // NOT OK + console.log(foo); + + var foo = [1,2,3].findLast(n => { equals(n, 3); }) // NOT OK + console.log(foo); +} diff --git a/misc/codegen/codegen.py b/misc/codegen/codegen.py index acc8e59bba5f..ae3a67d3fba6 100755 --- a/misc/codegen/codegen.py +++ b/misc/codegen/codegen.py @@ -54,6 +54,8 @@ def _parse_args() -> argparse.Namespace: "generated qll file importing every class file"), p.add_argument("--ql-test-output", help="output directory for QL generated extractor test files"), + p.add_argument("--ql-cfg-output", + help="output directory for QL CFG layer (optional)."), p.add_argument("--cpp-output", help="output directory for generated C++ files, required if trap or cpp is provided to " "--generate"), diff --git a/misc/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py index c5e7153489b6..e42c9d015522 100755 --- a/misc/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -118,17 +118,18 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic type_is_hideable="ql_hideable" in lookup[prop.type].pragmas if prop.type in lookup else False, internal="ql_internal" in prop.pragmas, ) + ql_name = prop.pragmas.get("ql_name", prop.name) if prop.is_single: args.update( - singular=inflection.camelize(prop.name), + singular=inflection.camelize(ql_name), tablename=inflection.tableize(cls.name), tableparams=["this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single], doc=_get_doc(cls, prop), ) elif prop.is_repeated: args.update( - singular=inflection.singularize(inflection.camelize(prop.name)), - plural=inflection.pluralize(inflection.camelize(prop.name)), + singular=inflection.singularize(inflection.camelize(ql_name)), + plural=inflection.pluralize(inflection.camelize(ql_name)), tablename=inflection.tableize(f"{cls.name}_{prop.name}"), tableparams=["this", "index", "result"] if not prop.is_unordered else ["this", "result"], doc=_get_doc(cls, prop, plural=False), @@ -136,14 +137,14 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic ) elif prop.is_optional: args.update( - singular=inflection.camelize(prop.name), + singular=inflection.camelize(ql_name), tablename=inflection.tableize(f"{cls.name}_{prop.name}"), tableparams=["this", "result"], doc=_get_doc(cls, prop), ) elif prop.is_predicate: args.update( - singular=inflection.camelize(prop.name, uppercase_first_letter=False), + singular=inflection.camelize(ql_name, uppercase_first_letter=False), tablename=inflection.underscore(f"{cls.name}_{prop.name}"), tableparams=["this"], doc=_get_doc(cls, prop), @@ -154,12 +155,16 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> ql.Class: + if "ql_name" in cls.pragmas: + raise Error("ql_name is not supported yet for classes, only for properties") prev_child = "" properties = [] for p in cls.properties: prop = get_ql_property(cls, p, lookup, prev_child) if prop.is_child: prev_child = prop.singular + if prop.type in lookup and lookup[prop.type].cfg: + prop.cfg = True properties.append(prop) return ql.Class( name=cls.name, @@ -171,6 +176,16 @@ def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> q doc=cls.doc, hideable="ql_hideable" in cls.pragmas, internal="ql_internal" in cls.pragmas, + cfg=cls.cfg, + ) + + +def get_ql_cfg_class(cls: schema.Class, lookup: typing.Dict[str, ql.Class]) -> ql.CfgClass: + return ql.CfgClass( + name=cls.name, + bases=[base for base in cls.bases if lookup[base.base].cfg], + properties=cls.properties, + doc=cls.doc ) @@ -361,6 +376,7 @@ def generate(opts, renderer): input = opts.schema out = opts.ql_output stub_out = opts.ql_stub_output + cfg_out = opts.ql_cfg_output test_out = opts.ql_test_output missing_test_source_filename = "MISSING_SOURCE.txt" include_file = stub_out.with_suffix(".qll") @@ -385,6 +401,7 @@ def generate(opts, renderer): imports = {} imports_impl = {} classes_used_by = {} + cfg_classes = [] generated_import_prefix = get_import(out, opts.root_dir) registry = opts.generated_registry or pathlib.Path( os.path.commonpath((out, stub_out, test_out)), ".generated.list") @@ -402,6 +419,8 @@ def generate(opts, renderer): imports[c.name] = path path_impl = get_import(stub_out / c.dir / "internal" / c.name, opts.root_dir) imports_impl[c.name + "Impl"] = path_impl + "Impl" + if c.cfg: + cfg_classes.append(get_ql_cfg_class(c, classes)) for c in classes.values(): qll = out / c.path.with_suffix(".qll") @@ -411,6 +430,14 @@ def generate(opts, renderer): c.import_prefix = generated_import_prefix renderer.render(c, qll) + if cfg_out: + cfg_classes_val = ql.CfgClasses( + include_file_import=get_import(include_file, opts.root_dir), + classes=cfg_classes + ) + cfg_qll = cfg_out / "CfgNodes.qll" + renderer.render(cfg_classes_val, cfg_qll) + for c in data.classes.values(): path = _get_path(c) path_impl = _get_path_impl(c) diff --git a/misc/codegen/lib/ql.py b/misc/codegen/lib/ql.py index 1920a813e20d..1182c7f5dc16 100644 --- a/misc/codegen/lib/ql.py +++ b/misc/codegen/lib/ql.py @@ -45,6 +45,7 @@ class Property: synth: bool = False type_is_hideable: bool = False internal: bool = False + cfg: bool = False def __post_init__(self): if self.tableparams: @@ -110,6 +111,7 @@ class Class: internal: bool = False doc: List[str] = field(default_factory=list) hideable: bool = False + cfg: bool = False def __post_init__(self): def get_bases(bases): return [Base(str(b), str(prev)) for b, prev in zip(bases, itertools.chain([""], bases))] @@ -333,3 +335,18 @@ class ConstructorStub: cls: "Synth.FinalClass" import_prefix: str + + +@dataclass +class CfgClass: + name: str + bases: List[Base] = field(default_factory=list) + properties: List[Property] = field(default_factory=list) + doc: List[str] = field(default_factory=list) + + +@dataclass +class CfgClasses: + template: ClassVar = 'ql_cfg_nodes' + include_file_import: Optional[str] = None + classes: List[CfgClass] = field(default_factory=list) diff --git a/misc/codegen/lib/schema.py b/misc/codegen/lib/schema.py index c5c3dc810b68..23f1aea2ba42 100644 --- a/misc/codegen/lib/schema.py +++ b/misc/codegen/lib/schema.py @@ -94,6 +94,7 @@ class Class: properties: List[Property] = field(default_factory=list) pragmas: List[str] | Dict[str, object] = field(default_factory=dict) doc: List[str] = field(default_factory=list) + cfg: bool = False def __post_init__(self): if not isinstance(self.pragmas, dict): diff --git a/misc/codegen/lib/schemadefs.py b/misc/codegen/lib/schemadefs.py index 997b85b4ca6a..8651240c1a3d 100644 --- a/misc/codegen/lib/schemadefs.py +++ b/misc/codegen/lib/schemadefs.py @@ -72,11 +72,11 @@ def include(source: str): @_dataclass class _Namespace: """ simple namespacing mechanism """ - name: str + _name: str def add(self, pragma: "_PragmaBase", key: str | None = None): self.__dict__[pragma.pragma] = pragma - pragma.pragma = key or f"{self.name}_{pragma.pragma}" + pragma.pragma = key or f"{self._name}_{pragma.pragma}" @_dataclass @@ -87,7 +87,7 @@ def modify(self, prop: _schema.Property): prop.synth = self.synth def negate(self) -> _schema.PropertyModifier: - return _SynthModifier(self.name, False) + return _SynthModifier(self._name, False) qltest = _Namespace("qltest") @@ -239,6 +239,7 @@ def __getitem__(self, item): ql.add(_ParametrizedClassPragma("default_doc_name", factory=lambda doc: doc)) ql.add(_ClassPragma("hideable", inherited=True)) ql.add(_Pragma("internal")) +ql.add(_ParametrizedPragma("name", factory=lambda name: name)) cpp.add(_Pragma("skip")) @@ -256,30 +257,24 @@ def __getitem__(self, item): _schema.SynthInfo(on_arguments={k: _schema.get_type_name(t) for k, t in kwargs.items()})), key="synth") +@_dataclass(frozen=True) class _PropertyModifierList(_schema.PropertyModifier): - def __init__(self): - self._mods = [] + _mods: tuple[_schema.PropertyModifier, ...] def __or__(self, other: _schema.PropertyModifier): - self._mods.append(other) - return self + return _PropertyModifierList(self._mods + (other,)) def modify(self, prop: Property): for m in self._mods: m.modify(prop) -class _PropertyAnnotation: - def __or__(self, other: _schema.PropertyModifier): - return _PropertyModifierList() | other - - -_ = _PropertyAnnotation() +_ = _PropertyModifierList(()) drop = object() -def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None) -> _Callable[[type], _PropertyAnnotation]: +def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, replace_bases: _Dict[type, type] | None = None, cfg: bool = False) -> _Callable[[type], _PropertyModifierList]: """ Add or modify schema annotations after a class has been defined previously. @@ -287,7 +282,7 @@ def annotate(annotated_cls: type, add_bases: _Iterable[type] | None = None, repl `replace_bases` can be used to replace bases on the annotated class. """ - def decorator(cls: type) -> _PropertyAnnotation: + def decorator(cls: type) -> _PropertyModifierList: if cls.__name__ != "_": raise _schema.Error("Annotation classes must be named _") if cls.__doc__ is not None: @@ -298,6 +293,7 @@ def decorator(cls: type) -> _PropertyAnnotation: annotated_cls.__bases__ = tuple(replace_bases.get(b, b) for b in annotated_cls.__bases__) if add_bases: annotated_cls.__bases__ += tuple(add_bases) + annotated_cls.__cfg__ = cfg for a in dir(cls): if a.startswith(_schema.inheritable_pragma_prefix): setattr(annotated_cls, a, getattr(cls, a)) @@ -306,7 +302,7 @@ def decorator(cls: type) -> _PropertyAnnotation: del annotated_cls.__annotations__[p] elif p in annotated_cls.__annotations__: annotated_cls.__annotations__[p] |= a - elif isinstance(a, (_PropertyAnnotation, _PropertyModifierList)): + elif isinstance(a, (_PropertyModifierList, _PropertyModifierList)): raise _schema.Error(f"annotated property {p} not present in annotated class " f"{annotated_cls.__name__}") else: diff --git a/misc/codegen/loaders/schemaloader.py b/misc/codegen/loaders/schemaloader.py index 069e3b654740..dd1edee1de09 100644 --- a/misc/codegen/loaders/schemaloader.py +++ b/misc/codegen/loaders/schemaloader.py @@ -53,6 +53,7 @@ def _get_class(cls: type) -> schema.Class: bases=[b.__name__ for b in cls.__bases__ if b is not object], derived=derived, pragmas=pragmas, + cfg=cls.__cfg__ if hasattr(cls, "__cfg__") else False, # in the following we don't use `getattr` to avoid inheriting properties=[ a | _PropertyNamer(n) diff --git a/misc/codegen/templates/ql_cfg_nodes.mustache b/misc/codegen/templates/ql_cfg_nodes.mustache new file mode 100644 index 000000000000..a2edf4410be0 --- /dev/null +++ b/misc/codegen/templates/ql_cfg_nodes.mustache @@ -0,0 +1,199 @@ +// generated by {{generator}}, do not edit +/** + * This module provides generated wrappers around the `CfgNode` type. + * + * INTERNAL: Do not import directly. + */ + +private import codeql.util.Location +private import codeql.util.Unit +private import {{include_file_import}} + +/** Provides the input to `MakeCfgNodes` */ +signature module InputSig { + class CfgNode { + AstNode getAstNode(); + + string toString(); + + Loc getLocation(); + } + + AstNode getDesugared(AstNode n); +} + +/** + * Given a `CfgNode` implementation, provides the module `Nodes` that + * contains wrappers around `CfgNode` for relevant classes. + */ +module MakeCfgNodes Input> { + private import Input + + final private class AstNodeFinal = AstNode; + + final private class CfgNodeFinal = CfgNode; + + /** + * INTERNAL: Do not expose. + */ + abstract class ParentAstNode extends AstNodeFinal { + /** + * Holds if `child` is a (possibly nested) child of this AST node + * for which we would like to find a matching CFG child. + */ + abstract predicate relevantChild(AstNode child); + } + + /** + * INTERNAL: Do not expose. + */ + abstract class ChildMapping extends Unit { + /** + * Holds if `child` is a (possibly nested) child of AST node `parent` + * for which we would like to find a matching CFG child. + */ + final predicate relevantChild(AstNode parent, AstNode child) { + parent.(ParentAstNode).relevantChild(child) + } + + /** + * Holds if there is a control flow path from `cfn` to `cfnChild`, where `cfn` + * is a control flow node for this AST node, and `cfnChild` is a control flow + * node for `child`. + * + * This predicate should be implemented at the place where `MakeCfgNodes` is + * invoked. Ideally, `MakeCfgNodes` should be a higher-order parameterized + * module, but since that is currently not supported, we achieve the "callback" + * effect using this `abstract` class instead. + */ + cached + abstract predicate hasCfgChild(AstNode parent, AstNode child, CfgNode cfn, CfgNode cfnChild); + } + + /** Provides sub classes of `CfgNode`. */ + module Nodes { + {{#classes}} + private final class Parent{{name}} extends ParentAstNode, {{name}} { + override predicate relevantChild(AstNode child) { + none() + {{#properties}} + {{#cfg}} + or + child = this.{{getter}}({{#is_indexed}}_{{/is_indexed}}) + {{/cfg}} + {{/properties}} + } + } + + /** + {{#doc}} + * {{.}} + {{/doc}} + */ + final class {{name}}CfgNode extends CfgNodeFinal{{#bases}}, {{.}}CfgNode{{/bases}} { + private {{name}} node; + + {{name}}CfgNode() { + node = this.getAstNode() + } + + /** Gets the underlying `{{name}}`. */ + {{name}} get{{name}}() { result = node } + + {{#properties}} + /** + * {{>ql_property_doc}} * + {{#description}} + * {{.}} + {{/description}} + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + {{type}}{{#cfg}}CfgNode{{/cfg}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { + {{#cfg}} + any(ChildMapping mapping).hasCfgChild(node, node.{{getter}}({{#is_indexed}}index{{/is_indexed}}), this, result) + {{/cfg}} + {{^cfg}} + {{^is_predicate}}result = {{/is_predicate}}node.{{getter}}({{#is_indexed}}index{{/is_indexed}}) + {{/cfg}} + } + + {{#is_optional}} + /** + * Holds if `{{getter}}({{#is_repeated}}index{{/is_repeated}})` exists. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + predicate has{{singular}}({{#is_repeated}}int index{{/is_repeated}}) { + exists(this.{{getter}}({{#is_repeated}}index{{/is_repeated}})) + } + {{/is_optional}} + {{#is_indexed}} + + /** + * Gets any of the {{doc_plural}}. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + {{type}}{{#cfg}}CfgNode{{/cfg}} {{indefinite_getter}}() { + result = this.{{getter}}(_) + } + {{^is_optional}} + + /** + * Gets the number of {{doc_plural}}. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + int getNumberOf{{plural}}() { + result = count(int i | exists(this.{{getter}}(i))) + } + {{/is_optional}} + {{/is_indexed}} + {{#is_unordered}} + /** + * Gets the number of {{doc_plural}}. + {{#internal}} + * INTERNAL: Do not use. + {{/internal}} + */ + int getNumberOf{{plural}}() { + result = count(this.{{getter}}()) + } + {{/is_unordered}} + {{/properties}} + } + {{/classes}} + } + + module Consistency { + private predicate hasCfgNode(AstNode astNode) { + astNode = any(CfgNode cfgNode).getAstNode() + } + + query predicate missingCfgChild(CfgNode parent, string pred, int i, AstNode child) { + none() + {{#classes}} + {{#properties}} + {{#cfg}} + or + pred = "{{getter}}" and + parent = any(Nodes::{{name}}CfgNode cfgNode, {{name}} astNode | + astNode = cfgNode.get{{name}}() and + child = getDesugared(astNode.{{getter}}({{#is_indexed}}i{{/is_indexed}})) + {{^is_indexed}}and i = -1{{/is_indexed}} and + hasCfgNode(child) and + not child = cfgNode.{{getter}}({{#is_indexed}}i{{/is_indexed}}).getAstNode() + | + cfgNode + ) + {{/cfg}} + {{/properties}} + {{/classes}} + } + } +} \ No newline at end of file diff --git a/misc/scripts/create-change-note.py b/misc/scripts/create-change-note.py new file mode 100644 index 000000000000..548fa4e87fb0 --- /dev/null +++ b/misc/scripts/create-change-note.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +# Creates a change note and opens it in VSCode for editing. + +# Expects to receive the following arguments: +# - What language the change note is for +# - Whether it's a query or library change (the string `src` or `lib`) +# - The name of the change note (in kebab-case) +# - The category of the change. + +# The change note will be created in the `{language}/ql/{subdir}/change-notes` directory, where `subdir` is either `src` or `lib`. + +# The format of the change note filename is `{current_date}-{change_note_name}.md` with the date in +# the format `YYYY-MM-DD`. + +import sys +import os + +# Read the given arguments +language = sys.argv[1] +subdir = sys.argv[2] +change_note_name = sys.argv[3] +change_category = sys.argv[4] + +# Find the root of the repository. The current script should be located in `misc/scripts`. +root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +# Go to the repo root +os.chdir(root) + +output_dir = f"{language}/ql/{subdir}/change-notes" + +# Abort if the output directory doesn't exist +if not os.path.exists(output_dir): + print(f"Output directory {output_dir} does not exist") + sys.exit(1) + +# Get the current date +import datetime +current_date = datetime.datetime.now().strftime("%Y-%m-%d") + +# Create the change note file +change_note_file = f"{output_dir}/{current_date}-{change_note_name}.md" + +change_note = f""" +--- +category: {change_category} +--- +* """.lstrip() + +with open(change_note_file, "w") as f: + f.write(change_note) + +# Open the change note file in VSCode, reusing the existing window if possible +os.system(f"code -r {change_note_file}") diff --git a/python/extractor/semmle/python/passes/pruner.py b/python/extractor/semmle/python/passes/pruner.py index d6363e529f18..fe3b03d453cd 100644 --- a/python/extractor/semmle/python/passes/pruner.py +++ b/python/extractor/semmle/python/passes/pruner.py @@ -196,6 +196,25 @@ def visit_Attribute(self, node): if isinstance(node.value, ast.Name): self.nodes.add(node.value) +class NotBooleanTestVisitor(ASTVisitor): + """Visitor that checks if a test is not a boolean test.""" + + def __init__(self): + self.nodes = set() + + def visit_MatchLiteralPattern(self, node): + # MatchLiteralPatterns _look_ like boolean tests, but are not. + # Thus, without this check, we would interpret + # + # match x: + # case False: + # pass + # + # (and similarly for True) as if it was a boolean test. This would cause the true edge + # (leading to pass) to be pruned later on. + if isinstance(node.literal, ast.Name) and node.literal.id in ('True', 'False'): + self.nodes.add(node.literal) + class NonlocalVisitor(ASTVisitor): def __init__(self): self.names = set() @@ -306,6 +325,8 @@ def effective_constants_definitions(bool_const_defns, graph, branching_edges): def do_pruning(tree, graph): v = BoolConstVisitor() v.visit(tree) + not_boolean_test = NotBooleanTestVisitor() + not_boolean_test.visit(tree) nonlocals = NonlocalVisitor() nonlocals.visit(tree) global_vars = GlobalVisitor() @@ -353,6 +374,8 @@ def do_pruning(tree, graph): b = const_value(pred.node) if b is None: continue + if pred.node in not_boolean_test.nodes: + continue if b.contradicts(val): to_be_removed.add((pred, succ)) if not to_be_removed: diff --git a/python/extractor/semmle/util.py b/python/extractor/semmle/util.py index 1763d24e99e7..e0720a86312b 100644 --- a/python/extractor/semmle/util.py +++ b/python/extractor/semmle/util.py @@ -10,7 +10,7 @@ #Semantic version of extractor. #Update this if any changes are made -VERSION = "7.1.1" +VERSION = "7.1.2" PY_EXTENSIONS = ".py", ".pyw" diff --git a/python/ql/lib/change-notes/2024-11-26-fix-match-cfg-pruning.md b/python/ql/lib/change-notes/2024-11-26-fix-match-cfg-pruning.md new file mode 100644 index 000000000000..3ee1094c13b7 --- /dev/null +++ b/python/ql/lib/change-notes/2024-11-26-fix-match-cfg-pruning.md @@ -0,0 +1,5 @@ +--- +category: fix +--- + +- Fixed a problem with the control-flow graph construction, where writing `case True:` or `case False:` would cause parts of the graph to be pruned by mistake. diff --git a/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.expected b/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.expected new file mode 100644 index 000000000000..366de37b8677 --- /dev/null +++ b/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.expected @@ -0,0 +1,4 @@ +argumentToEnsureNotTaintedNotMarkedAsSpurious +untaintedArgumentToEnsureTaintedNotMarkedAsMissing +testFailures +failures diff --git a/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.py b/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.py new file mode 100644 index 000000000000..7719021890f8 --- /dev/null +++ b/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.py @@ -0,0 +1,118 @@ +import threading +import time + +# Test 1 +# TP - Flow is tracked through a global variable +foo1 = None + +def bar1(): + time.sleep(1) + ensure_tainted(foo1) # $tainted + +# The intent of these tests is to test how dataflow is handled through shared state accessed by different threads; +# but the presense or absense of the actual call to start a thread does not affect the results (there is no special modelling for Thread) +# threading.Thread(target=bar).start() + +foo1 = TAINTED_STRING + +# Test 2 +# FN - Flow is *not* tracked through an access path on a global variable +foo2 = [] + +def bar2(): + time.sleep(1) + ensure_tainted(foo2[0]) # $MISSING:tainted + +threading.Thread(target=bar2).start() + +foo2.append(TAINTED_STRING) + +# Test 3 +# FN - Flow is not found even when there is a direct call +foo3 = [] + +def bar3(): + time.sleep(1) + ensure_tainted(foo2[0]) # $MISSING:tainted + +foo3.append(TAINTED_STRING) +bar3() + +# Tast 4 +# TP - Sanity check: Flow is found through a ListElement directly without a call +foo4 = [] +foo4.append(TAINTED_STRING) +ensure_tainted(foo4[0]) # $tainted + +# Test 5 +# FN - Flow is *not* tracked through a shared captured but non-global variable +def test5(): + foo5 = None + + def bar5(): + time.sleep(1) + ensure_tainted(foo5) # $MISSING:tainted + + threading.Thread(target=bar5).start() # Only the presense of this thread call makes this an FN rather than a TN + + foo5 = TAINTED_STRING + + # Test 6 + # TP - Flow is tracked through a shared captured but non-global variable with a direct call +def test6(): + foo6 = [] + + def bar6(): + time.sleep(1) + ensure_tainted(foo6[0]) # $tainted + + foo6.append(TAINTED_STRING) + bar6() + + +# Test 7 +# FN - Flow is *not* found through an access path on a global variable that's also used as a parameter +# We'd like to cover this case in order to be able to cover this CVE: https://github.com/github/codeql-python-CVE-coverage/issues/3176 + +foo7 = [] + +def bar7(): + time.sleep(1) + ensure_tainted(foo7[0]) # $MISSING: tainted + +def baz7(loc_foo): + loc_foo.append(TAINTED_STRING) + +threading.Thread(target=bar7).start() + +baz7(foo7) + +# Test 8 +# FN - Flow is also *not* found in the above case through a direct call + +foo8 = [] + +def bar8(): + time.sleep(1) + ensure_tainted(foo8[0]) # $MISSING: tainted + +def baz8(loc_foo): + loc_foo.append(TAINTED_STRING) + +baz8(foo8) +bar8() + +# Test 9 +# TP - Flow is found in the above case when the variable is captured rather than global + +def test9(): + foo9 = [] + def bar9(): + time.sleep(1) + ensure_tainted(foo9[0]) # $tainted + + def baz9(loc_foo): + loc_foo.append(TAINTED_STRING) + + baz9(foo9) + bar9() \ No newline at end of file diff --git a/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.ql b/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.ql new file mode 100644 index 000000000000..dd01b5d3e341 --- /dev/null +++ b/python/ql/test/library-tests/dataflow/global-or-captured-vars/test.ql @@ -0,0 +1,3 @@ +import python +import experimental.meta.InlineTaintTest +import MakeInlineTaintTest diff --git a/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected b/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected index 013d7a0fe68d..2417041f472d 100644 --- a/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected +++ b/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected @@ -4,5 +4,3 @@ | test.py:21:5:21:38 | For | This statement is unreachable. | | test.py:28:9:28:21 | ExprStmt | This statement is unreachable. | | test.py:84:5:84:21 | ExceptStmt | This statement is unreachable. | -| test.py:144:13:144:16 | Pass | This statement is unreachable. | -| test.py:147:9:148:16 | Case | This statement is unreachable. | diff --git a/rust/ast-generator/src/main.rs b/rust/ast-generator/src/main.rs index 665ffbac6c75..dbc9686a90f6 100644 --- a/rust/ast-generator/src/main.rs +++ b/rust/ast-generator/src/main.rs @@ -14,24 +14,29 @@ fn project_root() -> PathBuf { PathBuf::from(dir).parent().unwrap().to_owned() } -fn class_name(type_name: &String) -> String { - match type_name.as_str() { - "BinExpr" => "BinaryExpr".to_owned(), - "ElseBranch" => "Expr".to_owned(), - "Fn" => "Function".to_owned(), - "Literal" => "LiteralExpr".to_owned(), - "Type" => "TypeRef".to_owned(), - _ => type_name.to_owned(), - } +fn class_name(type_name: &str) -> String { + let name = match type_name { + "BinExpr" => "BinaryExpr", + "ElseBranch" => "Expr", + "Fn" => "Function", + "Literal" => "LiteralExpr", + "Type" => "TypeRef", + _ => type_name, + }; + name.to_owned() } -fn property_name(type_name: &String, field_name: &String) -> String { - match (type_name.as_str(), field_name.as_str()) { - ("Path", "segment") => "part".to_owned(), - (_, "then_branch") => "then".to_owned(), - (_, "else_branch") => "else_".to_owned(), - _ => field_name.to_owned(), - } +fn property_name(type_name: &str, field_name: &str) -> String { + let name = match (type_name, field_name) { + ("CallExpr", "expr") => "function", + ("LetExpr", "expr") => "scrutinee", + ("MatchExpr", "expr") => "scrutinee", + ("Path", "segment") => "part", + (_, "then_branch") => "then", + (_, "else_branch") => "else_", + _ => field_name, + }; + name.to_owned() } fn to_lower_snake_case(s: &str) -> String { @@ -61,7 +66,7 @@ fn write_schema( for node in &grammar.enums { let super_classses = if let Some(cls) = super_types.get(&node.name) { - let super_classes: Vec = cls.iter().map(class_name).collect(); + let super_classes: Vec = cls.iter().map(|s| class_name(s)).collect(); super_classes.join(",") } else { "AstNode".to_owned() @@ -76,7 +81,7 @@ fn write_schema( } for node in &grammar.nodes { let super_classses = if let Some(cls) = super_types.get(&node.name) { - let super_classes: Vec = cls.iter().map(class_name).collect(); + let super_classes: Vec = cls.iter().map(|s| class_name(s)).collect(); super_classes.join(",") } else { "AstNode".to_owned() diff --git a/rust/codegen.conf b/rust/codegen.conf index 29b6edc89853..d40fada446bb 100644 --- a/rust/codegen.conf +++ b/rust/codegen.conf @@ -4,6 +4,7 @@ --dbscheme=ql/lib/rust.dbscheme --ql-output=ql/lib/codeql/rust/elements/internal/generated --ql-stub-output=ql/lib/codeql/rust/elements +--ql-cfg-output=ql/lib/codeql/rust/controlflow/internal/generated --ql-test-output=ql/test/extractor-tests/generated --rust-output=extractor/src/generated --script-name=codegen diff --git a/rust/extractor/src/generated/.generated.list b/rust/extractor/src/generated/.generated.list index 7335c95f7b8c..ec1f28154422 100644 --- a/rust/extractor/src/generated/.generated.list +++ b/rust/extractor/src/generated/.generated.list @@ -1,2 +1,2 @@ mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 -top.rs cdfb9890318d847e6db320abd8b9e9939524ecc47bcdc8491b9c8253bd3178c2 cdfb9890318d847e6db320abd8b9e9939524ecc47bcdc8491b9c8253bd3178c2 +top.rs 272ecf2f56f35211d2449dbf55b1907d8414a8e4cceded03fd12f6f599852c73 272ecf2f56f35211d2449dbf55b1907d8414a8e4cceded03fd12f6f599852c73 diff --git a/rust/extractor/src/generated/top.rs b/rust/extractor/src/generated/top.rs index 13a0adecbca4..73048514fda3 100644 --- a/rust/extractor/src/generated/top.rs +++ b/rust/extractor/src/generated/top.rs @@ -200,6 +200,51 @@ impl From> for trap::Label { } } +#[derive(Debug)] +pub struct Addressable { + _unused: () +} + +impl Addressable { + pub fn emit_extended_canonical_path(id: trap::Label, value: String, out: &mut trap::Writer) { + out.add_tuple("addressable_extended_canonical_paths", vec![id.into(), value.into()]); + } + pub fn emit_crate_origin(id: trap::Label, value: String, out: &mut trap::Writer) { + out.add_tuple("addressable_crate_origins", vec![id.into(), value.into()]); + } +} + +impl trap::TrapClass for Addressable { + fn class_name() -> &'static str { "Addressable" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Addressable is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Addressable is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Addressable is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + #[derive(Debug)] pub struct ArgList { pub id: trap::TrapId, @@ -1501,57 +1546,35 @@ impl From> for trap::Label { } #[derive(Debug)] -pub struct Param { - pub id: trap::TrapId, - pub attrs: Vec>, - pub pat: Option>, - pub ty: Option>, -} - -impl trap::TrapEntry for Param { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("params", vec![id.into()]); - for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("param_attrs", vec![id.into(), i.into(), v.into()]); - } - if let Some(v) = self.pat { - out.add_tuple("param_pats", vec![id.into(), v.into()]); - } - if let Some(v) = self.ty { - out.add_tuple("param_ties", vec![id.into(), v.into()]); - } - } +pub struct ParamBase { + _unused: () } -impl trap::TrapClass for Param { - fn class_name() -> &'static str { "Param" } +impl trap::TrapClass for ParamBase { + fn class_name() -> &'static str { "ParamBase" } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme Param is a subclass of AstNode +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ParamBase is a subclass of AstNode unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme Param is a subclass of Element +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ParamBase is a subclass of Element unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme Param is a subclass of Locatable +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ParamBase is a subclass of Locatable unsafe { Self::from_untyped(value.as_untyped()) } @@ -2203,72 +2226,6 @@ impl From> for trap::Label { } } -#[derive(Debug)] -pub struct SelfParam { - pub id: trap::TrapId, - pub attrs: Vec>, - pub is_mut: bool, - pub lifetime: Option>, - pub name: Option>, - pub ty: Option>, -} - -impl trap::TrapEntry for SelfParam { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("self_params", vec![id.into()]); - for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("self_param_attrs", vec![id.into(), i.into(), v.into()]); - } - if self.is_mut { - out.add_tuple("self_param_is_mut", vec![id.into()]); - } - if let Some(v) = self.lifetime { - out.add_tuple("self_param_lifetimes", vec![id.into(), v.into()]); - } - if let Some(v) = self.name { - out.add_tuple("self_param_names", vec![id.into(), v.into()]); - } - if let Some(v) = self.ty { - out.add_tuple("self_param_ties", vec![id.into(), v.into()]); - } - } -} - -impl trap::TrapClass for SelfParam { - fn class_name() -> &'static str { "SelfParam" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - #[derive(Debug)] pub struct SourceFile { pub id: trap::TrapId, @@ -2817,72 +2774,6 @@ impl From> for trap::Label { } } -#[derive(Debug)] -pub struct Variant { - pub id: trap::TrapId, - pub attrs: Vec>, - pub expr: Option>, - pub field_list: Option>, - pub name: Option>, - pub visibility: Option>, -} - -impl trap::TrapEntry for Variant { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("variants", vec![id.into()]); - for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("variant_attrs", vec![id.into(), i.into(), v.into()]); - } - if let Some(v) = self.expr { - out.add_tuple("variant_exprs", vec![id.into(), v.into()]); - } - if let Some(v) = self.field_list { - out.add_tuple("variant_field_lists", vec![id.into(), v.into()]); - } - if let Some(v) = self.name { - out.add_tuple("variant_names", vec![id.into(), v.into()]); - } - if let Some(v) = self.visibility { - out.add_tuple("variant_visibilities", vec![id.into(), v.into()]); - } - } -} - -impl trap::TrapClass for Variant { - fn class_name() -> &'static str { "Variant" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme Variant is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme Variant is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme Variant is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - #[derive(Debug)] pub struct VariantList { pub id: trap::TrapId, @@ -3569,131 +3460,40 @@ impl From> for trap::Label { } #[derive(Debug)] -pub struct BlockExpr { - pub id: trap::TrapId, - pub attrs: Vec>, - pub is_async: bool, - pub is_const: bool, - pub is_gen: bool, - pub is_move: bool, - pub is_try: bool, - pub is_unsafe: bool, - pub label: Option>, - pub stmt_list: Option>, +pub struct BoxPat { + pub id: trap::TrapId, + pub pat: Option>, } -impl trap::TrapEntry for BlockExpr { +impl trap::TrapEntry for BoxPat { fn extract_id(&mut self) -> trap::TrapId { std::mem::replace(&mut self.id, trap::TrapId::Star) } fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("block_exprs", vec![id.into()]); - for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("block_expr_attrs", vec![id.into(), i.into(), v.into()]); - } - if self.is_async { - out.add_tuple("block_expr_is_async", vec![id.into()]); - } - if self.is_const { - out.add_tuple("block_expr_is_const", vec![id.into()]); - } - if self.is_gen { - out.add_tuple("block_expr_is_gen", vec![id.into()]); - } - if self.is_move { - out.add_tuple("block_expr_is_move", vec![id.into()]); - } - if self.is_try { - out.add_tuple("block_expr_is_try", vec![id.into()]); - } - if self.is_unsafe { - out.add_tuple("block_expr_is_unsafe", vec![id.into()]); - } - if let Some(v) = self.label { - out.add_tuple("block_expr_labels", vec![id.into(), v.into()]); - } - if let Some(v) = self.stmt_list { - out.add_tuple("block_expr_stmt_lists", vec![id.into(), v.into()]); + out.add_tuple("box_pats", vec![id.into()]); + if let Some(v) = self.pat { + out.add_tuple("box_pat_pats", vec![id.into(), v.into()]); } } } -impl trap::TrapClass for BlockExpr { - fn class_name() -> &'static str { "BlockExpr" } +impl trap::TrapClass for BoxPat { + fn class_name() -> &'static str { "BoxPat" } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of AstNode +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BoxPat is a subclass of AstNode unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of Expr - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -#[derive(Debug)] -pub struct BoxPat { - pub id: trap::TrapId, - pub pat: Option>, -} - -impl trap::TrapEntry for BoxPat { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("box_pats", vec![id.into()]); - if let Some(v) = self.pat { - out.add_tuple("box_pat_pats", vec![id.into(), v.into()]); - } - } -} - -impl trap::TrapClass for BoxPat { - fn class_name() -> &'static str { "BoxPat" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme BoxPat is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme BoxPat is a subclass of Element +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BoxPat is a subclass of Element unsafe { Self::from_untyped(value.as_untyped()) } @@ -4582,81 +4382,6 @@ impl From> for trap::Label { } } -#[derive(Debug)] -pub struct ForExpr { - pub id: trap::TrapId, - pub attrs: Vec>, - pub iterable: Option>, - pub label: Option>, - pub loop_body: Option>, - pub pat: Option>, -} - -impl trap::TrapEntry for ForExpr { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("for_exprs", vec![id.into()]); - for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("for_expr_attrs", vec![id.into(), i.into(), v.into()]); - } - if let Some(v) = self.iterable { - out.add_tuple("for_expr_iterables", vec![id.into(), v.into()]); - } - if let Some(v) = self.label { - out.add_tuple("for_expr_labels", vec![id.into(), v.into()]); - } - if let Some(v) = self.loop_body { - out.add_tuple("for_expr_loop_bodies", vec![id.into(), v.into()]); - } - if let Some(v) = self.pat { - out.add_tuple("for_expr_pats", vec![id.into(), v.into()]); - } - } -} - -impl trap::TrapClass for ForExpr { - fn class_name() -> &'static str { "ForExpr" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of Expr - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - #[derive(Debug)] pub struct ForType { pub id: trap::TrapId, @@ -5119,19 +4844,19 @@ pub struct Item { _unused: () } -impl Item { - pub fn emit_extended_canonical_path(id: trap::Label, value: String, out: &mut trap::Writer) { - out.add_tuple("item_extended_canonical_paths", vec![id.into(), value.into()]); - } - pub fn emit_crate_origin(id: trap::Label, value: String, out: &mut trap::Writer) { - out.add_tuple("item_crate_origins", vec![id.into(), value.into()]); - } -} - impl trap::TrapClass for Item { fn class_name() -> &'static str { "Item" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Item is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Item is a subclass of AstNode @@ -5168,11 +4893,56 @@ impl From> for trap::Label { } } +#[derive(Debug)] +pub struct LabelableExpr { + _unused: () +} + +impl trap::TrapClass for LabelableExpr { + fn class_name() -> &'static str { "LabelableExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LabelableExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LabelableExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LabelableExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LabelableExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + #[derive(Debug)] pub struct LetExpr { pub id: trap::TrapId, pub attrs: Vec>, - pub expr: Option>, + pub scrutinee: Option>, pub pat: Option>, } @@ -5186,8 +4956,8 @@ impl trap::TrapEntry for LetExpr { for (i, v) in self.attrs.into_iter().enumerate() { out.add_tuple("let_expr_attrs", vec![id.into(), i.into(), v.into()]); } - if let Some(v) = self.expr { - out.add_tuple("let_expr_exprs", vec![id.into(), v.into()]); + if let Some(v) = self.scrutinee { + out.add_tuple("let_expr_scrutinees", vec![id.into(), v.into()]); } if let Some(v) = self.pat { out.add_tuple("let_expr_pats", vec![id.into(), v.into()]); @@ -5558,73 +5328,6 @@ impl From> for trap::Label { } } -#[derive(Debug)] -pub struct LoopExpr { - pub id: trap::TrapId, - pub attrs: Vec>, - pub label: Option>, - pub loop_body: Option>, -} - -impl trap::TrapEntry for LoopExpr { - fn extract_id(&mut self) -> trap::TrapId { - std::mem::replace(&mut self.id, trap::TrapId::Star) - } - - fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("loop_exprs", vec![id.into()]); - for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("loop_expr_attrs", vec![id.into(), i.into(), v.into()]); - } - if let Some(v) = self.label { - out.add_tuple("loop_expr_labels", vec![id.into(), v.into()]); - } - if let Some(v) = self.loop_body { - out.add_tuple("loop_expr_loop_bodies", vec![id.into(), v.into()]); - } - } -} - -impl trap::TrapClass for LoopExpr { - fn class_name() -> &'static str { "LoopExpr" } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of AstNode - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of Expr - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of Locatable - unsafe { - Self::from_untyped(value.as_untyped()) - } - } -} - #[derive(Debug)] pub struct MacroExpr { pub id: trap::TrapId, @@ -5806,7 +5509,7 @@ impl From> for trap::Label { pub struct MatchExpr { pub id: trap::TrapId, pub attrs: Vec>, - pub expr: Option>, + pub scrutinee: Option>, pub match_arm_list: Option>, } @@ -5820,8 +5523,8 @@ impl trap::TrapEntry for MatchExpr { for (i, v) in self.attrs.into_iter().enumerate() { out.add_tuple("match_expr_attrs", vec![id.into(), i.into(), v.into()]); } - if let Some(v) = self.expr { - out.add_tuple("match_expr_exprs", vec![id.into(), v.into()]); + if let Some(v) = self.scrutinee { + out.add_tuple("match_expr_scrutinees", vec![id.into(), v.into()]); } if let Some(v) = self.match_arm_list { out.add_tuple("match_expr_match_arm_lists", vec![id.into(), v.into()]); @@ -6051,23 +5754,90 @@ impl From> for trap::Label { } #[derive(Debug)] -pub struct ParenExpr { - pub id: trap::TrapId, +pub struct Param { + pub id: trap::TrapId, pub attrs: Vec>, - pub expr: Option>, + pub ty: Option>, + pub pat: Option>, } -impl trap::TrapEntry for ParenExpr { +impl trap::TrapEntry for Param { fn extract_id(&mut self) -> trap::TrapId { std::mem::replace(&mut self.id, trap::TrapId::Star) } fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("paren_exprs", vec![id.into()]); + out.add_tuple("params", vec![id.into()]); for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("paren_expr_attrs", vec![id.into(), i.into(), v.into()]); + out.add_tuple("param_base_attrs", vec![id.into(), i.into(), v.into()]); } - if let Some(v) = self.expr { + if let Some(v) = self.ty { + out.add_tuple("param_base_ties", vec![id.into(), v.into()]); + } + if let Some(v) = self.pat { + out.add_tuple("param_pats", vec![id.into(), v.into()]); + } + } +} + +impl trap::TrapClass for Param { + fn class_name() -> &'static str { "Param" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Param is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Param is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Param is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Param is a subclass of ParamBase + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +#[derive(Debug)] +pub struct ParenExpr { + pub id: trap::TrapId, + pub attrs: Vec>, + pub expr: Option>, +} + +impl trap::TrapEntry for ParenExpr { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("paren_exprs", vec![id.into()]); + for (i, v) in self.attrs.into_iter().enumerate() { + out.add_tuple("paren_expr_attrs", vec![id.into(), i.into(), v.into()]); + } + if let Some(v) = self.expr { out.add_tuple("paren_expr_exprs", vec![id.into(), v.into()]); } } @@ -7241,6 +7011,81 @@ impl From> for trap::Label { } } +#[derive(Debug)] +pub struct SelfParam { + pub id: trap::TrapId, + pub attrs: Vec>, + pub ty: Option>, + pub is_mut: bool, + pub lifetime: Option>, + pub name: Option>, +} + +impl trap::TrapEntry for SelfParam { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("self_params", vec![id.into()]); + for (i, v) in self.attrs.into_iter().enumerate() { + out.add_tuple("param_base_attrs", vec![id.into(), i.into(), v.into()]); + } + if let Some(v) = self.ty { + out.add_tuple("param_base_ties", vec![id.into(), v.into()]); + } + if self.is_mut { + out.add_tuple("self_param_is_mut", vec![id.into()]); + } + if let Some(v) = self.lifetime { + out.add_tuple("self_param_lifetimes", vec![id.into(), v.into()]); + } + if let Some(v) = self.name { + out.add_tuple("self_param_names", vec![id.into(), v.into()]); + } + } +} + +impl trap::TrapClass for SelfParam { + fn class_name() -> &'static str { "SelfParam" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme SelfParam is a subclass of ParamBase + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + #[derive(Debug)] pub struct SlicePat { pub id: trap::TrapId, @@ -7915,70 +7760,74 @@ impl From> for trap::Label { } #[derive(Debug)] -pub struct WhileExpr { - pub id: trap::TrapId, +pub struct Variant { + pub id: trap::TrapId, pub attrs: Vec>, - pub condition: Option>, - pub label: Option>, - pub loop_body: Option>, + pub expr: Option>, + pub field_list: Option>, + pub name: Option>, + pub visibility: Option>, } -impl trap::TrapEntry for WhileExpr { +impl trap::TrapEntry for Variant { fn extract_id(&mut self) -> trap::TrapId { std::mem::replace(&mut self.id, trap::TrapId::Star) } fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("while_exprs", vec![id.into()]); + out.add_tuple("variants", vec![id.into()]); for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("while_expr_attrs", vec![id.into(), i.into(), v.into()]); + out.add_tuple("variant_attrs", vec![id.into(), i.into(), v.into()]); } - if let Some(v) = self.condition { - out.add_tuple("while_expr_conditions", vec![id.into(), v.into()]); + if let Some(v) = self.expr { + out.add_tuple("variant_exprs", vec![id.into(), v.into()]); } - if let Some(v) = self.label { - out.add_tuple("while_expr_labels", vec![id.into(), v.into()]); + if let Some(v) = self.field_list { + out.add_tuple("variant_field_lists", vec![id.into(), v.into()]); } - if let Some(v) = self.loop_body { - out.add_tuple("while_expr_loop_bodies", vec![id.into(), v.into()]); + if let Some(v) = self.name { + out.add_tuple("variant_names", vec![id.into(), v.into()]); + } + if let Some(v) = self.visibility { + out.add_tuple("variant_visibilities", vec![id.into(), v.into()]); } } } -impl trap::TrapClass for WhileExpr { - fn class_name() -> &'static str { "WhileExpr" } +impl trap::TrapClass for Variant { + fn class_name() -> &'static str { "Variant" } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of AstNode +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Variant is a subclass of Addressable unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of Element +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Variant is a subclass of AstNode unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of Expr +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Variant is a subclass of Element unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of Locatable +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Variant is a subclass of Locatable unsafe { Self::from_untyped(value.as_untyped()) } @@ -8167,59 +8016,159 @@ impl From> for trap::Label { } #[derive(Debug)] -pub struct CallExpr { - pub id: trap::TrapId, - pub arg_list: Option>, +pub struct BlockExpr { + pub id: trap::TrapId, + pub label: Option>, pub attrs: Vec>, - pub expr: Option>, + pub is_async: bool, + pub is_const: bool, + pub is_gen: bool, + pub is_move: bool, + pub is_try: bool, + pub is_unsafe: bool, + pub stmt_list: Option>, } -impl trap::TrapEntry for CallExpr { +impl trap::TrapEntry for BlockExpr { fn extract_id(&mut self) -> trap::TrapId { std::mem::replace(&mut self.id, trap::TrapId::Star) } fn emit(self, id: trap::Label, out: &mut trap::Writer) { - out.add_tuple("call_exprs", vec![id.into()]); - if let Some(v) = self.arg_list { - out.add_tuple("call_expr_base_arg_lists", vec![id.into(), v.into()]); + out.add_tuple("block_exprs", vec![id.into()]); + if let Some(v) = self.label { + out.add_tuple("labelable_expr_labels", vec![id.into(), v.into()]); } for (i, v) in self.attrs.into_iter().enumerate() { - out.add_tuple("call_expr_base_attrs", vec![id.into(), i.into(), v.into()]); + out.add_tuple("block_expr_attrs", vec![id.into(), i.into(), v.into()]); } - if let Some(v) = self.expr { - out.add_tuple("call_expr_exprs", vec![id.into(), v.into()]); + if self.is_async { + out.add_tuple("block_expr_is_async", vec![id.into()]); + } + if self.is_const { + out.add_tuple("block_expr_is_const", vec![id.into()]); + } + if self.is_gen { + out.add_tuple("block_expr_is_gen", vec![id.into()]); + } + if self.is_move { + out.add_tuple("block_expr_is_move", vec![id.into()]); + } + if self.is_try { + out.add_tuple("block_expr_is_try", vec![id.into()]); + } + if self.is_unsafe { + out.add_tuple("block_expr_is_unsafe", vec![id.into()]); + } + if let Some(v) = self.stmt_list { + out.add_tuple("block_expr_stmt_lists", vec![id.into(), v.into()]); } } } -impl trap::TrapClass for CallExpr { - fn class_name() -> &'static str { "CallExpr" } +impl trap::TrapClass for BlockExpr { + fn class_name() -> &'static str { "BlockExpr" } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme CallExpr is a subclass of AstNode +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of AstNode unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme CallExpr is a subclass of CallExprBase +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of Element unsafe { Self::from_untyped(value.as_untyped()) } } } -impl From> for trap::Label { - fn from(value: trap::Label) -> Self { - // SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Element - unsafe { - Self::from_untyped(value.as_untyped()) +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of LabelableExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme BlockExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +#[derive(Debug)] +pub struct CallExpr { + pub id: trap::TrapId, + pub arg_list: Option>, + pub attrs: Vec>, + pub function: Option>, +} + +impl trap::TrapEntry for CallExpr { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("call_exprs", vec![id.into()]); + if let Some(v) = self.arg_list { + out.add_tuple("call_expr_base_arg_lists", vec![id.into(), v.into()]); + } + for (i, v) in self.attrs.into_iter().enumerate() { + out.add_tuple("call_expr_base_attrs", vec![id.into(), i.into(), v.into()]); + } + if let Some(v) = self.function { + out.add_tuple("call_expr_functions", vec![id.into(), v.into()]); + } + } +} + +impl trap::TrapClass for CallExpr { + fn class_name() -> &'static str { "CallExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme CallExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme CallExpr is a subclass of CallExprBase + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme CallExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) } } } @@ -8289,6 +8238,15 @@ impl trap::TrapClass for Const { fn class_name() -> &'static str { "Const" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Const is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Const is a subclass of AssocItem @@ -8386,6 +8344,15 @@ impl trap::TrapClass for Enum { fn class_name() -> &'static str { "Enum" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Enum is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Enum is a subclass of AstNode @@ -8466,6 +8433,15 @@ impl trap::TrapClass for ExternBlock { fn class_name() -> &'static str { "ExternBlock" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ExternBlock is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme ExternBlock is a subclass of AstNode @@ -8546,6 +8522,15 @@ impl trap::TrapClass for ExternCrate { fn class_name() -> &'static str { "ExternCrate" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ExternCrate is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme ExternCrate is a subclass of AstNode @@ -8666,6 +8651,15 @@ impl trap::TrapClass for Function { fn class_name() -> &'static str { "Function" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Function is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Function is a subclass of AssocItem @@ -8797,6 +8791,15 @@ impl trap::TrapClass for Impl { fn class_name() -> &'static str { "Impl" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Impl is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Impl is a subclass of AstNode @@ -8842,6 +8845,60 @@ impl From> for trap::Label { } } +#[derive(Debug)] +pub struct LoopingExpr { + _unused: () +} + +impl trap::TrapClass for LoopingExpr { + fn class_name() -> &'static str { "LoopingExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopingExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopingExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopingExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopingExpr is a subclass of LabelableExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopingExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + #[derive(Debug)] pub struct MacroCall { pub id: trap::TrapId, @@ -8879,6 +8936,15 @@ impl trap::TrapClass for MacroCall { fn class_name() -> &'static str { "MacroCall" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroCall is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme MacroCall is a subclass of AssocItem @@ -8981,6 +9047,15 @@ impl trap::TrapClass for MacroDef { fn class_name() -> &'static str { "MacroDef" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroDef is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme MacroDef is a subclass of AstNode @@ -9061,6 +9136,15 @@ impl trap::TrapClass for MacroRules { fn class_name() -> &'static str { "MacroRules" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme MacroRules is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme MacroRules is a subclass of AstNode @@ -9234,6 +9318,15 @@ impl trap::TrapClass for Module { fn class_name() -> &'static str { "Module" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Module is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Module is a subclass of AstNode @@ -9398,6 +9491,15 @@ impl trap::TrapClass for Static { fn class_name() -> &'static str { "Static" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Static is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Static is a subclass of AstNode @@ -9495,6 +9597,15 @@ impl trap::TrapClass for Struct { fn class_name() -> &'static str { "Struct" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Struct is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Struct is a subclass of AstNode @@ -9595,6 +9706,15 @@ impl trap::TrapClass for Trait { fn class_name() -> &'static str { "Trait" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Trait is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Trait is a subclass of AstNode @@ -9683,6 +9803,15 @@ impl trap::TrapClass for TraitAlias { fn class_name() -> &'static str { "TraitAlias" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme TraitAlias is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme TraitAlias is a subclass of AstNode @@ -9779,6 +9908,15 @@ impl trap::TrapClass for TypeAlias { fn class_name() -> &'static str { "TypeAlias" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme TypeAlias is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme TypeAlias is a subclass of AssocItem @@ -9885,6 +10023,15 @@ impl trap::TrapClass for Union { fn class_name() -> &'static str { "Union" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Union is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Union is a subclass of AstNode @@ -9961,6 +10108,15 @@ impl trap::TrapClass for Use { fn class_name() -> &'static str { "Use" } } +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme Use is a subclass of Addressable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + impl From> for trap::Label { fn from(value: trap::Label) -> Self { // SAFETY: this is safe because in the dbscheme Use is a subclass of AstNode @@ -10005,3 +10161,270 @@ impl From> for trap::Label { } } } + +#[derive(Debug)] +pub struct ForExpr { + pub id: trap::TrapId, + pub label: Option>, + pub loop_body: Option>, + pub attrs: Vec>, + pub iterable: Option>, + pub pat: Option>, +} + +impl trap::TrapEntry for ForExpr { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("for_exprs", vec![id.into()]); + if let Some(v) = self.label { + out.add_tuple("labelable_expr_labels", vec![id.into(), v.into()]); + } + if let Some(v) = self.loop_body { + out.add_tuple("looping_expr_loop_bodies", vec![id.into(), v.into()]); + } + for (i, v) in self.attrs.into_iter().enumerate() { + out.add_tuple("for_expr_attrs", vec![id.into(), i.into(), v.into()]); + } + if let Some(v) = self.iterable { + out.add_tuple("for_expr_iterables", vec![id.into(), v.into()]); + } + if let Some(v) = self.pat { + out.add_tuple("for_expr_pats", vec![id.into(), v.into()]); + } + } +} + +impl trap::TrapClass for ForExpr { + fn class_name() -> &'static str { "ForExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of LabelableExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme ForExpr is a subclass of LoopingExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +#[derive(Debug)] +pub struct LoopExpr { + pub id: trap::TrapId, + pub label: Option>, + pub loop_body: Option>, + pub attrs: Vec>, +} + +impl trap::TrapEntry for LoopExpr { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("loop_exprs", vec![id.into()]); + if let Some(v) = self.label { + out.add_tuple("labelable_expr_labels", vec![id.into(), v.into()]); + } + if let Some(v) = self.loop_body { + out.add_tuple("looping_expr_loop_bodies", vec![id.into(), v.into()]); + } + for (i, v) in self.attrs.into_iter().enumerate() { + out.add_tuple("loop_expr_attrs", vec![id.into(), i.into(), v.into()]); + } + } +} + +impl trap::TrapClass for LoopExpr { + fn class_name() -> &'static str { "LoopExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of LabelableExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme LoopExpr is a subclass of LoopingExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +#[derive(Debug)] +pub struct WhileExpr { + pub id: trap::TrapId, + pub label: Option>, + pub loop_body: Option>, + pub attrs: Vec>, + pub condition: Option>, +} + +impl trap::TrapEntry for WhileExpr { + fn extract_id(&mut self) -> trap::TrapId { + std::mem::replace(&mut self.id, trap::TrapId::Star) + } + + fn emit(self, id: trap::Label, out: &mut trap::Writer) { + out.add_tuple("while_exprs", vec![id.into()]); + if let Some(v) = self.label { + out.add_tuple("labelable_expr_labels", vec![id.into(), v.into()]); + } + if let Some(v) = self.loop_body { + out.add_tuple("looping_expr_loop_bodies", vec![id.into(), v.into()]); + } + for (i, v) in self.attrs.into_iter().enumerate() { + out.add_tuple("while_expr_attrs", vec![id.into(), i.into(), v.into()]); + } + if let Some(v) = self.condition { + out.add_tuple("while_expr_conditions", vec![id.into(), v.into()]); + } + } +} + +impl trap::TrapClass for WhileExpr { + fn class_name() -> &'static str { "WhileExpr" } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of AstNode + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of Element + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of Expr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of LabelableExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of Locatable + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} + +impl From> for trap::Label { + fn from(value: trap::Label) -> Self { + // SAFETY: this is safe because in the dbscheme WhileExpr is a subclass of LoopingExpr + unsafe { + Self::from_untyped(value.as_untyped()) + } + } +} diff --git a/rust/extractor/src/translate/base.rs b/rust/extractor/src/translate/base.rs index c7e00edb3314..003c86919b67 100644 --- a/rust/extractor/src/translate/base.rs +++ b/rust/extractor/src/translate/base.rs @@ -10,7 +10,9 @@ use log::Level; use ra_ap_base_db::salsa::InternKey; use ra_ap_base_db::CrateOrigin; use ra_ap_hir::db::ExpandDatabase; -use ra_ap_hir::{Adt, Crate, ItemContainer, Module, ModuleDef, PathResolution, Semantics, Type}; +use ra_ap_hir::{ + Adt, Crate, ItemContainer, Module, ModuleDef, PathResolution, Semantics, Type, Variant, +}; use ra_ap_hir_def::type_ref::Mutability; use ra_ap_hir_def::ModuleId; use ra_ap_hir_expand::ExpandTo; @@ -47,6 +49,9 @@ macro_rules! emit_detached { (Module, $self:ident, $node:ident, $label:ident) => { $self.extract_canonical_origin(&$node, $label.into()); }; + (Variant, $self:ident, $node:ident, $label:ident) => { + $self.extract_canonical_origin_of_enum_variant(&$node, $label); + }; // TODO canonical origin of other items (Path, $self:ident, $node:ident, $label:ident) => { $self.extract_canonical_destination(&$node, $label); @@ -396,16 +401,24 @@ impl<'a> Translator<'a> { ModuleDef::Adt(Adt::Struct(it)) => self.canonical_path_from_hir(it), ModuleDef::Adt(Adt::Union(it)) => self.canonical_path_from_hir(it), ModuleDef::Trait(it) => self.canonical_path_from_hir(it), + ModuleDef::Variant(it) => self.canonical_path_from_enum_variant(it), ModuleDef::Static(_) => None, ModuleDef::TraitAlias(_) => None, ModuleDef::TypeAlias(_) => None, ModuleDef::BuiltinType(_) => None, ModuleDef::Macro(_) => None, - ModuleDef::Variant(_) => None, ModuleDef::Const(_) => None, } } + fn canonical_path_from_enum_variant(&self, item: Variant) -> Option { + // if we have a Hir entity, it means we have semantics + let sema = self.semantics.as_ref().unwrap(); + let prefix = self.canonical_path_from_hir(item.parent_enum(sema.db))?; + let name = item.name(sema.db); + Some(format!("{prefix}::{}", name.as_str())) + } + fn origin_from_hir(&self, item: impl AddressableHir) -> String { // if we have a Hir entity, it means we have semantics let sema = self.semantics.as_ref().unwrap(); @@ -437,28 +450,58 @@ impl<'a> Translator<'a> { ModuleDef::Adt(Adt::Struct(it)) => Some(self.origin_from_hir(it)), ModuleDef::Adt(Adt::Union(it)) => Some(self.origin_from_hir(it)), ModuleDef::Trait(it) => Some(self.origin_from_hir(it)), + ModuleDef::Variant(it) => Some(self.origin_from_enum_variant(it)), ModuleDef::Static(_) => None, ModuleDef::TraitAlias(_) => None, ModuleDef::TypeAlias(_) => None, ModuleDef::BuiltinType(_) => None, ModuleDef::Macro(_) => None, - ModuleDef::Variant(_) => None, ModuleDef::Const(_) => None, } } + fn origin_from_enum_variant(&self, item: Variant) -> String { + // if we have a Hir entity, it means we have semantics + let sema = self.semantics.as_ref().unwrap(); + self.origin_from_hir(item.parent_enum(sema.db)) + } + pub(crate) fn extract_canonical_origin( &mut self, item: &T, - label: Label, + label: Label, ) { (|| { let sema = self.semantics.as_ref()?; let def = T::Hir::try_from_source(item, sema)?; let path = self.canonical_path_from_hir(def)?; let origin = self.origin_from_hir(def); - generated::Item::emit_crate_origin(label, origin, &mut self.trap.writer); - generated::Item::emit_extended_canonical_path(label, path, &mut self.trap.writer); + generated::Addressable::emit_crate_origin(label, origin, &mut self.trap.writer); + generated::Addressable::emit_extended_canonical_path( + label, + path, + &mut self.trap.writer, + ); + Some(()) + })(); + } + + pub(crate) fn extract_canonical_origin_of_enum_variant( + &mut self, + item: &ast::Variant, + label: Label, + ) { + (|| { + let sema = self.semantics.as_ref()?; + let def = sema.to_enum_variant_def(item)?; + let path = self.canonical_path_from_enum_variant(def)?; + let origin = self.origin_from_enum_variant(def); + generated::Addressable::emit_crate_origin(label.into(), origin, &mut self.trap.writer); + generated::Addressable::emit_extended_canonical_path( + label.into(), + path, + &mut self.trap.writer, + ); Some(()) })(); } diff --git a/rust/extractor/src/translate/generated.rs b/rust/extractor/src/translate/generated.rs index aea607b753df..8e4a7986fbf7 100644 --- a/rust/extractor/src/translate/generated.rs +++ b/rust/extractor/src/translate/generated.rs @@ -397,12 +397,12 @@ impl Translator<'_> { pub(crate) fn emit_call_expr(&mut self, node: ast::CallExpr) -> Label { let arg_list = node.arg_list().map(|x| self.emit_arg_list(x)); let attrs = node.attrs().map(|x| self.emit_attr(x)).collect(); - let expr = node.expr().map(|x| self.emit_expr(x)); + let function = node.expr().map(|x| self.emit_expr(x)); let label = self.trap.emit(generated::CallExpr { id: TrapId::Star, arg_list, attrs, - expr, + function, }); self.emit_location(label, &node); emit_detached!(CallExpr, self, node, label); @@ -958,12 +958,12 @@ impl Translator<'_> { pub(crate) fn emit_let_expr(&mut self, node: ast::LetExpr) -> Label { let attrs = node.attrs().map(|x| self.emit_attr(x)).collect(); - let expr = node.expr().map(|x| self.emit_expr(x)); + let scrutinee = node.expr().map(|x| self.emit_expr(x)); let pat = node.pat().map(|x| self.emit_pat(x)); let label = self.trap.emit(generated::LetExpr { id: TrapId::Star, attrs, - expr, + scrutinee, pat, }); self.emit_location(label, &node); @@ -1224,12 +1224,12 @@ impl Translator<'_> { pub(crate) fn emit_match_expr(&mut self, node: ast::MatchExpr) -> Label { let attrs = node.attrs().map(|x| self.emit_attr(x)).collect(); - let expr = node.expr().map(|x| self.emit_expr(x)); + let scrutinee = node.expr().map(|x| self.emit_expr(x)); let match_arm_list = node.match_arm_list().map(|x| self.emit_match_arm_list(x)); let label = self.trap.emit(generated::MatchExpr { id: TrapId::Star, attrs, - expr, + scrutinee, match_arm_list, }); self.emit_location(label, &node); diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index ca25e0533fc8..f556bcb5df34 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -1,4 +1,6 @@ +lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll a8e083c7d8c4dea6459c5e128e2123f5cf8fd14c076f2256ebda508c13d553cd 16fcc0d34097b0b37a0041281515ca028d2702eec6d9c1d03c39a1158883bdef lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893 +lib/codeql/rust/elements/Addressable.qll 13011bfd2e1556694c3d440cc34af8527da4df49ad92b62f2939d3699ff2cea5 ddb25935f7553a1a384b1abe2e4b4fa90ab50b952dadec32fd867afcb054f4be lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71 lib/codeql/rust/elements/ArrayExpr.qll a3e6e122632f4011644ec31b37f88b32fe3f2b7e388e7e878a6883309937049f 12ccb5873d95c433da5606fd371d182ef2f71b78d0c53c2d6dec10fa45852bdc lib/codeql/rust/elements/ArrayType.qll affd43d308200d60d08e8924cdbb2a17a827ebaa62a296e07bb9ce97451e3c4c 80589a7f79bf2ac293a027faf2589b3027a6c4a286533f2ffccad259a306a8cb @@ -11,7 +13,7 @@ lib/codeql/rust/elements/Attr.qll 53887a49513b95e38344b57d824a7474331467561f1edf lib/codeql/rust/elements/AwaitExpr.qll d8b37c01f7d27f0ec40d92a533a8f09a06af7ece1ae832b4ea8f2450c1762511 92cdb7ff0efddf26bed2b7b2729fddd197e26c1a11c8fec0c747aab642710c21 lib/codeql/rust/elements/BecomeExpr.qll 7a3cfc4894feb6be1cde664f675b18936434e68ccea52e55314c33d01491e34f 49666eca509b30d44bb02702bda67239c76bf8d9f231022c9cf6ecca123f8616 lib/codeql/rust/elements/BinaryExpr.qll 394522da3bc3a716fc7bc40c3560143ca840f5d210cfcba2a752c3026dd0f725 fbbd6fb79bf16a7d9820613654c584cd7ff3e7a29988f3920b6cfbe746acfd8d -lib/codeql/rust/elements/BlockExpr.qll b952fd44b89de248931d4089834d2c9406f6f2fc1a3f5c2365156be4e55157cf daccc07ab11ac696679b9fadc99f40b1bf579c90bf6c7cca6e82eaa313932ede +lib/codeql/rust/elements/BlockExpr.qll b5cf57119b15f27d0bc258dfa375b0ef2730c157870ff543f0dc7a8cfe514182 f6a01999606b010c81ef9c6ff1385e6640632b6f5ce067ffeb0ef0af0a0aeb92 lib/codeql/rust/elements/BoxPat.qll 1b2c3fff171aa6aa238c9460b122f26c79e04577cea67fa856de99842ba873d4 0caf8d23ed6e0997a6b8751def27641582151fba6e24fccf798712a4690b42f1 lib/codeql/rust/elements/BreakExpr.qll 7ca3807a20e9a9a988d1fd7abebf240325ed422fcb45c719ba46272f031f94db dffb7379d3f3ba220acfbd05eb7bb6cfd9cfda211e9c8b1f5240ca5fa61be3fc lib/codeql/rust/elements/CallExpr.qll f336500ca7a611b164d48b90e80edb0c0d3816792b0ececce659ac1ff1ffeb3e f99a9c55466418ef53860c44d9f2d6161af4b492178ddd9e5870dff742b70ae5 @@ -38,12 +40,12 @@ lib/codeql/rust/elements/ExternItemList.qll bc96f188970e8dc0cd1e77dea3e49b715edf lib/codeql/rust/elements/FieldExpr.qll 8102cd659f9059cf6af2a22033cfcd2aae9c35204b86f7d219a05f1f8de54b3b f818169dddf5102095ae1410583615f80031376a08b5307d0c464e79953c3975 lib/codeql/rust/elements/FieldList.qll bd243adc4696c60f636055a1c2da28039fe2028476c9247eb6a68003b849b757 ab63cdf410afd1e515f873b49f46bb5c2bf27e6c78fd206ccbdba064c4c0a4b2 lib/codeql/rust/elements/FnPtrType.qll c4a90dc660cf620972dc23b95494f5caf9f050eabd4bdb52fdc061f8797ba9a1 f8defc91582fa503607664668f9e2e6c2cd8b320c7c449610f21e52e332a129f -lib/codeql/rust/elements/ForExpr.qll 312804d53dd9236a2f2a15c9d6ec348b46e139a54eb5893e7e12487725df7444 fa5e20099b1179033bc209bad3548e3d1d4019c7fe0e455cec8ca1a9d48692ab +lib/codeql/rust/elements/ForExpr.qll 0cc8bfe10b8baf62a1ff65c8463cfb17ab64b41c30c9e1edb962a227df2036d9 b1be73294e6da0f49fd32177ad0b05fecf26081d5ce424f288be99a4bd59cc84 lib/codeql/rust/elements/ForType.qll 0036bed8749358c356d78c4a0eef40d73e2796284293cde5604ae70ddd6d0470 4edcaf8f7c67d42ebe3ebb1be6a7643758717d4fe88f5f648b6a1c5ff4ee4de7 -lib/codeql/rust/elements/Format.qll 506172d176f4b965f428585c032464f4abe07a0e47c574f8e011d8641ec45370 653e81bf233b8729649064de64f4a7a8533f8864ac6d2ea913f347088c924c60 +lib/codeql/rust/elements/Format.qll 51222fa2d2e85d496ab093d74d3bc606ede3ce48f926106e059dc8478e657203 b4da6be38413c86f2e9d82004624abab16e23ef238197a5c85246009cce276d5 lib/codeql/rust/elements/FormatArgsArg.qll 5bc9b4cd1bac7131165836e93838c45452a08ea6011741cbddace3cbf9c69440 f825140e98dc9800d5c045402186793c7b21511448e2f6bf6402d1e06305219c -lib/codeql/rust/elements/FormatArgsExpr.qll f2ffad5a1105b29a8437c8ed6cf918cfcf4d65ac164bbf1be0585c3b673ca749 3ba20dc312a0a994bb43b37b2db72cbd4e06061b97918fa0e84ce355070ffbeb -lib/codeql/rust/elements/FormatArgument.qll bdd93e1da78637f19beee6f953d3a45512100e925d90cb5ad08a097f412009b8 2a0ae7eb885615e380f925c0d130a1b795bf3c395486550a1f1c9c82848f8d77 +lib/codeql/rust/elements/FormatArgsExpr.qll 8127cbe4082f7acc3d8a05298c2c9bea302519b8a6cd2d158a83c516d18fc487 88cf9b3bedd69a1150968f9a465c904bbb6805da0e0b90cfd1fc0dab1f6d9319 +lib/codeql/rust/elements/FormatArgument.qll f6fe17ee1481c353dd42edae8b5fa79aeb99dff25b4842ec9a6f267b1837d1e3 5aed19c2daf2383b89ad7fd527375641cff26ddee7afddb89bc0d18d520f4034 lib/codeql/rust/elements/FormatTemplateVariableAccess.qll ff3218a1dda30c232d0ecd9d1c60bbb9f3973456ef0bee1d1a12ad14b1e082b5 e4316291c939800d8b34d477d92be9404a30d52b7eee37302aef3d3205cf4ae0 lib/codeql/rust/elements/Function.qll 2c76c2c7036891996b1f0ebde16c414edf37ebb44ff9c3483088dc6218733e07 d84d017d98aa240bf3bee6502a030aa8cfb7ed95425ffa9853e73b41485e1f4a lib/codeql/rust/elements/GenericArg.qll 5f11ce0e3c5f08de84db61f56ba1b984652455ba6b95a8b8a5b5a235913d4072 756b6a73d66fde45bdcc65ce2362a5b1391af2927e6d54b6550b3ecd5fd11e75 @@ -56,9 +58,10 @@ lib/codeql/rust/elements/Impl.qll 9593c47af4fa08afb19c52aab7d0bac6740fed7ec60201 lib/codeql/rust/elements/ImplTraitType.qll f7241044f6666a509cfbc01bf6df3db5360e67dd0f9baba4a323566701359203 350636d0b1c7a77e006170cbfa9108c259dd5831b0f242da76c10be3ecc32870 lib/codeql/rust/elements/IndexExpr.qll 0e2e9f018d06ae72be0fc4ddbc019a9aacd8a06f42b4c4431760bd149e7f2290 2bcfd557abd53a48e48de7915c4f2089107c62dfb3e732a904848248dfd3727b lib/codeql/rust/elements/InferType.qll c71184ae6aa181be94e299882503350e057493e17f1133a1e96162a0e5cbd1ef f0f19b611708df45a6ff811f8066c8042a8e1ac9b7bd94910514547ea430d3d5 -lib/codeql/rust/elements/Item.qll 5c9148ff0eaeb4404c2d8156e7df0ef5753fd44ead972da05a49659ddaa25480 78446f788617e40525d4d4b489848e75f2143a90e18d40974c3bff7b1e7c825c +lib/codeql/rust/elements/Item.qll 59353bf99dea5b464f45ed0dc5cef2db8208e92985d81dcd0b5ea09b638d10e4 2b0b87a4b1a1d9b512a67279d1dec2089d22d1df121585f7a9ca9661d689f74f lib/codeql/rust/elements/ItemList.qll c33e46a9ee45ccb194a0fe5b30a6ad3bcecb0f51486c94e0191a943710a17a7d 5a69c4e7712b4529681c4406d23dc1b6b9e5b3c03552688c55addab271912ed5 lib/codeql/rust/elements/Label.qll a31d41db351af7f99a55b26cdbbc7f13b4e96b660a74e2f1cc90c17ee8df8d73 689f87cb056c8a2aefe1a0bfc2486a32feb44eb3175803c61961a6aeee53d66e +lib/codeql/rust/elements/LabelableExpr.qll 598be487cd051b004ab95cbbc3029100069dc9955851c492029d80f230e56f0d 92c49b3cfdaba07982f950e18a8d62dae4e96f5d9ae0d7d2f4292628361f0ddc lib/codeql/rust/elements/LetElse.qll 85d16cb9cb2162493a9bacfe4b9e6a3b325d9466175b6d1a8e649bdf2191b864 c268d0878e9f82e8ede930b3825745c39ab8cd4db818eb9be6dc5ca49bee7579 lib/codeql/rust/elements/LetExpr.qll 435f233890799a9f52972a023e381bc6fe2e0b3df1e696dc98b21682a3c1d88e b34da72dd222a381e098f160551ec614ebb98eb46af35c6e1d337e173d8ec4b9 lib/codeql/rust/elements/LetStmt.qll e589d750ff87c25e28e15dab61e1a3555a45ced42158b05c991c6f5873abd86a 383484181b825cd7bc20e014fc4d5888f66e1f257502e1893f3d55aed2cdef3d @@ -68,7 +71,8 @@ lib/codeql/rust/elements/LifetimeParam.qll db9f2c7bb32d49808993b400875e79560ac54 lib/codeql/rust/elements/LiteralExpr.qll 40b67404b7c2b81e5afabc53a2a93e0a503f687bb31a2b4bfa4e07b2d764eb8d 67ab1be2286e769fba7a50ca16748e3c141760ccaefaebae99faa71f523a43d5 lib/codeql/rust/elements/LiteralPat.qll daffb5f380a47543669c8cc92628b0e0de478c3ac82685802c63e8d75a206bed adfe9796598cf6ca4a9170c89ffd871e117f1cea6dd7dd80ecbbb947327a1a5d lib/codeql/rust/elements/Locatable.qll 2855efa4a469b54e0ca85daa89309a8b991cded6f3f10db361010831ba1e11d3 00c3406d14603f90abea11bf074eaf2c0b623a30e29cf6afc3a247cb58b92f0f -lib/codeql/rust/elements/LoopExpr.qll 58ade0bc4a01a1cc361363682fde3ea56f4c5fbb4b28f5723ceff52ebaf897d7 fa299162c742bcf3b2211dc20821b312e3c133350c288a050eb26e6f8b5a5c78 +lib/codeql/rust/elements/LoopExpr.qll ee171177650fa23eef102a9580765f4b6073a1cc41bab1ec31ad4f84ffe6c2c9 bfcf0cca4dc944270d9748a202829a38c64dfae167c0d3a4202788ceb9daf5f6 +lib/codeql/rust/elements/LoopingExpr.qll 7ad7d4bbfd05adc0bb9b4ca90ff3377b8298121ca5360ffb45d5a7a1e20fe37a 964168b2045ee9bad827bba53f10a64d649b3513f2d1e3c17a1b1f11d0fc7f3a lib/codeql/rust/elements/MacroCall.qll a39a11d387355f59af3007dcbab3282e2b9e3289c1f8f4c6b96154ddb802f8c3 88d4575e462af2aa780219ba1338a790547fdfc1d267c4b84f1b929f4bc08d05 lib/codeql/rust/elements/MacroDef.qll acb39275a1a3257084314a46ad4d8477946130f57e401c70c5949ad6aafc5c5f 6a8a8db12a3ec345fede51ca36e8c6acbdce58c5144388bb94f0706416fa152a lib/codeql/rust/elements/MacroExpr.qll ea9fed13f610bab1a2c4541c994510e0cb806530b60beef0d0c36b23e3b620f0 ad11a6bbd3a229ad97a16049cc6b0f3c8740f9f75ea61bbf4eebb072db9b12d2 @@ -90,18 +94,19 @@ lib/codeql/rust/elements/NameRef.qll f11e33cdbefb3efdd8db6cd1eee593948a16ef5dd13 lib/codeql/rust/elements/NeverType.qll 669823dd60bba0cebac614f9dbad9dc9228405d76e62092e265df57fdd2e04e2 8fe32975ef80d86fb8b218f56962f0a89911008a8d6989e245c3e0362f2c747f lib/codeql/rust/elements/OffsetOfExpr.qll 8f6dd1fe0aad1642e58f5e97620306e4b36cdf01324fead1e2a92e8e60951c41 b192f7a5fae3049a6cac3b7a225a0e590f744e6c5ff6346ffdd1699f83bf718f lib/codeql/rust/elements/OrPat.qll 408b71f51edbfc79bf93b86fb058d01fa79caf2ebfeef37b50ae1da886c71b68 4a3f2b00db33fe26ee0859e35261016312cb491e23c46746cdd6d8bb1f6c88ef -lib/codeql/rust/elements/Param.qll 3108a710214977218421b220d1330793173d6b6b91708b641e3d1275f80faedb 4bb2b80d0a9a4d86f980440851d59ca6fffea681e5518f5d605c521191efd7b4 +lib/codeql/rust/elements/Param.qll d0c0a427c003bbbacaeb0c2f4566f35b997ad0bca4d49f97b50c3a4bd1ddbd71 e654a17dfcb7aaeb589e7944c38f591c4cf922ebceb834071bcb9f9165ee48be +lib/codeql/rust/elements/ParamBase.qll ab8cb39ac313a5dce7d1a6dcd490c5033034d88f0e402f315f4236bb76c2c464 414afc1f34c1df28f76220c5d3255ae3d7629f3df8b870d0949f3a6c87e26d71 lib/codeql/rust/elements/ParamList.qll 33a22ba7de565db4009d3f56eecd5ef809c28d9dce9bbac3fb71b528baae4f70 004375e227d87f76f930322ad3eac274f9b691bf58785ae69977fa319f3dba7e lib/codeql/rust/elements/ParenExpr.qll b635f0e5d300cd9cf3651cfcefd58316c21727295bbfd44b1f5672f9e3de67b6 d81c0034d4ea7ca5829f9b00e0a634ba5b557a6296d99f0b5344b11e1ba705a1 lib/codeql/rust/elements/ParenPat.qll 40d033de6c85ad042223e0da80479adebab35494396ab652da85d3497e435c5a 8f2febe5d5cefcb076d201ae9607d403b9cfe8169d2f4b71d13868e0af43dc25 lib/codeql/rust/elements/ParenType.qll e1f5695b143c97b98ccdb460a5cf872461cfc13b83a4f005f26c288dc0afae10 1164f8efae7f255925411bddb33939fab0bf1c07955a16fef173b3f4675d09ae lib/codeql/rust/elements/Pat.qll 56211c5cb4709e7c12a2bfd2da5e413a451672d99e23a8386c08ad0b999fd45c b1b1893a13a75c4f0390f7e2a14ee98a46f067cfdc991a8d43adc82497d20aff -lib/codeql/rust/elements/Path.qll a0078e6d57dfd5a3b7fb2be4587f55f8e9c65ee042815a8a5b8dbd5273b4076a 0e2d4f8cbd54bd60aa4929b5fd50fe214346b6c0451f73e45143445d15420108 +lib/codeql/rust/elements/Path.qll 94869df09b929c4a60bae42b7e3a66c007f41078c08b7d9c6defb705b953ce8e eb317f75b89978d41fd3b166c7e3d871da4c04b3e17afbbcd0a5d73881e0d1d9 lib/codeql/rust/elements/PathExpr.qll 906df1d80c662b79f1b0b0428c39754b7f8dbcb2234919dd45dd8206a099dd36 1d6015afab6378c926c5838c9a5772cfcfeedf474e2eeca3e46085300ff8d4e1 lib/codeql/rust/elements/PathExprBase.qll bb41092ec690ae926e3233c215dcaf1fd8e161b8a6955151949f492e02dba13a b2257072f8062d31c29c63ee1311b07e0d2eb37075f582cfc76bb542ef773198 lib/codeql/rust/elements/PathPat.qll 6897e69bcb24b56d39ede796cf5767988dcd5741e02333fa8495dd7c814f771a 2a011fb92f17e4b4ff713e6d29f591054dfede22a9aaa006e67fca2c23ab76bf -lib/codeql/rust/elements/PathSegment.qll 536a8fe172db367e5f1dc678a014e2350eadfc379242d2b5451725e826ab1448 1a3a237f56c1d9ccdce6832ec6417fed25cd3e29ba836363cc6085e2125de4c5 -lib/codeql/rust/elements/PathType.qll a7bd3b05dc2c0e96c91c5485db508a1f5bb8fe3a01486be6815ae9dabb163add b11e996b6c0cc21a3d8d1ddc23c37e4d54a78e84a9278b3ceca1e94cb7321532 +lib/codeql/rust/elements/PathSegment.qll 9560551cf8b65e84705e7f302e12b48330e048613129e87c0f65a7eb297a6cc3 3aa75a5fd81f8ea32bd2b4bf0c51c386de57cbe9ab035fe3ec68ad7fcf51b375 +lib/codeql/rust/elements/PathType.qll 257ede178bb74ebdb8e266ebaa95082e7fb7cc8d921ef476f4df268ee8a1366c c48f6e04a8945a11f965e71819f68c00abc53a055042882b61716feda3ca63ae lib/codeql/rust/elements/PrefixExpr.qll 107e7bd111b637fd6d76026062d54c2780760b965f172ef119c50dd0714a377d 46954a9404e561c51682395729daac3bda5442113f29839d043e9605d63f7f6d lib/codeql/rust/elements/PtrType.qll b137f47a53e41b3b30c7d80dbdd6724bf15f99530ca40cc264a04af5f07aa878 b2ffdf739bfb7564d942fe54409834a59511c0b305b6d5b2219a8ee0ef594332 lib/codeql/rust/elements/RangeExpr.qll 43785bea08a6a537010db1138e68ae92eed7e481744188dfb3bad119425ff740 5e81cfbdf4617372a73d662a248a0b380c1f40988a5daefb7f00057cae10d3d4 @@ -123,7 +128,7 @@ lib/codeql/rust/elements/RestPat.qll a898a2c396f974a52424efbc8168174416ac6ed30f9 lib/codeql/rust/elements/RetType.qll 36ea39240a56c504d94d5487ea9679563eef3dfe0e23bf42d992d1ab2b883518 2fe5b6f62a634c6aa30a1ecd620f3446c167669cf1285c8ef8dd5e5a6ef5fc71 lib/codeql/rust/elements/ReturnExpr.qll b87187cff55bc33c8c18558c9b88617179183d1341b322c1cab35ba07167bbdb 892f3a9df2187e745c869e67f33c228ee42754bc9e4f8f4c1718472eb8f8c80f lib/codeql/rust/elements/ReturnTypeSyntax.qll 0aa9125f5ea8864ecf1e4ff6e85f060f1b11fdd603448816145fea1b290f0232 3911819548ad1cf493199aac2ed15652c8e48b532a1e92153388b062191c1e6e -lib/codeql/rust/elements/SelfParam.qll 5c9629e1cd837f5d84bdd79a1aef9cca6fb0acb1fb18671d4a4d28c23a74551a 41eb92527cf4379a2df54a0c9fabc368cb6f9b8d1ac73bd2ab3f13214573e764 +lib/codeql/rust/elements/SelfParam.qll 7d720c99097a340bc7bf6cc27ac6fe291a04af53e9bac23bf070b04b36e6e033 736488794a46ea702dcd3f603134052598207f3953acce3c9237bd6c6a038b23 lib/codeql/rust/elements/SlicePat.qll f48f13bb13378cc68f935d5b09175c316f3e81f50ef6a3ac5fdbfbfb473d6fc1 4c8df0b092274f37028e287a949f1a287f7505b7c2c36ee8d5f47fb8365d278a lib/codeql/rust/elements/SliceType.qll 7e49dba57826c7bb72a88f9e802febdb09adfc49804f6205dc88f2a307fd1f30 6c3ee430f812f1d9fbb1fb1fdd2c47130a4bde7fccf17f09404b8cbc8104678a lib/codeql/rust/elements/SourceFile.qll 5916d550385d618bd3b3d4835fbd3040485822220af8ce52ee1adb649b3d8594 0b79766216649e948fa59de467d64fa752de4666c28e0e503e88740ae27a2aef @@ -155,21 +160,21 @@ lib/codeql/rust/elements/Union.qll 92ffb1abc03889b9b71dae9491d4595e443c80b472474 lib/codeql/rust/elements/Use.qll e27d30ece0456a73732dfd867dfc5abdf48a50de56e7dafcab444b688610af72 7efe59c04dd2f10b4a25b8a17beb51362be0a93d73e5a9e1251cf133cf1227c3 lib/codeql/rust/elements/UseTree.qll 16b6e42146dc4c2e9d8cc6bc143933d675d1a4c9a56b309f390f4bf5df99b25d 9f8dd7d621dd15f6f1ccec676b08da02773673cbb3a3570781c16167c6e08ef4 lib/codeql/rust/elements/UseTreeList.qll 768c4ec25e8807bba65619f566b22fa5c0946c36e96c88cfdee04c2875b44554 6433c8d9acd4e346cadd5fef01d79dd35bb6245115bdceb5322c0511106030b0 -lib/codeql/rust/elements/Variant.qll b0770c3ce0a82dcb2e238024b1db4ee2b76271f5a3d94f03bdaee71a25218da1 af242bd8651b653d931bf4cd3c234bdb58c8516eb4576edc03a929232946c38e +lib/codeql/rust/elements/Variant.qll 328323ef59faf01dcf71e7d728fd10a60465a1bd24e1d3578289cdf6554e5b63 ba49c635790395d9df4398c3c0fec700c3c7761fcc6581623a45d381d23ac34d lib/codeql/rust/elements/VariantList.qll 07adfe5750b2d5b50c8629f36feba24edd84f75698a80339d4cee20f4e95829d 7d322e60c84ea45f8c8b509226da7ae3c0125bcda42a98a94e3e6a9855cab79e lib/codeql/rust/elements/Visibility.qll d2cf0727efaf8df6b3808cb4a6b2e26d18e42db766d92e97ad3ef046d91cb9e5 8947a1e2d48b532c6455ddf143fa5b1dff28c40da1f1c6a72769fc9db7ecbaf6 lib/codeql/rust/elements/WhereClause.qll da51212766700e40713fff968078a0172a4f73eebc5425d8e0d60b03c2fe59fa 0ec036aea729b8f4af0eb8118911dce715e2eb4640ae7b5e40a007a48da03899 lib/codeql/rust/elements/WherePred.qll 4815cd8f2a536c895e1f6831bef2ee6b9ea42c4fea12df1f164de1c965795bc1 3b46806767d81218d2e21656afe39c957c364ff7067c9af3ae8bacbf7f93858b -lib/codeql/rust/elements/WhileExpr.qll 9c12c26f953163c70020669327bd8c931493ef7fb4b75e6711202c0bab1d2697 2e2c96425bcd4414c65d9069a71a5123a3a10dd1449cafc121ac08f91ea49728 +lib/codeql/rust/elements/WhileExpr.qll 9e0c23057bf3fa3e050d5f6de0650f554ce576861783ea7d1e4c7d35db129ad3 b294c4f6e4dea922a4274779287edcb484409b2654a553298626ded9d1e8c5a4 lib/codeql/rust/elements/WildcardPat.qll 4f941afc5f9f8d319719312399a8f787c75a0dbb709ec7cf488f019339635aab a9140a86da752f9126e586ddb9424b23b3fb4841a5420bac48108c38bb218930 lib/codeql/rust/elements/YeetExpr.qll 4172bf70de31cab17639da6eed4a12a7afcefd7aa9182216c3811c822d3d6b17 88223aab1bef696f508e0605615d6b83e1eaef755314e6a651ae977edd3757c3 lib/codeql/rust/elements/YieldExpr.qll de2dc096a077f6c57bba9d1c2b2dcdbecce501333753b866d77c3ffbe06aa516 1f3e8949689c09ed356ff4777394fe39f2ed2b1e6c381fd391790da4f5d5c76a lib/codeql/rust/elements/internal/AbiConstructor.qll 4484538db49d7c1d31c139f0f21879fceb48d00416e24499a1d4b1337b4141ac 460818e397f2a1a8f2e5466d9551698b0e569d4640fcb87de6c4268a519b3da1 lib/codeql/rust/elements/internal/AbiImpl.qll 01439712ecadc9dc8da6f74d2e19cee13c77f8e1e25699055da675b2c88cb02d dcc9395ef8abd1af3805f3e7fcbc2d7ce30affbce654b6f5e559924768db403c +lib/codeql/rust/elements/internal/AddressableImpl.qll e01a6104980960f5708d5a0ada774ba21db9a344e33deeaf3d3239c627268c77 b8bfc711b267df305ac9fe5f6a994f051ddeca7fc95dacd76d1bae2d4fa7adde lib/codeql/rust/elements/internal/ArgListConstructor.qll a73685c8792ae23a2d628e7357658efb3f6e34006ff6e9661863ef116ec0b015 0bee572a046e8dfc031b1216d729843991519d94ae66280f5e795d20aea07a22 lib/codeql/rust/elements/internal/ArgListImpl.qll 19664651c06b46530f0ae5745ccb3233afc97b9152e053761d641de6e9c62d38 40af167e571f5c255f264b3be7cc7f5ff42ec109661ca03dcee94e92f8facfc6 lib/codeql/rust/elements/internal/ArrayExprConstructor.qll f4ac4efefe5fe4fe1e666f35b1ee92d2243d977b3f3308151c89f61582203c09 4167ae58ec869f7dbd8467093c4a53afd7c1efcf1cc865efa62b4eb484bd7ff8 -lib/codeql/rust/elements/internal/ArrayExprImpl.qll 205db9816ec56409db1a0c3987e3a64b8e88b9942055d4bcf84a5fd5943efded 094c954c2861fa7dea69247c9c16ddc6c8699dcd3201a993c72229450bed1490 lib/codeql/rust/elements/internal/ArrayTypeConstructor.qll 9e92e6c40df992b4d71ae0e80392e81499604c7586a671b89d31d2d98060380e 76a1915a88f50ffa60bf129237bae2d66cf26d2a9018aca8ccb343929e847531 lib/codeql/rust/elements/internal/ArrayTypeImpl.qll e22d4f4eb21ba1ea44dd53e0c80aa60ec3a42818c1fc2d512c92dc496a6e2cb3 1b4a7347dbb9310ace1e9e3d08c3ba53c1dc441539cebcb4a78f64a58097bc0a lib/codeql/rust/elements/internal/AsmExprConstructor.qll 36c68023b58beec30af9f05d9d902a4c49faa0206b5528d6aad494a91da07941 4d91b7d30def03e634b92c0d7b99b47c3aadd75f4499f425b80355bc775ea5b6 @@ -182,25 +187,19 @@ lib/codeql/rust/elements/internal/AssocTypeArgImpl.qll 429f12a1a53c81634fc35331b lib/codeql/rust/elements/internal/AttrConstructor.qll de1dd30692635810277430291ba3889a456344dbd25938d9f8289ab22506d5cd 57b62b2b07dee4a9daeed241e0b4514ba36fd5ec0abb089869a4d5b2c79d6e72 lib/codeql/rust/elements/internal/AttrImpl.qll 486d307f74a48e6475fe014b07d5e0e13bbdf493ea80823e77e39747edf470d7 0847aa78d0e075aedbe46c10935969046bde4a7ab842da9d184739eb99a777c2 lib/codeql/rust/elements/internal/AwaitExprConstructor.qll 44ff1653e73d5b9f6885c0a200b45175bb8f2ceb8942c0816520976c74f1fc77 11e6f4a1e1462a59e2652925c8bd6663e0346c311c0b60ebe80daa3b55b268b0 -lib/codeql/rust/elements/internal/AwaitExprImpl.qll 97eb9abc0f30ead9385f31c87b461e6f1bbfbeaac17810838bb94543bfca181f 66357ffc8c106aae565524d7110e9f50f2b3f573b1508c1d1b02db02af4cc52e lib/codeql/rust/elements/internal/BecomeExprConstructor.qll ba073aaa256cb8827a0307c3128d50f62b11aac0b1f324e48c95f30351a9b942 3a787ded505c3158fa4f4923f66e8ecdcb7b5f86f27f64c5412dc32dca031f18 -lib/codeql/rust/elements/internal/BecomeExprImpl.qll 8522410257ca9ff09e5314c3a39fba02f6ba18e1d4349b91f8823586317f3e47 073a877a6d72c5b762aac64cdd843fd2872aaefb9e264fb90eac8c25753a6e07 lib/codeql/rust/elements/internal/BinaryExprConstructor.qll 7f9b17757f78b9fb7c46e21d2040a77fa50083bef4911c8464991c3d1ad91d87 a59390cd8e896c0bfbdc9ba0674e06d980ffcefa710fbc9886be52ed427e9717 lib/codeql/rust/elements/internal/BlockExprConstructor.qll 438337c807645e98a01440f3f4610d68b0567ba15c8f51dc43bf5a30c9af3696 48ce7a546910c884619762349b8ada9836284f8008298fdb0070a38f7ddf25a0 lib/codeql/rust/elements/internal/BlockExprImpl.qll 36ac09e4a6eeeec22919b62b1d004bdb5bb2527e67932c308aec383a770768d6 3b4b2a2014f6fe075c63a2d633b297566b548ef2e4343cadf067a9edbcadc876 lib/codeql/rust/elements/internal/BoxPatConstructor.qll 153f110ba25fd6c889092bfd16f73bb610fa60d6e0c8965d5f44d2446fcd48a2 9324cf0d8aa29945551bf8ab64801d598f57aab8cd4e19bcd4e9ef8a4a4e06eb -lib/codeql/rust/elements/internal/BoxPatImpl.qll d62a3cc1d5bab6bd258f702ec731ec57f0e5ef2672ab9de4b6f3b558078629eb 26b4fabb676adbbdb0d7f81449e493ee49380ea04d131f779714ac2434bb323a lib/codeql/rust/elements/internal/BreakExprConstructor.qll 356be043c28e0b34fdf925a119c945632ee883c6f5ebb9a27003c6a8d250afd9 bb77e66b04bb9489340e7506931559b94285c6904b6f9d2f83b214cba4f3cfd5 lib/codeql/rust/elements/internal/CallExprBaseImpl.qll d2749cc1a9d7ee8bf7f34b6c3e0238a576a68e439a8c10a503c164ff45ffcbeb ffc7b0a8841945fe6736b0e1aed7d9ed69185db03dee2b16da121325b39397c7 lib/codeql/rust/elements/internal/CallExprConstructor.qll 742b38e862e2cf82fd1ecc4d4fc5b4782a9c7c07f031452b2bae7aa59d5aa13a cad6e0a8be21d91b20ac2ec16cab9c30eae810b452c0f1992ed87d5c7f4144dc -lib/codeql/rust/elements/internal/CallExprImpl.qll 7e48610680ba6f2876a1a005ab0743496dd2364b9c44aca441bd33e11317e2d7 bb12c3c28156b40796fe3ba112760f87bb5abb323aab3c5b7bb3e0facaef8d35 lib/codeql/rust/elements/internal/CallableImpl.qll 917a7d298583e15246428f32fba4cde6fc57a1790262731be27a96baddd8cf5e c5c0848024e0fe3fbb775e7750cf1a2c2dfa454a5aef0df55fec3d0a6fe99190 lib/codeql/rust/elements/internal/CastExprConstructor.qll f3d6e10c4731f38a384675aeab3fba47d17b9e15648293787092bb3247ed808d d738a7751dbadb70aa1dcffcf8af7fa61d4cf8029798369a7e8620013afff4ed -lib/codeql/rust/elements/internal/CastExprImpl.qll 3c57b75f01efc70013ba3f05bd79fe2747fe1d1de47b84ff73b06ad38b4f1093 da813adc3390d23ec0643e37226a58e8afdb78e889380ad265d7531a344b841c lib/codeql/rust/elements/internal/ClosureBinderConstructor.qll 6e376ab9d40308e95bcdaf1cc892472c92099d477720192cd382d2c4e0d9c8a1 60a0efe50203ad5bb97bdfc06d602182edcc48ac9670f2d27a9675bd9fd8e19f lib/codeql/rust/elements/internal/ClosureBinderImpl.qll 58c6b17d34d678802ce3484f556482f3f6e3c3ff9a4be0e845bc2077818ab6fb 467261e12cba46f324364f5366bdb0034bf3c922b08307d39441ea5181e3f5f8 lib/codeql/rust/elements/internal/ClosureExprConstructor.qll a348229d2b25c7ebd43b58461830b7915e92d31ae83436ec831e0c4873f6218a 70a1d2ac33db3ac4da5826b0e8628f2f29a8f9cdfd8e4fd0e488d90ce0031a38 -lib/codeql/rust/elements/internal/ClosureExprImpl.qll 5ae3d211273b3effc3bff9f06bcef480f8264084e0509e69b8ff29bc29f47b05 ff562bc8d15ecb76ada3111c7c74dd990a0e80f41a32477f5f2f7db9e8f71102 lib/codeql/rust/elements/internal/CommentConstructor.qll 0b4a6a976d667bf7595500dfb91b9cfc87460a501837ba5382d9a8d8321d7736 7d02d8c94a319dc48e7978d5270e33fc5c308d443768ff96b618236d250123f1 lib/codeql/rust/elements/internal/ConstArgConstructor.qll f63021dc1ca2276786da3a981d06c18d7a360b5e75c08bca5d1afece4f7c4a83 487a870cbf5ed6554d671a8e159edd9261d853eba2d28ce2bd459759f47f11f2 lib/codeql/rust/elements/internal/ConstArgImpl.qll 234fe6533c208a1731cdb423aa3a28909bd7e042dbc28bbedfd4f62e42b6f21e c576a49006f7a10483041fc07f2f0d089710ac61840be61a2e71140db709f9c6 @@ -214,7 +213,6 @@ lib/codeql/rust/elements/internal/ContinueExprConstructor.qll cd93f1b35ccdb031d7 lib/codeql/rust/elements/internal/DynTraitTypeConstructor.qll 2bfd81fdf116b76f4a62b47bed5f0a730c04ce79747ecd1d3b683b8de22ff4aa 375c57350c432351396b92f28fded1e95a8002e3a1b31f3b66039f9b3d9bdea9 lib/codeql/rust/elements/internal/DynTraitTypeImpl.qll 8ccf27db0b898f518874ae094e5c97206384ad2fd3f82f81a5ecaad953278f71 e28ab56b8814a804e23afa790ca0f9a2665195b0b316d6cc52936e76ce5c0011 lib/codeql/rust/elements/internal/EnumConstructor.qll eca1a13937faacb1db50e4cf69d175f992f2204a5aaed9144bb6f3cb63814ac5 1bafba78b2729fdb052a25a1ba3f4f70871564aa4df632b4a1d467858a437924 -lib/codeql/rust/elements/internal/EnumImpl.qll c4dfa97b0c656957390417ab09c81b29b67fbff1b7b14976d65625ebea6b2c11 940303d4d4cec130f1981d309f8eaea6803c14a41174bbe9a87dd12ce4975945 lib/codeql/rust/elements/internal/ExprImpl.qll ab20ee174e2e786f34af6e5dedf3ec071bb89fc266b3e91df6377f72aa38d3f2 f68192700f449bf1c229cfbaabd5353c7c559941c915d5a0c88752cf9844194b lib/codeql/rust/elements/internal/ExprStmtConstructor.qll dd6bb06a7d48c12f630aafd611621cc50ce0f3e7d9abba5484a695f90879264b dc8b6ec8acc314e041ae71868803630c5d4cab488c72c1ea929bb756e1847c52 lib/codeql/rust/elements/internal/ExprStmtImpl.qll 420221c64245b490dab85f4e50d6b408cf488349869eb87312c166e185ad8145 2c2a4c71eea8c1ad8823e8e22780fadebb38ae502b3a7b9b062923a188fef692 @@ -226,12 +224,10 @@ lib/codeql/rust/elements/internal/ExternItemImpl.qll 577c8ac387c47746e3b45f94337 lib/codeql/rust/elements/internal/ExternItemListConstructor.qll 9e4f6a036707c848c0553119272fd2b11c1740dd9910a626a9a0cf68a55b249b efde86b18bd419154fb5b6d28790a14ea989b317d84b5c1ddbdfb29c6924fd86 lib/codeql/rust/elements/internal/ExternItemListImpl.qll e89d0cf938f6e137ba1ce7907a923b1ab2be7be2fdd642c3b7a722f11b9199f8 85906d3ce89e5abc301cc96ea5104d53e90af3f5f22f8d54ec437687096e39d8 lib/codeql/rust/elements/internal/FieldExprConstructor.qll b3be2c4ccaf2c8a1283f3d5349d7f4f49f87b35e310ef33491023c5ab6f3abc5 645d0d4073b032f6b7284fc36a10a6ec85596fb95c68f30c09504f2c5a6f789f -lib/codeql/rust/elements/internal/FieldExprImpl.qll bae3828bdee6fa3b36219e831cecc2a09fd3c40c4a945f8a19fb5d8765c6f302 be4b89e39013a380bc172ac46e496f14ebdebb1d93e1b7ffb3bab98e08db3f6f lib/codeql/rust/elements/internal/FieldListImpl.qll 02a09d1d146030c68cead4614f4eef75854f19e55ed1eda60b34c4858a8d4a88 9b9f5e77546434c771d2f785119577ec46569a18473daa4169fb84a097369493 lib/codeql/rust/elements/internal/FnPtrTypeConstructor.qll 494c53ee599039c02145f91394d8dfe7635b32d03f9fcde5efcc99ced437fec8 992462b1b6b9e64b6201f3c6c232ca524f126efcb562c9f0c176677bb559f33c lib/codeql/rust/elements/internal/FnPtrTypeImpl.qll 5d70f71e08341dfa851fc53a47cf362786b57f44244a636e2fbbad3d1c41371e 51d6a1b1132204129bb8ee9d2b72c6d13ce4b3ec8b185d3732d2e64d3f80e807 lib/codeql/rust/elements/internal/ForExprConstructor.qll d79b88dac19256300b758ba0f37ce3f07e9f848d6ae0c1fdb87bd348e760aa3e 62123b11858293429aa609ea77d2f45cb8c8eebae80a1d81da6f3ad7d1dbc19b -lib/codeql/rust/elements/internal/ForExprImpl.qll 88fc37b7030d3bfca6071f275c4eac6760ad7dea9a01135cee2079170efeb9d5 cd7216c460f8382498dfb0d61d65d83a9aa608b6a9b6657ccd552b82b55ffc5a lib/codeql/rust/elements/internal/ForTypeConstructor.qll 32c40b78aded314b5f51af904bfbd5ae4f1f0ea65854dd6249983cc26b8601bc 729069d58fac648a4b212b0068fb6bca348443b502c38978f171a7539b24333f lib/codeql/rust/elements/internal/ForTypeImpl.qll b515639844778d0fbe51e6161a2ec19201b0ba15156a91cdfecc93523081fd61 ab0c09ee415e55db6abcc07493a5d880c5ae0974f0cb760194e40b68a961676b lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll 8bd9b4e035ef8adeb3ac510dd68043934c0140facb933be1f240096d01cdfa11 74e9d3bbd8882ae59a7e88935d468e0a90a6529a4e2af6a3d83e93944470f0ee @@ -240,45 +236,33 @@ lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll ce29ff5a839b885b lib/codeql/rust/elements/internal/FunctionConstructor.qll b50aea579938d03745dfbd8b5fa8498f7f83b967369f63d6875510e09ab7f5d2 19cca32aeaecaf9debc27329e8c39ecec69464bb1d89d7b09908a1d73a8d92a2 lib/codeql/rust/elements/internal/GenericArgImpl.qll 6b1b804c357425c223f926e560a688e81506f5a35b95485cecf704e88cc009ee cc1ccf6a23dadc397e82664f3911d4b385d4c8ca80b1ee16d5275d9c936148dd lib/codeql/rust/elements/internal/GenericArgListConstructor.qll 46859bb3eb09d77987a18642d65ba2e13471a4dc9c0a83a192fddc82e37c335c 2c7d54c876269a88d3461b05745e73b06532b1616cae9b614ac94b28735d8fc4 -lib/codeql/rust/elements/internal/GenericArgListImpl.qll 1a39ba7080147abccaaba451852c9c124fb6177f2ebd64e38ee74014444a34e1 80df3150c961936037ac02b46ef5f775c3f82e66490afbca00a016cb9eee798a lib/codeql/rust/elements/internal/GenericParamImpl.qll f435f80d7f275803c1311d362467f4a367deb5a2c0245b17a9e12468a2c3ce2f 8e8fcc29f510efa03ce194ad3a1e2ae3fbd7f8e04ab5a4a2d1db03e95f388446 lib/codeql/rust/elements/internal/GenericParamListConstructor.qll 7221146d1724e0add3a8e70e0e46670142589eb7143425e1871ac4358a8c8bdb 2fbb7576444d6b2da6164245e2660d592d276ae2c1ca9f2bda5656b1c5c0a73a lib/codeql/rust/elements/internal/GenericParamListImpl.qll 524aa0949df6d4d2cb9bee6226650f63a6f181d7644933fa265673b281074885 27b0210e5eaa2040bc8a093e35e1394befb6994b25369544738d0447ef269a9c lib/codeql/rust/elements/internal/IdentPatConstructor.qll 09792f5a070996b65f095dc6b1b9e0fb096a56648eed26c0643c59f82377cab0 0bb1a9fcdc62b5197aef3dd6e0ea4d679dde10d5be54b57b5209727ba66e078b lib/codeql/rust/elements/internal/IfExprConstructor.qll 03088b54c8fa623f93a5b5a7eb896f680e8b0e9025488157a02c48aaebc6ad56 906f916c3690d0721a31dd31b302dcdcec4233bb507683007d82cf10793a648f -lib/codeql/rust/elements/internal/IfExprImpl.qll 96dc5be0a650a74f96e0c2214eb58f1af5278ad1695ad790b660fdecb6738c14 06a292fcc459297ef3a0ef5c75c887f993ccd6350eb3fb0d2493e5b7c7199b6b lib/codeql/rust/elements/internal/ImplConstructor.qll 24edccca59f70d812d1458b412a45310ddc096d095332f6e3258903c54c1bb44 7eb673b3ab33a0873ee5ce189105425066b376821cce0fc9eb8ace22995f0bc7 -lib/codeql/rust/elements/internal/ImplImpl.qll 33a57be871fe3ab08467a65f2e2e9fb7df9f096c98e9f86d8a755eaf6da6e446 f01d0e9bfccf3926ae9720d3d660ba97e1c094f318bfb252449b2d387176f6a9 lib/codeql/rust/elements/internal/ImplTraitTypeConstructor.qll b47501280b026a4e9c21ace21d9ae59f4d126a3a1e03a6088ca38cd676cc4f6d 3b0b325ab0139b290a81355559227050ba3096a58f9ff01c4c0f5c5fb5beb6ee lib/codeql/rust/elements/internal/ImplTraitTypeImpl.qll 9826a676525c98c30019f62f3c5943b4f62f278ed738dcc023d15f82f36a9d32 da369a61b95685c29fce3c07082d2a58ab633d526d094fa9eaefa82f564609f6 lib/codeql/rust/elements/internal/IndexExprConstructor.qll 99bdc3d793c4dbd993860da60abe2b7c604345d645e86916462bc55a6939a5d1 3fe9d7da725956903707806aadbecac8d5b3874e8bed63c9bab54fff630e75dd -lib/codeql/rust/elements/internal/IndexExprImpl.qll 7914bace26dadf2c1752b65afad2ed226165507e20f3dba7949696103f3d586e 708a9f7eff1cbfcf93841ee009dc01354f4ea3d2e1e00608924e670070410e20 lib/codeql/rust/elements/internal/InferTypeConstructor.qll fb8f2aec6cd1e681cd84a7bd574459e19b9b2a152009290e2eac550f012a06b7 e2b1694f00a4e6a82b13d08d7bb95c98a73792370c1155263d696e60d39b2c3b -lib/codeql/rust/elements/internal/InferTypeImpl.qll 9d0bf471a7e0c2671aae52cebadc763ed13e6a62451bf22da3061d7781d8f0bf 4e9e218862e48700523d882eb64d24135289216653cf92195f74eb8a35f50d7c lib/codeql/rust/elements/internal/ItemImpl.qll 3eaa97dcbdb8870acaebc1e11a37a5cfdfa200751461e54d3a52ca48b90ba9bd 41fbd1110b0e24f4d5a3deee0a51c02d206178111a361a1e94501ca1ab70d7f7 lib/codeql/rust/elements/internal/ItemListConstructor.qll 08af3bd12536941c3dd4a43c81cc861be24325e242e2593c087a3ce632674291 2fa166159c409d2aaffa73a30babb40829a6de580bd40894d909ee6152801082 lib/codeql/rust/elements/internal/ItemListImpl.qll fb27417bb3ee17a739ae966dd7c6f382bc2a1de3e7efdfe1586d76a257c0b573 dee7ded650df8ef46b2ac9d472718536fd76dffee86bc208b5a6144060221886 lib/codeql/rust/elements/internal/LabelConstructor.qll 1f814c94251e664bfa1b1a606aef995382e40e78d4f953350ec951ee0bc8bd34 3157fb8c7c6bd365a739f217ad73ba1e0b65ccd59b922e5ab034e3449915b36c -lib/codeql/rust/elements/internal/LabelImpl.qll e1934c3f01e6c9a2517001285bc8e36166757a50ff63be09f9000171c04130f7 4f93e722af890b5241bf55674b29ac5cb134cfefb47eba983503dbd4212abb20 lib/codeql/rust/elements/internal/LetElseConstructor.qll b2b5d68e5701379a0870aa6278078e09f06aa18ddd14045fc6ae62e90827ece7 7359e70bea8a78bcaf6e6ecc8cc37c5135ae31415b74645594456cc8daa82118 -lib/codeql/rust/elements/internal/LetElseImpl.qll 1c801275993b809e80a847736f080a9b650710ef8862797504495d62904a3a71 b79d4760d8e333893e984e45f21eb463dce7f2a49ebd0708321c8653aa8c20cb lib/codeql/rust/elements/internal/LetExprConstructor.qll 66f27cbdafb2b72b31d99645ec5ed72f4b762a7d6f5d292d7639dd8b86272972 7da048f4d7f677919c41d5c87ead301eacc12ece634d30b30a8ae1fab580ff30 -lib/codeql/rust/elements/internal/LetExprImpl.qll d9e2f8a2f4c7cf3b80178012b5f38b029064a52e705301b99c7477ec1d9fe479 1a059d383a5988b32ade329d2ac809f3a830eb9c54020e3271861aa9ef136ab8 lib/codeql/rust/elements/internal/LetStmtConstructor.qll 7ee0d67bebd6d3b9c7560137c165675d17b231318c084952ba4a2226d61e501f 84199ba755bb6c00579eee245b2bca41da478ca813b202b05abaa1246dcf13d8 -lib/codeql/rust/elements/internal/LetStmtImpl.qll 2f3f387a78d1751652bd22dc0ea6cb39f0e186847b6f0dafd74d0f89e2db495a 2ab5a17f588e385f614c8a104a17a91859389227635bd239694a799643727ffc lib/codeql/rust/elements/internal/LifetimeArgConstructor.qll 270f7de475814d42e242e5bfe45d7365a675e62c10257110286e6a16ce026454 643d644b60bfe9943507a77011e5360231ac520fbc2f48e4064b80454b96c19b lib/codeql/rust/elements/internal/LifetimeArgImpl.qll 2d31b328c07b8922e2c448137d577af429150245170d26fe4a9220cba1a26bfe 18c5f5747ff4be87820c78cadd899d57e1d52c5cd6ae3f4e56ee2f5d3164bd41 lib/codeql/rust/elements/internal/LifetimeConstructor.qll 2babe40165547ac53f69296bb966201e8634d6d46bc413a174f52575e874d8cd ef419ae0e1b334d8b03cdb96bc1696787b8e76de5d1a08716e2ff5bd7d6dc60d -lib/codeql/rust/elements/internal/LifetimeImpl.qll 14ec1a4fa0c84fa9e75ea0babebae9c666909239806ed21325c32e47e11c8806 891168f29d4e06a927ec01ef8fd21ff6e0a0a3deadcf1481c99c74bf2ef20536 lib/codeql/rust/elements/internal/LifetimeParamConstructor.qll 530c59a701d814ebc5e12dc35e3bfb84ed6ee9b5be7a0956ea7ada65f75ff100 ff6507e5d82690e0eec675956813afabbbcfb89626b2dbfffe3da34baeff278c lib/codeql/rust/elements/internal/LifetimeParamImpl.qll 8909288801bff8d3e87096dff4b45f434a4c064a9d69d8943a0b30970e011ef9 6d8f80eca24112b5eb659fe5d5fca4fd91c3df20ecab1085dfee9176091237b8 lib/codeql/rust/elements/internal/LiteralExprConstructor.qll 8ea3569bd50704ce7d57be790d2dfd38f4c40cb0b12e0dd60d6830e8145a686f 88d07ad3298003f314f74bd8e3d64a3094de32080ad42a7e6741c416c3856095 lib/codeql/rust/elements/internal/LiteralPatConstructor.qll b660cb428a0cba0b713fc7b07d5d2921de4a2f65a805535fb6387684c40620de 2dbc9fbc56e9de53d24265d6b13738ef5b9ced33cc3c4c1c270e04dc2fc1330f -lib/codeql/rust/elements/internal/LiteralPatImpl.qll af74456649e3949bf27e91f2127389e5c9f2ee99241958afeaa5b55276170994 b8b744b1d0c1b85ec86c535a35fc75d6289636a0e1988500debf236faf24a2cd lib/codeql/rust/elements/internal/LoopExprConstructor.qll 45f3f8f7441fcab6adc58831421679ee07bac68ac0417f3cbc90c97426cc805b f7ab3361b4a11e898126378ea277d76949466946762cd6cb5e9e9b4bb9860420 -lib/codeql/rust/elements/internal/LoopExprImpl.qll 068b98978296b22ae59bf9e941e7e2683f4fee0f6c1affbda1fa42c93f015114 e40e384aeff61099d102a681e5dca1aabc6dd6694731f8570d6358e0197368b0 +lib/codeql/rust/elements/internal/LoopingExprImpl.qll 17885c1bcf7b5a3f9c7bbad3d4d55e24372af0dedd5e7fc0efcfc0a8b2cdad70 104dc45ca399b9f6e8227ad561679f728d60170398a52b31fc90cb2a2dd3c33c lib/codeql/rust/elements/internal/MacroCallConstructor.qll 707fee4fba1fd632cd00128f493e8919eaaea552ad653af4c1b7a138e362907d b49e7e36bf9306199f2326af042740ff858871b5c79f6aeddf3d5037044dbf1f -lib/codeql/rust/elements/internal/MacroCallImpl.qll 7732221a0d8677f32695be3e6263f6e5f8857225cf98cc31eb91592e175df260 7c4e15e092abbf3a6070141669f2614909eb0accaaee0da6f70495de6087337b lib/codeql/rust/elements/internal/MacroDefConstructor.qll 382a3bdf46905d112ee491620cc94f87d584d72f49e01eb1483f749e4709c055 eb61b90d8d8d655c2b00ff576ae20c8da9709eeef754212bc64d8e1558ad05ce lib/codeql/rust/elements/internal/MacroDefImpl.qll f26e787ffd43e8cb079db01eba04412dbf32c338938acf1bc09a2f094bbdfdfe 044f43bc94fe4b6df22afae32e9f039d1d0d9e85ad9f24b6388be71211c37ce5 lib/codeql/rust/elements/internal/MacroExprConstructor.qll b12edb21ea189a1b28d96309c69c3d08e08837621af22edd67ff9416c097d2df d35bc98e7b7b5451930214c0d93dce33a2c7b5b74f36bf99f113f53db1f19c14 @@ -294,7 +278,6 @@ lib/codeql/rust/elements/internal/MacroStmtsImpl.qll 27faff9da93ad7f22a6236c73eb lib/codeql/rust/elements/internal/MacroTypeConstructor.qll 0a23573a6f69b38f3d7470050b16197601d67bdd5a4b1a43a155b0b99ccdf6b5 19b623962e8e1f73e55e3ed9712d2a3fe84b9510b99062173902feb2458ec12a lib/codeql/rust/elements/internal/MacroTypeImpl.qll b8711279f09f521b05bb67568c089271b7913f863ee64dfdeec2c502de2cbdc8 51bd9d3a2fb2065bce7b193b485e225ca5c8ba2029e60cab427d43a90baf0880 lib/codeql/rust/elements/internal/MatchArmConstructor.qll b41c1d5822d54127ce376ef62c6a5fa60e11697319fc7d9c9c54fd313d784a93 96cca80e5684e5893c0e9c0dff365ef8ad9e15ff648c9969ba42d91f95abea05 -lib/codeql/rust/elements/internal/MatchArmImpl.qll 065dff16fc70b51924eb4db57be121283f4b5651105320901558bc93bfdf2641 37f4f6ecd23c5170ee5cb0041625c19a8d3245d56f6f1587a2e588eb86baecf9 lib/codeql/rust/elements/internal/MatchArmListConstructor.qll 8bc5ac978fe1158ef70d0ac06bdad9e02aadd657decb64abcc4ea03f6715a87a 4604ab0e524d0de6e19c16711b713f2090c95a8708909816a2b046f1bd83fe24 lib/codeql/rust/elements/internal/MatchArmListImpl.qll 896c6f1650e7ceb60d0b3d90e2b95fe7f8dc529203ddfec58edb063fa9b2871f a668fed1eb68806abfb021913786168d124de47b25da470e7b57f56bf8556891 lib/codeql/rust/elements/internal/MatchExprConstructor.qll 0355ca543a0f9ad56697bc2e1e2511fa3f233bc1f6344d9e1c2369106901c696 78622807a1c4bff61b751c715639510146c7a713e0c4f63246e9a2cf302f4875 @@ -306,46 +289,35 @@ lib/codeql/rust/elements/internal/MethodCallExprConstructor.qll a1b3c4587f0ae60d lib/codeql/rust/elements/internal/MissingConstructor.qll aab0b7f2846f14a5914661a18c7c9eae71b9bde2162a3c5e5e8a8ecafa20e854 8f30b00b5b7918a7500786cc749b61695158b5b3cc8e9f2277b6b6bf0f7850a0 lib/codeql/rust/elements/internal/MissingImpl.qll e81caa383797dfe837cf101fb78d23ab150b32fef7b47ffcc5489bfcd942ac3e 9f3212d45d77e5888e435e7babd55c1e6b42c3c16f5b1f71170ac41f93ee8d0b lib/codeql/rust/elements/internal/ModuleConstructor.qll 31cc83c9d8f25ac07375d19e568f05c068e1f5aa205ff3d9ac31c2510e6f8468 8a70f3f1c18ff87f17e6baf2f05ccaed55c70469288192fc39ef0bb5531b8c0e -lib/codeql/rust/elements/internal/ModuleImpl.qll bbff32cadbad54bdb613df8c1ac6da8cd2a80d0576361b843f1529e6c63b1938 7342473026561b8e4923625a083ba52c31d3b6797f9061accd1a712598244410 lib/codeql/rust/elements/internal/NameConstructor.qll a760134c6d4fc785746e1a5dc042a6bf25b8adaa3947a6897c31e50fd91dd5fd 1359f903d57112bcc1f62a609febb288301bfa810e569aa12e1045fd48b5b5c9 lib/codeql/rust/elements/internal/NameRefConstructor.qll 5ff6eacc614fd41f98b54cbb4960a07a1471cf4ea291758d33e54a48fd5d1bc4 c538d65414a24dfdbeb49cfd997588227559ba038f0b55d14bb5d89ed1a016f2 lib/codeql/rust/elements/internal/NeverTypeConstructor.qll 6a86bff9d885eddf39a159698710def40d693ccfd0888aefd090a283cb59ae95 9c51d6569f267dde5597067a8470d19d7714304399de4f730e7b85ca21feee20 -lib/codeql/rust/elements/internal/NeverTypeImpl.qll 8c7464cb76f9d081dab318d743817d87ecd69672f382d27323ade94c82e8e0f6 55351661214854bbf7faed6c7d17d598459d4e88eaba130a9b3a9f43f6665c37 lib/codeql/rust/elements/internal/OffsetOfExprConstructor.qll 616e146562adb3ac0fba4d6f55dd6ce60518ed377c0856f1f09ba49593e7bfab 80518ce90fc6d08011d6f5fc2a543958067739e1b0a6a5f2ed90fc9b1db078f0 lib/codeql/rust/elements/internal/OffsetOfExprImpl.qll e52d4596068cc54719438121f7d5afcaab04e0c70168ac5e4df1a3a0969817a6 6ab37e659d79e02fb2685d6802ae124157bf14b6f790b31688f437c87f40f52c lib/codeql/rust/elements/internal/OrPatConstructor.qll 4ef583e07298487c0c4c6d7c76ffcc04b1e5fe58aba0c1da3e2c8446a9e0c92b 980a6bd176ae5e5b11c134569910c5468ba91f480982d846e222d031a6a05f1a +lib/codeql/rust/elements/internal/ParamBaseImpl.qll fe11999c728c443c46c992e9bed7a2b3e23afa16ae99592e70054bc57ae371b8 df86fdb23266bdfb9ed8a8f02558a760b67f173943b9d075b081229eb5844f66 lib/codeql/rust/elements/internal/ParamConstructor.qll b98a2d8969f289fdcc8c0fb11cbd19a3b0c71be038c4a74f5988295a2bae52f0 77d81b31064167945b79b19d9697b57ca24462c3a7cc19e462c4693ce87db532 -lib/codeql/rust/elements/internal/ParamImpl.qll 8a5101559f5d636b60ab80237057944b537823ce054d760c3dbd58b2acf05a46 e7a08cefeb6a290a975899045b7b19a9624f5a2b0946cba0866b1854cc0c0fb0 lib/codeql/rust/elements/internal/ParamListConstructor.qll 3123142ab3cab46fb53d7f3eff6ba2d3ff7a45b78839a53dc1979a9c6a54920e 165f3d777ea257cfcf142cc4ba9a0ebcd1902eb99842b8a6657c87087f3df6fe -lib/codeql/rust/elements/internal/ParamListImpl.qll 0ed6e9affe1dc0144641502292c2ddd51958fe3d503419caf15198176e3a4174 92d053cc5fdf40a2d98acb665083b5da15403d7da205779a97a4ee66fac0add4 lib/codeql/rust/elements/internal/ParenExprConstructor.qll 104b67dc3fd53ab52e2a42ffde37f3a3a50647aa7bf35df9ba9528e9670da210 d1f5937756e87a477710c61698d141cdad0ccce8b07ecb51bab00330a1ca9835 -lib/codeql/rust/elements/internal/ParenExprImpl.qll 185e7c0f8f377f62a7ccf1c0d168caf500afd0654b82d47569bfcb97e368a26d 25a41998ce0ff3490d677676bf02fea1861d6c01db99a02fc940cc37ae580db6 lib/codeql/rust/elements/internal/ParenPatConstructor.qll 9aea3c3b677755177d85c63e20234c234f530a16db20ab699de05ca3f1b59787 29f24aed0d880629a53b30550467ade09a0a778dbf88891769c1e11b0b239f98 -lib/codeql/rust/elements/internal/ParenPatImpl.qll 39c45b3736c4d0329af7a1eec28a8470c3f244efd58a6ba62af482a0e9b4a842 d8aa9e6f8987666cd51cb65f81700d3b4584d3dc7d070836e52a9bc64e572d9e lib/codeql/rust/elements/internal/ParenTypeConstructor.qll d62e656a4a3c8ffd4eb87d49585a7a3bfb5dbe3826fbcbd11cb87b46f34c19ae febf6535965afa0f6eac4d2b08730f5a07bbb36a7434abe0a7663d7264961a3f -lib/codeql/rust/elements/internal/ParenTypeImpl.qll 6f7b4fade4ac0af69bf9766ee7d73da3da1742ba8a7c12d2a067b71c7f96d849 f065ea466111a5abca33d97b9878ef2fcc221f286fc65bec87f3a9c2fd5d57fc lib/codeql/rust/elements/internal/PatImpl.qll 37c9b1da7aa625117644e2cd74ec0b174f69a38cf66926add01786a05d5ad2ad 143685a0b4873fa0b73b204285dca956e59b32d527bfac6cc336326d244994b7 lib/codeql/rust/elements/internal/PathConstructor.qll 5c6354c28faf9f28f3efee8e19bdb82773adcf4b0c1a38788b06af25bcb6bc4a 3e2aeef7b6b9cda7f7f45a6c8119c98803aa644cf6a492cf0fce318eba40fe8f lib/codeql/rust/elements/internal/PathExprBaseImpl.qll e8b09447ee41b4123f7d94c6b366b2602d8022c9644f1088c670c7794307ab2e 96b9b328771aaf19ba18d0591e85fcc915c0f930b2479b433de3bfdd2ea25249 lib/codeql/rust/elements/internal/PathExprConstructor.qll cf6e0a338a8ed2d1042bdee4c2c49be5827e8c572d8c56e828db265d39e59ae3 36a3d1b7c5cc2cf527616be787b32071b9e2a6613a4f6b3f82e2a3b0e02a516f lib/codeql/rust/elements/internal/PathPatConstructor.qll 966c4ea22218ef71e000d7ce8dd5b570c39ad96b9239a3aa8a38292e2a9f36d2 8a1f348e9257ffc6e6bedcd70389b8e7ec2a3ed6e7b3733744ddfab284826e57 -lib/codeql/rust/elements/internal/PathPatImpl.qll 6ab5b5959cfd94e74f60422cbdbd764a5f51ff541db428938c36ba3a512d1d6b 47585157460e8384047de307b0b05deaab758d0f07fd0183d874f7bb9d8bda4b lib/codeql/rust/elements/internal/PathSegmentConstructor.qll 2d9639e42035dc7e73b7d6ddb8a977beadc6b4492dee4292b2f85b4409344441 c337fc3b9ef56366428772563e3f25f711474d16e860d3e89c1395a95d9e83e7 lib/codeql/rust/elements/internal/PathTypeConstructor.qll 8949742c7ab7fcfa3a3f6469e87355a6888931ab9ac7a6a07d2bd51e3fdf8283 fb1a402e94e9a1f33b7757338d7e95b107933339615a4fe86de33e41206dd94a -lib/codeql/rust/elements/internal/PathTypeImpl.qll 0e3b85df054d1194505796e457ee31a8dac2a2a77284c077cbf1a3bfc179294e c198d4fdf8d1d55f1cf57685a9ad2adf88cc2d6d4f84bafa1e9f039192761399 lib/codeql/rust/elements/internal/PrefixExprConstructor.qll 90c50b0df2d4b4cbf5e2b7d67a9d243a1af9bfff660b7a70d8b9c7859c28bca7 1a1b5ea1f06ed8d41a658c872e8e1915c241a7c799c691df81b9a7b55d8f2f1e lib/codeql/rust/elements/internal/PtrTypeConstructor.qll ee3c4326ea3f198d2537a914dd6eb51d0cf247310f037e13e87632fbd6cfb50a 3814218b5271f3c6c45b52082cca2a3250a2573abced43fe53e1b4145374afe3 lib/codeql/rust/elements/internal/PtrTypeImpl.qll ff4283ffab39b4a3c0e55e7d655dfdb846171cde0907bf1f893c86b35d2c1135 e54d3a6fb0b5a1484f00fd5a4631455902bab80642c3bb076e538ddcc29a85a4 lib/codeql/rust/elements/internal/RangeExprConstructor.qll a0aa90a1c38c5deea56475399016afae2a00a858b961fbbab8ddeb3bc6a08103 0ddf1bcf28aafc56d7334e6138fb268f9b36a429e4cbdd982cd8384e0644076b -lib/codeql/rust/elements/internal/RangeExprImpl.qll a6ff92a27e44c2184f5c2d8483de1d0d4a77eb7a5154ff93a8f3a9fc8b63e561 d53d44bc1c1ae426f208595002adcddb88643e1027bbee7445095ca09e433331 lib/codeql/rust/elements/internal/RangePatConstructor.qll fe4345cb41d970ab64196ca37eccb26e5b9cf85fab4253cacfd2b31de03bd070 1d09d5ec8203d76aed2dfb7e7f14c0c07d6559c8f589e11860fff8a2c682c1a6 lib/codeql/rust/elements/internal/RangePatImpl.qll ef11ab2c002896036553231741a7cf896fafa09e22e920e15661b9cbe4393cae 24ac2dcce3055a77f3a5e0b38cf13aebefd2eeaefa53674ff144a6225634ac0d lib/codeql/rust/elements/internal/RecordExprConstructor.qll 742198bd8223902b5625b4a574a9e3539a8b6cf8e48eecc57cc2de4e980fba6e 0a99e454e234e8b7b59dc11b167172a5fcd31b8a5282349956d6fd861ec735df lib/codeql/rust/elements/internal/RecordExprFieldConstructor.qll 11620bc4e2dc7b3903be764cd9510a8e002892722b502876cf3467994aa7a63c e42e50747dd9453a44705b2d6a05e7a4a8c6debed988a0335a774a547d8f7157 -lib/codeql/rust/elements/internal/RecordExprFieldImpl.qll 8af196cbaeeb7997e933fde9ddba50ec099df51f66e03501f00157f238505fe7 29ae10546577a354b0439876ce5deb5ab13455028f02c01fe3903b11eaee35e2 lib/codeql/rust/elements/internal/RecordExprFieldListConstructor.qll 3a0d6ec872792c400d3a0a5ed1c5051b248a597a4b17ada1a078ea5d972b6721 52bae8222e7aa5bc89b73bec3fd1c3c1de0fe11bf30ccf5668454f63fbfc9b83 lib/codeql/rust/elements/internal/RecordExprFieldListImpl.qll 1210c23c0495f5d1a72409afc8c559f8da2b8c71340ff2944af9d1f684d0a856 fea96b053cad4135ab09b1c070a4c9f26507dd890a62c30772cf3e2358686640 -lib/codeql/rust/elements/internal/RecordExprImpl.qll 233b3f7ee8dbd1e5431bea5436c6b7ee38e631c041111dcf53e45c6c4c08a6cf 9537497edb739c535d75ce80122f597ad93241bff5399b1dae17a7bfff1c15cd lib/codeql/rust/elements/internal/RecordFieldConstructor.qll 9fc05f5101e48a45a028c479b35ec3d2f1a3cc33f0938667fcb813c5a4ab9526 98791dcf7f3209524f6132f9c26980e499cbcf94c1559e95c67544732245f05b lib/codeql/rust/elements/internal/RecordFieldImpl.qll 2612dae3c95c9064420a3494872213f7fd7a3e1133243f4adea8a30808a209ae 143b75bb539a1bfea16e1c764a1f549522ef9c8d6d5de3fef377bbf67ba42075 lib/codeql/rust/elements/internal/RecordFieldListConstructor.qll 9f1d916f3784092dcbff7224451c8f4f0daf6f8293a466b0a30ec9b92cd41358 8aafe377714a134287362c4b96439c1c6baa5a31c2c36a544bd5f73e9213477a @@ -355,26 +327,21 @@ lib/codeql/rust/elements/internal/RecordPatFieldConstructor.qll 6e1880ed05401b39 lib/codeql/rust/elements/internal/RecordPatFieldImpl.qll 04bc31b857c8250096d9d1bf3fad1e556a28d83bb3f3b48a3f049048d1e6785f 5853105e55650d05a4b196f17b89baf12b898df0a010e4f88289ce01d16a0379 lib/codeql/rust/elements/internal/RecordPatFieldListConstructor.qll b8f0ef9b75ffe6be6ce7e601d528f0a1b871123c63e39cead3fd13b8bd4f54b7 166f07c708ab8b3de6bfaf193bac93081b2aacad046aa86de7441085dd20a8c5 lib/codeql/rust/elements/internal/RecordPatFieldListImpl.qll 2d1dd9910480eb65c59fcef2e1576ce639be85c35d90e4bce721ce22ec742ba3 1e788a2d7d00e9f96dbf7e93d3a18d5bfb4d7749194ff8e9810e9053fa88a94b -lib/codeql/rust/elements/internal/RecordPatImpl.qll 3c7086be84e336c069f4c7b538c7ad32a7728e7fbf42e4dc7f04c4c99d393c0d 8020215f38639965398c62ddb36c3560579d63928e71e0d773b254e121a68cc3 lib/codeql/rust/elements/internal/RefExprConstructor.qll 9ad08c0f3d980a56a2af8857cb84db589941d20ab3ae5c8ece004ccaccaaf950 4cac3ace31b7ed77a72e989fce9cdbae2247f03c28a3f0c50d67385d02c7f193 -lib/codeql/rust/elements/internal/RefExprImpl.qll 56ed831a3b30ed375e7369b0a60b9b7635a1b00f058364a6b15078031a85af5f ca7e772b409514363e49d56a174ae9bd2e076755cbd09c4e7e5b732d09acdb25 lib/codeql/rust/elements/internal/RefPatConstructor.qll d8b88c2c468b08072f6f853306eb61eb88ee1e6c5cfb63958f115a64a9715bb3 0c1d6a8af6a66912698acce47e89d4e3239e67f89c228a36a141f9c685c36394 -lib/codeql/rust/elements/internal/RefPatImpl.qll 3e06e8130d412b47267497097cffc9f4b930b9e54bc90465ab5ac620fbe52048 b8ac844ec99f30605ce476f89ced4fb1159d2df0df43c631f60b3c868e0e1fd7 lib/codeql/rust/elements/internal/RefTypeConstructor.qll e1952aa69586b440f878400a52d09b2d12d5a29dbe9651360344631cb9493cd4 e4ae45e89472dfd4547d647c75e1635cf065a7d221ed60ed34554f265c0c5405 lib/codeql/rust/elements/internal/RefTypeImpl.qll f72b760a8a26be21170435da2cb2981638513617fd82742f45f38bc437d9f2c4 f32df49f0b6df85ca5fc4393ccd341ac4304b4947a282ccea48468a26837ef3d lib/codeql/rust/elements/internal/RenameConstructor.qll 65fa2e938978d154701e6cac05b56320b176ee014ef5c20a7b66f3e94fd5c4a7 dfc0ff4606b8e1c14003cc93a0811f4d62ec993b07ff3c1aa0776746577ed103 lib/codeql/rust/elements/internal/RenameImpl.qll 4f5943fbda4ec772203e651ed4b7dd1fb072219ddc0cb208c0a0951af5e72bd6 b9854cdcf02e70ee372330a4e0bfdb03012bc81af79dd12af2a567fd7fc4672b lib/codeql/rust/elements/internal/ResolvableImpl.qll 7599625454fe81c3490a122943363a2a2522a7877b78a80649e93155a418fedd 442072c3d70bdaababd7de8bc6c9382f4a50bab41d13759dcd1a5bee9ea32e49 lib/codeql/rust/elements/internal/RestPatConstructor.qll 45430925ddf08fba70ede44c7f413ddb41b3113c149b7efc276e0c2bf72507b4 25c678898d72446e7a975bb8b7f2fde51e55b59dbd42f2cca997c833b1a995f1 -lib/codeql/rust/elements/internal/RestPatImpl.qll 1b83464367e5fdc28b0b3946ae74c67c64d30b286c39268b4118337539250e51 83a03308cba4cb3344d48f0a0730b1d3e41a73f16f729d39dc2bae6d3f57f232 lib/codeql/rust/elements/internal/RetTypeConstructor.qll a96d803c6e4b40be49cfed0853a3e04ae917c47351e5c880fcab06eddf1af9cc d06a0a191cb14c270c0441ffc3d289263808170dcbe05e01847a35ac9d61dfb3 lib/codeql/rust/elements/internal/RetTypeImpl.qll 0e96f1075ccade28ce5664ab0f5c2e98984ae1d0ed708bc02e40e882672d9e2f 350725d16bcb1e8911bfdd87d9dd21be73ec66d23c2a35827c8c8525c48dc885 lib/codeql/rust/elements/internal/ReturnExprConstructor.qll 57be5afbe20aa8db6e63c1f2871914c19c186730ad7dccaa424038c6305730d5 4d3c4f2e9b38a4b54ff26a0032455cdcca3d35fec201b6c932072a9e31fbb4fe -lib/codeql/rust/elements/internal/ReturnExprImpl.qll eef4960a8c27eaa0540d048fe88893cfe9a6ac377a770cc23d72ebe05d5782f1 b7f35650d80f2f8b4893f0091fea74646341af406b6248f75c477112aca96dea lib/codeql/rust/elements/internal/ReturnTypeSyntaxConstructor.qll 8994672e504d1674e5773157d0ad8a0dc3aad3d64ef295e7722e647e78e36c11 abe7df754721f4ff7f3e3bb22d275976b2e9a1ef51436a461fe52ebd2d29cff1 lib/codeql/rust/elements/internal/ReturnTypeSyntaxImpl.qll d47a3dcfcc2b02a6a9eaeefe9a7a4be2074ecd2019da129dda0f218bc3fbd94b 87198db7c0620ed49369da160f09287015e0cd1718784e1ba28ec3ec5a0bb4a8 lib/codeql/rust/elements/internal/SelfParamConstructor.qll a63af1d1ccde6013c09e0397f1247f5ab3efd97f3410dd1b6c15e1fb6cd96e54 0d8977653c074d5010c78144327f8b6c4da07f09d21e5cc3342082cd50107a81 -lib/codeql/rust/elements/internal/SelfParamImpl.qll 5408738c40f070e0cea83a6a38d638ac7a134b5a055ecf0cccc035af58ff9b36 604922319ecf9a9405fdd0fe953169162ee2c8cca36349b49163a2895c53ed40 +lib/codeql/rust/elements/internal/SelfParamImpl.qll def23beb8926f498fc81b7b44489001b35d704da1a2058c84c23b329e8bc2f49 c9be1e8fa2c4e23b314a4d0563be6cffcbab6f03d08b77a366f7638b28a09de4 lib/codeql/rust/elements/internal/SlicePatConstructor.qll 19216ec9e87ca98784d78b29b8b06ea9ac428e2faa468f0717d1c0d0a8e7351c 458e5be76aa51aec579566be39486525ec9d4c73d248cb228da74892e2a56c08 lib/codeql/rust/elements/internal/SlicePatImpl.qll c6176095360e3b23382557242d2d3ff0b5e0f01f8b1c438452518e9c36ff3c70 644ab41a59a619947f69f75e2d0807245d4ddefc247efaeab63b99b4f08c1cc1 lib/codeql/rust/elements/internal/SliceTypeConstructor.qll 643e7a2ae261e8f62de8bc2886efddcc096e0c7e8159c0b9e87b24d0509e10d0 719545abb0ccf6e8a203ec9c9f75109c5ab0593c838e2f90e388858680ec62f7 @@ -394,7 +361,6 @@ lib/codeql/rust/elements/internal/TokenTreeImpl.qll c61574f2b551db24640258117e0c lib/codeql/rust/elements/internal/TraitAliasConstructor.qll d2f159cac53b9d65ec8176b8c8ccb944541cd35c64f0d1ceabb32cd975c000bf 6564981793de762af2775cc729e25054ea788648509d151cbfdbdf99fc9ed364 lib/codeql/rust/elements/internal/TraitAliasImpl.qll f338dba5388973ec0c5928d4c60664737f75a93d0c7db5fb34053bc41c107641 f2e437469e4ba1d8dd321bc670978e7eed76508e728d1e08e52ddcf52a461d3a lib/codeql/rust/elements/internal/TraitConstructor.qll 1f790e63c32f1a22ae1b039ca585b5fe6ffef6339c1e2bf8bca108febb433035 535cebd676001bfbbb724d8006fa2da94e585951b8fd54c7dc092732214615b5 -lib/codeql/rust/elements/internal/TraitImpl.qll 776a0c10c944146b89d616e3bf1311502de9e1e84f0c9d5d7de5aecfc97b87e3 3795d920e98620b30f7e2c218cfb57ae91b37956f9165325b5da6705df8beffa lib/codeql/rust/elements/internal/TryExprConstructor.qll 98e3077ebc4d76f687488b344f532b698512af215b66f0a74b5cea8ed180836c b95603c10c262911eeffdf4ccba14849e8443916b360e287963d5f2582d8e434 lib/codeql/rust/elements/internal/TryExprImpl.qll 00635685db339557cfb89fad0bfc134e53efc6d88c68cce400b72c2dd428ef9f 43559b46e45c009f985b58896b542881b81a3e6b82a6f51b784e8a712ae3da2b lib/codeql/rust/elements/internal/TupleExprConstructor.qll 71c38786723225d3d90399b8a085b2b2664c62256654db9e1288fadd56745b9d 639ad70b49ebadc027127fbdc9de14e5180169a4285908233bc38ccac6f14110 @@ -421,12 +387,10 @@ lib/codeql/rust/elements/internal/TypeParamConstructor.qll a6e57cccd6b54fa68742d lib/codeql/rust/elements/internal/TypeParamImpl.qll 9e7169e8254e2d9d13b11a17cbe04e874f72fb67a75c3585e70eddec71ba5c7f b8c862b2cd53bc211caea23261d9832613418aae51f63ef08922d300c2d1f4f2 lib/codeql/rust/elements/internal/TypeRefImpl.qll cfc08bdcc8e7e588f533c7e64c0c08d317d63cdb50f4cba4b4b3e589b37b0fea b46ee7de9b5e9894807004e1bedf39e7d25912ed79de6ac5adfb37a43aa4804b lib/codeql/rust/elements/internal/UnderscoreExprConstructor.qll 8dc27831adb49c1a47b9f8997d6065e82b4e48e41e3c35bd8d35255cea459905 6c5a5272d37f83f1c1b17475f8adb7d867e95025d201320e20a32dab1f69f7bf -lib/codeql/rust/elements/internal/UnderscoreExprImpl.qll 4277b23a09a4ba5e53ca2cfbb20eba6a5f66039b6268da79410e0be30332fedd b9ed79468157a7e751f78aa7597165672cbc38191d5f85ecc15cfdaff388a26a lib/codeql/rust/elements/internal/UnextractedImpl.qll 5c23df7e448184d76ccab2c22757ace24663b8be2592a3fa2a44bef43159ebd3 77b0c9fe75a307adc08c422cc88423c5349756878793cf9e79c006c83b4c403b lib/codeql/rust/elements/internal/UnimplementedConstructor.qll 70b0489fdc75fed389de8203947ed9c8eabb91373a1264eb2c8018ddbb2d9baa 0f2592c1697a2f2f913014ecd73b0e3ff1ec5b038ba1c3a22e7939bf8759e664 lib/codeql/rust/elements/internal/UnimplementedImpl.qll 06771abc088e0a8fc24032c9d2633618e8e40343ef8757a68cc0a70f1617165a 5738f626f1f4f573fdf7dcd5bd57a0948d290ed89342b9160e95ef3c84044f9a lib/codeql/rust/elements/internal/UnionConstructor.qll d650551a1b3ef29c5a770bdad626269cf539ed0c675af954bc847d2c6111f3f6 aca9064ad653a126ab4f03703e96b274587c852dc5e7ff3fea0fec4d45993f10 -lib/codeql/rust/elements/internal/UnionImpl.qll f1765a7a37fb29eff98d67d166c35df4921eafc8cb61c11c7848185535f0497b 9f041f6ee82bd3cda2ddea0ee58d7a996123b1713b9d127f764eb74a9387f685 lib/codeql/rust/elements/internal/UseConstructor.qll a4f790795e18abc29a50d6fbaa0db64cba781e3259a42cbf0468c24ac66b63e7 2fa288f073ac094a838c11f091def2c790b347b6a1b79407c11b10c73d6bff57 lib/codeql/rust/elements/internal/UseImpl.qll ba779517c3c928ab6e794360b6344829e84ec6da5e1de1b03b4eaf8bdae58ce9 0f4ead9eecb584eb9827502276ffe8cb1da0d2fa4b8f660d2afc26ac4e0fba86 lib/codeql/rust/elements/internal/UseTreeConstructor.qll 3e6e834100fcc7249f8a20f8bd9debe09b705fcf5a0e655537e71ac1c6f7956b cdbc84b8f1b009be1e4a7aaba7f5237823cea62c86b38f1794aad97e3dfcf64b @@ -444,14 +408,13 @@ lib/codeql/rust/elements/internal/WhereClauseImpl.qll 59d33533e641ce3851e493de30 lib/codeql/rust/elements/internal/WherePredConstructor.qll f331c37085792a01159e8c218e9ef827e80e99b7c3d5978b6489808f05bd11f8 179cad3e4c5aaaf27755891694ef3569322fcf34c5290e6af49e5b5e3f8aa732 lib/codeql/rust/elements/internal/WherePredImpl.qll aad95f448ca051d5dcd462429fa1ca95dcec6df2e70b6f64a480bd6839307581 411a66a5d866aa8cb4911c5106849adb103a063e1b90a9ecc5d16db3022bb1f8 lib/codeql/rust/elements/internal/WhileExprConstructor.qll 01eb17d834584b3cba0098d367324d137aacfc60860752d9053ec414180897e7 e5e0999fb48a48ba9b3e09f87d8f44f43cc3d8a276059d9f67e7714a1852b8a5 -lib/codeql/rust/elements/internal/WhileExprImpl.qll 5e716498402be3a1a8ed3594e13a03938bb793ac80f2a648bc93c0d746028d8b efcee38fe5e984a690c33f8bfdc78c677c2b0cdc5902525e2196a68fdabb6823 lib/codeql/rust/elements/internal/WildcardPatConstructor.qll 5980c4e5724f88a8cb91365fc2b65a72a47183d01a37f3ff11dcd2021e612dd9 c015e94953e02dc405f8cdc1f24f7cae6b7c1134d69878e99c6858143fc7ab34 -lib/codeql/rust/elements/internal/WildcardPatImpl.qll 01e5fac111cce3bb139fc290dbdb2a80e7369a90952178228efeb025915d40b7 875e91fb1354ab8d94d5fa426b63714c70904f53d7bab15158fcbc290c62a0f1 lib/codeql/rust/elements/internal/YeetExprConstructor.qll 7763e1717d3672156587250a093dd21680ad88c8224a815b472e1c9bba18f976 70dd1fd50824902362554c8c6075468060d0abbe3b3335957be335057512a417 lib/codeql/rust/elements/internal/YeetExprImpl.qll e8924147c3ebe0c32d04c5b33edfd82ae965c32479acfd4429eeab525cf42efb b2debcfa42df901f254c58705a5009825ec153464c9ab4b323aa439e5924e59e lib/codeql/rust/elements/internal/YieldExprConstructor.qll 8cbfa6405acb151ee31ccc7c89336948a597d783e8890e5c3e53853850871712 966f685eb6b9063bc359213323d3ff760b536158ecd17608e7618a3e9adf475f lib/codeql/rust/elements/internal/YieldExprImpl.qll af184649a348ddd0be16dee9daae307240bf123ace09243950342e9d71ededd9 17df90f67dd51623e8a5715b344ccd8740c8fc415af092469f801b99caacb70d lib/codeql/rust/elements/internal/generated/Abi.qll 87e1ea6b2a8ebf60e1c69176632740e4e27fc56c3f173939b098ba376562b5fa 94b2121e71c4ec94d53a79f972c05a8484ef0d80ed638f53031e7cf4dc5343d5 +lib/codeql/rust/elements/internal/generated/Addressable.qll 96a8b45166dd035b8d2c6d36b8b67019f2d4d0b4ccff6d492677c0c87197613e d8f1ce29feafc8ff7179399fc7eac5db031a7e1a8bc6b2cd75cfce1da3132e9b lib/codeql/rust/elements/internal/generated/ArgList.qll 1b75b2d7dcf524eb468a0268af6293e9d17832d6bedf3feec49a535824339b57 2bcaf464454bdfdda45fbd24d063f0f1df0eb69f684197b37105adc8f72cd1ea lib/codeql/rust/elements/internal/generated/ArrayExpr.qll 2ca97b602a707fe2c566002d8709792bb166ae52fdb7da28d7c4b8e0d66dd4bc 1cae1ef017171ec9a1ca28b4f2993b1ee26d22b51b3b04816d9b4e89fdff1fb3 lib/codeql/rust/elements/internal/generated/ArrayType.qll 225ac477f67865d72b2a2e17420f5e52c25452a3c14f7ff367f873a859f97783 0030e3bf296dd5b69ea912fc85dc7120b060780033083127257cdca792dc3f4b @@ -464,10 +427,10 @@ lib/codeql/rust/elements/internal/generated/Attr.qll 2e7983b2c462750065ed58cc10c lib/codeql/rust/elements/internal/generated/AwaitExpr.qll 1d71af702a1f397fb231fae3e0642b3deeba0cd5a43c1d8fabdff29cac979340 e0bfa007bdecc5a09a266d449d723ae35f5a24fbdfc11e4e48aeea3ec0c5147c lib/codeql/rust/elements/internal/generated/BecomeExpr.qll 7a211b785a4a2f961242d1d73fd031d381aad809f7b600ce7f7f864518bb7242 17a0388680007871748cfdc6621f700a7c2817b9601e1bd817fb48561e7c63ad lib/codeql/rust/elements/internal/generated/BinaryExpr.qll 64e9bd9c571edd6e5f3e7662b956b1d87fa0354ce6fe95da9caf25ac16b66c68 3fca09fdbe879db2ca3293618896a462e96376a2963d15cce3d5b1baac552fcb -lib/codeql/rust/elements/internal/generated/BlockExpr.qll ccfbdc7bd268735a0424ff08dcf37d0e1fed61d5fe0520593c23f2490d400438 0facad59f6aba13ee0c069b691c99f52c04b723a2bfad4da226190c3c42dcabf +lib/codeql/rust/elements/internal/generated/BlockExpr.qll 5a5ddbe34bc478a7bd9b0d07d3b6f017c2d1f20581d859251a963314e6514d1f 9804c30b8b279038b864c52557535f854bd012bacdfe8e5840f1f777c74e52df lib/codeql/rust/elements/internal/generated/BoxPat.qll ec946a3e671ab7417e04b0207967adad004df512c570c4f0780ca5816d12d75f b0e64860855c4e85914042b1a51034899ff7cd1b2c6857188de89310a2726ea3 lib/codeql/rust/elements/internal/generated/BreakExpr.qll 0f428a8b2f4209b134c2ffc3e1c93c30bc6b0e9c9172f140cefa88c1f77d8690 957b39f38ff6befe9061f55bc0b403c2f1c366dd0cf63b874bae6f8216576d76 -lib/codeql/rust/elements/internal/generated/CallExpr.qll 23ee64e3bf643cd5e6ff705181d2bb31e1aeaffecb5bdce73836172dbf15f12f 34b280139b1f8f70d78e1432392f03c971be392e8cb68d014eb325d0c101bddd +lib/codeql/rust/elements/internal/generated/CallExpr.qll f1b8dae487077cc9d1dccf8c3cd61fd17afe860585f17ce8b860be4859be7ca4 6034fc03778e38802cdf3a6e460364b74e92912622581b31e6179951022bbbd6 lib/codeql/rust/elements/internal/generated/CallExprBase.qll cce796e36847249f416629bacf3ea146313084de3374587412e66c10d2917b83 c219aa2174321c161a4a742ca0605521687ca9a5ca32db453a5c62db6f7784cc lib/codeql/rust/elements/internal/generated/Callable.qll b0502b5263b7bcd18e740f284f992c0e600e37d68556e3e0ba54a2ac42b94934 bda3e1eea11cacf5a9b932cd72efc2de6105103e8c575880fcd0cd89daadf068 lib/codeql/rust/elements/internal/generated/CastExpr.qll d6fbf02e9e202254666082a9116634d0eb933177866ac4c0a57b5e9c4bb4b383 477f67773492e3b82695461d56327c9db05a7d1a67e8d192406265f2ce369670 @@ -491,12 +454,12 @@ lib/codeql/rust/elements/internal/generated/ExternItemList.qll 6bc97fdae6c411cab lib/codeql/rust/elements/internal/generated/FieldExpr.qll 3e506b5cb93793ec30f56bb637a600db869fcba6181b068516a671d55c362739 7bbf953696d763ad6b210f378f487ba85b875fa115b22c0c0508599a63633502 lib/codeql/rust/elements/internal/generated/FieldList.qll 43c13c6e3c9ba75a7a4cb870fc4f18752001584d48b9df0734055a6ebb789331 7c51b0b13eb02f1286d3365e53a976ba2655c4dbd8e735bc11c8b205c829e1ee lib/codeql/rust/elements/internal/generated/FnPtrType.qll 748d766dbefd19a7d644734c57885eeede66897029bbfe1b87919517f43bfde2 5a7d80acc00e56594ed85026a8ea4923104d2e98c2e42db8c5bcd32ddd164e48 -lib/codeql/rust/elements/internal/generated/ForExpr.qll 541b62b48911d4999f9ed64ab6c8b9910073ac4add0225761f319677328cf120 976c3a91c9eedfb1e2d9ea76ac501348643b3d23c723d7a777042258d416d091 +lib/codeql/rust/elements/internal/generated/ForExpr.qll d81751e9599874a1292a0aace80b2de60ab36fc43f74ec08fbdfe044fc19e5c1 34a64586f8ffbadd44d0e747f69ab550a16149b658a9c92d9593689cb9a4f6fc lib/codeql/rust/elements/internal/generated/ForType.qll 3d43d044a1189281f09c55caafb6c8020a836f49e2866077086101925a573cf2 646b59bfd1b428aaf7211f574c49f79cb4c6a79ca151aa0663b2b31480298721 -lib/codeql/rust/elements/internal/generated/Format.qll 37ad20cf2bf363b4027a8913d095292c8a4eb8ccdf2a9965f2fb7d41930f9bfe 329b89cdd75ce951269273dd18897e32ff5cfcc94f451001c64143386c1e48dd +lib/codeql/rust/elements/internal/generated/Format.qll df7ef61e6ba61fa0eb093f8e6b3e7a0329104e03f659c9507db9535b8b4ea759 ef8ddd98405fc84938ad8cd5f87d2858e01d06a6bb00566a785a984b60a79dc6 lib/codeql/rust/elements/internal/generated/FormatArgsArg.qll e07a1ae310f590003f1b88fada7dcf4847c99adb9d4c838d1c88e66e1da85c5f 0ef7342451fe2cb06e765fb4b33bb8c4a9b927f5edbc8feb5c6ba3655697f447 -lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll 40d6daa7d2bafb33798a21d79774dc802cfbd7a31618ac3bd0149399ea2bf893 d1172e2151791228559004792e125fc4625f6a26ffad25f29efb0ad263bf8795 -lib/codeql/rust/elements/internal/generated/FormatArgument.qll 00646f38217a66978b8b2648cca39dddbed22ece693b26cb682f019fbfedda95 e364e085f967847a7ed21b76156a9203d64032f0f0eea357b4779885a41bf9a7 +lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll 8aed8715a27d3af3de56ded4610c6792a25216b1544eb7e57c8b0b37c14bd9c1 590a2b0063d2ecd00bbbd1ce29603c8fd69972e34e6daddf309c915ce4ec1375 +lib/codeql/rust/elements/internal/generated/FormatArgument.qll cd05153276e63e689c95d5537fbc7d892615f62e110323759ef02e23a7587407 be2a4531b498f01625effa4c631d51ee8857698b00cfb829074120a0f2696d57 lib/codeql/rust/elements/internal/generated/FormatTemplateVariableAccess.qll a6175214fad445df9234b3ee9bf5147da75baf82473fb8d384b455e3add0dac1 a928db0ff126b2e54a18f5c488232abd1bd6c5eda24591d3c3bb80c6ee71c770 lib/codeql/rust/elements/internal/generated/Function.qll f285ee0c771f897eba6db34a7e98f3cfb7db91b0df252ff4b37fc9d779de0bfb 07401e832565ff376acda219514c2e2bbe4ae5058c76a73b40ca6ca66f1626c7 lib/codeql/rust/elements/internal/generated/GenericArg.qll 464da0ba1c5ddcd1be68617167f177773d99b5ac4775ec8ea24d503e789a9099 6faa1033d59baf7c210ac4837a55781cfc054b7acbad8027faf4630dbfa6e101 @@ -509,11 +472,12 @@ lib/codeql/rust/elements/internal/generated/Impl.qll e33ef5d3e49e64beca0ca9d5c0b lib/codeql/rust/elements/internal/generated/ImplTraitType.qll 3c29684f5ef386b883b79dc9758441d97f090e065be177ffc8240aaf0f3d1e7b 03ea42c2a95cf917ec73d88b7b4ca5e53e10d7b046074f59100c0ec6c2c1ed6d lib/codeql/rust/elements/internal/generated/IndexExpr.qll cf951fc40f6690e966b4dc78fa9a6221aa5c6cade44759dcb52254f799292d11 1572e71918cc4e0b7e028331b6d98c9db23100a3646cd3874d1915e06ab6211d lib/codeql/rust/elements/internal/generated/InferType.qll 23ee25135c59ea5578cdf7c34a41f606e217e7260c3c8f404d12836585d5cad4 400da322fa1be62c4e300ebdf481eb92d4226eb6c316c668da8cc5168065774f -lib/codeql/rust/elements/internal/generated/Item.qll 25e645cb41222c21065798fb6cb0488bfef007aeb9b89717f58913f9b29d5559 3146941e55db2ff7c51ec030b4414e20d66d154cf6854b1a3fa42e74a09dfb77 +lib/codeql/rust/elements/internal/generated/Item.qll 97f204f27c12689a01fef502a4eec3b587e4eaccd278ec07a34c70a33ce6119d 139af2d44f794d0f91d9aabc3d50d895107c34bd9bcb72457a2e243c14622e51 lib/codeql/rust/elements/internal/generated/ItemList.qll 73c8398a96d4caa47a2dc114d76c657bd3fcc59e4c63cb397ffac4a85b8cf8ab 540a13ca68d414e3727c3d53c6b1cc97687994d572bc74b3df99ecc8b7d8e791 lib/codeql/rust/elements/internal/generated/Label.qll 6630fe16e9d2de6c759ff2684f5b9950bc8566a1525c835c131ebb26f3eea63e 671143775e811fd88ec90961837a6c0ee4db96e54f42efd80c5ae2571661f108 +lib/codeql/rust/elements/internal/generated/LabelableExpr.qll 896fd165b438b60d7169e8f30fa2a94946490c4d284e1bbadfec4253b909ee6c 5c6b029ea0b22cf096df2b15fe6f9384ad3e65b50b253cae7f19a2e5ffb04a58 lib/codeql/rust/elements/internal/generated/LetElse.qll 7ca556118b5446bfc85abba8f0edd4970e029b30d414ea824a1b5f568310a76c a403540881336f9d0269cbcdb4b87107a17ab234a985247dc52a380f150a1641 -lib/codeql/rust/elements/internal/generated/LetExpr.qll 9af0f89b294c8a0a751317e7074fe370339563d36c1df4911d1ea082a4df77fd 68272593d1feb88990bfbd0b8c222776f085e49694894384fc6d96e9464ba734 +lib/codeql/rust/elements/internal/generated/LetExpr.qll 6f831be1d0f76258d5f74c847636e070a819dee5aa090be0c52a971f261eaff3 e85a48e7492862f738e184f5f1512c2d18d33a0cfb516e269334acf7448b508a lib/codeql/rust/elements/internal/generated/LetStmt.qll aa1852db86ec29f857a90677f0c6b4a07f0fd965fc193d4141be95ce15862fca 40f32a37c0cc161b099fe0b4c7d713da928781d3e2c3de90db991df1d9062647 lib/codeql/rust/elements/internal/generated/Lifetime.qll 90d01c76188ce0c053122c62b41e47f27c4c7717ca5a4999a76797360043da0d 7b9feb202da5a06cd17f7770bb66742fd9e7cff0d410fefc7ffaafe710ac16d6 lib/codeql/rust/elements/internal/generated/LifetimeArg.qll 7c1a44e3d480e75142b171eb51382c9492d393043833c0ab4a4036eba19043b8 7d8273b62794268dab6938ba1e3a3560a80a2c49cd9a9717345785dacd311059 @@ -521,7 +485,8 @@ lib/codeql/rust/elements/internal/generated/LifetimeParam.qll bcbde38bfb99034e47 lib/codeql/rust/elements/internal/generated/LiteralExpr.qll f3a564d0a3ed0d915f5ab48e12246777e4972ad987cd9deaafeb94cf407b2877 2337c3d5f60361bd10f6aeca301e88255f5dffb85301cf36cbbfa1a65bfad1cd lib/codeql/rust/elements/internal/generated/LiteralPat.qll ecc2bfe559abfce1be873fbf7b61b5728897c9afc3bb3f69551d8320d273da71 42196fb6a4a0ff9b570fd0bdbc920f24744b3f46772efbb46648af7fbfe1fbda lib/codeql/rust/elements/internal/generated/Locatable.qll c897dc1bdd4dfcb6ded83a4a93332ca3d8f421bae02493ea2a0555023071775e b32d242f8c9480dc9b53c1e13a5cb8dcfce575b0373991c082c1db460a3e37b8 -lib/codeql/rust/elements/internal/generated/LoopExpr.qll 22b755dfaf238ecea722c0c94c399992014e23481ec6fdd61f803bbec012b6f9 08731630c2dc05aa1e0ada222a6057752d9ce737329c62076708828247a358be +lib/codeql/rust/elements/internal/generated/LoopExpr.qll db6bc87e795c9852426ec661fa2c2c54106805897408b43a67f5b82fb4657afd 1492866ccf8213469be85bbdbcae0142f4e2a39df305d4c0d664229ecd1ebdb9 +lib/codeql/rust/elements/internal/generated/LoopingExpr.qll 0792c38d84b8c68114da2bbdfef32ef803b696cb0fd06e10e101756d5c46976c 111fe961fad512722006323c3f2a075fddf59bd3eb5c7afc349835fcec8eb102 lib/codeql/rust/elements/internal/generated/MacroCall.qll fc8988696493992cc4fdce8c0e5610c54ee92ea52ebb05262338f8b612353f50 188a2d7a484bd402a521787371e64f6e00e928306c8d437e6b19bf890a7aa14e lib/codeql/rust/elements/internal/generated/MacroDef.qll e9b3f07ba41aa12a8e0bd6ec1437b26a6c363065ce134b6d059478e96c2273a6 87470dea99da1a6afb3a19565291f9382e851ba864b50a995ac6f29589efbd70 lib/codeql/rust/elements/internal/generated/MacroExpr.qll 03a1daa41866f51e479ac20f51f8406d04e9946b24f3875e3cf75a6b172c3d35 1ae8ca0ee96bd2be32575d87c07cc999a6ff7770151b66c0e3406f9454153786 @@ -532,7 +497,7 @@ lib/codeql/rust/elements/internal/generated/MacroStmts.qll cb4f3c2721a4d0c8522e5 lib/codeql/rust/elements/internal/generated/MacroType.qll c462824df4a002956c036966d15cd0bce206e664888f8d0c7834dedb38b3c0bf 947480f07c40128ef3d00ad4c3a29a685472b3e20a661680c22f6bb318205ed1 lib/codeql/rust/elements/internal/generated/MatchArm.qll 8fb740a0f2e308782d9cf390672969cd7cf6e698e5b847fb02ae3fa6c205646f 42bfe8dd94fc24ec925fbd44016df111600f99d1216c9a698631373bb6048830 lib/codeql/rust/elements/internal/generated/MatchArmList.qll 13362680c037fe83fef4653562cc10a4429078316b5ec7c47b076336cf4aca2e 41c674293c13eceaca62134ae0c6778541f6a5201cbc5c146f0ba01b898dc267 -lib/codeql/rust/elements/internal/generated/MatchExpr.qll 689d65f690fe05bc262d0a5bfe69bb4f8a142db387c5765fcc4958a9b49989f8 2979cd2017d0538870d17b2b7592c75cc05b706bd36c9de3e5dc38fa3a957e5b +lib/codeql/rust/elements/internal/generated/MatchExpr.qll b686842e7000fd61e3a0598bf245fb4e18167b99eca9162fdfdff0b0963def22 00f1743b1b0f1a92c5a687f5260fda02d80cc5871694cad0d5e7d94bac7fe977 lib/codeql/rust/elements/internal/generated/MatchGuard.qll 521a507883963106780f1782084c581fbcf1179863c7c15438c4db79e30e78dd 6226feffaaa8d828a42ece0c693e616cd375672eb987c3b7ff1ca15fa23c116a lib/codeql/rust/elements/internal/generated/Meta.qll 38fca2c9958b4179de311546fe0850319010aca9cd17c97d57e12b521c5d0947 740f99c9d41044ceebfcc9d29baaa22f59c11a40f45502a34aa587d423c018f8 lib/codeql/rust/elements/internal/generated/MethodCallExpr.qll 17bffcc826851a8be32a1900b8fdf777f9bab6aed9f8268d566173c4974c1cf9 134a2860bdf16daafdb3e574c52a69d2598210653db89c2fa062ca25e8f8a649 @@ -543,25 +508,26 @@ lib/codeql/rust/elements/internal/generated/NameRef.qll 4292fc7aa9ba22a7fa5bd638 lib/codeql/rust/elements/internal/generated/NeverType.qll 14dd3c08db1db873b365fc7f0d1cf3f5d6229b1f78bc85100c36c22d1bb8ee40 34257df0ac59cfd982ea5f30ab225c8bfece71d9fd3be84ff79cf1b0bff55060 lib/codeql/rust/elements/internal/generated/OffsetOfExpr.qll bb17a1e1d4332225cf4bbbae4a1bab9302c2d81d191fe835f2f973915d40dd2a f9e73210b81992040a5a5a9ac3ad936159fb3475445f130c7b28f83dfb4170f5 lib/codeql/rust/elements/internal/generated/OrPat.qll ee0487b90849c3e2a836c956ae8837f27515a9dc795bf17287cba2cf7a39d839 35117b6a3dcebab09f12665441332b6863200e206679ee97894170dd9ef7795c -lib/codeql/rust/elements/internal/generated/Param.qll c57bf238123e8337adb1556cf788bde2b2e8841d4afa0799649db9d507b02d85 7cb580219ec9b6257735f7c53260cd2bb5533dbe342bef3b793ec7b6a65e7027 +lib/codeql/rust/elements/internal/generated/Param.qll 4f853cece9ca8d41ef41ff7656a7f291568f1218403bebcd8afbf07e93fab6bf 93a1372f1d129b83470aa0dc481f46649771d1f5b72b114f215a51514ddd641a +lib/codeql/rust/elements/internal/generated/ParamBase.qll 9d9a82643019d2a13f28555dbdd60221cf6dc2e890f6541e7f85a91646585f2c 0e4a3e4c0e069a43d449167cb706c6f5d0d097b4cab2a7ade84c2c1b5528eca7 lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b63a2ca5296b5506bffdeea054893a56cde08f91560 d4599c52231f93e1260fbae7de8891fe4287fa68b1423592b7a1d51c80146dc8 lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60 lib/codeql/rust/elements/internal/generated/ParenPat.qll ce24b8f8ecbf0f204af200317405724063887257460c80cf250c39b2fdf37185 e7c87d37e1a0ca7ea03840017e1aa9ddb7f927f1f3b6396c0305b46aeee33db6 lib/codeql/rust/elements/internal/generated/ParenType.qll 9cc954d73f8330dcac7b475f97748b63af5c8766dee9d2f2872c0a7e4c903537 c07534c8a9c683c4a9b11d490095647e420de0a0bfc23273eaf6f31b00244273 -lib/codeql/rust/elements/internal/generated/ParentChild.qll b4d25c43ed44715053255c3c2f8aeb8d21826adc365f24026b2123a4f25cba86 1bc4bb0380a1a8b69055ffeac203b11b2a1b94e5ad88d1b32ff659e8feb26016 +lib/codeql/rust/elements/internal/generated/ParentChild.qll db7a782f11a14305acc666c865118475e2d324d2bf5d4110b157e1d488b62b75 3b5d31528d0baa0ceee139097e93461d18503797a1507288dc43428f378500e2 lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4 -lib/codeql/rust/elements/internal/generated/Path.qll f2b1be2f8f44001a6533533c978c4a9a8b7d64838d6f39eef5f0c0e7890611b8 d724a00a38f42429ffa8fb3bffbb5ec69e16a32ceeeb1d1f026fc7adf87424a8 +lib/codeql/rust/elements/internal/generated/Path.qll 4c1c8e840ed57880e574142b081b11d7a7428a009f10e3aa8f4645e211f6b2e0 989668cf0f1bdee7557e2f97c01e41d2a56848227fed41477833f5fc1e1d35f6 lib/codeql/rust/elements/internal/generated/PathExpr.qll 2096e3c1db22ee488a761690adabfc9cfdea501c99f7c5d96c0019cb113fc506 54245ce0449c4e263173213df01e079d5168a758503a5dbd61b25ad35a311140 lib/codeql/rust/elements/internal/generated/PathExprBase.qll d8218e201b8557fa6d9ca2c30b764e5ad9a04a2e4fb695cc7219bbd7636a6ac2 4ef178426d7095a156f4f8c459b4d16f63abc64336cb50a6cf883a5f7ee09113 lib/codeql/rust/elements/internal/generated/PathPat.qll 98c9938d6a359fd717829b196eb09701d2c798e18c1f43fa7b2a9145afdf6c19 caba2e629cae08682baac90a76ae9a48cda2d7d6f9c23d506fa0ff3f292978a4 -lib/codeql/rust/elements/internal/generated/PathSegment.qll 4621597fd86246f788b8f9ca73f6b0f27929fc04261ce3ccf85da1183071431d aadda8bce386a3b7a9c53b98465eedcc4f724e37b8a904c1775af5b7ffb041ee -lib/codeql/rust/elements/internal/generated/PathType.qll 45de78e5374d6eb0446e2112ec72d3692c2811df9fa2ad03d0127e426940abe3 622cf70408413a565a0dac58f451035ac1339c8d0ee5b24f630680201cb0aa48 +lib/codeql/rust/elements/internal/generated/PathSegment.qll 0fa07886deb0fc4d909d7edf691238a344f2739900aafb168cbac171eb1729a8 8f4bb418d8bea5e40128a87977c57d0a9183d06d111601ad93130c8615c11465 +lib/codeql/rust/elements/internal/generated/PathType.qll df6fd322ba0d99d6cb315edce8dbf099b661b84fdfcc3ad629fdd1fd066c1986 e11c8615cd7b02034b47b58f30a7b6fcbc6d33ec53303288dfd34d9a25f5a186 lib/codeql/rust/elements/internal/generated/PrefixExpr.qll c9ede5f2deb7b41bc8240969e8554f645057018fe96e7e9ad9c2924c8b14722b 5ae2e3c3dc8fa73e7026ef6534185afa6b0b5051804435d8b741dd3640c864e1 lib/codeql/rust/elements/internal/generated/PtrType.qll 40099c5a4041314b66932dfd777c9e2bef90a0711fb8d7c2c2cec764c003ac4a cf8297d93557356a572223d3e8acca701837c4b1f54e8d4351ba195fb7ed27f8 lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590 ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590 lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9 lib/codeql/rust/elements/internal/generated/RangePat.qll efd93730de217cf50dcba5875595263a5eadf9f7e4e1272401342a094d158614 229b251b3d118932e31e78ac4dfb75f48b766f240f20d436062785606d44467b -lib/codeql/rust/elements/internal/generated/Raw.qll 5f83209cda8319c5c6c932631b60c6f2163d2d9cf7be63f63523e2206c01d004 3581039746e86365f37644e86ac2c89d67e2123aa1b039d9e0afdffc7156c96d +lib/codeql/rust/elements/internal/generated/Raw.qll 7de290d66bd594f4c5b5a296502792e803e9f1084bb2616d9774196e33b16c87 28150fdd3cff3bb49b407f0c2119602be13e78cbb1f8fd749edd31f5d9772f7a lib/codeql/rust/elements/internal/generated/RecordExpr.qll eb6cb662e463f9260efae1a6ce874fa781172063b916ef1963f861e9942d308d 1a21cbccc8f3799ff13281e822818ebfb21d81591720a427cac3625512cb9d40 lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1 lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0 @@ -579,7 +545,7 @@ lib/codeql/rust/elements/internal/generated/RestPat.qll b3a4206e68cf67a0310a4667 lib/codeql/rust/elements/internal/generated/RetType.qll a26860cd526b339b9527c089d126c5486e678dd080e88c60ea2fe641e7d661fd a83c1ce32fd043945ad455b892a60c2a9b6a62d7a5aadf121c4b4056d1dfb094 lib/codeql/rust/elements/internal/generated/ReturnExpr.qll c9c05400d326cd8e0da11c3bfa524daa08b2579ecaee80e468076e5dd7911d56 e7694926727220f46a7617b6ca336767450e359c6fa3782e82b1e21d85d37268 lib/codeql/rust/elements/internal/generated/ReturnTypeSyntax.qll 34e32623d2c0e848c57ce1892c16f4bc81ccca7df22dc21dad5eb48969224465 ccb07c205468bce06392ff4a150136c0d8ebacfb15d1d96dd599ab020b353f47 -lib/codeql/rust/elements/internal/generated/SelfParam.qll cf6837c2731b45632f04092079d295eee3e02d19f73c73b3ccbce1abe12203bf 87eaa9d982506904c42030f7173dd01fd52f3edd9d2c8d19b572f6d5454f769b +lib/codeql/rust/elements/internal/generated/SelfParam.qll e1d994dea58a406dbfca3ea0c724ac48be66ac4380e7270e4037ca2714eef722 90f8ebfac723eef259e13d3c8a7ef6b886c2831d4f436a742144b96db6b6fc92 lib/codeql/rust/elements/internal/generated/SlicePat.qll 8b1463758d7b15a0303384c8136a48a8e71ce27da4ba6e421272b9751a988e64 7562d47308f197bc63ade0f114cd23a17e7f60fa696716f6a30fc7b7411642fe lib/codeql/rust/elements/internal/generated/SliceType.qll 98ee8b566be28f392ab9c9507600e8461ad0b48cbbbd422d22548aca691f8330 528d6eabddf49b9dc474971a2f3a6ddb6f2d77dc7f8449140ef54646c1ceb822 lib/codeql/rust/elements/internal/generated/SourceFile.qll 55d44c9f09c5ff28c4f715f779a0db74083e1180acaf0d410e63ca07b90d1cb5 78c0af48b0b64aa377413ea4799dfe977602a111208e1d25e4bdfa920dbd7238 @@ -587,7 +553,7 @@ lib/codeql/rust/elements/internal/generated/Static.qll 5fbd6879858cf356d4bdaa6da lib/codeql/rust/elements/internal/generated/Stmt.qll 8473ff532dd5cc9d7decaddcd174b94d610f6ca0aec8e473cc051dad9f3db917 6ef7d2b5237c2dbdcacbf7d8b39109d4dc100229f2b28b5c9e3e4fbf673ba72b lib/codeql/rust/elements/internal/generated/StmtList.qll a667193e32341e17400867c6e359878c4e645ef9f5f4d97676afc0283a33a026 a320ed678ee359302e2fc1b70a9476705cd616fcfa44a499d32f0c7715627f73 lib/codeql/rust/elements/internal/generated/Struct.qll 4d57f0db12dc7ad3e31e750a24172ef1505406b4dab16386af0674bd18bf8f4b 1a73c83df926b996f629316f74c61ea775be04532ab61b56af904223354f033e -lib/codeql/rust/elements/internal/generated/Synth.qll 1ba88215c3f0640558a644534b954e4b93acb15a0f51a1e4887230f451718aa9 747eb3bec1c7245e59ea2b500604f5b4e614e4f061473d1a22fa398ee48ba080 +lib/codeql/rust/elements/internal/generated/Synth.qll 65873a7fa44e223edc5e76cc768591a036eb2550960a6b6882476f43a01aefba 3e08e2bdfba53ae26d8f48f2d240b92b44c603f03105518c37a963e0cbe63e3f lib/codeql/rust/elements/internal/generated/SynthConstructors.qll e929c49ea60810a2bbc19ad38110b8bbaf21db54dae90393b21a3459a54abf6f e929c49ea60810a2bbc19ad38110b8bbaf21db54dae90393b21a3459a54abf6f lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c @@ -613,16 +579,16 @@ lib/codeql/rust/elements/internal/generated/Union.qll 06a602aa7c7097e72fff6ea33d lib/codeql/rust/elements/internal/generated/Use.qll d42ccf3516a9f79ae8766f93ad5f09d3cdcd7b96844d4c9de64189b56018a7b4 70a9553a8f71f6cbfdd0f59a4b42292d13177613ceb0542436436e0ac2e1f8ee lib/codeql/rust/elements/internal/generated/UseTree.qll b39cbc96e473802372726d580febbfa7d73668ba476095aa4a61fae914865913 40ce6515b7df068fa8c0a7e5ae8984f50b71f6f96d625d631b28d525e3e868b7 lib/codeql/rust/elements/internal/generated/UseTreeList.qll 829441cf309f008a6a9d2e784aa414ab4c11880a658f8ee71aa4df385cd2b6a8 ced82df94fea7a191f414f7e6496d13791d2f535046844b6f712a390663ac3d0 -lib/codeql/rust/elements/internal/generated/Variant.qll 2e3d8e7a7a97f2f33d6cad458ec0ded498c17a14b697722a96fffecd50c83097 46149bb257c08d5cd9139198b6519d7ad3fd25cc9ea6bfe99deea66f5f1ef201 +lib/codeql/rust/elements/internal/generated/Variant.qll e40dbb23e07c5b70adc577efdf7a064e773207f216cad8fe8905882b1da9f4a9 13f7be36d043afcfc156d2c01bb828de882df69aa732f284aa76c5f00b063544 lib/codeql/rust/elements/internal/generated/VariantList.qll 4eb923ca341033c256ca9b8a8a5b4e14c7eac9d015be187fd97eeb25dfb1e18e e7865e975c35db49cd72cb8f9864797d3cfed16c3a675b5032b867ced2bbb405 lib/codeql/rust/elements/internal/generated/Visibility.qll aba81820f30bed0fd2cd06831f7256af15ae32525b2a437896420b4cc067ea38 d6aed90b27124b812daf2ddd14b4e181277cbe638b4ccaab74e27681ac30e4ab lib/codeql/rust/elements/internal/generated/WhereClause.qll d6c8f72bbec5d71c024f0d365c1c5e474f4d24ded0d34c56c1f66b1e4a384e9d ed14311d140eee00d3b26a4972f53e20d5af1bddf88fb5618e7e2d3ae1d816f3 lib/codeql/rust/elements/internal/generated/WherePred.qll 342050e824ca6eb6116488d46cfc03efa79193b4de6049e1f5d4a9fe527b3036 ed07a81de7d63f853c93cbb7291eea3d7169953e34c2f2f98b570028dd1f8cd9 -lib/codeql/rust/elements/internal/generated/WhileExpr.qll fec8a9211b82a80601bf731db17409c5de6bf145295623bd86e28f96452fd91d 3916cf0c0e3b82b834727fc37809dd3e158f395bdf39971abe40b98e5f95a4d2 +lib/codeql/rust/elements/internal/generated/WhileExpr.qll 7edf1f23fbf953a2baabcdbf753a20dff9cf2bc645dcf935f1e68f412971a8f7 d2fa7ada1f48f6b4566c75747584068e925be925d39d6e6ebf61d21bde3b6522 lib/codeql/rust/elements/internal/generated/WildcardPat.qll d74b70b57a0a66bfae017a329352a5b27a6b9e73dd5521d627f680e810c6c59e 4b913b548ba27ff3c82fcd32cf996ff329cb57d176d3bebd0fcef394486ea499 lib/codeql/rust/elements/internal/generated/YeetExpr.qll cac328200872a35337b4bcb15c851afb4743f82c080f9738d295571eb01d7392 94af734eea08129b587fed849b643e7572800e8330c0b57d727d41abda47930b lib/codeql/rust/elements/internal/generated/YieldExpr.qll 37e5f0c1e373a22bbc53d8b7f2c0e1f476e5be5080b8437c5e964f4e83fad79a 4a9a68643401637bf48e5c2b2f74a6bf0ddcb4ff76f6bffb61d436b685621e85 -lib/codeql/rust/elements.qll 173d5ffbcc2874757033caab37559e84dbcbfed319730f8e41a4e9e10b146835 173d5ffbcc2874757033caab37559e84dbcbfed319730f8e41a4e9e10b146835 +lib/codeql/rust/elements.qll ced76fbeebc6e2e972ecaed65ef97851f90a215cf330f28a0f31a253f1c03442 ced76fbeebc6e2e972ecaed65ef97851f90a215cf330f28a0f31a253f1c03442 test/extractor-tests/generated/Abi/Abi.ql 7f6e7dc4af86eca3ebdc79b10373988cd0871bd78b51997d3cffd969105e5fdd 2f936b6ca005c6157c755121584410c03e4a3949c23bee302fbe05ee10ce118f test/extractor-tests/generated/Abi/Abi_getAbiString.ql a496762fcec5a0887b87023bbf93e9b650f02e20113e25c44d6e4281ae8f5335 14109c7ce11ba25e3cd6e7f1b3fcb4cb00622f2a4eac91bfe43145c5f366bc52 test/extractor-tests/generated/ArgList/ArgList.ql e412927756e72165d0e7c5c9bd3fca89d08197bbf760db8fb7683c64bb2229bc 043dba8506946fbb87753e22c387987d7eded6ddb963aa067f9e60ef9024d684 @@ -658,7 +624,7 @@ test/extractor-tests/generated/BinaryExpr/BinaryExpr_getAttr.ql 26d985ac4b668d78 test/extractor-tests/generated/BinaryExpr/BinaryExpr_getLhs.ql c3f19d8a60066ad6b1810291a669473c75b659cd2f6ac3ab9ed3db2203d4145c c05c5e0226e30f923155669ffc79cfe63af1ca464e8dfc85888dda5f7049711b test/extractor-tests/generated/BinaryExpr/BinaryExpr_getOperatorName.ql 33612159be1c111e3306009d0b04579450fc962a81119b6ea4e255d3c409b401 1a0995b298f50242217cfef81dca8ac978e19e06f90a5f4caadcb6f84460fec2 test/extractor-tests/generated/BinaryExpr/BinaryExpr_getRhs.ql 3bcd36b678e87d5c29a43b69c54c80468a89aefa7e69481b48158ae794a53160 a629dc1472b3f6fd7c608ff760e83d8e1363db81dfe9a4b2968690c2ba4925ca -test/extractor-tests/generated/BlockExpr/BlockExpr.ql 0ab66b190d4e2aa784e61088c4779ef4d08cb4453677ea087c4f9aa369494bc2 1c3b5794008114d1297695d82590220929e3974e27836b2c6062d14b73379a40 +test/extractor-tests/generated/BlockExpr/BlockExpr.ql 19caa39aaa39356219dda740b7152f85e43a4f8d6295841e2c535c7e3bda7a5a bd668574ba41021e758e391d4790b871439badb2486ccf6a5aaf788ad6ae4142 test/extractor-tests/generated/BlockExpr/BlockExpr_getAttr.ql 15d4d9853d3262ce6ec629c075c60a76eb112dcafe34b71df0e09b39282223cf 792c498bc7079bb5b93034b8a87db3b275a591d78954e844821aeacffe4258ea test/extractor-tests/generated/BlockExpr/BlockExpr_getLabel.ql de3c28a2677ed71ebd95207aa43ce270765f7f556283f095f1f6296622b80cbc 414ebbb2bfbe4350f933fc3d3636b49a6bb8242e200180780caf95ab8523adb0 test/extractor-tests/generated/BlockExpr/BlockExpr_getStmtList.ql 8c391dfeb69bd92c547a2417bf231cc960a8f34845802722214294728772316a f3e847fa594e9d9cf25d09a0396a10176aad1100c1977a24756ff6287a79e69e @@ -668,10 +634,10 @@ test/extractor-tests/generated/BreakExpr/BreakExpr.ql cdde2855d98f658187c60b9edc test/extractor-tests/generated/BreakExpr/BreakExpr_getAttr.ql c7690a9aab1923bf3c2fb06f0a1d441d480b3c91ee1df3a868bbbd96c4042053 c592dd077fb6e22b2d6ddcaec37da2c5a26ba92d84f5d1ae4c78a615b9013765 test/extractor-tests/generated/BreakExpr/BreakExpr_getExpr.ql 0358f4fe6a66da56177703cf0e991042729c5e34ae8b6dccbb827f95fe936c72 1cb2dd778c50e19fe04c5fdf3a08a502635ea8303e71ff38d03aa7dc53213986 test/extractor-tests/generated/BreakExpr/BreakExpr_getLifetime.ql ad83cc0db3c0f959fef6bb7ce0938d241a877e8cf84d15fb63879be2fe47238c 240b2fe2156b763d3a82fc64159615872db65b65ffb9ba2f3fd5d1ebd6c60f34 -test/extractor-tests/generated/CallExpr/CallExpr.ql 69d88b3c799f6e81fe53fe04724ed6c1cbfbfcc21023dd62aed3a3f852c6a2aa 0caa94802919d30bf2749d8a1c58545163e2b1cad5490f19158b5e5063806443 +test/extractor-tests/generated/CallExpr/CallExpr.ql ffb0cf1cb359a6dcbdf792a570c281e2d300779dca2dbc0f324990652adb972f 978a9e6c82758f9e8b334a682a02d6b893a6bf1db3cd85e9535839a9696b09b4 test/extractor-tests/generated/CallExpr/CallExpr_getArgList.ql b022e7b6b6db9932e787e37b7760c6a09c91140a0368940374a2c919688e0488 c20849c96b53c96f6f717efff5e8b4c0e900c0ef5d715cfbaf7101c7056ad8f4 test/extractor-tests/generated/CallExpr/CallExpr_getAttr.ql 1ace458070875b9ff2c671c2ee18392ea7bf6e51b68ee98d412c8606e8eb8d33 4c35da8255d2975cef4adee15623662441bb8f2e1d73582e4c193d1bc11cc1b5 -test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql f680f04423ece282c459d5908e5aa0bc43ca072ff0e605587dfa94210da1d06d f8a709015b8317b8e2dcf3b3ee9370e2c3a655ef7e3c6034b1b90f4d75ebdda2 +test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql 060a6c8b5b85c839b14fe96f9e50291a7a0e5662a945f4f337070f782ec76715 e9a1e44433936146d87be939aa160848b9a7d7333c36da601fb7d1a66d71eb59 test/extractor-tests/generated/CastExpr/CastExpr.ql 2ffb22ebc6e47953a49162488b3605d36b9d89330b1e71187066e7bbc40a22ad 7621a39d49f573b9862b9a4e1021d53205670ee59b49e4d81128637926f76485 test/extractor-tests/generated/CastExpr/CastExpr_getAttr.ql 5d5d98172e495cdb8b5cea9d6588c4c245107b441464e3ffd6c27668af11ab4e 5820bf083aaa4c3275004a2cd9eeecc4b45ab96916cbc0655a1b42611c540715 test/extractor-tests/generated/CastExpr/CastExpr_getExpr.ql c37186b8f3e3dab8ae28c0da7263ff7272c40501beb16736ec0fb8990d285e22 59d50d7349234afcf84986b7570db9dcd342e16812f7c46199d4736cdfa5462d @@ -742,7 +708,7 @@ test/extractor-tests/generated/FnPtrType/FnPtrType.ql 50b76d678582cd0b8d7cc4a765 test/extractor-tests/generated/FnPtrType/FnPtrType_getAbi.ql de1706382c2980c02dbdd295e0a2320c992afa3f19af0c2378b9980a7cd0c481 a3fa36711949d9d5ac53cc5dd39cb19b397c3f2e47c1d457df470c6e5142f9be test/extractor-tests/generated/FnPtrType/FnPtrType_getParamList.ql 9ea393acf37919e2fd1bbc16e738440e00a56552bf80baef9bfd2a9a405afb93 3b4237b22eea569cef0081eb3ea16b2d0f01f8f070f21e16390267e9cbe0cf57 test/extractor-tests/generated/FnPtrType/FnPtrType_getRetType.ql 57f662e4778e1bf4103f061bb8085def0708528f94045c9ff4a95ce802fff13d 924b924c7d766458e956afa0963e6eb1bfc083e5f9aeae64cf2d08929f79612c -test/extractor-tests/generated/ForExpr/ForExpr.ql eff335a301b9a71292bb6da0dffdf901c7a51df9960e9250f9eb980aaaa0c7ae ce7ab100c21c6fc334a4445b2ee311ae6c67992ef659ca32c94d60ac884936e3 +test/extractor-tests/generated/ForExpr/ForExpr.ql 1f8b7a9bbe7a8c077864be64dc51d91ec267c4f34f1cad80fc79902cc0af04ff ae999fb206b04ed81fa08bdd7617cbfe932c5e4109285e10108613cdebba8f7a test/extractor-tests/generated/ForExpr/ForExpr_getAttr.ql d3399b7453e10ff48efc79ec38dd9b6e06bb472b9c39f559242d003e7f63b1d9 ba37e6bf129e1c2f9094e093bbfbf41864f2cb7725a64334f9443270dafdbfdc test/extractor-tests/generated/ForExpr/ForExpr_getIterable.ql 90a6540f8a91cfe3ed1bdde1e680786ce5a00edbb797a8fe70bcc0507c438fcc 65c67ad5890aa502628ee73efd26bcbd4597a8bdfc9839233ede9e26393638f8 test/extractor-tests/generated/ForExpr/ForExpr_getLabel.ql ce90da75e040f448d524187357f3ceededba72407a84c1dc8e1498ed9788044d 0e23d43e0b3412fe90c6a5a4331f8da85eebe19e05b8c7d9710056857280797b @@ -751,13 +717,19 @@ test/extractor-tests/generated/ForExpr/ForExpr_getPat.ql 1e0205a9b3a58fd2ddba49e test/extractor-tests/generated/ForType/ForType.ql ba930d0c4fe52d57449ce4025b1c3e49c688afc5ef18ee8ac1ed7a9fd3eb8d41 08e9aa0301a942f6f9564ddeddc69606f3e2916e1b551cc56ae3b6048c56ce61 test/extractor-tests/generated/ForType/ForType_getGenericParamList.ql e25cd79737bbae92d8f417c6bbf6fb8ae660976b8005cd91d0900c7076fdd827 b1e32b7e3ca9f29a4564f83e37ae53de6baf04837a393e6dedc64a01cc7d10e8 test/extractor-tests/generated/ForType/ForType_getTy.ql e932d3412828bb83afc42e2dc1a4cbe9fcf25ec9a9617ec138722f834091a61a 298fc9df34b2cb436c8f180c4d229341ee4a73e3c451b905f017f32a6f65056c -test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.ql a521903c73f79e2616f7b8ef76790e11cbf432f8437825d52d117da232022b9e 4cb195d09ecb51e5bbd5c1c069ec1720f74fc074efc88b0f5c07cfc140167775 -test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.ql 7e1a7f902fb661660760d2a2f3f4cb6818a0c9f5b5061ede6ae80223774e4e09 8a50f64cba6f56320631206c801160201e3c98e74367bb035d689baaa9b4e411 -test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.ql 0e2f24388d516e14d195957163a2d5d97029c9e11a83ca71cf69e00ecc0bb2a8 dab2969f5ae6a15ec331c0152e7c116d1ee2c3d073b2d4da59ffbcb83404c65f -test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql 0cd439f61569ecf046e9548c458329647f331bfa034ae8b3d4f7628595881287 013a948607e1ac96100ea9a8cd3c8f357e378ac21baa015dcf4927022c2bdafb +test/extractor-tests/generated/FormatArgsExpr/Format.ql 25268dd7ad2a58b071c3a38164944c1b7389dfdda01c99ef2694a475596341b4 0a3f674d5a4f005835b9a5ba11a6e8bf58477829258f30ae7d8f76f8986f7b7f +test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.ql a521903c73f79e2616f7b8ef76790e11cbf432f8437825d52d117da232022b9e 4cb195d09ecb51e5bbd5c1c069ec1720f74fc074efc88b0f5c07cfc140167775 +test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.ql 7e1a7f902fb661660760d2a2f3f4cb6818a0c9f5b5061ede6ae80223774e4e09 8a50f64cba6f56320631206c801160201e3c98e74367bb035d689baaa9b4e411 +test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.ql 0e2f24388d516e14d195957163a2d5d97029c9e11a83ca71cf69e00ecc0bb2a8 dab2969f5ae6a15ec331c0152e7c116d1ee2c3d073b2d4da59ffbcb83404c65f +test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql 7b6f09b23d0dffa19b8dddf7f5cfe53068f8a8e5279e235c6d54e60616bd0822 47db74f035770ce708a00355acbfd4ae99152b7eb29cf28001985806a4efe5aa test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.ql 8f692486be1546b914b17abdff4a989dfbaa889bfa1fc44597f4357806c1a1dd da9fd237e31e9c8dd0ef0c3c968157815b87d3e8dcdfd74674c988ce2ab6d270 test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getAttr.ql 1f9bf1344f942e65c3a3591b6ae04d3f5a2a1a65459bce0d976698de7d8a5958 02acb861d8ab4d32cf144c589881a888c3da5e2ade27e8c85fec3ae45219bb3b +test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql 02d3fad540700966488b24c62dcf200548154a2f10f578ee2995d8c4ebe32287 cccfe779b9804c2bb968a2b1f54da8a72393805c2c8b31d7160e8538f2f335f2 test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.ql c912ac37275cbe7b3b29607bed1a3190c80779436422c14a475113e1bfd91a54 ef90f67a9b952a38ce557b1afbf0b5ce8551e83ddfaad8309a0c9523e40b5ea7 +test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql 7a7ee3a3322b4af8cb3b525cfed8cc9719d136ea80aa6b3fb30c7e16394dd93f 5aa8a77d7741b02f8ceb9e5991efa4c2c43c6f1624989218990e985108dae535 +test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql 7bd4ec3dde2ef0463585794101e6cc426c368b0e4ab95fbb1f24f8f0a76cf471 e7b01e8b21df5b22c51643e2c909c6fc4ca96fda41b3290c907ba228abe8669b +test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql 2793ba1ff52182dab992d82d3767a000928f6b2fbfdb621349cafc183f0d2480 c3777d03214f7feb9020de3ce45af6556129e39e9b30d083de605b70ab9a0a12 +test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql 26d592398a17795427b5b6b51ff4a013ee15c31443e732a000baca5f2e65acca 7940a864b84b89e84d7fb186599cb8b6bcbead7141c592b8ab0c59fcd380d5fb test/extractor-tests/generated/Function/Function.ql c1c2a9b68c35f839ccd2b5e62e87d1acd94dcc2a3dc4c307c269b84b2a0806e6 1c446f19d2f81dd139aa5a1578d1b165e13bddbaeab8cfee8f0430bced3a99ab test/extractor-tests/generated/Function/Function_getAbi.ql e5c9c97de036ddd51cae5d99d41847c35c6b2eabbbd145f4467cb501edc606d8 0b81511528bd0ef9e63b19edfc3cb638d8af43eb87d018fad69d6ef8f8221454 test/extractor-tests/generated/Function/Function_getAttr.ql 44067ee11bdec8e91774ff10de0704a8c5c1b60816d587378e86bf3d82e1f660 b4bebf9441bda1f2d1e34e9261e07a7468cbabf53cf8047384f3c8b11869f04e @@ -807,10 +779,10 @@ test/extractor-tests/generated/Label/Label.ql 6a92a27d615dd9c380cb9d889eecf827fc test/extractor-tests/generated/Label/Label_getLifetime.ql 3d6ddc3b44182e6432e938d5c1c95e0281575e320d517e431f6bad7748efb93e 56d07e485cb5e4263443eb5a0d62d7d4456bb0c2748331b371e519bfe14d3b81 test/extractor-tests/generated/LetElse/LetElse.ql bdf2b17d5efe6b9cb5bb4fcfe854a5fcd72443d39ae1e7981d2a0459c481e394 a14a611d0783ae38d631600c2bde7409f4e739ba2f284314b90ec9a21c23ab3a test/extractor-tests/generated/LetElse/LetElse_getBlockExpr.ql 32c21ad843884944738a735f01e272032a347d1860fa6d27d17652c549f941b0 2bfd8a5e3d42eb1c73eb679ada847dd29f2f0657a0ad8ef15da126e54fff5ef5 -test/extractor-tests/generated/LetExpr/LetExpr.ql a25072a00cfe1242dc846b38199c000ed7217d33fdd50d2763237fdfda7b9449 8c9367af79d9fbc98ed2fe62450929fa876512f1c999615b5c1ecff082fdc7bc +test/extractor-tests/generated/LetExpr/LetExpr.ql c76a0c4aaa73f4064207dacc8d2c649d3a5f8046c0f6e1aae985d2402a342e73 c5abe3845d4975d05c98ee6496732da384cdaca60ed49235776338e6dbe80b3d test/extractor-tests/generated/LetExpr/LetExpr_getAttr.ql 911b143afebaa0a487b13d533f089c5b0eaf336a44a4cab42147c284338484ba 625c91fb6d8c2e3a9f13e5679cc0cd29329c6c2b213d2e1191e23db2b65841dd -test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql ccabfaa15cfc8685e86cb950cb62b7f2fec278f28906ab34deb97b308f160cc4 e0574537d47a77f1be85090970f3e1263858174479002fd4de3f85b777ee4336 test/extractor-tests/generated/LetExpr/LetExpr_getPat.ql bc0363f77bc2ba583619ab7d309293ace0ed6a851bfb9b886f75729f96eb40a8 bc0cd9233b7904d8cc7f9021377120f5f4bcc5c7aa28b1b55f17bc738c434d78 +test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql ee33d3bbaf0ee7cdf9bd7b800e9684b5ac7ce8cf1939378cd460cb0c5ea11742 5d69e727b3e9d1ab4ce9eef702a7b1911515469625056bce87fac1d27ba863e6 test/extractor-tests/generated/LetStmt/LetStmt.ql 02db64303bfe87a11a85663e4c79bdabd9ca13693f146c7923b47c4c92850fcc 9ec1326b8bc58b270b178a4c02621b1650d107de7c02a9408d97c59f0d8a6178 test/extractor-tests/generated/LetStmt/LetStmt_getAttr.ql 68f69c4c054514140c0f0833a170e9f3facf950bd7af663ac9019f6c88ba0ea7 ca54d25cc052289458c7e34e40f0304bca2c412cecfb407f31279262bd74c15a test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.ql 6a5f0eed3ce3e8cbc57be6ec2b4eed732f00e084108d21a61d9ab28b65e494ca a48b426b97a6c347ad04fe2e592cd25b5c66b2a6a299cbf8c0da03e14304fd70 @@ -830,7 +802,7 @@ test/extractor-tests/generated/LiteralExpr/LiteralExpr_getAttr.ql 6e76da2bb7858f test/extractor-tests/generated/LiteralExpr/LiteralExpr_getTextValue.ql 7049fec0bbbf0e048af1ff318f42f43d0f8a7354a5638dc21174c4ea725b54ce 2edc94cc0a7f58ec9808b63ddb4d20a3907c88e50bd9ffb14f0281b433f5621b test/extractor-tests/generated/LiteralPat/LiteralPat.ql 3d3db6cad0eb13f84b69efa24a9f9a32d35c62582274d2751cc3ac54dca3b538 7feb64af87546ea64c139c61ac20176a99ad40b9949b361742a424b164fe6d54 test/extractor-tests/generated/LiteralPat/LiteralPat_getLiteral.ql 2cb03a22220e99237d4f3cd94d5090757cd6e57df708d32e80bca3964507651f 4dd9a6c1e23ad9851d9aa8c42c79535f7a2c7224bbaaff286eac7fd04b39c6f0 -test/extractor-tests/generated/LoopExpr/LoopExpr.ql 636c28bff5f8c1ca0fb834f614b3215e02bdb00826fd8be26f9c4fa22c68a79a 1694c27850419d4edf366fe3f1d60fff578094adc3aeeb9691a3d6a8ec0100e1 +test/extractor-tests/generated/LoopExpr/LoopExpr.ql 37b320acefa3734331f87414de270c98ab3309fe069d428550738197e3498a8c e744c25640b5c46aab53ce5114b789e13319572b0c99d0f2bc3c177849e61541 test/extractor-tests/generated/LoopExpr/LoopExpr_getAttr.ql d557c1a34ae8762b32702d6b50e79c25bc506275c33a896b6b94bbbe73d04c49 34846c9eefa0219f4a16e28b518b2afa23f372d0aa03b08d042c5a35375e0cd6 test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.ql 0b77b9d9fb5903d37bce5a2c0d6b276e6269da56fcb37b83cd931872fb88490f c7f09c526e59dcadec13ec9719980d68b8619d630caab2c26b8368b06c1f2cc0 test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.ql 0267f54077640f3dfeb38524577e4a1229115eeb1c839398d0c5f460c1d65129 96ec876635b8c561f7add19e57574444f630eae3df9ab9bc33ac180e61f3a7b8 @@ -875,10 +847,10 @@ test/extractor-tests/generated/MatchArm/MatchArm_getPat.ql b346bca229226414b32ac test/extractor-tests/generated/MatchArmList/MatchArmList.ql 14b5e110d48e2b77c85b7a188262e6a98300e0d4d507bb7ed9179c5802251dd6 4d091f06b12fef0fffe1c80a10f74438d8068f2fa09c50d5e240b6d140e60d90 test/extractor-tests/generated/MatchArmList/MatchArmList_getArm.ql 4781d002538a92b7f40fb0ec3d61aeedb6348341ddc354bbdd3ff61b74d59767 ae0da9497a30ce006e03bdb70e0ee24b685df529ac15a7d99a6869b5f7d7b371 test/extractor-tests/generated/MatchArmList/MatchArmList_getAttr.ql 4d7e6d152d2dbeb4c9f594becabea27d3b25fecbde40d791a2907c69cc0c9631 4be9be658bb22e1b764c4ebc8d6b99bf50fd939f35ea44fbb869056c14632bd4 -test/extractor-tests/generated/MatchExpr/MatchExpr.ql ec116bca37079488977a50beeba508c440cf337799947fcb810b6bd7a7605255 42dc7b5f0dd6fd91417d9846a7b4f678cbfcf095791aaf57c8d3b4548ce2dd98 +test/extractor-tests/generated/MatchExpr/MatchExpr.ql 2966bf0507c0d45db1b933442ce8f1c4e0a9d4212c53a768791665cd2e0927f0 8af3b87528b6dd4cd3ff4fc6d2d389b1a743f979d9ccacd0aff134b5a4376118 test/extractor-tests/generated/MatchExpr/MatchExpr_getAttr.ql cb8057372dcf24dfa02896ebf4e60a0b757dc4742b94011edc38f5b898ed4d25 6809695c2d3ac3b92c06049c9b920e8c0e99ee1998a11a7f181f2b0ceb47c197 -test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.ql 7baaa64071cf2666e3b2bc05630d92a7a3b6cf04a026b1f7053c5e2a735bcaa8 d9ba8d8bbff05cfc0461ab41295f921b48429b4376c29adf54428bd5a9aa5298 test/extractor-tests/generated/MatchExpr/MatchExpr_getMatchArmList.ql d97055bcb0431e8b258b5ecdd98aa07cb24ece06b0cd658b697cd71da4ede8fc 5e9c03b2665ef6b2af98897996abb2e0a9c18d54eb64588340b8efbcee9793bd +test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.ql 0bfeb8f903fb23356d50b7edd80377f4a67045010ffbed04c835191b5bd62820 7dc8e38730ad72b4cea91c1f023cdbe83057053e8dbd077ff925c59e92744498 test/extractor-tests/generated/MatchGuard/MatchGuard.ql 23e47ec1b13e2d80e31b57894a46ec789d6ab5ed1eb66bdb6bba9bd5ae71d3ef 7302f4a93108a83228e0ebd5b4a1bc6bccc1f6f0f3272054866fa90378c0dcc4 test/extractor-tests/generated/MatchGuard/MatchGuard_getCondition.ql 8a79dd46798f111f8d0d5a975380b5cebe5e337267752b77b3718b268ba2773d 6691d8fb483f64fc7e3ad3f46e3129e0a1184d7beb9f83a1000acdbb081c8b5e test/extractor-tests/generated/Meta/Meta.ql 16f163f00ba2bbaa0a8c6f3f6710c860a8f61d02d43321c78e05a10a3606e39b ba982c6bb93ddb4fc2c44d24635bd487128a5b1d1f885214044c989a21f4d05a @@ -911,7 +883,7 @@ test/extractor-tests/generated/OffsetOfExpr/OffsetOfExpr_getField.ql 6d729fb91de test/extractor-tests/generated/OffsetOfExpr/OffsetOfExpr_getTy.ql b8597637cffd7a492148020b306c4ab1d2f17f919f441f462ebc00d229b038ca 2c7de1df4351929c221b30e3cede4cd6981fe8a2c1861e194489981c65e00f33 test/extractor-tests/generated/OrPat/OrPat.ql 49d881b384acaf68fa79de46da997cacab3e75467641f61150908f4112c47fa4 5d721da23be44e79d7b8a0dd475119836828d6a1edaff2c55decea8da83e65b8 test/extractor-tests/generated/OrPat/OrPat_getPat.ql d56b78287cecebacb25249380647500387e0d9e28be20034b8a12406a999a7c4 cba7bb60afaaed4333ea5ff6d3850fb44a8b42edee67d86fd16df85938454269 -test/extractor-tests/generated/Param/Param.ql 060c53b7e93840ae9cbf0c8fdaea17b16d6825f4b7aaa2eab164a660c5a7ea4d 172f6f4b86a98720f710e5d4342b7d52839c6f3c169ce1debb37629961a702ba +test/extractor-tests/generated/Param/Param.ql ab8d0f8cc3c71f5d24be4aebde1ef7d016519490a9715aca6069e58fd11aeb1c 61197a0c2b8d6f0c5a9cddda39585dcd413644cf80e3ea28b037385142100b27 test/extractor-tests/generated/Param/Param_getAttr.ql e1dcf86540fd2971ced34a33b2959f001c3f654914d82e576caa4534b80fbfbf 987a826bf6dcd25c3426edb603a22f6caa030c82c1cb0e9e11062fdbfed23030 test/extractor-tests/generated/Param/Param_getPat.ql 0c448e8ba8bf3432be08b5eb4a052aa19cccf0eb4596a3239481401dae9d2dc2 c943d4da36e1e734c1a012f092b2f597cb389a7ab33d5371ff8ee9c93e115ffc test/extractor-tests/generated/Param/Param_getTy.ql 134dec0c5562a8df68224069f10ee51c7dcc35e0b44a49c0e2078c305487db87 94fa72a213c37f2f63f03789a33e55fc5a22bd83cf0c1d293281bceffb63bd78 @@ -926,25 +898,25 @@ test/extractor-tests/generated/ParenPat/ParenPat_getPat.ql 96f3db0ec4e71fd870619 test/extractor-tests/generated/ParenType/ParenType.ql 81c8ad667397ce36157941abd9b879e9305a440018853af4528eb737ae4d2935 3ef3b86203b0143be2d7f7f4833f55fd6c226cb9205e3c1940b6c2a1371622f3 test/extractor-tests/generated/ParenType/ParenType_getTy.ql 41dd6605e7b348618156712b559e2f1b6aac02d6c727e8cbf8653530794ec969 30ac6611c730e76cfb75f98efcf817783a50cec0cf3b3197459d7642f74dde85 test/extractor-tests/generated/Path/Path.ql f17c1c4d23c0d5e9776cee84444f6ee7445de88afbc1f26c34b96e13ab618158 89499cb0f63b3634d6b5e2b8c4a13bd4401ce82e54af0ab46e41a34b0288eeb9 +test/extractor-tests/generated/Path/PathExpr.ql b9696cd7ad9f3874e4bc4b1b9c77f42f06ab6c61b77fb641458da63667087b9b db84a7a8dd05e30ff80733af01f08d43ff031bb4b3e3af06332a73ba7e7bbc43 +test/extractor-tests/generated/Path/PathExpr_getAttr.ql 2ccac48cd91d86670c1d2742de20344135d424e6f0e3dafcc059555046f92d92 9b7b5f5f9e3674fad9b3a5bcd3cabc0dff32a95640da0fce6f4d0eb931f1757d +test/extractor-tests/generated/Path/PathExpr_getPath.ql e7894071313a74166bdd31d7cd974037fcd5a7f0e92d5eec42833266196eb858 46a06e8a1207e7a0fa175cd4b61068e5fd6c43b5575b88986409f0ac2be64c51 +test/extractor-tests/generated/Path/PathPat.ql 823732954a5882e33a37bd0bf0cafb2cec51659a5203a4831eec2516da0e49fa 54001149718a9ca15d8c0d4be63f3fe00a9f0d44fa1309e2f605d7932355ea5d +test/extractor-tests/generated/Path/PathPat_getPath.ql 6c0c71c80a6e631ea7775ec8660b470ff6b264bab14a399606cf113b1fb190fc 8e34cbb4d064db929e94652e1901ec4f26affa71e30e556b7acdff71dd622cbb +test/extractor-tests/generated/Path/PathSegment.ql efc39cea1b4c0b2b0da6434136334430d074699f84124d6bcf94c24aa854dc64 c0a4bd60c67665c058ca22a59e535e925fdb00dec95ffc5c71697fb0ed78a329 +test/extractor-tests/generated/Path/PathSegment_getGenericArgList.ql 8f6e67b3e316309f20e21d7e7944accf66b0256b76fa50ee9a714044c6ec8cea 15f10a701fc4d3f9fd6734da90790cdbc8a1ddd57bf52695740acedcb2e6e485 +test/extractor-tests/generated/Path/PathSegment_getNameRef.ql 799d284e2f9267d6bbe67aa7035e525ef347dc74cb3e2180e7b2171b5cb49674 592130bc2358989536abf62e8a261272c851483ede4f19783f7d61ffc1803e4b +test/extractor-tests/generated/Path/PathSegment_getParamList.ql e1e7b9b5062f936c33b7e7e29b21456448242df4985c6cffb54900063cfd3e63 6568e851cb6bcb32622f89d01e3aa6e7dd21940d21572a9988584e34bdf25366 +test/extractor-tests/generated/Path/PathSegment_getPathType.ql 01942da6d0b10c1d15caec6abb8c53f1dc7f8c04a91a797f572063aa003dbc4b cb21e6cb160652527ba571265297dae86beffe191dd7dfc4d0beee45cb0cda29 +test/extractor-tests/generated/Path/PathSegment_getRetType.ql 36386a514bc925f5b17ad87afba9fef7986900c1b791732de061213c6e86743f f38bcee68c1da19e70bb1e1c4a4047c763a466f1b8ef2c4f65f8c724c0b58197 +test/extractor-tests/generated/Path/PathSegment_getReturnTypeSyntax.ql d1db51208a311c30af369ce2fdc3a3296e7d598b27bf4960b8b34622a9d9163b 561b1e38c6d8b301fdc016e1d012dd805fde1b42b0720c17d7b15535715047f2 +test/extractor-tests/generated/Path/PathSegment_getTy.ql a0ceaf3f37e521cc92c21cc0bae929499ef3584f86349ef34808c20963d31c75 d674e56e08a6d2a7d211503a466df2cc90c35a3951e41598febf62c8dc693655 +test/extractor-tests/generated/Path/PathType.ql cb67b05cf7e4f32cbd46ac89a15f6eafe3507cc655db0b9d54a1cf8e7fbcca40 890053e7fd8cd8a92015c09588c7c646f075901cddc3eb8d57210b02b23a5944 +test/extractor-tests/generated/Path/PathType_getPath.ql 7043c7939e4f835e4b2c7e3e207637c362d7a9dbdba0151b38c873fdaf43e7a5 ee2aad1b4fb2b00e1a5d39387848aa164a39e3cd49141f07c175b205c8451bb1 test/extractor-tests/generated/Path/Path_getPart.ql 8aa45a0b58203ef1177166efbe1c2851faf4b4c9a453c83137f0c9298badcdbf b82d490d9b3a8237487cd5da8b3b6fc4aa477977b332a5c6539b3cd4e6d5b45b test/extractor-tests/generated/Path/Path_getQualifier.ql 9af95e22cdf3a65da6a41d93136aef4523db5ce81d38f6ed4bc613f1c68784d0 3102d9241a417a92c97a53ac56a7a8683463f1adc7a593cda1382c0d25b3f261 test/extractor-tests/generated/Path/Path_getResolvedCrateOrigin.ql 7c0ff524595514630de4178028260d4832bfc4f57bfddec9f8e72a6c6dbf241c 55e617380476c183ef9259199d2cfd551b07466e94bc452c4723754d0c82691b test/extractor-tests/generated/Path/Path_getResolvedPath.ql 20c8977781dfe687d5db03290612179cf1360eb47b86ea62d25d1eef62a681e7 c35b76e7d63c05dc80867285bb913042cbe90b45d4d4306df9eac2cba5e8db70 -test/extractor-tests/generated/PathExpr/PathExpr.ql b9696cd7ad9f3874e4bc4b1b9c77f42f06ab6c61b77fb641458da63667087b9b db84a7a8dd05e30ff80733af01f08d43ff031bb4b3e3af06332a73ba7e7bbc43 -test/extractor-tests/generated/PathExpr/PathExpr_getAttr.ql 2ccac48cd91d86670c1d2742de20344135d424e6f0e3dafcc059555046f92d92 9b7b5f5f9e3674fad9b3a5bcd3cabc0dff32a95640da0fce6f4d0eb931f1757d -test/extractor-tests/generated/PathExpr/PathExpr_getPath.ql e7894071313a74166bdd31d7cd974037fcd5a7f0e92d5eec42833266196eb858 46a06e8a1207e7a0fa175cd4b61068e5fd6c43b5575b88986409f0ac2be64c51 -test/extractor-tests/generated/PathPat/PathPat.ql 823732954a5882e33a37bd0bf0cafb2cec51659a5203a4831eec2516da0e49fa 54001149718a9ca15d8c0d4be63f3fe00a9f0d44fa1309e2f605d7932355ea5d -test/extractor-tests/generated/PathPat/PathPat_getPath.ql 6c0c71c80a6e631ea7775ec8660b470ff6b264bab14a399606cf113b1fb190fc 8e34cbb4d064db929e94652e1901ec4f26affa71e30e556b7acdff71dd622cbb -test/extractor-tests/generated/PathSegment/PathSegment.ql efc39cea1b4c0b2b0da6434136334430d074699f84124d6bcf94c24aa854dc64 c0a4bd60c67665c058ca22a59e535e925fdb00dec95ffc5c71697fb0ed78a329 -test/extractor-tests/generated/PathSegment/PathSegment_getGenericArgList.ql 8f6e67b3e316309f20e21d7e7944accf66b0256b76fa50ee9a714044c6ec8cea 15f10a701fc4d3f9fd6734da90790cdbc8a1ddd57bf52695740acedcb2e6e485 -test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.ql 799d284e2f9267d6bbe67aa7035e525ef347dc74cb3e2180e7b2171b5cb49674 592130bc2358989536abf62e8a261272c851483ede4f19783f7d61ffc1803e4b -test/extractor-tests/generated/PathSegment/PathSegment_getParamList.ql e1e7b9b5062f936c33b7e7e29b21456448242df4985c6cffb54900063cfd3e63 6568e851cb6bcb32622f89d01e3aa6e7dd21940d21572a9988584e34bdf25366 -test/extractor-tests/generated/PathSegment/PathSegment_getPathType.ql 01942da6d0b10c1d15caec6abb8c53f1dc7f8c04a91a797f572063aa003dbc4b cb21e6cb160652527ba571265297dae86beffe191dd7dfc4d0beee45cb0cda29 -test/extractor-tests/generated/PathSegment/PathSegment_getRetType.ql 36386a514bc925f5b17ad87afba9fef7986900c1b791732de061213c6e86743f f38bcee68c1da19e70bb1e1c4a4047c763a466f1b8ef2c4f65f8c724c0b58197 -test/extractor-tests/generated/PathSegment/PathSegment_getReturnTypeSyntax.ql d1db51208a311c30af369ce2fdc3a3296e7d598b27bf4960b8b34622a9d9163b 561b1e38c6d8b301fdc016e1d012dd805fde1b42b0720c17d7b15535715047f2 -test/extractor-tests/generated/PathSegment/PathSegment_getTy.ql a0ceaf3f37e521cc92c21cc0bae929499ef3584f86349ef34808c20963d31c75 d674e56e08a6d2a7d211503a466df2cc90c35a3951e41598febf62c8dc693655 -test/extractor-tests/generated/PathType/PathType.ql cb67b05cf7e4f32cbd46ac89a15f6eafe3507cc655db0b9d54a1cf8e7fbcca40 890053e7fd8cd8a92015c09588c7c646f075901cddc3eb8d57210b02b23a5944 -test/extractor-tests/generated/PathType/PathType_getPath.ql 7043c7939e4f835e4b2c7e3e207637c362d7a9dbdba0151b38c873fdaf43e7a5 ee2aad1b4fb2b00e1a5d39387848aa164a39e3cd49141f07c175b205c8451bb1 test/extractor-tests/generated/PrefixExpr/PrefixExpr.ql 44fb7174365c6deecdc22c720d84617c6e060c05d49c41c90433451588f8aa6f 871fab471c82fede3c36edc003f9decee5bb7844c016951d28be78d0c91487e5 test/extractor-tests/generated/PrefixExpr/PrefixExpr_getAttr.ql fdad6ad5199435ded1e4a9ea6b246e76b904cd73a36aaa4780e84eef91741c5b 75d63940046e62c1efa1151b0cac45b5ec0bab5e39aec2e11d43f6c385e37984 test/extractor-tests/generated/PrefixExpr/PrefixExpr_getExpr.ql 2d1d97f6277794871fbb032ea87ac30b1aa902a74cd874720156162057ea202e b1b9880fce07d66df7ec87f12189c37adf9f233a1d0b38a1b09808d052a95642 @@ -1006,7 +978,7 @@ test/extractor-tests/generated/ReturnExpr/ReturnExpr.ql 8e9eba0837a466255e8e249e test/extractor-tests/generated/ReturnExpr/ReturnExpr_getAttr.ql 9fb7e1c79798e4f42e18785f3af17ea75f901a36abf9beb47a1eede69c613ba9 9cdb7cc4a4742865f6c92357973f84cee9229f55ff28081e5d17b6d57d6d275f test/extractor-tests/generated/ReturnExpr/ReturnExpr_getExpr.ql 7d4562efb0d26d92d11f03a0ef80338eb7d5a0c073f1f09cbb8a826f0cef33de 523ebd51b97f957afaf497e5a4d27929eed18e1d276054e3d5a7c5cfe7285c6e test/extractor-tests/generated/ReturnTypeSyntax/ReturnTypeSyntax.ql 976ce33fe3fd34aae2028a11b4accdee122b6d82d07722488c3239f0d2c14609 906bf8c8e7769a1052196bc78947b655158dd3b2903fef2802e2031cffbc1d78 -test/extractor-tests/generated/SelfParam/SelfParam.ql d051c7a2dd88382e37895f1d691f2702aed7f925d3936f51d49949463e4757c8 37f1f429093be7923a55f8b4f46b37bbf71d0dff3843c4d3686383c2863dee1a +test/extractor-tests/generated/SelfParam/SelfParam.ql 12ad3244a2700e13a84603d6992f0c872572bca68d25515a7a9414b3c96a62e0 70028e344bc4ab2937f391f1fd8afd1549935aa621ce2cb9944da6a1dcf4be27 test/extractor-tests/generated/SelfParam/SelfParam_getAttr.ql 00dd5409c07e9a7b5dc51c1444e24b35d2ac3cab11320396ef70f531a3b65dc0 effbed79ad530a835e85b931389a0c8609a10ee035cb694f2e39b8539f8e54ba test/extractor-tests/generated/SelfParam/SelfParam_getLifetime.ql 0b7c243f609e005dd63fd1b3b9f0096fc13cb98fe113e6f3fefb0d5c414e9a5f f6e06de8bcddfc9bd978c058079e53174edbe7b39f18df3c0bd4e80486808eda test/extractor-tests/generated/SelfParam/SelfParam_getName.ql 69207a57b415ba590e50003d506a64fd1780b27b8832b14f9bd3c909bddb5593 56fa28ba1222f45893237052fa5a9421d960e14fbf1396b2d1049b440c2e5abe @@ -1127,9 +1099,11 @@ test/extractor-tests/generated/UseTree/UseTree_getRename.ql ec3917501f3c89ac4974 test/extractor-tests/generated/UseTree/UseTree_getUseTreeList.ql c265a88347e813840969ae934dfd2904bc06f502de77709bc0b1c7255e46382a 52a239c8ea5fd8fbfbd606559d70ecadc769887437a9bcab6fb3e774208ad868 test/extractor-tests/generated/UseTreeList/UseTreeList.ql cd943c15c86e66244caafeb95b960a5c3d351d5edbd506258744fb60a61af3b2 cfa584cd9d8aa08267fd1106745a66226b2c99fadd1da65059cc7ecf2f2e68cf test/extractor-tests/generated/UseTreeList/UseTreeList_getUseTree.ql dd72966b1cb7b04f0267503013809063fcfb145e2b2d7d5250d9f24d2e405f9a 75b953aa11c51ca0fe95e67d50d6238962d8df4a4b9054999a2c6338e5a5613d -test/extractor-tests/generated/Variant/Variant.ql bf9b928ab3b1911e6c81fdc3fb9811e754ea28bfd0e4a21dca08b844aa42c3f1 bffd4bcc5019f721010722453985b39a4285240774e474e233ebe46f1cd5beb1 +test/extractor-tests/generated/Variant/Variant.ql c60dd31adac91e09f8b1e5523d6b859747e64ef072c077b5a3326763f9f461f7 55d6446a3a831ed1137264678c5df027eb94cb3570a88d364994851fe6236999 test/extractor-tests/generated/Variant/Variant_getAttr.ql dd38e48e1eb05ce280b880652a90010eb63f7de3be7232411ba6265691249420 f8980680104de1e5fd40f264d8d62346aacaf6403a5e051f6fd680e234c82c1f +test/extractor-tests/generated/Variant/Variant_getCrateOrigin.ql 99e79930f8ff87a25f256926e5c3ce1ee0847daf6fadc5445fb33c85328b4c61 2dd64a53813790654c83be25b5e175c9c5b388e758723c2138fff095353fdd7b test/extractor-tests/generated/Variant/Variant_getExpr.ql ce00af303d28f60c5fd1dc7df628c7974aced21884e223a2f656cb4f0d1a74d5 9de51a65510cf9a15801d4207b616915bd959c95ec7330fdb502c5dff5b650cc +test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.ql fe6a4bfd1440e7629d47283910de84c5e8c2f5645512780e710f53540b5bc886 b1e31b765cb1a5fe063abb8c1b2115e881ae28aa3ccd39e088ff8f2af20d6cf4 test/extractor-tests/generated/Variant/Variant_getFieldList.ql 083c8cf61989663de33d99b72dec231c308ccc8bb6739921465c473a07e8ea03 d03bff6945853c940acdc053b813d53b008ddab9a8bd4307826433828d4763ce test/extractor-tests/generated/Variant/Variant_getName.ql 0d7b47bec9f9031c67f7b684112a84a311ef9b2efeb260bd7cd6f424011ca0d8 73565e6f965dd7fd7bb9b3408c7d7b69120e1971b67ab307fed293eb663a59ae test/extractor-tests/generated/Variant/Variant_getVisibility.ql 2c8f365d28d96af55589f4d71ac3fee718b319b4cbc784560c0591d1f605a119 13160d9cf39fe169410eff6c338f5d063e1948109e8f18dd33ea0064f1dd9283 @@ -1144,7 +1118,7 @@ test/extractor-tests/generated/WherePred/WherePred_getGenericParamList.ql 21c3aa test/extractor-tests/generated/WherePred/WherePred_getLifetime.ql e08d9d6cccf634746f42a6ee583bbb3e7e9a9edbb63242e73b2bff4463df55d8 139543750c18f88d9c1ad2cdbcf1699d597cf2264bbb6b02a7e5792444e277ef test/extractor-tests/generated/WherePred/WherePred_getTy.ql 34cee0335bbaf8946fe15e3c32449150d07a730fcca56b4faed554fbb8689e21 883976c8c27c276c402d591ebd89d076c2c4d8da4d4f738f3c860c34d4a03b97 test/extractor-tests/generated/WherePred/WherePred_getTypeBoundList.ql c78e31ff4d1822a6b76f403e5ccb8f5529b4f784e14e618833df0378adca55fc 8bb1c9b5a1cfca0f5e8335464f7439aa098063176fbd3edbaf3407169f1899e6 -test/extractor-tests/generated/WhileExpr/WhileExpr.ql e061fac7584adf999d31ed0785041e2cc14b26a1c9901281f90c859335d8f614 fb1e597e28841e3b2d275d697aa6de7158db51b70a348d634291a75b25e4e80a +test/extractor-tests/generated/WhileExpr/WhileExpr.ql 61c49414f2ed786a68b79bd9a77093e4086457edb6c136cf8a94f2ac830c2f5b 7737f724a297d011c12143e009a63926812c63c08a1067b03e8677697ab00f83 test/extractor-tests/generated/WhileExpr/WhileExpr_getAttr.ql f8527130eb2492743c0e629c97db291abcefe3d35302c840fee327ab0d8f10fd b41bedd429e5566fd68a50140ff1f50b51e2c7c351cbc8253fbc126527073f7e test/extractor-tests/generated/WhileExpr/WhileExpr_getCondition.ql 84a021806423425b24eaeb9fb9967a6aadabe823c24e77a0dfefcb3509041597 147aa8bbe4dbf9b90be2467db8207dc96aed281e722eb6b9c998442a90911a6c test/extractor-tests/generated/WhileExpr/WhileExpr_getLabel.ql 60ef4de57d85c7df23c0518b944b3839a9b2478044326829b5bf709a8c8d7240 3916e9ff50733c58afdc09837339b72a555a043f92f1c4e09e1652866029b017 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index a532f142ec98..26c3d123a377 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -1,6 +1,8 @@ /.generated.list linguist-generated /.gitattributes linguist-generated +/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll linguist-generated /lib/codeql/rust/elements/Abi.qll linguist-generated +/lib/codeql/rust/elements/Addressable.qll linguist-generated /lib/codeql/rust/elements/ArgList.qll linguist-generated /lib/codeql/rust/elements/ArrayExpr.qll linguist-generated /lib/codeql/rust/elements/ArrayType.qll linguist-generated @@ -61,6 +63,7 @@ /lib/codeql/rust/elements/Item.qll linguist-generated /lib/codeql/rust/elements/ItemList.qll linguist-generated /lib/codeql/rust/elements/Label.qll linguist-generated +/lib/codeql/rust/elements/LabelableExpr.qll linguist-generated /lib/codeql/rust/elements/LetElse.qll linguist-generated /lib/codeql/rust/elements/LetExpr.qll linguist-generated /lib/codeql/rust/elements/LetStmt.qll linguist-generated @@ -71,6 +74,7 @@ /lib/codeql/rust/elements/LiteralPat.qll linguist-generated /lib/codeql/rust/elements/Locatable.qll linguist-generated /lib/codeql/rust/elements/LoopExpr.qll linguist-generated +/lib/codeql/rust/elements/LoopingExpr.qll linguist-generated /lib/codeql/rust/elements/MacroCall.qll linguist-generated /lib/codeql/rust/elements/MacroDef.qll linguist-generated /lib/codeql/rust/elements/MacroExpr.qll linguist-generated @@ -93,6 +97,7 @@ /lib/codeql/rust/elements/OffsetOfExpr.qll linguist-generated /lib/codeql/rust/elements/OrPat.qll linguist-generated /lib/codeql/rust/elements/Param.qll linguist-generated +/lib/codeql/rust/elements/ParamBase.qll linguist-generated /lib/codeql/rust/elements/ParamList.qll linguist-generated /lib/codeql/rust/elements/ParenExpr.qll linguist-generated /lib/codeql/rust/elements/ParenPat.qll linguist-generated @@ -168,10 +173,10 @@ /lib/codeql/rust/elements/YieldExpr.qll linguist-generated /lib/codeql/rust/elements/internal/AbiConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/AbiImpl.qll linguist-generated +/lib/codeql/rust/elements/internal/AddressableImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ArgListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ArgListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ArrayExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ArrayExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ArrayTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ArrayTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/AsmExprConstructor.qll linguist-generated @@ -184,25 +189,19 @@ /lib/codeql/rust/elements/internal/AttrConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/AttrImpl.qll linguist-generated /lib/codeql/rust/elements/internal/AwaitExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/AwaitExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/BecomeExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/BecomeExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/BinaryExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/BlockExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/BlockExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/BoxPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/BoxPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/BreakExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/CallExprBaseImpl.qll linguist-generated /lib/codeql/rust/elements/internal/CallExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/CallExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/CallableImpl.qll linguist-generated /lib/codeql/rust/elements/internal/CastExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/CastExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ClosureBinderConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ClosureBinderImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ClosureExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ClosureExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/CommentConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ConstArgConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ConstArgImpl.qll linguist-generated @@ -216,7 +215,6 @@ /lib/codeql/rust/elements/internal/DynTraitTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/DynTraitTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/EnumConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/EnumImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ExprStmtConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ExprStmtImpl.qll linguist-generated @@ -228,12 +226,10 @@ /lib/codeql/rust/elements/internal/ExternItemListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ExternItemListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FieldExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FieldExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FieldListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FnPtrTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/FnPtrTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ForExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ForExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ForTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ForTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll linguist-generated @@ -242,45 +238,33 @@ /lib/codeql/rust/elements/internal/FunctionConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/GenericArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/GenericArgListConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/GenericArgListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/GenericParamImpl.qll linguist-generated /lib/codeql/rust/elements/internal/GenericParamListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/GenericParamListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/IdentPatConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/IfExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/IfExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ImplConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ImplImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ImplTraitTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ImplTraitTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/IndexExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/IndexExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/InferTypeConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/InferTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ItemImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ItemListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ItemListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LabelConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LabelImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LetElseConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LetElseImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LetExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LetExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LetStmtConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LetStmtImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LifetimeArgConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/LifetimeArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LifetimeConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LifetimeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LifetimeParamConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/LifetimeParamImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LiteralExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/LiteralPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LiteralPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/LoopExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/LoopExprImpl.qll linguist-generated +/lib/codeql/rust/elements/internal/LoopingExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MacroCallConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/MacroCallImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MacroDefConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MacroDefImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MacroExprConstructor.qll linguist-generated @@ -296,7 +280,6 @@ /lib/codeql/rust/elements/internal/MacroTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MacroTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MatchArmConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/MatchArmImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MatchArmListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MatchArmListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/MatchExprConstructor.qll linguist-generated @@ -308,46 +291,35 @@ /lib/codeql/rust/elements/internal/MissingConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/MissingImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ModuleConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ModuleImpl.qll linguist-generated /lib/codeql/rust/elements/internal/NameConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/NameRefConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/NeverTypeConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/NeverTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/OffsetOfExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/OffsetOfExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/OrPatConstructor.qll linguist-generated +/lib/codeql/rust/elements/internal/ParamBaseImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParamConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ParamImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParamListConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ParamListImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParenExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ParenExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParenPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ParenPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ParenTypeConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ParenTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/PatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/PathConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/PathExprBaseImpl.qll linguist-generated /lib/codeql/rust/elements/internal/PathExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/PathPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/PathPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/PathSegmentConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/PathTypeConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/PathTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/PrefixExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/PtrTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/PtrTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RangeExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/RangeExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RangePatConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RangePatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RecordExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RecordExprFieldConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/RecordExprFieldImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RecordExprFieldListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RecordExprFieldListImpl.qll linguist-generated -/lib/codeql/rust/elements/internal/RecordExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RecordFieldConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RecordFieldImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RecordFieldListConstructor.qll linguist-generated @@ -357,22 +329,17 @@ /lib/codeql/rust/elements/internal/RecordPatFieldImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RecordPatFieldListConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RecordPatFieldListImpl.qll linguist-generated -/lib/codeql/rust/elements/internal/RecordPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RefExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/RefExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RefPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/RefPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RefTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RefTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RenameConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RenameImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ResolvableImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RestPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/RestPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/RetTypeConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/RetTypeImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ReturnExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/ReturnExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/ReturnTypeSyntaxConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/ReturnTypeSyntaxImpl.qll linguist-generated /lib/codeql/rust/elements/internal/SelfParamConstructor.qll linguist-generated @@ -396,7 +363,6 @@ /lib/codeql/rust/elements/internal/TraitAliasConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/TraitAliasImpl.qll linguist-generated /lib/codeql/rust/elements/internal/TraitConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/TraitImpl.qll linguist-generated /lib/codeql/rust/elements/internal/TryExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/TryExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/TupleExprConstructor.qll linguist-generated @@ -423,12 +389,10 @@ /lib/codeql/rust/elements/internal/TypeParamImpl.qll linguist-generated /lib/codeql/rust/elements/internal/TypeRefImpl.qll linguist-generated /lib/codeql/rust/elements/internal/UnderscoreExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/UnderscoreExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/UnextractedImpl.qll linguist-generated /lib/codeql/rust/elements/internal/UnimplementedConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/UnimplementedImpl.qll linguist-generated /lib/codeql/rust/elements/internal/UnionConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/UnionImpl.qll linguist-generated /lib/codeql/rust/elements/internal/UseConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/UseImpl.qll linguist-generated /lib/codeql/rust/elements/internal/UseTreeConstructor.qll linguist-generated @@ -446,14 +410,13 @@ /lib/codeql/rust/elements/internal/WherePredConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/WherePredImpl.qll linguist-generated /lib/codeql/rust/elements/internal/WhileExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/WhileExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/WildcardPatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/WildcardPatImpl.qll linguist-generated /lib/codeql/rust/elements/internal/YeetExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/YeetExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/YieldExprConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/YieldExprImpl.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Abi.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/Addressable.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ArgList.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ArrayExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ArrayType.qll linguist-generated @@ -514,6 +477,7 @@ /lib/codeql/rust/elements/internal/generated/Item.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ItemList.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Label.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/LabelableExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/LetElse.qll linguist-generated /lib/codeql/rust/elements/internal/generated/LetExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/LetStmt.qll linguist-generated @@ -524,6 +488,7 @@ /lib/codeql/rust/elements/internal/generated/LiteralPat.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Locatable.qll linguist-generated /lib/codeql/rust/elements/internal/generated/LoopExpr.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/LoopingExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroCall.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroDef.qll linguist-generated /lib/codeql/rust/elements/internal/generated/MacroExpr.qll linguist-generated @@ -546,6 +511,7 @@ /lib/codeql/rust/elements/internal/generated/OffsetOfExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/OrPat.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Param.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/ParamBase.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ParamList.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ParenExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ParenPat.qll linguist-generated @@ -673,7 +639,7 @@ /test/extractor-tests/generated/CallExpr/CallExpr.ql linguist-generated /test/extractor-tests/generated/CallExpr/CallExpr_getArgList.ql linguist-generated /test/extractor-tests/generated/CallExpr/CallExpr_getAttr.ql linguist-generated -/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql linguist-generated +/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql linguist-generated /test/extractor-tests/generated/CastExpr/CastExpr.ql linguist-generated /test/extractor-tests/generated/CastExpr/CastExpr_getAttr.ql linguist-generated /test/extractor-tests/generated/CastExpr/CastExpr_getExpr.ql linguist-generated @@ -753,13 +719,19 @@ /test/extractor-tests/generated/ForType/ForType.ql linguist-generated /test/extractor-tests/generated/ForType/ForType_getGenericParamList.ql linguist-generated /test/extractor-tests/generated/ForType/ForType_getTy.ql linguist-generated -/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.ql linguist-generated -/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.ql linguist-generated -/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/Format.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.ql linguist-generated /test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql linguist-generated /test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.ql linguist-generated /test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getAttr.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql linguist-generated /test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql linguist-generated +/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql linguist-generated /test/extractor-tests/generated/Function/Function.ql linguist-generated /test/extractor-tests/generated/Function/Function_getAbi.ql linguist-generated /test/extractor-tests/generated/Function/Function_getAttr.ql linguist-generated @@ -811,8 +783,8 @@ /test/extractor-tests/generated/LetElse/LetElse_getBlockExpr.ql linguist-generated /test/extractor-tests/generated/LetExpr/LetExpr.ql linguist-generated /test/extractor-tests/generated/LetExpr/LetExpr_getAttr.ql linguist-generated -/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql linguist-generated /test/extractor-tests/generated/LetExpr/LetExpr_getPat.ql linguist-generated +/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql linguist-generated /test/extractor-tests/generated/LetStmt/LetStmt.ql linguist-generated /test/extractor-tests/generated/LetStmt/LetStmt_getAttr.ql linguist-generated /test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.ql linguist-generated @@ -879,8 +851,8 @@ /test/extractor-tests/generated/MatchArmList/MatchArmList_getAttr.ql linguist-generated /test/extractor-tests/generated/MatchExpr/MatchExpr.ql linguist-generated /test/extractor-tests/generated/MatchExpr/MatchExpr_getAttr.ql linguist-generated -/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.ql linguist-generated /test/extractor-tests/generated/MatchExpr/MatchExpr_getMatchArmList.ql linguist-generated +/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.ql linguist-generated /test/extractor-tests/generated/MatchGuard/MatchGuard.ql linguist-generated /test/extractor-tests/generated/MatchGuard/MatchGuard_getCondition.ql linguist-generated /test/extractor-tests/generated/Meta/Meta.ql linguist-generated @@ -928,25 +900,25 @@ /test/extractor-tests/generated/ParenType/ParenType.ql linguist-generated /test/extractor-tests/generated/ParenType/ParenType_getTy.ql linguist-generated /test/extractor-tests/generated/Path/Path.ql linguist-generated +/test/extractor-tests/generated/Path/PathExpr.ql linguist-generated +/test/extractor-tests/generated/Path/PathExpr_getAttr.ql linguist-generated +/test/extractor-tests/generated/Path/PathExpr_getPath.ql linguist-generated +/test/extractor-tests/generated/Path/PathPat.ql linguist-generated +/test/extractor-tests/generated/Path/PathPat_getPath.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getGenericArgList.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getNameRef.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getParamList.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getPathType.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getRetType.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getReturnTypeSyntax.ql linguist-generated +/test/extractor-tests/generated/Path/PathSegment_getTy.ql linguist-generated +/test/extractor-tests/generated/Path/PathType.ql linguist-generated +/test/extractor-tests/generated/Path/PathType_getPath.ql linguist-generated /test/extractor-tests/generated/Path/Path_getPart.ql linguist-generated /test/extractor-tests/generated/Path/Path_getQualifier.ql linguist-generated /test/extractor-tests/generated/Path/Path_getResolvedCrateOrigin.ql linguist-generated /test/extractor-tests/generated/Path/Path_getResolvedPath.ql linguist-generated -/test/extractor-tests/generated/PathExpr/PathExpr.ql linguist-generated -/test/extractor-tests/generated/PathExpr/PathExpr_getAttr.ql linguist-generated -/test/extractor-tests/generated/PathExpr/PathExpr_getPath.ql linguist-generated -/test/extractor-tests/generated/PathPat/PathPat.ql linguist-generated -/test/extractor-tests/generated/PathPat/PathPat_getPath.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getGenericArgList.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getParamList.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getPathType.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getRetType.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getReturnTypeSyntax.ql linguist-generated -/test/extractor-tests/generated/PathSegment/PathSegment_getTy.ql linguist-generated -/test/extractor-tests/generated/PathType/PathType.ql linguist-generated -/test/extractor-tests/generated/PathType/PathType_getPath.ql linguist-generated /test/extractor-tests/generated/PrefixExpr/PrefixExpr.ql linguist-generated /test/extractor-tests/generated/PrefixExpr/PrefixExpr_getAttr.ql linguist-generated /test/extractor-tests/generated/PrefixExpr/PrefixExpr_getExpr.ql linguist-generated @@ -1131,7 +1103,9 @@ /test/extractor-tests/generated/UseTreeList/UseTreeList_getUseTree.ql linguist-generated /test/extractor-tests/generated/Variant/Variant.ql linguist-generated /test/extractor-tests/generated/Variant/Variant_getAttr.ql linguist-generated +/test/extractor-tests/generated/Variant/Variant_getCrateOrigin.ql linguist-generated /test/extractor-tests/generated/Variant/Variant_getExpr.ql linguist-generated +/test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.ql linguist-generated /test/extractor-tests/generated/Variant/Variant_getFieldList.ql linguist-generated /test/extractor-tests/generated/Variant/Variant_getName.ql linguist-generated /test/extractor-tests/generated/Variant/Variant_getVisibility.ql linguist-generated diff --git a/rust/ql/integration-tests/hello-project/functions.expected b/rust/ql/integration-tests/hello-project/functions.expected index fc49564084e3..2665ea7df769 100644 --- a/rust/ql/integration-tests/hello-project/functions.expected +++ b/rust/ql/integration-tests/hello-project/functions.expected @@ -1 +1 @@ -| src/main.rs:4:1:6:1 | main | +| src/main.rs:4:1:6:1 | fn main | diff --git a/rust/ql/integration-tests/hello-workspace/functions.expected b/rust/ql/integration-tests/hello-workspace/functions.expected index 0ec9937972e2..0633774edf73 100644 --- a/rust/ql/integration-tests/hello-workspace/functions.expected +++ b/rust/ql/integration-tests/hello-workspace/functions.expected @@ -1,2 +1,2 @@ -| exe/src/main.rs:5:1:7:1 | main | -| lib/src/a_module/mod.rs:1:1:3:1 | hello | +| exe/src/main.rs:5:1:7:1 | fn main | +| lib/src/a_module/mod.rs:1:1:3:1 | fn hello | diff --git a/rust/ql/integration-tests/options/cfg/functions.expected b/rust/ql/integration-tests/options/cfg/functions.expected index a2042c5e4c49..cd022ca510e0 100644 --- a/rust/ql/integration-tests/options/cfg/functions.expected +++ b/rust/ql/integration-tests/options/cfg/functions.expected @@ -1,3 +1,3 @@ -| src/lib.rs:7:1:8:19 | cfg_no_flag | -| src/lib.rs:10:1:11:18 | cfg_no_key | -| src/lib.rs:16:1:17:24 | pointer_width_64 | +| src/lib.rs:7:1:8:19 | fn cfg_no_flag | +| src/lib.rs:10:1:11:18 | fn cfg_no_key | +| src/lib.rs:16:1:17:24 | fn pointer_width_64 | diff --git a/rust/ql/integration-tests/options/cfg/functions.override.expected b/rust/ql/integration-tests/options/cfg/functions.override.expected index 4a19db56a741..34feddaf1490 100644 --- a/rust/ql/integration-tests/options/cfg/functions.override.expected +++ b/rust/ql/integration-tests/options/cfg/functions.override.expected @@ -1,4 +1,4 @@ -| src/lib.rs:1:1:2:16 | cfg_flag | -| src/lib.rs:4:1:5:15 | cfg_key | -| src/lib.rs:13:1:14:12 | test | -| src/lib.rs:19:1:20:24 | pointer_width_32 | +| src/lib.rs:1:1:2:16 | fn cfg_flag | +| src/lib.rs:4:1:5:15 | fn cfg_key | +| src/lib.rs:13:1:14:12 | fn test | +| src/lib.rs:19:1:20:24 | fn pointer_width_32 | diff --git a/rust/ql/integration-tests/options/features/functions.all.expected b/rust/ql/integration-tests/options/features/functions.all.expected index 5ce4cae2ab0d..1fa14be6da60 100644 --- a/rust/ql/integration-tests/options/features/functions.all.expected +++ b/rust/ql/integration-tests/options/features/functions.all.expected @@ -1,3 +1,3 @@ -| src/lib.rs:1:1:2:11 | foo | -| src/lib.rs:4:1:5:11 | bar | -| src/lib.rs:7:1:7:14 | always | +| src/lib.rs:1:1:2:11 | fn foo | +| src/lib.rs:4:1:5:11 | fn bar | +| src/lib.rs:7:1:7:14 | fn always | diff --git a/rust/ql/integration-tests/options/features/functions.bar.expected b/rust/ql/integration-tests/options/features/functions.bar.expected index cad441d6749b..fae918e493a3 100644 --- a/rust/ql/integration-tests/options/features/functions.bar.expected +++ b/rust/ql/integration-tests/options/features/functions.bar.expected @@ -1,2 +1,2 @@ -| src/lib.rs:4:1:5:11 | bar | -| src/lib.rs:7:1:7:14 | always | +| src/lib.rs:4:1:5:11 | fn bar | +| src/lib.rs:7:1:7:14 | fn always | diff --git a/rust/ql/integration-tests/options/features/functions.expected b/rust/ql/integration-tests/options/features/functions.expected index 523c21876884..d095a8993d8a 100644 --- a/rust/ql/integration-tests/options/features/functions.expected +++ b/rust/ql/integration-tests/options/features/functions.expected @@ -1 +1 @@ -| src/lib.rs:7:1:7:14 | always | +| src/lib.rs:7:1:7:14 | fn always | diff --git a/rust/ql/integration-tests/options/features/functions.foo.expected b/rust/ql/integration-tests/options/features/functions.foo.expected index b78754230833..3768144364f3 100644 --- a/rust/ql/integration-tests/options/features/functions.foo.expected +++ b/rust/ql/integration-tests/options/features/functions.foo.expected @@ -1,2 +1,2 @@ -| src/lib.rs:1:1:2:11 | foo | -| src/lib.rs:7:1:7:14 | always | +| src/lib.rs:1:1:2:11 | fn foo | +| src/lib.rs:7:1:7:14 | fn always | diff --git a/rust/ql/integration-tests/options/target/functions.Darwin.expected b/rust/ql/integration-tests/options/target/functions.Darwin.expected index 217974bb7c63..8b879e8ca7c7 100644 --- a/rust/ql/integration-tests/options/target/functions.Darwin.expected +++ b/rust/ql/integration-tests/options/target/functions.Darwin.expected @@ -1 +1 @@ -| src/lib.rs:7:1:8:13 | macos | +| src/lib.rs:7:1:8:13 | fn macos | diff --git a/rust/ql/integration-tests/options/target/functions.Linux.expected b/rust/ql/integration-tests/options/target/functions.Linux.expected index 57662579f1f5..2e023fb887c0 100644 --- a/rust/ql/integration-tests/options/target/functions.Linux.expected +++ b/rust/ql/integration-tests/options/target/functions.Linux.expected @@ -1 +1 @@ -| src/lib.rs:1:1:2:13 | linux | +| src/lib.rs:1:1:2:13 | fn linux | diff --git a/rust/ql/integration-tests/options/target/functions.Windows.expected b/rust/ql/integration-tests/options/target/functions.Windows.expected index 8ae2d8c86ccf..170a6e62e80e 100644 --- a/rust/ql/integration-tests/options/target/functions.Windows.expected +++ b/rust/ql/integration-tests/options/target/functions.Windows.expected @@ -1 +1 @@ -| src/lib.rs:4:1:5:15 | windows | +| src/lib.rs:4:1:5:15 | fn windows | diff --git a/rust/ql/integration-tests/qltest/dependencies/functions.expected b/rust/ql/integration-tests/qltest/dependencies/functions.expected deleted file mode 100644 index c062595f9237..000000000000 --- a/rust/ql/integration-tests/qltest/dependencies/functions.expected +++ /dev/null @@ -1 +0,0 @@ -| test.rs:4:1:7:1 | foo | diff --git a/rust/ql/integration-tests/qltest/dependencies/functions.nested.expected b/rust/ql/integration-tests/qltest/dependencies/functions.nested.expected new file mode 100644 index 000000000000..9ee4b080b97e --- /dev/null +++ b/rust/ql/integration-tests/qltest/dependencies/functions.nested.expected @@ -0,0 +1 @@ +| test.rs:4:1:7:1 | fn foo | diff --git a/rust/ql/integration-tests/qltest/lib/functions.expected b/rust/ql/integration-tests/qltest/lib/functions.expected deleted file mode 100644 index 613d53954dcc..000000000000 --- a/rust/ql/integration-tests/qltest/lib/functions.expected +++ /dev/null @@ -1 +0,0 @@ -| test.rs:1:1:1:11 | foo | diff --git a/rust/ql/integration-tests/qltest/lib/functions.nested.expected b/rust/ql/integration-tests/qltest/lib/functions.nested.expected new file mode 100644 index 000000000000..74d1d680dae3 --- /dev/null +++ b/rust/ql/integration-tests/qltest/lib/functions.nested.expected @@ -0,0 +1 @@ +| test.rs:1:1:1:11 | fn foo | diff --git a/rust/ql/integration-tests/qltest/main/functions.expected b/rust/ql/integration-tests/qltest/main/functions.expected deleted file mode 100644 index 9d3631034191..000000000000 --- a/rust/ql/integration-tests/qltest/main/functions.expected +++ /dev/null @@ -1,2 +0,0 @@ -| main.rs:1:1:1:12 | main | -| test.rs:1:1:1:11 | foo | diff --git a/rust/ql/integration-tests/qltest/main/functions.nested.expected b/rust/ql/integration-tests/qltest/main/functions.nested.expected new file mode 100644 index 000000000000..fc9c578919ce --- /dev/null +++ b/rust/ql/integration-tests/qltest/main/functions.nested.expected @@ -0,0 +1,2 @@ +| main.rs:1:1:1:12 | fn main | +| test.rs:1:1:1:11 | fn foo | diff --git a/rust/ql/integration-tests/qltest/test.py b/rust/ql/integration-tests/qltest/test_qltest.py similarity index 84% rename from rust/ql/integration-tests/qltest/test.py rename to rust/ql/integration-tests/qltest/test_qltest.py index e488dee25717..edd62bf600ef 100644 --- a/rust/ql/integration-tests/qltest/test.py +++ b/rust/ql/integration-tests/qltest/test_qltest.py @@ -11,10 +11,12 @@ def default_options(codeql): threads = 1, show_extractor_output = True, check_databases = False, + learn = True, ) @pytest.mark.parametrize("dir", ["lib", "main", "dependencies"]) -def test(codeql, rust, dir): +def test(codeql, rust, expected_files, dir): + expected_files.add(f"{dir}/functions.expected", expected=".nested.expected") codeql.test.run(dir) def test_failing_cargo_check(codeql, rust): diff --git a/rust/ql/lib/codeql/rust/AstConsistency.qll b/rust/ql/lib/codeql/rust/AstConsistency.qll index dbb7f7216d72..3902f56d20ba 100644 --- a/rust/ql/lib/codeql/rust/AstConsistency.qll +++ b/rust/ql/lib/codeql/rust/AstConsistency.qll @@ -10,8 +10,9 @@ private predicate multipleToStrings(Element e) { strictcount(e.toString()) > 1 } /** * Holds if `e` has more than one `toString()` result. */ -query predicate multipleToStrings(Element e, string s) { +query predicate multipleToStrings(Element e, string cls, string s) { multipleToStrings(e) and + cls = e.getPrimaryQlClasses() and s = strictconcat(e.toString(), ", ") } @@ -39,9 +40,11 @@ private predicate multipleParents(Element child) { strictcount(getParent(child)) /** * Holds if `child` has more than one AST parent. */ -query predicate multipleParents(Element child, Element parent) { +query predicate multipleParents(Element child, string childClass, Element parent, string parentClass) { multipleParents(child) and - parent = getParent(child) + childClass = child.getPrimaryQlClasses() and + parent = getParent(child) and + parentClass = parent.getPrimaryQlClasses() } /** diff --git a/rust/ql/lib/codeql/rust/Concepts.qll b/rust/ql/lib/codeql/rust/Concepts.qll new file mode 100644 index 000000000000..9369668923f8 --- /dev/null +++ b/rust/ql/lib/codeql/rust/Concepts.qll @@ -0,0 +1,174 @@ +/** + * Provides abstract classes representing generic concepts such as file system + * access or system command execution, for which individual framework libraries + * provide concrete subclasses. + */ + +private import codeql.rust.dataflow.DataFlow +private import codeql.threatmodels.ThreatModels +private import codeql.rust.Frameworks + +/** + * A data flow source for a specific threat-model. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `ThreatModelSource::Range` instead. + */ +final class ThreatModelSource = ThreatModelSource::Range; + +/** + * Provides a class for modeling new sources for specific threat-models. + */ +module ThreatModelSource { + /** + * A data flow source, for a specific threat-model. + */ + abstract class Range extends DataFlow::Node { + /** + * Gets a string that represents the source kind with respect to threat modeling. + * + * See + * - https://github.com/github/codeql/blob/main/docs/codeql/reusables/threat-model-description.rst + * - https://github.com/github/codeql/blob/main/shared/threat-models/ext/threat-model-grouping.model.yml + */ + abstract string getThreatModel(); + + /** + * Gets a string that describes the type of this threat-model source. + */ + abstract string getSourceType(); + } +} + +/** + * A data flow source that is enabled in the current threat model configuration. + */ +class ActiveThreatModelSource extends ThreatModelSource { + ActiveThreatModelSource() { currentThreatModel(this.getThreatModel()) } +} + +/** + * A data flow source corresponding to the program's command line arguments or path. + */ +final class CommandLineArgsSource = CommandLineArgsSource::Range; + +/** + * Provides a class for modeling new sources for the program's command line arguments or path. + */ +module CommandLineArgsSource { + /** + * A data flow source corresponding to the program's command line arguments or path. + */ + abstract class Range extends ThreatModelSource::Range { + override string getThreatModel() { result = "commandargs" } + + override string getSourceType() { result = "CommandLineArgs" } + } +} + +/** + * A data flow source corresponding to the program's environment. + */ +final class EnvironmentSource = EnvironmentSource::Range; + +/** + * Provides a class for modeling new sources for the program's environment. + */ +module EnvironmentSource { + /** + * A data flow source corresponding to the program's environment. + */ + abstract class Range extends ThreatModelSource::Range { + override string getThreatModel() { result = "environment" } + + override string getSourceType() { result = "EnvironmentSource" } + } +} + +/** + * A data flow source for remote (network) data. + */ +final class RemoteSource = RemoteSource::Range; + +/** + * Provides a class for modeling new sources of remote (network) data. + */ +module RemoteSource { + /** + * A data flow source for remote (network) data. + */ + abstract class Range extends ThreatModelSource::Range { + override string getThreatModel() { result = "remote" } + + override string getSourceType() { result = "RemoteSource" } + } +} + +/** + * A data-flow node that constructs a SQL statement. + * + * Often, it is worthy of an alert if a SQL statement is constructed such that + * executing it would be a security risk. + * + * If it is important that the SQL statement is executed, use `SqlExecution`. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `SqlConstruction::Range` instead. + */ +final class SqlConstruction = SqlConstruction::Range; + +/** + * Provides a class for modeling new SQL execution APIs. + */ +module SqlConstruction { + /** + * A data-flow node that constructs a SQL statement. + */ + abstract class Range extends DataFlow::Node { + /** + * Gets the argument that specifies the SQL statements to be constructed. + */ + abstract DataFlow::Node getSql(); + } +} + +/** + * A data-flow node that executes SQL statements. + * + * If the context of interest is such that merely constructing a SQL statement + * would be valuable to report, consider using `SqlConstruction`. + * + * Extend this class to refine existing API models. If you want to model new APIs, + * extend `SqlExecution::Range` instead. + */ +final class SqlExecution = SqlExecution::Range; + +/** + * Provides a class for modeling new SQL execution APIs. + */ +module SqlExecution { + /** + * A data-flow node that executes SQL statements. + */ + abstract class Range extends DataFlow::Node { + /** + * Gets the argument that specifies the SQL statements to be executed. + */ + abstract DataFlow::Node getSql(); + } +} + +/** + * A data-flow node that performs SQL sanitization. + */ +final class SqlSanitization = SqlSanitization::Range; + +/** + * Provides a class for modeling new SQL sanitization APIs. + */ +module SqlSanitization { + /** + * A data-flow node that performs SQL sanitization. + */ + abstract class Range extends DataFlow::Node { } +} diff --git a/rust/ql/lib/codeql/rust/Frameworks.qll b/rust/ql/lib/codeql/rust/Frameworks.qll new file mode 100644 index 000000000000..601e87ef6ebc --- /dev/null +++ b/rust/ql/lib/codeql/rust/Frameworks.qll @@ -0,0 +1,6 @@ +/** + * This file imports all models of frameworks and libraries. + */ + +private import codeql.rust.frameworks.Reqwest +private import codeql.rust.frameworks.stdlib.Env diff --git a/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll index 4a51506dbc0a..07bc8946bc18 100644 --- a/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll +++ b/rust/ql/lib/codeql/rust/controlflow/CfgNodes.qll @@ -5,56 +5,219 @@ private import rust private import ControlFlowGraph -private import internal.ControlFlowGraphImpl +private import internal.ControlFlowGraphImpl as CfgImpl +private import internal.CfgNodes +import Nodes -/** A CFG node that corresponds to an element in the AST. */ -class AstCfgNode extends CfgNode { - AstNode node; +class AstCfgNode = CfgImpl::AstCfgNode; - AstCfgNode() { node = this.getAstNode() } +class ExitCfgNode = CfgImpl::ExitNode; - /** Gets the underlying ast node. */ - AstNode getAstNode() { result = node } -} +class AnnotatedExitCfgNode = CfgImpl::AnnotatedExitNode; -/** A CFG node that corresponds to a parameter in the AST. */ -class ParamCfgNode extends AstCfgNode { - override Param node; +/** + * An assignment expression, for example + * + * ```rust + * x = y; + * ``` + */ +final class AssignmentExprCfgNode extends BinaryExprCfgNode { + AssignmentExpr a; - /** Gets the underlying parameter. */ - Param getParam() { result = node } + AssignmentExprCfgNode() { a = this.getBinaryExpr() } + + /** Gets the underlying `AssignmentExpr`. */ + AssignmentExpr getAssignmentExpr() { result = a } } -/** A CFG node that corresponds to a parameter in the AST. */ -class PatCfgNode extends AstCfgNode { - override Pat node; +/** + * A match expression. For example: + * ```rust + * match x { + * Option::Some(y) => y, + * Option::None => 0, + * } + * ``` + * ```rust + * match x { + * Some(y) if y != 0 => 1 / y, + * _ => 0, + * } + * ``` + */ +final class MatchExprCfgNode extends Nodes::MatchExprCfgNode { + private MatchExpr node; + + MatchExprCfgNode() { node = this.getMatchExpr() } + + /** + * Gets the pattern of the `i`th match arm, if it exists. + */ + PatCfgNode getArmPat(int i) { + any(ChildMapping mapping).hasCfgChild(node, node.getArm(i).getPat(), this, result) + } + + /** + * Gets the guard of the `i`th match arm, if it exists. + */ + ExprCfgNode getArmGuard(int i) { + any(ChildMapping mapping) + .hasCfgChild(node, node.getArm(i).getGuard().getCondition(), this, result) + } - /** Gets the underlying pattern. */ - Pat getPat() { result = node } + /** + * Gets the expression of the `i`th match arm, if it exists. + */ + ExprCfgNode getArmExpr(int i) { + any(ChildMapping mapping).hasCfgChild(node, node.getArm(i).getExpr(), this, result) + } } -/** A CFG node that corresponds to an expression in the AST. */ -class ExprCfgNode extends AstCfgNode { - override Expr node; +/** + * A block expression. For example: + * ```rust + * { + * let x = 42; + * } + * ``` + * ```rust + * 'label: { + * let x = 42; + * x + * } + * ``` + */ +final class BlockExprCfgNode extends Nodes::BlockExprCfgNode { + private BlockExprChildMapping node; - /** Gets the underlying expression. */ - Expr getExpr() { result = node } + BlockExprCfgNode() { node = this.getAstNode() } + + /** + * Gets the tail expression of this block, if it exists. + */ + ExprCfgNode getTailExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getStmtList().getTailExpr(), this, result) + } } -/** A CFG node that corresponds to a call in the AST. */ -class CallExprCfgNode extends ExprCfgNode { - override CallExpr node; +/** + * A break expression. For example: + * ```rust + * loop { + * if not_ready() { + * break; + * } + * } + * ``` + * ```rust + * let x = 'label: loop { + * if done() { + * break 'label 42; + * } + * }; + * ``` + * ```rust + * let x = 'label: { + * if exit() { + * break 'label 42; + * } + * 0; + * }; + * ``` + */ +final class BreakExprCfgNode extends Nodes::BreakExprCfgNode { + /** + * Gets the target of this `break` expression. + * + * The target is either a `LoopExpr`, a `ForExpr`, a `WhileExpr`, or a + * `BlockExpr`. + */ + ExprCfgNode getTarget() { + any(ChildMapping mapping) + .hasCfgChild(this.getBreakExpr().getTarget(), this.getBreakExpr(), result, this) + } +} - /** Gets the underlying `CallExpr`. */ - CallExpr getCallExpr() { result = node } +/** + * A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details. + */ +final class CallExprBaseCfgNode extends Nodes::CallExprBaseCfgNode { + private CallExprBaseChildMapping node; + + CallExprBaseCfgNode() { node = this.getAstNode() } + + /** Gets the `i`th argument of this call. */ + ExprCfgNode getArgument(int i) { + any(ChildMapping mapping).hasCfgChild(node, node.getArgList().getArg(i), this, result) + } } -/** A CFG node that corresponds to a call in the AST. */ -class MethodCallExprCfgNode extends ExprCfgNode { - override MethodCallExpr node; +/** + * A method call expression. For example: + * ```rust + * x.foo(42); + * x.foo::(42); + * ``` + */ +final class MethodCallExprCfgNode extends CallExprBaseCfgNode, Nodes::MethodCallExprCfgNode { } + +/** + * A function call expression. For example: + * ```rust + * foo(42); + * foo::(42); + * foo[0](42); + * foo(1) = 4; + * ``` + */ +final class CallExprCfgNode extends CallExprBaseCfgNode, Nodes::CallExprCfgNode { } + +/** + * A record expression. For example: + * ```rust + * let first = Foo { a: 1, b: 2 }; + * let second = Foo { a: 2, ..first }; + * Foo { a: 1, b: 2 }[2] = 10; + * Foo { .. } = second; + * ``` + */ +final class RecordExprCfgNode extends Nodes::RecordExprCfgNode { + private RecordExprChildMapping node; - /** Gets the underlying `MethodCallExpr`. */ - MethodCallExpr getMethodCallExpr() { result = node } + RecordExprCfgNode() { node = this.getRecordExpr() } + + /** Gets the record expression for the field `field`. */ + pragma[nomagic] + ExprCfgNode getFieldExpr(string field) { + exists(RecordExprField ref | + ref = node.getRecordExprFieldList().getAField() and + any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result) and + field = ref.getNameRef().getText() + ) + } } -final class ExitCfgNode = ExitNode; +/** + * A record pattern. For example: + * ```rust + * match x { + * Foo { a: 1, b: 2 } => "ok", + * Foo { .. } => "fail", + * } + * ``` + */ +final class RecordPatCfgNode extends Nodes::RecordPatCfgNode { + private RecordPatChildMapping node; + + RecordPatCfgNode() { node = this.getRecordPat() } + + /** Gets the record pattern for the field `field`. */ + PatCfgNode getFieldPat(string field) { + exists(RecordPatField rpf | + rpf = node.getRecordPatFieldList().getAField() and + any(ChildMapping mapping).hasCfgChild(node, rpf.getPat(), this, result) and + field = rpf.getNameRef().getText() + ) + } +} diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll b/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll index 2722661494d6..62ac5822dbbc 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/CfgConsistency.qll @@ -8,6 +8,8 @@ import Consistency private import codeql.rust.controlflow.ControlFlowGraph private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl private import codeql.rust.controlflow.internal.Completion +private import codeql.rust.controlflow.internal.CfgNodes::Consistency as CfgNodes +private import codeql.rust.Diagnostics private predicate nonPostOrderExpr(Expr e) { not e instanceof LetExpr and @@ -54,6 +56,25 @@ query predicate deadEnd(CfgImpl::Node node) { not letElsePanic(node.getAstNode()) } +pragma[nomagic] +private predicate successfullyExtractedFile(File f) { + not exists(ExtractionWarning ee | ee.getLocation().getFile() = f) +} + +query predicate missingCfgChild(CfgNode parent, string pred, int i, AstNode child) { + CfgNodes::missingCfgChild(parent, pred, i, child) and + successfullyExtractedFile(child.getLocation().getFile()) and + not exists(AstNode last, CfgImpl::Completion c | CfgImpl::last(child, last, c) | + // In for example `if (a && true) ...`, there is no edge from the CFG node + // for `true` into the `[false] a && true` node. + strictcount(ConditionalSuccessor cs | exists(last.getACfgNode().getASuccessor(cs)) | cs) = 1 + or + // In for example `x && return`, there is no edge from the node for + // `return` into the `&&` node. + not c instanceof CfgImpl::NormalCompletion + ) +} + /** * Gets counts of control flow graph inconsistencies of each type. */ @@ -99,4 +120,7 @@ int getCfgInconsistencyCounts(string type) { or type = "Non-PostOrderTree Expr node" and result = count(Expr e | nonPostOrderExpr(e) | e) + or + type = "Missing CFG child" and + result = count(CfgNode parent, string pred, int child | missingCfgChild(parent, pred, child, _)) } diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll new file mode 100644 index 000000000000..0f3dee7a9f49 --- /dev/null +++ b/rust/ql/lib/codeql/rust/controlflow/internal/CfgNodes.qll @@ -0,0 +1,154 @@ +private import rust +private import codeql.rust.controlflow.internal.generated.CfgNodes +private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl +private import codeql.rust.controlflow.ControlFlowGraph +private import codeql.rust.controlflow.BasicBlocks +private import codeql.rust.controlflow.CfgNodes +private import codeql.rust.internal.CachedStages + +private predicate isPostOrder(AstNode n) { + n instanceof Expr and + not n instanceof LetExpr + or + n instanceof OrPat + or + n instanceof IdentPat + or + n instanceof LiteralPat + or + n instanceof Param +} + +private module CfgNodesInput implements InputSig { + private import codeql.rust.controlflow.ControlFlowGraph as Cfg + + class CfgNode = AstCfgNode; + + private AstNode desugar(AstNode n) { + result = n.(ParenPat).getPat() + or + result = n.(ParenExpr).getExpr() + } + + AstNode getDesugared(AstNode n) { + result = getDesugared(desugar(n)) + or + not exists(desugar(n)) and + result = n + } +} + +import MakeCfgNodes + +class MatchExprChildMapping extends ParentAstNode, MatchExpr { + override predicate relevantChild(AstNode child) { + child = this.getAnArm().getPat() + or + child = this.getAnArm().getGuard().getCondition() + or + child = this.getAnArm().getExpr() + } +} + +class BlockExprChildMapping extends ParentAstNode, BlockExpr { + override predicate relevantChild(AstNode child) { child = this.getStmtList().getTailExpr() } +} + +class BreakExprTargetChildMapping extends ParentAstNode, Expr { + override predicate relevantChild(AstNode child) { child.(BreakExpr).getTarget() = this } +} + +class CallExprBaseChildMapping extends ParentAstNode, CallExprBase { + override predicate relevantChild(AstNode child) { child = this.getArgList().getAnArg() } +} + +class RecordExprChildMapping extends ParentAstNode, RecordExpr { + override predicate relevantChild(AstNode child) { + child = this.getRecordExprFieldList().getAField().getExpr() + } +} + +class RecordPatChildMapping extends ParentAstNode, RecordPat { + override predicate relevantChild(AstNode child) { + child = this.getRecordPatFieldList().getAField().getPat() + } +} + +class FormatArgsExprChildMapping extends ParentAstNode, CfgImpl::ExprTrees::FormatArgsExprTree { + override predicate relevantChild(AstNode child) { child = this.getChildNode(_) } +} + +private class ChildMappingImpl extends ChildMapping { + /** Gets a CFG node for `child`, where `child` is a relevant child node of `parent`. */ + private CfgNode getRelevantChildCfgNode(AstNode parent, AstNode child) { + this.relevantChild(parent, child) and + result = CfgNodesInput::getDesugared(child).getACfgNode() + } + + pragma[nomagic] + private BasicBlock getARelevantBasicBlock(AstNode parent) { + result.getANode().getAstNode() = parent or + result.getANode() = this.getRelevantChildCfgNode(parent, _) + } + + /** + * Holds if CFG node `cfnChild` can reach basic block `bb`, without going + * through an intermediate block that contains a CFG node for `parent` or + * any other relevant child of `parent`. + */ + pragma[nomagic] + predicate childNodeReachesBasicBlock( + AstNode parent, AstNode child, CfgNode cfnChild, BasicBlock bb + ) { + exists(BasicBlock bb0 | + cfnChild = this.getRelevantChildCfgNode(parent, child) and + bb0.getANode() = cfnChild + | + bb = bb0 + or + not bb0.getANode().getAstNode() = parent and + if isPostOrder(parent) then bb = bb0.getASuccessor() else bb = bb0.getAPredecessor() + ) + or + exists(BasicBlock mid | + this.childNodeReachesBasicBlock(parent, child, cfnChild, mid) and + not mid = this.getARelevantBasicBlock(parent) and + if isPostOrder(parent) then bb = mid.getASuccessor() else bb = mid.getAPredecessor() + ) + } + + /** + * Holds if CFG node `cfnChild` can reach CFG node `cfnParent`, without going + * through an intermediate block that contains a CFG node for `parent`. + */ + pragma[nomagic] + predicate childNodeReachesParentNode( + AstNode parent, CfgNode cfnParent, AstNode child, CfgNode cfnChild + ) { + // `cfnChild` can reach `cfnParent` directly + exists(BasicBlock bb | + this.childNodeReachesBasicBlock(parent, child, cfnChild, bb) and + cfnParent.getAstNode() = parent + | + cfnParent = bb.getANode() + or + if isPostOrder(parent) + then cfnParent = bb.getASuccessor().getANode() + else cfnParent = bb.getAPredecessor().getANode() + ) + or + // `cfnChild` can reach `cfnParent` by going via another relevant child + exists(CfgNode cfnOtherChild | + this.childNodeReachesParentNode(parent, cfnParent, _, cfnOtherChild) and + exists(BasicBlock bb | + this.childNodeReachesBasicBlock(parent, child, cfnChild, bb) and + bb.getANode() = cfnOtherChild + ) + ) + } + + override predicate hasCfgChild(AstNode parent, AstNode child, AstCfgNode cfn, AstCfgNode cfnChild) { + Stages::CfgStage::ref() and + this.childNodeReachesParentNode(parent, cfn, child, cfnChild) + } +} diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index b331ddd2d540..0b78b44f1803 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -19,7 +19,7 @@ private module CfgInput implements InputSig { predicate completionIsValidFor = C::completionIsValidFor/2; - /** An AST node with an associated control-flow graph. */ + /** An AST node with an associated control flow graph. */ class CfgScope = Scope::CfgScope; CfgScope getCfgScope(AstNode n) { @@ -73,9 +73,12 @@ class CallableScopeTree extends StandardTree, PreOrderTree, PostOrderTree, Scope override predicate propagatesAbnormal(AstNode child) { none() } override AstNode getChildNode(int i) { - result = this.getParamList().getParam(i) + i = 0 and + result = this.getParamList().getSelfParam() or - i = this.getParamList().getNumberOfParams() and + result = this.getParamList().getParam(i - 1) + or + i = this.getParamList().getNumberOfParams() + 1 and result = this.getBody() } } @@ -191,6 +194,10 @@ class NameTree extends LeafTree, Name { } class NameRefTree extends LeafTree, NameRef { } +class SelfParamTree extends StandardPostOrderTree, SelfParam { + override AstNode getChildNode(int i) { i = 0 and result = this.getName() } +} + class TypeRefTree extends LeafTree instanceof TypeRef { } /** @@ -306,7 +313,7 @@ module ExprTrees { class CallExprTree extends StandardPostOrderTree instanceof CallExpr { override AstNode getChildNode(int i) { - i = 0 and result = super.getExpr() + i = 0 and result = super.getFunction() or result = super.getArgList().getArg(i - 1) } @@ -403,7 +410,7 @@ module ExprTrees { class LetExprTree extends StandardPreOrderTree, LetExpr { override AstNode getChildNode(int i) { i = 0 and - result = this.getExpr() + result = this.getScrutinee() or i = 1 and result = this.getPat() @@ -507,14 +514,14 @@ module ExprTrees { class MatchExprTree extends PostOrderTree instanceof MatchExpr { override predicate propagatesAbnormal(AstNode child) { - child = [super.getExpr(), super.getAnArm().getExpr()] + child = [super.getScrutinee(), super.getAnArm().getExpr()] } - override predicate first(AstNode node) { first(super.getExpr(), node) } + override predicate first(AstNode node) { first(super.getScrutinee(), node) } override predicate succ(AstNode pred, AstNode succ, Completion c) { // Edge from the scrutinee to the first arm or to the match expression if no arms. - last(super.getExpr(), pred, c) and + last(super.getScrutinee(), pred, c) and ( first(super.getArm(0).getPat(), succ) or diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll index 7b3367690ec6..cf779ed152f4 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/Scope.qll @@ -4,7 +4,7 @@ private import ControlFlowGraphImpl private import codeql.rust.elements.internal.generated.ParentChild /** - * A control-flow graph (CFG) scope. + * A control flow graph (CFG) scope. */ abstract private class CfgScopeImpl extends AstNode { /** Holds if `first` is executed first when entering `scope`. */ diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll new file mode 100644 index 000000000000..1c3afbc83b0b --- /dev/null +++ b/rust/ql/lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll @@ -0,0 +1,3690 @@ +// generated by codegen, do not edit +/** + * This module provides generated wrappers around the `CfgNode` type. + * + * INTERNAL: Do not import directly. + */ + +private import codeql.util.Location +private import codeql.util.Unit +private import codeql.rust.elements + +/** Provides the input to `MakeCfgNodes` */ +signature module InputSig { + class CfgNode { + AstNode getAstNode(); + + string toString(); + + Loc getLocation(); + } + + AstNode getDesugared(AstNode n); +} + +/** + * Given a `CfgNode` implementation, provides the module `Nodes` that + * contains wrappers around `CfgNode` for relevant classes. + */ +module MakeCfgNodes Input> { + private import Input + + final private class AstNodeFinal = AstNode; + + final private class CfgNodeFinal = CfgNode; + + /** + * INTERNAL: Do not expose. + */ + abstract class ParentAstNode extends AstNodeFinal { + /** + * Holds if `child` is a (possibly nested) child of this AST node + * for which we would like to find a matching CFG child. + */ + abstract predicate relevantChild(AstNode child); + } + + /** + * INTERNAL: Do not expose. + */ + abstract class ChildMapping extends Unit { + /** + * Holds if `child` is a (possibly nested) child of AST node `parent` + * for which we would like to find a matching CFG child. + */ + final predicate relevantChild(AstNode parent, AstNode child) { + parent.(ParentAstNode).relevantChild(child) + } + + /** + * Holds if there is a control flow path from `cfn` to `cfnChild`, where `cfn` + * is a control flow node for this AST node, and `cfnChild` is a control flow + * node for `child`. + * + * This predicate should be implemented at the place where `MakeCfgNodes` is + * invoked. Ideally, `MakeCfgNodes` should be a higher-order parameterized + * module, but since that is currently not supported, we achieve the "callback" + * effect using this `abstract` class instead. + */ + cached + abstract predicate hasCfgChild(AstNode parent, AstNode child, CfgNode cfn, CfgNode cfnChild); + } + + /** Provides sub classes of `CfgNode`. */ + module Nodes { + final private class ParentArrayExpr extends ParentAstNode, ArrayExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr(_) + } + } + + /** + * An array expression. For example: + * ```rust + * [1, 2, 3]; + * [1; 10]; + * ``` + */ + final class ArrayExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ArrayExpr node; + + ArrayExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ArrayExpr`. */ + ArrayExpr getArrayExpr() { result = node } + + /** + * Gets the `index`th attr of this array expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this array expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this array expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the `index`th expression of this array expression (0-based). + */ + ExprCfgNode getExpr(int index) { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(index), this, result) + } + + /** + * Gets any of the expressions of this array expression. + */ + ExprCfgNode getAnExpr() { result = this.getExpr(_) } + + /** + * Gets the number of expressions of this array expression. + */ + int getNumberOfExprs() { result = count(int i | exists(this.getExpr(i))) } + } + + final private class ParentAsmExpr extends ParentAstNode, AsmExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * An inline assembly expression. For example: + * ```rust + * unsafe { + * builtin # asm(_); + * } + * ``` + */ + final class AsmExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private AsmExpr node; + + AsmExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `AsmExpr`. */ + AsmExpr getAsmExpr() { result = node } + + /** + * Gets the `index`th attr of this asm expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this asm expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this asm expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this asm expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class ParentAwaitExpr extends ParentAstNode, AwaitExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * An `await` expression. For example: + * ```rust + * async { + * let x = foo().await; + * x + * } + * ``` + */ + final class AwaitExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private AwaitExpr node; + + AwaitExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `AwaitExpr`. */ + AwaitExpr getAwaitExpr() { result = node } + + /** + * Gets the `index`th attr of this await expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this await expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this await expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this await expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class ParentBecomeExpr extends ParentAstNode, BecomeExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A `become` expression. For example: + * ```rust + * fn fact_a(n: i32, a: i32) -> i32 { + * if n == 0 { + * a + * } else { + * become fact_a(n - 1, n * a) + * } + * } + * ``` + */ + final class BecomeExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BecomeExpr node; + + BecomeExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BecomeExpr`. */ + BecomeExpr getBecomeExpr() { result = node } + + /** + * Gets the `index`th attr of this become expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this become expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this become expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this become expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class ParentBinaryExpr extends ParentAstNode, BinaryExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getLhs() + or + child = this.getRhs() + } + } + + /** + * A binary operation expression. For example: + * ```rust + * x + y; + * x && y; + * x <= y; + * x = y; + * x += y; + * ``` + */ + final class BinaryExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BinaryExpr node; + + BinaryExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BinaryExpr`. */ + BinaryExpr getBinaryExpr() { result = node } + + /** + * Gets the `index`th attr of this binary expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this binary expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this binary expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the lhs of this binary expression, if it exists. + */ + ExprCfgNode getLhs() { + any(ChildMapping mapping).hasCfgChild(node, node.getLhs(), this, result) + } + + /** + * Holds if `getLhs()` exists. + */ + predicate hasLhs() { exists(this.getLhs()) } + + /** + * Gets the operator name of this binary expression, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + + /** + * Gets the rhs of this binary expression, if it exists. + */ + ExprCfgNode getRhs() { + any(ChildMapping mapping).hasCfgChild(node, node.getRhs(), this, result) + } + + /** + * Holds if `getRhs()` exists. + */ + predicate hasRhs() { exists(this.getRhs()) } + } + + final private class ParentBlockExpr extends ParentAstNode, BlockExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A block expression. For example: + * ```rust + * { + * let x = 42; + * } + * ``` + * ```rust + * 'label: { + * let x = 42; + * x + * } + * ``` + */ + final class BlockExprCfgNode extends CfgNodeFinal, LabelableExprCfgNode { + private BlockExpr node; + + BlockExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BlockExpr`. */ + BlockExpr getBlockExpr() { result = node } + + /** + * Gets the `index`th attr of this block expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this block expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this block expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Holds if this block expression is async. + */ + predicate isAsync() { node.isAsync() } + + /** + * Holds if this block expression is const. + */ + predicate isConst() { node.isConst() } + + /** + * Holds if this block expression is gen. + */ + predicate isGen() { node.isGen() } + + /** + * Holds if this block expression is move. + */ + predicate isMove() { node.isMove() } + + /** + * Holds if this block expression is try. + */ + predicate isTry() { node.isTry() } + + /** + * Holds if this block expression is unsafe. + */ + predicate isUnsafe() { node.isUnsafe() } + + /** + * Gets the statement list of this block expression, if it exists. + */ + StmtList getStmtList() { result = node.getStmtList() } + + /** + * Holds if `getStmtList()` exists. + */ + predicate hasStmtList() { exists(this.getStmtList()) } + } + + final private class ParentBoxPat extends ParentAstNode, BoxPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A box pattern. For example: + * ```rust + * match x { + * box Option::Some(y) => y, + * box Option::None => 0, + * }; + * ``` + */ + final class BoxPatCfgNode extends CfgNodeFinal, PatCfgNode { + private BoxPat node; + + BoxPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BoxPat`. */ + BoxPat getBoxPat() { result = node } + + /** + * Gets the pat of this box pat, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class ParentBreakExpr extends ParentAstNode, BreakExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A break expression. For example: + * ```rust + * loop { + * if not_ready() { + * break; + * } + * } + * ``` + * ```rust + * let x = 'label: loop { + * if done() { + * break 'label 42; + * } + * }; + * ``` + * ```rust + * let x = 'label: { + * if exit() { + * break 'label 42; + * } + * 0; + * }; + * ``` + */ + final class BreakExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private BreakExpr node; + + BreakExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `BreakExpr`. */ + BreakExpr getBreakExpr() { result = node } + + /** + * Gets the `index`th attr of this break expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this break expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this break expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this break expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the lifetime of this break expression, if it exists. + */ + Lifetime getLifetime() { result = node.getLifetime() } + + /** + * Holds if `getLifetime()` exists. + */ + predicate hasLifetime() { exists(this.getLifetime()) } + } + + final private class ParentCallExpr extends ParentAstNode, CallExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getFunction() + } + } + + /** + * A function call expression. For example: + * ```rust + * foo(42); + * foo::(42); + * foo[0](42); + * foo(1) = 4; + * ``` + */ + final class CallExprCfgNode extends CfgNodeFinal, CallExprBaseCfgNode { + private CallExpr node; + + CallExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `CallExpr`. */ + CallExpr getCallExpr() { result = node } + + /** + * Gets the function of this call expression, if it exists. + */ + ExprCfgNode getFunction() { + any(ChildMapping mapping).hasCfgChild(node, node.getFunction(), this, result) + } + + /** + * Holds if `getFunction()` exists. + */ + predicate hasFunction() { exists(this.getFunction()) } + } + + final private class ParentCallExprBase extends ParentAstNode, CallExprBase { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details. + */ + final class CallExprBaseCfgNode extends CfgNodeFinal, ExprCfgNode { + private CallExprBase node; + + CallExprBaseCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `CallExprBase`. */ + CallExprBase getCallExprBase() { result = node } + + /** + * Gets the argument list of this call expression base, if it exists. + */ + ArgList getArgList() { result = node.getArgList() } + + /** + * Holds if `getArgList()` exists. + */ + predicate hasArgList() { exists(this.getArgList()) } + + /** + * Gets the `index`th attr of this call expression base (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this call expression base. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this call expression base. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class ParentConstBlockPat extends ParentAstNode, ConstBlockPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getBlockExpr() + } + } + + /** + * A const block pattern. For example: + * ```rust + * match x { + * const { 1 + 2 + 3 } => "ok", + * _ => "fail", + * }; + * ``` + */ + final class ConstBlockPatCfgNode extends CfgNodeFinal, PatCfgNode { + private ConstBlockPat node; + + ConstBlockPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ConstBlockPat`. */ + ConstBlockPat getConstBlockPat() { result = node } + + /** + * Gets the block expression of this const block pat, if it exists. + */ + BlockExprCfgNode getBlockExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getBlockExpr(), this, result) + } + + /** + * Holds if `getBlockExpr()` exists. + */ + predicate hasBlockExpr() { exists(this.getBlockExpr()) } + + /** + * Holds if this const block pat is const. + */ + predicate isConst() { node.isConst() } + } + + final private class ParentContinueExpr extends ParentAstNode, ContinueExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A continue expression. For example: + * ```rust + * loop { + * if not_ready() { + * continue; + * } + * } + * ``` + * ```rust + * 'label: loop { + * if not_ready() { + * continue 'label; + * } + * } + * ``` + */ + final class ContinueExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ContinueExpr node; + + ContinueExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ContinueExpr`. */ + ContinueExpr getContinueExpr() { result = node } + + /** + * Gets the `index`th attr of this continue expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this continue expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this continue expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the lifetime of this continue expression, if it exists. + */ + Lifetime getLifetime() { result = node.getLifetime() } + + /** + * Holds if `getLifetime()` exists. + */ + predicate hasLifetime() { exists(this.getLifetime()) } + } + + final private class ParentExpr extends ParentAstNode, Expr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * The base class for expressions. + */ + final class ExprCfgNode extends CfgNodeFinal { + private Expr node; + + ExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `Expr`. */ + Expr getExpr() { result = node } + } + + final private class ParentFieldExpr extends ParentAstNode, FieldExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A field access expression. For example: + * ```rust + * x.foo + * ``` + */ + final class FieldExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private FieldExpr node; + + FieldExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `FieldExpr`. */ + FieldExpr getFieldExpr() { result = node } + + /** + * Gets the `index`th attr of this field expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this field expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this field expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this field expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the name reference of this field expression, if it exists. + */ + NameRef getNameRef() { result = node.getNameRef() } + + /** + * Holds if `getNameRef()` exists. + */ + predicate hasNameRef() { exists(this.getNameRef()) } + } + + final private class ParentForExpr extends ParentAstNode, ForExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getIterable() + or + child = this.getPat() + } + } + + /** + * A ForExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class ForExprCfgNode extends CfgNodeFinal, LoopingExprCfgNode { + private ForExpr node; + + ForExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ForExpr`. */ + ForExpr getForExpr() { result = node } + + /** + * Gets the `index`th attr of this for expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this for expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this for expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the iterable of this for expression, if it exists. + */ + ExprCfgNode getIterable() { + any(ChildMapping mapping).hasCfgChild(node, node.getIterable(), this, result) + } + + /** + * Holds if `getIterable()` exists. + */ + predicate hasIterable() { exists(this.getIterable()) } + + /** + * Gets the pat of this for expression, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class ParentFormatArgsExpr extends ParentAstNode, FormatArgsExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getTemplate() + } + } + + /** + * A FormatArgsExpr. For example: + * ```rust + * format_args!("no args"); + * format_args!("{} foo {:?}", 1, 2); + * format_args!("{b} foo {a:?}", a=1, b=2); + * let (x, y) = (1, 42); + * format_args!("{x}, {y}"); + * ``` + */ + final class FormatArgsExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private FormatArgsExpr node; + + FormatArgsExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `FormatArgsExpr`. */ + FormatArgsExpr getFormatArgsExpr() { result = node } + + /** + * Gets the `index`th argument of this format arguments expression (0-based). + */ + FormatArgsArg getArg(int index) { result = node.getArg(index) } + + /** + * Gets any of the arguments of this format arguments expression. + */ + FormatArgsArg getAnArg() { result = this.getArg(_) } + + /** + * Gets the number of arguments of this format arguments expression. + */ + int getNumberOfArgs() { result = count(int i | exists(this.getArg(i))) } + + /** + * Gets the `index`th attr of this format arguments expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this format arguments expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this format arguments expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the template of this format arguments expression, if it exists. + */ + ExprCfgNode getTemplate() { + any(ChildMapping mapping).hasCfgChild(node, node.getTemplate(), this, result) + } + + /** + * Holds if `getTemplate()` exists. + */ + predicate hasTemplate() { exists(this.getTemplate()) } + + /** + * Gets the `index`th format of this format arguments expression (0-based). + */ + Format getFormat(int index) { result = node.getFormat(index) } + + /** + * Gets any of the formats of this format arguments expression. + */ + Format getAFormat() { result = this.getFormat(_) } + + /** + * Gets the number of formats of this format arguments expression. + */ + int getNumberOfFormats() { result = count(int i | exists(this.getFormat(i))) } + } + + final private class ParentFormatTemplateVariableAccess extends ParentAstNode, + FormatTemplateVariableAccess + { + override predicate relevantChild(AstNode child) { none() } + } + + /** + */ + final class FormatTemplateVariableAccessCfgNode extends CfgNodeFinal, PathExprBaseCfgNode { + private FormatTemplateVariableAccess node; + + FormatTemplateVariableAccessCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `FormatTemplateVariableAccess`. */ + FormatTemplateVariableAccess getFormatTemplateVariableAccess() { result = node } + } + + final private class ParentIdentPat extends ParentAstNode, IdentPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A binding pattern. For example: + * ```rust + * match x { + * Option::Some(y) => y, + * Option::None => 0, + * }; + * ``` + * ```rust + * match x { + * y@Option::Some(_) => y, + * Option::None => 0, + * }; + * ``` + */ + final class IdentPatCfgNode extends CfgNodeFinal, PatCfgNode { + private IdentPat node; + + IdentPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `IdentPat`. */ + IdentPat getIdentPat() { result = node } + + /** + * Gets the `index`th attr of this ident pat (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this ident pat. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this ident pat. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Holds if this ident pat is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Holds if this ident pat is reference. + */ + predicate isRef() { node.isRef() } + + /** + * Gets the name of this ident pat, if it exists. + */ + Name getName() { result = node.getName() } + + /** + * Holds if `getName()` exists. + */ + predicate hasName() { exists(this.getName()) } + + /** + * Gets the pat of this ident pat, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class ParentIfExpr extends ParentAstNode, IfExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getCondition() + or + child = this.getElse() + or + child = this.getThen() + } + } + + /** + * An `if` expression. For example: + * ```rust + * if x == 42 { + * println!("that's the answer"); + * } + * ``` + * ```rust + * let y = if x > 0 { + * 1 + * } else { + * 0 + * }; + * ``` + */ + final class IfExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private IfExpr node; + + IfExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `IfExpr`. */ + IfExpr getIfExpr() { result = node } + + /** + * Gets the `index`th attr of this if expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this if expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this if expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the condition of this if expression, if it exists. + */ + ExprCfgNode getCondition() { + any(ChildMapping mapping).hasCfgChild(node, node.getCondition(), this, result) + } + + /** + * Holds if `getCondition()` exists. + */ + predicate hasCondition() { exists(this.getCondition()) } + + /** + * Gets the else of this if expression, if it exists. + */ + ExprCfgNode getElse() { + any(ChildMapping mapping).hasCfgChild(node, node.getElse(), this, result) + } + + /** + * Holds if `getElse()` exists. + */ + predicate hasElse() { exists(this.getElse()) } + + /** + * Gets the then of this if expression, if it exists. + */ + BlockExprCfgNode getThen() { + any(ChildMapping mapping).hasCfgChild(node, node.getThen(), this, result) + } + + /** + * Holds if `getThen()` exists. + */ + predicate hasThen() { exists(this.getThen()) } + } + + final private class ParentIndexExpr extends ParentAstNode, IndexExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getBase() + or + child = this.getIndex() + } + } + + /** + * An index expression. For example: + * ```rust + * list[42]; + * list[42] = 1; + * ``` + */ + final class IndexExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private IndexExpr node; + + IndexExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `IndexExpr`. */ + IndexExpr getIndexExpr() { result = node } + + /** + * Gets the `index`th attr of this index expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this index expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this index expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the base of this index expression, if it exists. + */ + ExprCfgNode getBase() { + any(ChildMapping mapping).hasCfgChild(node, node.getBase(), this, result) + } + + /** + * Holds if `getBase()` exists. + */ + predicate hasBase() { exists(this.getBase()) } + + /** + * Gets the index of this index expression, if it exists. + */ + ExprCfgNode getIndex() { + any(ChildMapping mapping).hasCfgChild(node, node.getIndex(), this, result) + } + + /** + * Holds if `getIndex()` exists. + */ + predicate hasIndex() { exists(this.getIndex()) } + } + + final private class ParentLabelableExpr extends ParentAstNode, LabelableExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * The base class for expressions that can be labeled (`LoopExpr`, `ForExpr`, `WhileExpr` or `BlockExpr`). + */ + final class LabelableExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private LabelableExpr node; + + LabelableExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LabelableExpr`. */ + LabelableExpr getLabelableExpr() { result = node } + + /** + * Gets the label of this labelable expression, if it exists. + */ + Label getLabel() { result = node.getLabel() } + + /** + * Holds if `getLabel()` exists. + */ + predicate hasLabel() { exists(this.getLabel()) } + } + + final private class ParentLetExpr extends ParentAstNode, LetExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getScrutinee() + or + child = this.getPat() + } + } + + /** + * A `let` expression. For example: + * ```rust + * if let Some(x) = maybe_some { + * println!("{}", x); + * } + * ``` + */ + final class LetExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private LetExpr node; + + LetExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LetExpr`. */ + LetExpr getLetExpr() { result = node } + + /** + * Gets the `index`th attr of this let expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this let expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this let expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the scrutinee of this let expression, if it exists. + */ + ExprCfgNode getScrutinee() { + any(ChildMapping mapping).hasCfgChild(node, node.getScrutinee(), this, result) + } + + /** + * Holds if `getScrutinee()` exists. + */ + predicate hasScrutinee() { exists(this.getScrutinee()) } + + /** + * Gets the pat of this let expression, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class ParentLetStmt extends ParentAstNode, LetStmt { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getInitializer() + or + child = this.getPat() + } + } + + /** + * A let statement. For example: + * ```rust + * let x = 42; + * let x: i32 = 42; + * let x: i32; + * let x; + * let (x, y) = (1, 2); + * let Some(x) = std::env::var("FOO") else { + * return; + * }; + * ``` + */ + final class LetStmtCfgNode extends CfgNodeFinal { + private LetStmt node; + + LetStmtCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LetStmt`. */ + LetStmt getLetStmt() { result = node } + + /** + * Gets the `index`th attr of this let statement (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this let statement. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this let statement. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the initializer of this let statement, if it exists. + */ + ExprCfgNode getInitializer() { + any(ChildMapping mapping).hasCfgChild(node, node.getInitializer(), this, result) + } + + /** + * Holds if `getInitializer()` exists. + */ + predicate hasInitializer() { exists(this.getInitializer()) } + + /** + * Gets the let else of this let statement, if it exists. + */ + LetElse getLetElse() { result = node.getLetElse() } + + /** + * Holds if `getLetElse()` exists. + */ + predicate hasLetElse() { exists(this.getLetElse()) } + + /** + * Gets the pat of this let statement, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + + /** + * Gets the ty of this let statement, if it exists. + */ + TypeRef getTy() { result = node.getTy() } + + /** + * Holds if `getTy()` exists. + */ + predicate hasTy() { exists(this.getTy()) } + } + + final private class ParentLiteralExpr extends ParentAstNode, LiteralExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A literal expression. For example: + * ```rust + * 42; + * 42.0; + * "Hello, world!"; + * b"Hello, world!"; + * 'x'; + * b'x'; + * r"Hello, world!"; + * true; + * ``` + */ + final class LiteralExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private LiteralExpr node; + + LiteralExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LiteralExpr`. */ + LiteralExpr getLiteralExpr() { result = node } + + /** + * Gets the `index`th attr of this literal expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this literal expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this literal expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the text value of this literal expression, if it exists. + */ + string getTextValue() { result = node.getTextValue() } + + /** + * Holds if `getTextValue()` exists. + */ + predicate hasTextValue() { exists(this.getTextValue()) } + } + + final private class ParentLiteralPat extends ParentAstNode, LiteralPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getLiteral() + } + } + + /** + * A literal pattern. For example: + * ```rust + * match x { + * 42 => "ok", + * _ => "fail", + * } + * ``` + */ + final class LiteralPatCfgNode extends CfgNodeFinal, PatCfgNode { + private LiteralPat node; + + LiteralPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LiteralPat`. */ + LiteralPat getLiteralPat() { result = node } + + /** + * Gets the literal of this literal pat, if it exists. + */ + LiteralExprCfgNode getLiteral() { + any(ChildMapping mapping).hasCfgChild(node, node.getLiteral(), this, result) + } + + /** + * Holds if `getLiteral()` exists. + */ + predicate hasLiteral() { exists(this.getLiteral()) } + } + + final private class ParentLoopExpr extends ParentAstNode, LoopExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A loop expression. For example: + * ```rust + * loop { + * println!("Hello, world (again)!"); + * }; + * ``` + * ```rust + * 'label: loop { + * println!("Hello, world (once)!"); + * break 'label; + * }; + * ``` + * ```rust + * let mut x = 0; + * loop { + * if x < 10 { + * x += 1; + * } else { + * break; + * } + * }; + * ``` + */ + final class LoopExprCfgNode extends CfgNodeFinal, LoopingExprCfgNode { + private LoopExpr node; + + LoopExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LoopExpr`. */ + LoopExpr getLoopExpr() { result = node } + + /** + * Gets the `index`th attr of this loop expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this loop expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this loop expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class ParentLoopingExpr extends ParentAstNode, LoopingExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getLoopBody() + } + } + + /** + * The base class for expressions that loop (`LoopExpr`, `ForExpr` or `WhileExpr`). + */ + final class LoopingExprCfgNode extends CfgNodeFinal, LabelableExprCfgNode { + private LoopingExpr node; + + LoopingExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `LoopingExpr`. */ + LoopingExpr getLoopingExpr() { result = node } + + /** + * Gets the loop body of this looping expression, if it exists. + */ + BlockExprCfgNode getLoopBody() { + any(ChildMapping mapping).hasCfgChild(node, node.getLoopBody(), this, result) + } + + /** + * Holds if `getLoopBody()` exists. + */ + predicate hasLoopBody() { exists(this.getLoopBody()) } + } + + final private class ParentMacroCall extends ParentAstNode, MacroCall { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A MacroCall. For example: + * ```rust + * todo!() + * ``` + */ + final class MacroCallCfgNode extends CfgNodeFinal { + private MacroCall node; + + MacroCallCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroCall`. */ + MacroCall getMacroCall() { result = node } + + /** + * Gets the `index`th attr of this macro call (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this macro call. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this macro call. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the path of this macro call, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + + /** + * Gets the token tree of this macro call, if it exists. + */ + TokenTree getTokenTree() { result = node.getTokenTree() } + + /** + * Holds if `getTokenTree()` exists. + */ + predicate hasTokenTree() { exists(this.getTokenTree()) } + + /** + * Gets the expanded of this macro call, if it exists. + */ + AstNode getExpanded() { result = node.getExpanded() } + + /** + * Holds if `getExpanded()` exists. + */ + predicate hasExpanded() { exists(this.getExpanded()) } + } + + final private class ParentMacroExpr extends ParentAstNode, MacroExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getMacroCall() + } + } + + /** + * A MacroExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class MacroExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private MacroExpr node; + + MacroExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroExpr`. */ + MacroExpr getMacroExpr() { result = node } + + /** + * Gets the macro call of this macro expression, if it exists. + */ + MacroCallCfgNode getMacroCall() { + any(ChildMapping mapping).hasCfgChild(node, node.getMacroCall(), this, result) + } + + /** + * Holds if `getMacroCall()` exists. + */ + predicate hasMacroCall() { exists(this.getMacroCall()) } + } + + final private class ParentMacroPat extends ParentAstNode, MacroPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getMacroCall() + } + } + + /** + * A MacroPat. For example: + * ```rust + * todo!() + * ``` + */ + final class MacroPatCfgNode extends CfgNodeFinal, PatCfgNode { + private MacroPat node; + + MacroPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MacroPat`. */ + MacroPat getMacroPat() { result = node } + + /** + * Gets the macro call of this macro pat, if it exists. + */ + MacroCallCfgNode getMacroCall() { + any(ChildMapping mapping).hasCfgChild(node, node.getMacroCall(), this, result) + } + + /** + * Holds if `getMacroCall()` exists. + */ + predicate hasMacroCall() { exists(this.getMacroCall()) } + } + + final private class ParentMatchExpr extends ParentAstNode, MatchExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getScrutinee() + } + } + + /** + * A match expression. For example: + * ```rust + * match x { + * Option::Some(y) => y, + * Option::None => 0, + * } + * ``` + * ```rust + * match x { + * Some(y) if y != 0 => 1 / y, + * _ => 0, + * } + * ``` + */ + final class MatchExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private MatchExpr node; + + MatchExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MatchExpr`. */ + MatchExpr getMatchExpr() { result = node } + + /** + * Gets the `index`th attr of this match expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this match expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this match expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the scrutinee (the expression being matched) of this match expression, if it exists. + */ + ExprCfgNode getScrutinee() { + any(ChildMapping mapping).hasCfgChild(node, node.getScrutinee(), this, result) + } + + /** + * Holds if `getScrutinee()` exists. + */ + predicate hasScrutinee() { exists(this.getScrutinee()) } + + /** + * Gets the match arm list of this match expression, if it exists. + */ + MatchArmList getMatchArmList() { result = node.getMatchArmList() } + + /** + * Holds if `getMatchArmList()` exists. + */ + predicate hasMatchArmList() { exists(this.getMatchArmList()) } + } + + final private class ParentMethodCallExpr extends ParentAstNode, MethodCallExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getReceiver() + } + } + + /** + * A method call expression. For example: + * ```rust + * x.foo(42); + * x.foo::(42); + * ``` + */ + final class MethodCallExprCfgNode extends CfgNodeFinal, CallExprBaseCfgNode { + private MethodCallExpr node; + + MethodCallExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `MethodCallExpr`. */ + MethodCallExpr getMethodCallExpr() { result = node } + + /** + * Gets the generic argument list of this method call expression, if it exists. + */ + GenericArgList getGenericArgList() { result = node.getGenericArgList() } + + /** + * Holds if `getGenericArgList()` exists. + */ + predicate hasGenericArgList() { exists(this.getGenericArgList()) } + + /** + * Gets the name reference of this method call expression, if it exists. + */ + NameRef getNameRef() { result = node.getNameRef() } + + /** + * Holds if `getNameRef()` exists. + */ + predicate hasNameRef() { exists(this.getNameRef()) } + + /** + * Gets the receiver of this method call expression, if it exists. + */ + ExprCfgNode getReceiver() { + any(ChildMapping mapping).hasCfgChild(node, node.getReceiver(), this, result) + } + + /** + * Holds if `getReceiver()` exists. + */ + predicate hasReceiver() { exists(this.getReceiver()) } + } + + final private class ParentOffsetOfExpr extends ParentAstNode, OffsetOfExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * An `offset_of` expression. For example: + * ```rust + * builtin # offset_of(Struct, field); + * ``` + */ + final class OffsetOfExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private OffsetOfExpr node; + + OffsetOfExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `OffsetOfExpr`. */ + OffsetOfExpr getOffsetOfExpr() { result = node } + + /** + * Gets the `index`th attr of this offset of expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this offset of expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this offset of expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the `index`th field of this offset of expression (0-based). + */ + NameRef getField(int index) { result = node.getField(index) } + + /** + * Gets any of the fields of this offset of expression. + */ + NameRef getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this offset of expression. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + + /** + * Gets the ty of this offset of expression, if it exists. + */ + TypeRef getTy() { result = node.getTy() } + + /** + * Holds if `getTy()` exists. + */ + predicate hasTy() { exists(this.getTy()) } + } + + final private class ParentOrPat extends ParentAstNode, OrPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat(_) + } + } + + /** + * An or pattern. For example: + * ```rust + * match x { + * Option::Some(y) | Option::None => 0, + * } + * ``` + */ + final class OrPatCfgNode extends CfgNodeFinal, PatCfgNode { + private OrPat node; + + OrPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `OrPat`. */ + OrPat getOrPat() { result = node } + + /** + * Gets the `index`th pat of this or pat (0-based). + */ + PatCfgNode getPat(int index) { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(index), this, result) + } + + /** + * Gets any of the pats of this or pat. + */ + PatCfgNode getAPat() { result = this.getPat(_) } + + /** + * Gets the number of pats of this or pat. + */ + int getNumberOfPats() { result = count(int i | exists(this.getPat(i))) } + } + + final private class ParentParam extends ParentAstNode, Param { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A parameter in a function or method. For example `x` in: + * ```rust + * fn new(x: T) -> Foo { + * // ... + * } + * ``` + */ + final class ParamCfgNode extends CfgNodeFinal, ParamBaseCfgNode { + private Param node; + + ParamCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `Param`. */ + Param getParam() { result = node } + + /** + * Gets the pat of this parameter, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class ParentParamBase extends ParentAstNode, ParamBase { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A normal parameter, `Param`, or a self parameter `SelfParam`. + */ + final class ParamBaseCfgNode extends CfgNodeFinal { + private ParamBase node; + + ParamBaseCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ParamBase`. */ + ParamBase getParamBase() { result = node } + + /** + * Gets the `index`th attr of this parameter base (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this parameter base. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this parameter base. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the ty of this parameter base, if it exists. + */ + TypeRef getTy() { result = node.getTy() } + + /** + * Holds if `getTy()` exists. + */ + predicate hasTy() { exists(this.getTy()) } + } + + final private class ParentPat extends ParentAstNode, Pat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * The base class for patterns. + */ + final class PatCfgNode extends CfgNodeFinal { + private Pat node; + + PatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `Pat`. */ + Pat getPat() { result = node } + } + + final private class ParentPathExpr extends ParentAstNode, PathExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A path expression. For example: + * ```rust + * let x = variable; + * let x = foo::bar; + * let y = ::foo; + * let z = ::foo; + * ``` + */ + final class PathExprCfgNode extends CfgNodeFinal, PathExprBaseCfgNode { + private PathExpr node; + + PathExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PathExpr`. */ + PathExpr getPathExpr() { result = node } + + /** + * Gets the `index`th attr of this path expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this path expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this path expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the path of this path expression, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + } + + final private class ParentPathExprBase extends ParentAstNode, PathExprBase { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A path expression or a variable access in a formatting template. See `PathExpr` and `FormatTemplateVariableAccess` for further details. + */ + final class PathExprBaseCfgNode extends CfgNodeFinal, ExprCfgNode { + private PathExprBase node; + + PathExprBaseCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PathExprBase`. */ + PathExprBase getPathExprBase() { result = node } + } + + final private class ParentPathPat extends ParentAstNode, PathPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A path pattern. For example: + * ```rust + * match x { + * Foo::Bar => "ok", + * _ => "fail", + * } + * ``` + */ + final class PathPatCfgNode extends CfgNodeFinal, PatCfgNode { + private PathPat node; + + PathPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PathPat`. */ + PathPat getPathPat() { result = node } + + /** + * Gets the path of this path pat, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + } + + final private class ParentPrefixExpr extends ParentAstNode, PrefixExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A unary operation expression. For example: + * ```rust + * let x = -42; + * let y = !true; + * let z = *ptr; + * ``` + */ + final class PrefixExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private PrefixExpr node; + + PrefixExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `PrefixExpr`. */ + PrefixExpr getPrefixExpr() { result = node } + + /** + * Gets the `index`th attr of this prefix expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this prefix expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this prefix expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this prefix expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Gets the operator name of this prefix expression, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + } + + final private class ParentRangeExpr extends ParentAstNode, RangeExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getEnd() + or + child = this.getStart() + } + } + + /** + * A range expression. For example: + * ```rust + * let x = 1..=10; + * let x = 1..10; + * let x = 10..; + * let x = ..10; + * let x = ..=10; + * let x = ..; + * ``` + */ + final class RangeExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private RangeExpr node; + + RangeExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RangeExpr`. */ + RangeExpr getRangeExpr() { result = node } + + /** + * Gets the `index`th attr of this range expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this range expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this range expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the end of this range expression, if it exists. + */ + ExprCfgNode getEnd() { + any(ChildMapping mapping).hasCfgChild(node, node.getEnd(), this, result) + } + + /** + * Holds if `getEnd()` exists. + */ + predicate hasEnd() { exists(this.getEnd()) } + + /** + * Gets the operator name of this range expression, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + + /** + * Gets the start of this range expression, if it exists. + */ + ExprCfgNode getStart() { + any(ChildMapping mapping).hasCfgChild(node, node.getStart(), this, result) + } + + /** + * Holds if `getStart()` exists. + */ + predicate hasStart() { exists(this.getStart()) } + } + + final private class ParentRangePat extends ParentAstNode, RangePat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getEnd() + or + child = this.getStart() + } + } + + /** + * A range pattern. For example: + * ```rust + * match x { + * ..15 => "too cold", + * 16..=25 => "just right", + * 26.. => "too hot", + * } + * ``` + */ + final class RangePatCfgNode extends CfgNodeFinal, PatCfgNode { + private RangePat node; + + RangePatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RangePat`. */ + RangePat getRangePat() { result = node } + + /** + * Gets the end of this range pat, if it exists. + */ + PatCfgNode getEnd() { + any(ChildMapping mapping).hasCfgChild(node, node.getEnd(), this, result) + } + + /** + * Holds if `getEnd()` exists. + */ + predicate hasEnd() { exists(this.getEnd()) } + + /** + * Gets the operator name of this range pat, if it exists. + */ + string getOperatorName() { result = node.getOperatorName() } + + /** + * Holds if `getOperatorName()` exists. + */ + predicate hasOperatorName() { exists(this.getOperatorName()) } + + /** + * Gets the start of this range pat, if it exists. + */ + PatCfgNode getStart() { + any(ChildMapping mapping).hasCfgChild(node, node.getStart(), this, result) + } + + /** + * Holds if `getStart()` exists. + */ + predicate hasStart() { exists(this.getStart()) } + } + + final private class ParentRecordExpr extends ParentAstNode, RecordExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A record expression. For example: + * ```rust + * let first = Foo { a: 1, b: 2 }; + * let second = Foo { a: 2, ..first }; + * Foo { a: 1, b: 2 }[2] = 10; + * Foo { .. } = second; + * ``` + */ + final class RecordExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private RecordExpr node; + + RecordExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RecordExpr`. */ + RecordExpr getRecordExpr() { result = node } + + /** + * Gets the path of this record expression, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + + /** + * Gets the record expression field list of this record expression, if it exists. + */ + RecordExprFieldList getRecordExprFieldList() { result = node.getRecordExprFieldList() } + + /** + * Holds if `getRecordExprFieldList()` exists. + */ + predicate hasRecordExprFieldList() { exists(this.getRecordExprFieldList()) } + } + + final private class ParentRecordPat extends ParentAstNode, RecordPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A record pattern. For example: + * ```rust + * match x { + * Foo { a: 1, b: 2 } => "ok", + * Foo { .. } => "fail", + * } + * ``` + */ + final class RecordPatCfgNode extends CfgNodeFinal, PatCfgNode { + private RecordPat node; + + RecordPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RecordPat`. */ + RecordPat getRecordPat() { result = node } + + /** + * Gets the path of this record pat, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + + /** + * Gets the record pat field list of this record pat, if it exists. + */ + RecordPatFieldList getRecordPatFieldList() { result = node.getRecordPatFieldList() } + + /** + * Holds if `getRecordPatFieldList()` exists. + */ + predicate hasRecordPatFieldList() { exists(this.getRecordPatFieldList()) } + } + + final private class ParentRefExpr extends ParentAstNode, RefExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A reference expression. For example: + * ```rust + * let ref_const = &foo; + * let ref_mut = &mut foo; + * let raw_const: &mut i32 = &raw const foo; + * let raw_mut: &mut i32 = &raw mut foo; + * ``` + */ + final class RefExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private RefExpr node; + + RefExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RefExpr`. */ + RefExpr getRefExpr() { result = node } + + /** + * Gets the `index`th attr of this reference expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this reference expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this reference expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this reference expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + + /** + * Holds if this reference expression is const. + */ + predicate isConst() { node.isConst() } + + /** + * Holds if this reference expression is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Holds if this reference expression is raw. + */ + predicate isRaw() { node.isRaw() } + } + + final private class ParentRefPat extends ParentAstNode, RefPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat() + } + } + + /** + * A reference pattern. For example: + * ```rust + * match x { + * &mut Option::Some(y) => y, + * &Option::None => 0, + * }; + * ``` + */ + final class RefPatCfgNode extends CfgNodeFinal, PatCfgNode { + private RefPat node; + + RefPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RefPat`. */ + RefPat getRefPat() { result = node } + + /** + * Holds if this reference pat is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Gets the pat of this reference pat, if it exists. + */ + PatCfgNode getPat() { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(), this, result) + } + + /** + * Holds if `getPat()` exists. + */ + predicate hasPat() { exists(this.getPat()) } + } + + final private class ParentRestPat extends ParentAstNode, RestPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A RestPat. For example: + * ```rust + * todo!() + * ``` + */ + final class RestPatCfgNode extends CfgNodeFinal, PatCfgNode { + private RestPat node; + + RestPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `RestPat`. */ + RestPat getRestPat() { result = node } + + /** + * Gets the `index`th attr of this rest pat (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this rest pat. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this rest pat. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class ParentReturnExpr extends ParentAstNode, ReturnExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A return expression. For example: + * ```rust + * fn some_value() -> i32 { + * return 42; + * } + * ``` + * ```rust + * fn no_value() -> () { + * return; + * } + * ``` + */ + final class ReturnExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private ReturnExpr node; + + ReturnExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `ReturnExpr`. */ + ReturnExpr getReturnExpr() { result = node } + + /** + * Gets the `index`th attr of this return expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this return expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this return expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this return expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class ParentSelfParam extends ParentAstNode, SelfParam { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A `self` parameter. For example `self` in: + * ```rust + * fn push(&mut self, value: T) { + * // ... + * } + * ``` + */ + final class SelfParamCfgNode extends CfgNodeFinal, ParamBaseCfgNode { + private SelfParam node; + + SelfParamCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `SelfParam`. */ + SelfParam getSelfParam() { result = node } + + /** + * Holds if this self parameter is mut. + */ + predicate isMut() { node.isMut() } + + /** + * Gets the lifetime of this self parameter, if it exists. + */ + Lifetime getLifetime() { result = node.getLifetime() } + + /** + * Holds if `getLifetime()` exists. + */ + predicate hasLifetime() { exists(this.getLifetime()) } + + /** + * Gets the name of this self parameter, if it exists. + */ + Name getName() { result = node.getName() } + + /** + * Holds if `getName()` exists. + */ + predicate hasName() { exists(this.getName()) } + } + + final private class ParentSlicePat extends ParentAstNode, SlicePat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getPat(_) + } + } + + /** + * A slice pattern. For example: + * ```rust + * match x { + * [1, 2, 3, 4, 5] => "ok", + * [1, 2, ..] => "fail", + * [x, y, .., z, 7] => "fail", + * } + * ``` + */ + final class SlicePatCfgNode extends CfgNodeFinal, PatCfgNode { + private SlicePat node; + + SlicePatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `SlicePat`. */ + SlicePat getSlicePat() { result = node } + + /** + * Gets the `index`th pat of this slice pat (0-based). + */ + PatCfgNode getPat(int index) { + any(ChildMapping mapping).hasCfgChild(node, node.getPat(index), this, result) + } + + /** + * Gets any of the pats of this slice pat. + */ + PatCfgNode getAPat() { result = this.getPat(_) } + + /** + * Gets the number of pats of this slice pat. + */ + int getNumberOfPats() { result = count(int i | exists(this.getPat(i))) } + } + + final private class ParentTryExpr extends ParentAstNode, TryExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A TryExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class TryExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private TryExpr node; + + TryExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TryExpr`. */ + TryExpr getTryExpr() { result = node } + + /** + * Gets the `index`th attr of this try expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this try expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this try expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this try expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class ParentTupleExpr extends ParentAstNode, TupleExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getField(_) + } + } + + /** + * A tuple expression. For example: + * ```rust + * (1, "one"); + * (2, "two")[0] = 3; + * ``` + */ + final class TupleExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private TupleExpr node; + + TupleExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TupleExpr`. */ + TupleExpr getTupleExpr() { result = node } + + /** + * Gets the `index`th attr of this tuple expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this tuple expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this tuple expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the `index`th field of this tuple expression (0-based). + */ + ExprCfgNode getField(int index) { + any(ChildMapping mapping).hasCfgChild(node, node.getField(index), this, result) + } + + /** + * Gets any of the fields of this tuple expression. + */ + ExprCfgNode getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this tuple expression. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + } + + final private class ParentTuplePat extends ParentAstNode, TuplePat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getField(_) + } + } + + /** + * A tuple pattern. For example: + * ```rust + * let (x, y) = (1, 2); + * let (a, b, .., z) = (1, 2, 3, 4, 5); + * ``` + */ + final class TuplePatCfgNode extends CfgNodeFinal, PatCfgNode { + private TuplePat node; + + TuplePatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TuplePat`. */ + TuplePat getTuplePat() { result = node } + + /** + * Gets the `index`th field of this tuple pat (0-based). + */ + PatCfgNode getField(int index) { + any(ChildMapping mapping).hasCfgChild(node, node.getField(index), this, result) + } + + /** + * Gets any of the fields of this tuple pat. + */ + PatCfgNode getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this tuple pat. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + } + + final private class ParentTupleStructPat extends ParentAstNode, TupleStructPat { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getField(_) + } + } + + /** + * A tuple struct pattern. For example: + * ```rust + * match x { + * Tuple("a", 1, 2, 3) => "great", + * Tuple(.., 3) => "fine", + * Tuple(..) => "fail", + * }; + * ``` + */ + final class TupleStructPatCfgNode extends CfgNodeFinal, PatCfgNode { + private TupleStructPat node; + + TupleStructPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `TupleStructPat`. */ + TupleStructPat getTupleStructPat() { result = node } + + /** + * Gets the `index`th field of this tuple struct pat (0-based). + */ + PatCfgNode getField(int index) { + any(ChildMapping mapping).hasCfgChild(node, node.getField(index), this, result) + } + + /** + * Gets any of the fields of this tuple struct pat. + */ + PatCfgNode getAField() { result = this.getField(_) } + + /** + * Gets the number of fields of this tuple struct pat. + */ + int getNumberOfFields() { result = count(int i | exists(this.getField(i))) } + + /** + * Gets the path of this tuple struct pat, if it exists. + */ + Path getPath() { result = node.getPath() } + + /** + * Holds if `getPath()` exists. + */ + predicate hasPath() { exists(this.getPath()) } + } + + final private class ParentUnderscoreExpr extends ParentAstNode, UnderscoreExpr { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * An underscore expression. For example: + * ```rust + * _ = 42; + * ``` + */ + final class UnderscoreExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private UnderscoreExpr node; + + UnderscoreExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `UnderscoreExpr`. */ + UnderscoreExpr getUnderscoreExpr() { result = node } + + /** + * Gets the `index`th attr of this underscore expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this underscore expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this underscore expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + } + + final private class ParentWhileExpr extends ParentAstNode, WhileExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getCondition() + } + } + + /** + * A WhileExpr. For example: + * ```rust + * todo!() + * ``` + */ + final class WhileExprCfgNode extends CfgNodeFinal, LoopingExprCfgNode { + private WhileExpr node; + + WhileExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `WhileExpr`. */ + WhileExpr getWhileExpr() { result = node } + + /** + * Gets the `index`th attr of this while expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this while expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this while expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the condition of this while expression, if it exists. + */ + ExprCfgNode getCondition() { + any(ChildMapping mapping).hasCfgChild(node, node.getCondition(), this, result) + } + + /** + * Holds if `getCondition()` exists. + */ + predicate hasCondition() { exists(this.getCondition()) } + } + + final private class ParentWildcardPat extends ParentAstNode, WildcardPat { + override predicate relevantChild(AstNode child) { none() } + } + + /** + * A wildcard pattern. For example: + * ```rust + * let _ = 42; + * ``` + */ + final class WildcardPatCfgNode extends CfgNodeFinal, PatCfgNode { + private WildcardPat node; + + WildcardPatCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `WildcardPat`. */ + WildcardPat getWildcardPat() { result = node } + } + + final private class ParentYeetExpr extends ParentAstNode, YeetExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A `yeet` expression. For example: + * ```rust + * if x < size { + * do yeet "index out of bounds"; + * } + * ``` + */ + final class YeetExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private YeetExpr node; + + YeetExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `YeetExpr`. */ + YeetExpr getYeetExpr() { result = node } + + /** + * Gets the `index`th attr of this yeet expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this yeet expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this yeet expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this yeet expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + + final private class ParentYieldExpr extends ParentAstNode, YieldExpr { + override predicate relevantChild(AstNode child) { + none() + or + child = this.getExpr() + } + } + + /** + * A `yield` expression. For example: + * ```rust + * let one = #[coroutine] + * || { + * yield 1; + * }; + * ``` + */ + final class YieldExprCfgNode extends CfgNodeFinal, ExprCfgNode { + private YieldExpr node; + + YieldExprCfgNode() { node = this.getAstNode() } + + /** Gets the underlying `YieldExpr`. */ + YieldExpr getYieldExpr() { result = node } + + /** + * Gets the `index`th attr of this yield expression (0-based). + */ + Attr getAttr(int index) { result = node.getAttr(index) } + + /** + * Gets any of the attrs of this yield expression. + */ + Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this yield expression. + */ + int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the expression of this yield expression, if it exists. + */ + ExprCfgNode getExpr() { + any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result) + } + + /** + * Holds if `getExpr()` exists. + */ + predicate hasExpr() { exists(this.getExpr()) } + } + } + + module Consistency { + private predicate hasCfgNode(AstNode astNode) { astNode = any(CfgNode cfgNode).getAstNode() } + + query predicate missingCfgChild(CfgNode parent, string pred, int i, AstNode child) { + none() + or + pred = "getExpr" and + parent = + any(Nodes::ArrayExprCfgNode cfgNode, ArrayExpr astNode | + astNode = cfgNode.getArrayExpr() and + child = getDesugared(astNode.getExpr(i)) and + hasCfgNode(child) and + not child = cfgNode.getExpr(i).getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::AsmExprCfgNode cfgNode, AsmExpr astNode | + astNode = cfgNode.getAsmExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::AwaitExprCfgNode cfgNode, AwaitExpr astNode | + astNode = cfgNode.getAwaitExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::BecomeExprCfgNode cfgNode, BecomeExpr astNode | + astNode = cfgNode.getBecomeExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getLhs" and + parent = + any(Nodes::BinaryExprCfgNode cfgNode, BinaryExpr astNode | + astNode = cfgNode.getBinaryExpr() and + child = getDesugared(astNode.getLhs()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getLhs().getAstNode() + | + cfgNode + ) + or + pred = "getRhs" and + parent = + any(Nodes::BinaryExprCfgNode cfgNode, BinaryExpr astNode | + astNode = cfgNode.getBinaryExpr() and + child = getDesugared(astNode.getRhs()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getRhs().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::BoxPatCfgNode cfgNode, BoxPat astNode | + astNode = cfgNode.getBoxPat() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::BreakExprCfgNode cfgNode, BreakExpr astNode | + astNode = cfgNode.getBreakExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getFunction" and + parent = + any(Nodes::CallExprCfgNode cfgNode, CallExpr astNode | + astNode = cfgNode.getCallExpr() and + child = getDesugared(astNode.getFunction()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getFunction().getAstNode() + | + cfgNode + ) + or + pred = "getBlockExpr" and + parent = + any(Nodes::ConstBlockPatCfgNode cfgNode, ConstBlockPat astNode | + astNode = cfgNode.getConstBlockPat() and + child = getDesugared(astNode.getBlockExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getBlockExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::FieldExprCfgNode cfgNode, FieldExpr astNode | + astNode = cfgNode.getFieldExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getIterable" and + parent = + any(Nodes::ForExprCfgNode cfgNode, ForExpr astNode | + astNode = cfgNode.getForExpr() and + child = getDesugared(astNode.getIterable()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getIterable().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::ForExprCfgNode cfgNode, ForExpr astNode | + astNode = cfgNode.getForExpr() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getTemplate" and + parent = + any(Nodes::FormatArgsExprCfgNode cfgNode, FormatArgsExpr astNode | + astNode = cfgNode.getFormatArgsExpr() and + child = getDesugared(astNode.getTemplate()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getTemplate().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::IdentPatCfgNode cfgNode, IdentPat astNode | + astNode = cfgNode.getIdentPat() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getCondition" and + parent = + any(Nodes::IfExprCfgNode cfgNode, IfExpr astNode | + astNode = cfgNode.getIfExpr() and + child = getDesugared(astNode.getCondition()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getCondition().getAstNode() + | + cfgNode + ) + or + pred = "getElse" and + parent = + any(Nodes::IfExprCfgNode cfgNode, IfExpr astNode | + astNode = cfgNode.getIfExpr() and + child = getDesugared(astNode.getElse()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getElse().getAstNode() + | + cfgNode + ) + or + pred = "getThen" and + parent = + any(Nodes::IfExprCfgNode cfgNode, IfExpr astNode | + astNode = cfgNode.getIfExpr() and + child = getDesugared(astNode.getThen()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getThen().getAstNode() + | + cfgNode + ) + or + pred = "getBase" and + parent = + any(Nodes::IndexExprCfgNode cfgNode, IndexExpr astNode | + astNode = cfgNode.getIndexExpr() and + child = getDesugared(astNode.getBase()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getBase().getAstNode() + | + cfgNode + ) + or + pred = "getIndex" and + parent = + any(Nodes::IndexExprCfgNode cfgNode, IndexExpr astNode | + astNode = cfgNode.getIndexExpr() and + child = getDesugared(astNode.getIndex()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getIndex().getAstNode() + | + cfgNode + ) + or + pred = "getScrutinee" and + parent = + any(Nodes::LetExprCfgNode cfgNode, LetExpr astNode | + astNode = cfgNode.getLetExpr() and + child = getDesugared(astNode.getScrutinee()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getScrutinee().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::LetExprCfgNode cfgNode, LetExpr astNode | + astNode = cfgNode.getLetExpr() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getInitializer" and + parent = + any(Nodes::LetStmtCfgNode cfgNode, LetStmt astNode | + astNode = cfgNode.getLetStmt() and + child = getDesugared(astNode.getInitializer()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getInitializer().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::LetStmtCfgNode cfgNode, LetStmt astNode | + astNode = cfgNode.getLetStmt() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getLiteral" and + parent = + any(Nodes::LiteralPatCfgNode cfgNode, LiteralPat astNode | + astNode = cfgNode.getLiteralPat() and + child = getDesugared(astNode.getLiteral()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getLiteral().getAstNode() + | + cfgNode + ) + or + pred = "getLoopBody" and + parent = + any(Nodes::LoopingExprCfgNode cfgNode, LoopingExpr astNode | + astNode = cfgNode.getLoopingExpr() and + child = getDesugared(astNode.getLoopBody()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getLoopBody().getAstNode() + | + cfgNode + ) + or + pred = "getMacroCall" and + parent = + any(Nodes::MacroExprCfgNode cfgNode, MacroExpr astNode | + astNode = cfgNode.getMacroExpr() and + child = getDesugared(astNode.getMacroCall()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getMacroCall().getAstNode() + | + cfgNode + ) + or + pred = "getMacroCall" and + parent = + any(Nodes::MacroPatCfgNode cfgNode, MacroPat astNode | + astNode = cfgNode.getMacroPat() and + child = getDesugared(astNode.getMacroCall()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getMacroCall().getAstNode() + | + cfgNode + ) + or + pred = "getScrutinee" and + parent = + any(Nodes::MatchExprCfgNode cfgNode, MatchExpr astNode | + astNode = cfgNode.getMatchExpr() and + child = getDesugared(astNode.getScrutinee()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getScrutinee().getAstNode() + | + cfgNode + ) + or + pred = "getReceiver" and + parent = + any(Nodes::MethodCallExprCfgNode cfgNode, MethodCallExpr astNode | + astNode = cfgNode.getMethodCallExpr() and + child = getDesugared(astNode.getReceiver()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getReceiver().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::OrPatCfgNode cfgNode, OrPat astNode | + astNode = cfgNode.getOrPat() and + child = getDesugared(astNode.getPat(i)) and + hasCfgNode(child) and + not child = cfgNode.getPat(i).getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::ParamCfgNode cfgNode, Param astNode | + astNode = cfgNode.getParam() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::PrefixExprCfgNode cfgNode, PrefixExpr astNode | + astNode = cfgNode.getPrefixExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getEnd" and + parent = + any(Nodes::RangeExprCfgNode cfgNode, RangeExpr astNode | + astNode = cfgNode.getRangeExpr() and + child = getDesugared(astNode.getEnd()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getEnd().getAstNode() + | + cfgNode + ) + or + pred = "getStart" and + parent = + any(Nodes::RangeExprCfgNode cfgNode, RangeExpr astNode | + astNode = cfgNode.getRangeExpr() and + child = getDesugared(astNode.getStart()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getStart().getAstNode() + | + cfgNode + ) + or + pred = "getEnd" and + parent = + any(Nodes::RangePatCfgNode cfgNode, RangePat astNode | + astNode = cfgNode.getRangePat() and + child = getDesugared(astNode.getEnd()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getEnd().getAstNode() + | + cfgNode + ) + or + pred = "getStart" and + parent = + any(Nodes::RangePatCfgNode cfgNode, RangePat astNode | + astNode = cfgNode.getRangePat() and + child = getDesugared(astNode.getStart()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getStart().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::RefExprCfgNode cfgNode, RefExpr astNode | + astNode = cfgNode.getRefExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::RefPatCfgNode cfgNode, RefPat astNode | + astNode = cfgNode.getRefPat() and + child = getDesugared(astNode.getPat()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getPat().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::ReturnExprCfgNode cfgNode, ReturnExpr astNode | + astNode = cfgNode.getReturnExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getPat" and + parent = + any(Nodes::SlicePatCfgNode cfgNode, SlicePat astNode | + astNode = cfgNode.getSlicePat() and + child = getDesugared(astNode.getPat(i)) and + hasCfgNode(child) and + not child = cfgNode.getPat(i).getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::TryExprCfgNode cfgNode, TryExpr astNode | + astNode = cfgNode.getTryExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getField" and + parent = + any(Nodes::TupleExprCfgNode cfgNode, TupleExpr astNode | + astNode = cfgNode.getTupleExpr() and + child = getDesugared(astNode.getField(i)) and + hasCfgNode(child) and + not child = cfgNode.getField(i).getAstNode() + | + cfgNode + ) + or + pred = "getField" and + parent = + any(Nodes::TuplePatCfgNode cfgNode, TuplePat astNode | + astNode = cfgNode.getTuplePat() and + child = getDesugared(astNode.getField(i)) and + hasCfgNode(child) and + not child = cfgNode.getField(i).getAstNode() + | + cfgNode + ) + or + pred = "getField" and + parent = + any(Nodes::TupleStructPatCfgNode cfgNode, TupleStructPat astNode | + astNode = cfgNode.getTupleStructPat() and + child = getDesugared(astNode.getField(i)) and + hasCfgNode(child) and + not child = cfgNode.getField(i).getAstNode() + | + cfgNode + ) + or + pred = "getCondition" and + parent = + any(Nodes::WhileExprCfgNode cfgNode, WhileExpr astNode | + astNode = cfgNode.getWhileExpr() and + child = getDesugared(astNode.getCondition()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getCondition().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::YeetExprCfgNode cfgNode, YeetExpr astNode | + astNode = cfgNode.getYeetExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + or + pred = "getExpr" and + parent = + any(Nodes::YieldExprCfgNode cfgNode, YieldExpr astNode | + astNode = cfgNode.getYieldExpr() and + child = getDesugared(astNode.getExpr()) and + i = -1 and + hasCfgNode(child) and + not child = cfgNode.getExpr().getAstNode() + | + cfgNode + ) + } + } +} diff --git a/rust/ql/lib/codeql/rust/dataflow/DataFlow.qll b/rust/ql/lib/codeql/rust/dataflow/DataFlow.qll index 3a09df2c45d1..c0d47f8f6a77 100644 --- a/rust/ql/lib/codeql/rust/dataflow/DataFlow.qll +++ b/rust/ql/lib/codeql/rust/dataflow/DataFlow.qll @@ -19,6 +19,12 @@ module DataFlow { final class PostUpdateNode = Node::PostUpdateNode; + final class Content = DataFlowImpl::Content; + + final class VariantContent = DataFlowImpl::VariantContent; + + final class ContentSet = DataFlowImpl::ContentSet; + /** * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local * (intra-procedural) step. diff --git a/rust/ql/lib/codeql/rust/dataflow/Ssa.qll b/rust/ql/lib/codeql/rust/dataflow/Ssa.qll index ff1aae058aaa..5b452a329fa9 100644 --- a/rust/ql/lib/codeql/rust/dataflow/Ssa.qll +++ b/rust/ql/lib/codeql/rust/dataflow/Ssa.qll @@ -9,6 +9,7 @@ module Ssa { private import rust private import codeql.rust.controlflow.BasicBlocks private import codeql.rust.controlflow.ControlFlowGraph + private import codeql.rust.controlflow.CfgNodes private import codeql.rust.controlflow.internal.ControlFlowGraphImpl as CfgImpl private import internal.SsaImpl as SsaImpl @@ -26,7 +27,7 @@ module Ssa { } /** - * Gets a control-flow node that reads the value of this SSA definition. + * Gets a control flow node that reads the value of this SSA definition. * * Example: * @@ -53,7 +54,7 @@ module Ssa { final CfgNode getARead() { result = SsaImpl::getARead(this) } /** - * Gets a first control-flow node that reads the value of this SSA definition. + * Gets a first control flow node that reads the value of this SSA definition. * That is, a read that can be reached from this definition without passing * through other reads. * @@ -82,7 +83,7 @@ module Ssa { final CfgNode getAFirstRead() { SsaImpl::firstRead(this, result) } /** - * Gets a last control-flow node that reads the value of this SSA definition. + * Gets a last control flow node that reads the value of this SSA definition. * That is, a read that can reach the end of the enclosing CFG scope, or another * SSA definition for the source variable, without passing through any other read. * @@ -221,11 +222,11 @@ module Ssa { * end * ``` */ - predicate assigns(CfgNode value) { - exists(AssignmentExpr ae, BasicBlock bb, int i | + predicate assigns(ExprCfgNode value) { + exists(AssignmentExprCfgNode ae, BasicBlock bb, int i | this.definesAt(_, bb, i) and - ae.getLhs() = bb.getNode(i).getAstNode() and - value.getAstNode() = ae.getRhs() + ae.getLhs() = bb.getNode(i) and + value = ae.getRhs() ) } diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll index c31ef9e81072..6fcb878c8ea6 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll @@ -43,22 +43,59 @@ final class DataFlowCallable extends TDataFlowCallable { } final class DataFlowCall extends TDataFlowCall { + private CallExprBaseCfgNode call; + + DataFlowCall() { this = TCall(call) } + /** Gets the underlying call in the CFG, if any. */ - CallExprCfgNode asCallExprCfgNode() { this = TNormalCall(result) } + CallExprCfgNode asCallExprCfgNode() { result = call } - MethodCallExprCfgNode asMethodCallExprCfgNode() { this = TMethodCall(result) } + MethodCallExprCfgNode asMethodCallExprCfgNode() { result = call } - ExprCfgNode asExprCfgNode() { - result = this.asCallExprCfgNode() or result = this.asMethodCallExprCfgNode() - } + CallExprBaseCfgNode asCallBaseExprCfgNode() { result = call } DataFlowCallable getEnclosingCallable() { - result = TCfgScope(this.asExprCfgNode().getExpr().getEnclosingCfgScope()) + result = TCfgScope(call.getExpr().getEnclosingCfgScope()) } - string toString() { result = this.asExprCfgNode().toString() } + string toString() { result = this.asCallBaseExprCfgNode().toString() } - Location getLocation() { result = this.asExprCfgNode().getLocation() } + Location getLocation() { result = this.asCallBaseExprCfgNode().getLocation() } +} + +/** + * The position of a parameter or an argument in a function or call. + * + * As there is a 1-to-1 correspondence between parameter positions and + * arguments positions in Rust we use the same type for both. + */ +final class ParameterPosition extends TParameterPosition { + /** Gets the underlying integer position, if any. */ + int getPosition() { this = TPositionalParameterPosition(result) } + + /** Holds if this position represents the `self` position. */ + predicate isSelf() { this = TSelfParameterPosition() } + + /** Gets a textual representation of this position. */ + string toString() { + result = this.getPosition().toString() + or + result = "self" and this.isSelf() + } + + ParamBase getParameterIn(ParamList ps) { + result = ps.getParam(this.getPosition()) + or + result = ps.getSelfParam() and this.isSelf() + } +} + +/** Holds if `arg` is an argument of `call` at the position `pos`. */ +private predicate isArgumentForCall(ExprCfgNode arg, CallExprBaseCfgNode call, ParameterPosition pos) { + arg = call.getArgument(pos.getPosition()) + or + // The self argument in a method call. + arg = call.(MethodCallExprCfgNode).getReceiver() and pos.isSelf() } module Node { @@ -76,7 +113,12 @@ module Node { /** * Gets the expression that corresponds to this node, if any. */ - Expr asExpr() { none() } + ExprCfgNode asExpr() { none() } + + /** + * Gets the pattern that corresponds to this node, if any. + */ + PatCfgNode asPat() { none() } /** Gets the enclosing callable. */ DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) } @@ -93,11 +135,6 @@ module Node { * Gets this node's underlying SSA definition, if any. */ Ssa::Definition asDefinition() { none() } - - /** - * Gets the parameter that corresponds to this node, if any. - */ - Param asParameter() { none() } } /** A node type that is not implemented. */ @@ -111,24 +148,24 @@ module Node { override Location getLocation() { none() } } - /** A data flow node that corresponds to a CFG node for an AST node. */ + /** A data flow node that corresponds directly to a CFG node for an AST node. */ abstract class AstCfgFlowNode extends Node { AstCfgNode n; - override CfgNode getCfgNode() { result = n } + final override CfgNode getCfgNode() { result = n } - override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() } + final override CfgScope getCfgScope() { result = n.getAstNode().getEnclosingCfgScope() } - override Location getLocation() { result = n.getAstNode().getLocation() } + final override Location getLocation() { result = n.getAstNode().getLocation() } - override string toString() { result = n.getAstNode().toString() } + final override string toString() { result = n.getAstNode().toString() } } /** * A node in the data flow graph that corresponds to an expression in the * AST. * - * Note that because of control-flow splitting, one `Expr` may correspond + * Note that because of control flow splitting, one `Expr` may correspond * to multiple `ExprNode`s, just like it may correspond to multiple * `ControlFlow::Node`s. */ @@ -137,7 +174,7 @@ module Node { ExprNode() { this = TExprNode(n) } - override Expr asExpr() { result = n.getExpr() } + override ExprCfgNode asExpr() { result = n } } final class PatNode extends AstCfgFlowNode, TPatNode { @@ -145,8 +182,7 @@ module Node { PatNode() { this = TPatNode(n) } - /** Gets the `Pat` in the AST that this node corresponds to. */ - Pat getPat() { result = n.getPat() } + override PatCfgNode asPat() { result = n } } /** @@ -154,15 +190,17 @@ module Node { * flow graph. */ final class ParameterNode extends AstCfgFlowNode, TParameterNode { - override ParamCfgNode n; + override ParamBaseCfgNode n; ParameterNode() { this = TParameterNode(n) } - /** Gets the parameter in the AST that this node corresponds to. */ - Param getParameter() { result = n.getParam() } + /** Gets the parameter in the CFG that this node corresponds to. */ + ParamBaseCfgNode getParameter() { result = n } } - final class ArgumentNode = NaNode; + final class ArgumentNode extends ExprNode { + ArgumentNode() { isArgumentForCall(n, _, _) } + } /** An SSA node. */ class SsaNode extends Node, TSsaNode { @@ -185,7 +223,7 @@ module Node { /** A data flow node that represents a value returned by a callable. */ final class ReturnNode extends ExprNode { - ReturnNode() { this.getCfgNode().getASuccessor() instanceof ExitCfgNode } + ReturnNode() { this.getCfgNode().getASuccessor() instanceof AnnotatedExitCfgNode } ReturnKind getKind() { any() } } @@ -197,10 +235,10 @@ module Node { } final private class ExprOutNode extends ExprNode, OutNode { - ExprOutNode() { this.asExpr() instanceof CallExpr } + ExprOutNode() { this.asExpr() instanceof CallExprBaseCfgNode } /** Gets the underlying call CFG node that includes this out node. */ - override DataFlowCall getCall() { result.asExprCfgNode() = this.getCfgNode() } + override DataFlowCall getCall() { result.asCallBaseExprCfgNode() = this.getCfgNode() } } /** @@ -214,9 +252,19 @@ module Node { * Nodes corresponding to AST elements, for example `ExprNode`, usually refer * to the value before the update. */ - final class PostUpdateNode extends Node::NaNode { + final class PostUpdateNode extends Node, TArgumentPostUpdateNode { + private ExprCfgNode n; + + PostUpdateNode() { this = TArgumentPostUpdateNode(n) } + /** Gets the node before the state update. */ - Node getPreUpdateNode() { none() } + Node getPreUpdateNode() { result = TExprNode(n) } + + final override CfgScope getCfgScope() { result = n.getScope() } + + final override Location getLocation() { result = n.getLocation() } + + final override string toString() { result = n.toString() } } final class CastNode = NaNode; @@ -226,51 +274,42 @@ final class Node = Node::Node; /** Provides logic related to SSA. */ module SsaFlow { - private module Impl = SsaImpl::DataFlowIntegration; + private module SsaFlow = SsaImpl::DataFlowIntegration; - private Node::ParameterNode toParameterNode(Param p) { result.getParameter() = p } + private Node::ParameterNode toParameterNode(ParamCfgNode p) { + result.(Node::ParameterNode).getParameter() = p + } /** Converts a control flow node into an SSA control flow node. */ - Impl::Node asNode(Node n) { + SsaFlow::Node asNode(Node n) { n = TSsaNode(result) or - result.(Impl::ExprNode).getExpr() = n.(Node::ExprNode).getCfgNode() + result.(SsaFlow::ExprNode).getExpr() = n.asExpr() or - n = toParameterNode(result.(Impl::ParameterNode).getParameter()) + n = toParameterNode(result.(SsaFlow::ParameterNode).getParameter()) } predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) { - Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep) + SsaFlow::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep) } predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) { - Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo)) + SsaFlow::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo)) } } -/** - * Holds for expressions `e` that evaluate to the value of any last (in - * evaluation order) subexpressions within it. E.g., expressions that propagate - * a values from a subexpression. - * - * For instance, the predicate holds for if expressions as `if b { e1 } else { - * e2 }` evalates to the value of one of the subexpressions `e1` or `e2`. - */ -private predicate propagatesValue(Expr e) { - e instanceof IfExpr or - e instanceof LoopExpr or - e instanceof ReturnExpr or - e instanceof BreakExpr or - e.(BlockExpr).getStmtList().hasTailExpr() or - e instanceof MatchExpr -} - /** * Gets a node that may execute last in `n`, and which, when it executes last, * will be the value of `n`. */ -private ExprCfgNode getALastEvalNode(ExprCfgNode n) { - propagatesValue(n.getExpr()) and result.getASuccessor() = n +private ExprCfgNode getALastEvalNode(ExprCfgNode e) { + e = any(IfExprCfgNode n | result = [n.getThen(), n.getElse()]) or + result = e.(LoopExprCfgNode).getLoopBody() or + result = e.(ReturnExprCfgNode).getExpr() or + result = e.(BreakExprCfgNode).getExpr() or + result = e.(BlockExprCfgNode).getTailExpr() or + result = e.(MatchExprCfgNode).getArmExpr(_) or + result.(BreakExprCfgNode).getTarget() = e } module LocalFlow { @@ -278,26 +317,182 @@ module LocalFlow { predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) { nodeFrom.getCfgNode() = getALastEvalNode(nodeTo.getCfgNode()) or - exists(LetStmt s | - nodeFrom.getCfgNode().getAstNode() = s.getInitializer() and - nodeTo.getCfgNode().getAstNode() = s.getPat() + exists(LetStmtCfgNode s | + nodeFrom.getCfgNode() = s.getInitializer() and + nodeTo.getCfgNode() = s.getPat() ) or // An edge from a pattern/expression to its corresponding SSA definition. nodeFrom.(Node::AstCfgFlowNode).getCfgNode() = nodeTo.(Node::SsaNode).getDefinitionExt().(Ssa::WriteDefinition).getControlFlowNode() or + nodeFrom.(Node::ParameterNode).getParameter().(ParamCfgNode).getPat() = nodeTo.asPat() + or SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _) + or + exists(AssignmentExprCfgNode a | + a.getRhs() = nodeFrom.getCfgNode() and + a.getLhs() = nodeTo.getCfgNode() + ) + or + exists(MatchExprCfgNode match | + nodeFrom.asExpr() = match.getScrutinee() and + nodeTo.asPat() = match.getArmPat(_) + ) + or + nodeFrom.asPat().(OrPatCfgNode).getAPat() = nodeTo.asPat() + } +} + +private import codeql.util.Option + +private class CrateOrigin extends string { + CrateOrigin() { + this = [any(Item i).getCrateOrigin(), any(Resolvable r).getResolvedCrateOrigin()] + } +} + +private class CrateOriginOption = Option::Option; + +pragma[nomagic] +private predicate hasExtendedCanonicalPath(Item i, CrateOriginOption crate, string path) { + path = i.getExtendedCanonicalPath() and + ( + crate.asSome() = i.getCrateOrigin() + or + crate.isNone() and + not i.hasCrateOrigin() + ) +} + +pragma[nomagic] +private predicate variantHasExtendedCanonicalPath( + Enum e, Variant v, CrateOriginOption crate, string path, string name +) { + hasExtendedCanonicalPath(e, crate, path) and + v = e.getVariantList().getAVariant() and + name = v.getName().getText() +} + +pragma[nomagic] +private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption crate, string path) { + path = r.getResolvedPath() and + ( + crate.asSome() = r.getResolvedCrateOrigin() + or + crate.isNone() and + not r.hasResolvedCrateOrigin() + ) +} + +/** + * A path to a value contained in an object. For example a field name of a struct. + */ +abstract class Content extends TContent { + /** Gets a textual representation of this content. */ + abstract string toString(); +} + +/** A canonical path pointing to an enum variant. */ +private class VariantCanonicalPath extends MkVariantCanonicalPath { + CrateOriginOption crate; + string path; + string name; + + VariantCanonicalPath() { this = MkVariantCanonicalPath(crate, path, name) } + + /** Gets the underlying variant. */ + Variant getVariant() { variantHasExtendedCanonicalPath(_, result, crate, path, name) } + + string toString() { result = name } + + Location getLocation() { result = this.getVariant().getLocation() } +} + +/** + * A variant of an `enum`. In addition to the variant itself, this also includes the + * position (for tuple variants) or the field name (for record variants). + */ +abstract class VariantContent extends Content { } + +/** A tuple variant. */ +private class VariantPositionContent extends VariantContent, TVariantPositionContent { + private VariantCanonicalPath v; + private int pos_; + + VariantPositionContent() { this = TVariantPositionContent(v, pos_) } + + VariantCanonicalPath getVariantCanonicalPath(int pos) { result = v and pos = pos_ } + + final override string toString() { + // only print indices when the arity is > 1 + if exists(TVariantPositionContent(v, 1)) + then result = v.toString() + "(" + pos_ + ")" + else result = v.toString() } } -private class DataFlowCallableAlias = DataFlowCallable; +/** A record variant. */ +private class VariantFieldContent extends VariantContent, TVariantFieldContent { + private VariantCanonicalPath v; + private string field_; -private class ReturnKindAlias = ReturnKind; + VariantFieldContent() { this = TVariantFieldContent(v, field_) } -private class DataFlowCallAlias = DataFlowCall; + VariantCanonicalPath getVariantCanonicalPath(string field) { result = v and field = field_ } + + final override string toString() { + // only print field when the arity is > 1 + if strictcount(string f | exists(TVariantFieldContent(v, f))) > 1 + then result = v.toString() + "{" + field_ + "}" + else result = v.toString() + } +} + +/** A value that represents a set of `Content`s. */ +abstract class ContentSet extends TContentSet { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets a content that may be stored into when storing into this set. */ + abstract Content getAStoreContent(); + + /** Gets a content that may be read from when reading from this set. */ + abstract Content getAReadContent(); +} + +final private class SingletonContentSet extends ContentSet, TSingletonContentSet { + private Content c; + + SingletonContentSet() { this = TSingletonContentSet(c) } + + Content getContent() { result = c } + + override string toString() { result = c.toString() } + + override Content getAStoreContent() { result = c } + + override Content getAReadContent() { result = c } +} + +// Defines a set of aliases needed for the `RustDataFlow` module +private module Aliases { + class DataFlowCallableAlias = DataFlowCallable; + + class ReturnKindAlias = ReturnKind; + + class DataFlowCallAlias = DataFlowCall; + + class ParameterPositionAlias = ParameterPosition; + + class ContentAlias = Content; + + class ContentSetAlias = ContentSet; +} module RustDataFlow implements InputSig { + private import Aliases + /** * An element, viewed as a node in a data flow graph. Either an expression * (`ExprNode`) or a parameter (`ParameterNode`). @@ -316,9 +511,15 @@ module RustDataFlow implements InputSig { final class CastNode = Node::NaNode; - predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) { none() } + /** Holds if `p` is a parameter of `c` at the position `pos`. */ + predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) { + p.getCfgNode().getAstNode() = pos.getParameterIn(c.asCfgScope().(Callable).getParamList()) + } - predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) { none() } + /** Holds if `n` is an argument of `c` at the position `pos`. */ + predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) { + isArgumentForCall(n.getCfgNode(), call.asCallBaseExprCfgNode(), pos) + } DataFlowCallable nodeGetEnclosingCallable(Node node) { result = node.getEnclosingCallable() } @@ -329,7 +530,7 @@ module RustDataFlow implements InputSig { class DataFlowExpr = ExprCfgNode; /** Gets the node corresponding to `e`. */ - Node exprNode(DataFlowExpr e) { result.getCfgNode() = e } + Node exprNode(DataFlowExpr e) { result.asExpr() = e } final class DataFlowCall = DataFlowCallAlias; @@ -337,14 +538,19 @@ module RustDataFlow implements InputSig { final class ReturnKind = ReturnKindAlias; + pragma[nomagic] + private Resolvable getCallResolvable(CallExprBase call) { + result = call.(MethodCallExpr) + or + result = call.(CallExpr).getFunction().(PathExpr).getPath() + } + /** Gets a viable implementation of the target of the given `Call`. */ - DataFlowCallable viableCallable(DataFlowCall c) { - exists(Function f, string name | result.asCfgScope() = f and name = f.getName().toString() | - if f.getParamList().hasSelfParam() - then name = c.asMethodCallExprCfgNode().getMethodCallExpr().getNameRef().getText() - else - name = - c.asCallExprCfgNode().getCallExpr().getExpr().(PathExpr).getPath().getPart().toString() + DataFlowCallable viableCallable(DataFlowCall call) { + exists(Resolvable r, string path, CrateOriginOption crate | + hasExtendedCanonicalPath(result.asCfgScope(), crate, path) and + r = getCallResolvable(call.asCallBaseExprCfgNode().getExpr()) and + resolveExtendedCanonicalPath(r, crate, path) ) } @@ -358,44 +564,33 @@ module RustDataFlow implements InputSig { // NOTE: For now we use the type `Unit` and do not benefit from type // information in the data flow analysis. - final class DataFlowType = Unit; + final class DataFlowType extends Unit { + string toString() { result = "" } + } predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() } predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() } - final class Content = Void; - - predicate forceHighPrecision(Content c) { none() } - - class ContentSet extends TContentSet { - /** Gets a textual representation of this element. */ - string toString() { result = "ContentSet" } + class Content = ContentAlias; - /** Gets a content that may be stored into when storing into this set. */ - Content getAStoreContent() { none() } + class ContentSet = ContentSetAlias; - /** Gets a content that may be read from when reading from this set. */ - Content getAReadContent() { none() } - } + predicate forceHighPrecision(Content c) { none() } - final class ContentApprox = Void; + final class ContentApprox = Content; // TODO: Implement if needed - ContentApprox getContentApprox(Content c) { any() } + ContentApprox getContentApprox(Content c) { result = c } - class ParameterPosition extends string { - ParameterPosition() { this = "pos" } - } + class ParameterPosition = ParameterPositionAlias; - class ArgumentPosition extends string { - ArgumentPosition() { this = "pos" } - } + class ArgumentPosition = ParameterPosition; /** * Holds if the parameter position `ppos` matches the argument position * `apos`. */ - predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { none() } + predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos } /** * Holds if there is a simple local flow step from `node1` to `node2`. These @@ -413,19 +608,95 @@ module RustDataFlow implements InputSig { */ predicate jumpStep(Node node1, Node node2) { none() } + /** Holds if path `p` resolves to variant `v`. */ + private predicate pathResolveToVariantCanonicalPath(Path p, VariantCanonicalPath v) { + exists(CrateOriginOption crate, string path | + resolveExtendedCanonicalPath(p.getQualifier(), crate, path) and + v = MkVariantCanonicalPath(crate, path, p.getPart().getNameRef().getText()) + ) + or + // TODO: Remove once library types are extracted + not p.hasQualifier() and + v = MkVariantCanonicalPath(_, "crate::std::option::Option", p.getPart().getNameRef().getText()) + or + // TODO: Remove once library types are extracted + not p.hasQualifier() and + v = MkVariantCanonicalPath(_, "crate::std::result::Result", p.getPart().getNameRef().getText()) + } + + /** Holds if `p` destructs an enum variant `v`. */ + pragma[nomagic] + private predicate tupleVariantDestruction(TupleStructPat p, VariantCanonicalPath v) { + pathResolveToVariantCanonicalPath(p.getPath(), v) + } + + /** Holds if `p` destructs an enum variant `v`. */ + pragma[nomagic] + private predicate recordVariantDestruction(RecordPat p, VariantCanonicalPath v) { + pathResolveToVariantCanonicalPath(p.getPath(), v) + } + /** * Holds if data can flow from `node1` to `node2` via a read of `c`. Thus, * `node1` references an object with a content `c.getAReadContent()` whose * value ends up in `node2`. */ - predicate readStep(Node node1, ContentSet c, Node node2) { none() } + predicate readStep(Node node1, ContentSet cs, Node node2) { + exists(Content c | c = cs.(SingletonContentSet).getContent() | + exists(TupleStructPatCfgNode pat, int pos | + pat = node1.asPat() and + tupleVariantDestruction(pat.getPat(), + c.(VariantPositionContent).getVariantCanonicalPath(pos)) and + node2.asPat() = pat.getField(pos) + ) + or + exists(RecordPatCfgNode pat, string field | + pat = node1.asPat() and + recordVariantDestruction(pat.getPat(), + c.(VariantFieldContent).getVariantCanonicalPath(field)) and + node2.asPat() = pat.getFieldPat(field) + ) + ) + } + + /** Holds if `ce` constructs an enum value of type `v`. */ + pragma[nomagic] + private predicate tupleVariantConstruction(CallExpr ce, VariantCanonicalPath v) { + pathResolveToVariantCanonicalPath(ce.getFunction().(PathExpr).getPath(), v) + } + + /** Holds if `re` constructs an enum value of type `v`. */ + pragma[nomagic] + private predicate recordVariantConstruction(RecordExpr re, VariantCanonicalPath v) { + pathResolveToVariantCanonicalPath(re.getPath(), v) + } /** * Holds if data can flow from `node1` to `node2` via a store into `c`. Thus, * `node2` references an object with a content `c.getAStoreContent()` that * contains the value of `node1`. */ - predicate storeStep(Node node1, ContentSet c, Node node2) { none() } + predicate storeStep(Node node1, ContentSet cs, Node node2) { + exists(Content c | c = cs.(SingletonContentSet).getContent() | + node2.asExpr() = + any(CallExprCfgNode call, int pos | + tupleVariantConstruction(call.getCallExpr(), + c.(VariantPositionContent).getVariantCanonicalPath(pos)) and + node1.asExpr() = call.getArgument(pos) + | + call + ) + or + node2.asExpr() = + any(RecordExprCfgNode re, string field | + recordVariantConstruction(re.getRecordExpr(), + c.(VariantFieldContent).getVariantCanonicalPath(field)) and + node1.asExpr() = re.getFieldExpr(field) + | + re + ) + ) + } /** * Holds if values stored inside content `c` are cleared at node `n`. For example, @@ -492,8 +763,6 @@ module RustDataFlow implements InputSig { class DataFlowSecondLevelScope = Void; } -final class ContentSet = RustDataFlow::ContentSet; - import MakeImpl /** A collection of cached types and predicates to be evaluated in the same stage. */ @@ -502,22 +771,13 @@ private module Cached { cached newtype TNode = TExprNode(ExprCfgNode n) or - TParameterNode(ParamCfgNode p) or + TParameterNode(ParamBaseCfgNode p) or TPatNode(PatCfgNode p) or + TArgumentPostUpdateNode(ExprCfgNode e) { isArgumentForCall(e, _, _) } or TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) cached - newtype TDataFlowCall = - TNormalCall(CallExprCfgNode c) or - TMethodCall(MethodCallExprCfgNode c) - - cached - newtype TOptionalContentSet = - TAnyElementContent() or - TAnyContent() - - cached - class TContentSet = TAnyElementContent or TAnyContent; + newtype TDataFlowCall = TCall(CallExprBaseCfgNode c) cached newtype TDataFlowCallable = TCfgScope(CfgScope scope) @@ -527,6 +787,49 @@ private module Cached { predicate localFlowStepImpl(Node::Node nodeFrom, Node::Node nodeTo) { LocalFlow::localFlowStepCommon(nodeFrom, nodeTo) } + + cached + newtype TParameterPosition = + TPositionalParameterPosition(int i) { + i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1] + } or + TSelfParameterPosition() + + cached + newtype TVariantCanonicalPath = + MkVariantCanonicalPath(CrateOriginOption crate, string path, string name) { + variantHasExtendedCanonicalPath(_, _, crate, path, name) + or + // TODO: Remove once library types are extracted + crate.isNone() and + path = "crate::std::option::Option" and + name = "Some" + or + // TODO: Remove once library types are extracted + crate.isNone() and + path = "crate::std::result::Result" and + name = ["Ok", "Err"] + } + + cached + newtype TContent = + TVariantPositionContent(VariantCanonicalPath v, int pos) { + pos in [0 .. v.getVariant().getFieldList().(TupleFieldList).getNumberOfFields() - 1] + or + // TODO: Remove once library types are extracted + v = MkVariantCanonicalPath(_, "crate::std::option::Option", "Some") and + pos = 0 + or + // TODO: Remove once library types are extracted + v = MkVariantCanonicalPath(_, "crate::std::result::Result", ["Ok", "Err"]) and + pos = 0 + } or + TVariantFieldContent(VariantCanonicalPath v, string field) { + field = v.getVariant().getFieldList().(RecordFieldList).getAField().getName().getText() + } + + cached + newtype TContentSet = TSingletonContentSet(Content c) } import Cached diff --git a/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll b/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll index d5263fca8106..64e2d54722d8 100644 --- a/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll +++ b/rust/ql/lib/codeql/rust/dataflow/internal/SsaImpl.qll @@ -24,6 +24,8 @@ predicate variableWrite(AstNode write, Variable v) { not isUnitializedLet(pat, v) ) or + exists(SelfParam self | self = write and self = v.getSelfParam()) + or exists(VariableAccess access | access = write and access.getVariable() = v @@ -474,14 +476,14 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu /** Holds if SSA definition `def` assigns `value` to the underlying variable. */ predicate ssaDefAssigns(WriteDefinition def, Expr value) { - exists(BasicBlock bb, int i | def.definesAt(_, bb, i) and value = bb.getNode(i)) + none() // handled in `DataFlowImpl.qll` instead } - class Parameter = Param; + class Parameter = CfgNodes::ParamBaseCfgNode; /** Holds if SSA definition `def` initializes parameter `p` at function entry. */ predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) { - exists(BasicBlock bb, int i | bb.getNode(i).getAstNode() = p and def.definesAt(_, bb, i)) + none() // handled in `DataFlowImpl.qll` instead } class Guard extends CfgNodes::AstCfgNode { diff --git a/rust/ql/lib/codeql/rust/elements.qll b/rust/ql/lib/codeql/rust/elements.qll index b516d8a9d185..e37dde90d618 100644 --- a/rust/ql/lib/codeql/rust/elements.qll +++ b/rust/ql/lib/codeql/rust/elements.qll @@ -4,6 +4,7 @@ */ import codeql.rust.elements.Abi +import codeql.rust.elements.Addressable import codeql.rust.elements.ArgList import codeql.rust.elements.ArrayExpr import codeql.rust.elements.ArrayType @@ -64,6 +65,7 @@ import codeql.rust.elements.InferType import codeql.rust.elements.Item import codeql.rust.elements.ItemList import codeql.rust.elements.Label +import codeql.rust.elements.LabelableExpr import codeql.rust.elements.LetElse import codeql.rust.elements.LetExpr import codeql.rust.elements.LetStmt @@ -74,6 +76,7 @@ import codeql.rust.elements.LiteralExpr import codeql.rust.elements.LiteralPat import codeql.rust.elements.Locatable import codeql.rust.elements.LoopExpr +import codeql.rust.elements.LoopingExpr import codeql.rust.elements.MacroCall import codeql.rust.elements.MacroDef import codeql.rust.elements.MacroExpr @@ -96,6 +99,7 @@ import codeql.rust.elements.NeverType import codeql.rust.elements.OffsetOfExpr import codeql.rust.elements.OrPat import codeql.rust.elements.Param +import codeql.rust.elements.ParamBase import codeql.rust.elements.ParamList import codeql.rust.elements.ParenExpr import codeql.rust.elements.ParenPat diff --git a/rust/ql/lib/codeql/rust/elements/Addressable.qll b/rust/ql/lib/codeql/rust/elements/Addressable.qll new file mode 100644 index 000000000000..c5edd19adcb0 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/Addressable.qll @@ -0,0 +1,14 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `Addressable`. + */ + +private import internal.AddressableImpl +import codeql.rust.elements.AstNode + +/** + * Something that can be addressed by a path. + * + * TODO: This does not yet include all possible cases. + */ +final class Addressable = Impl::Addressable; diff --git a/rust/ql/lib/codeql/rust/elements/BlockExpr.qll b/rust/ql/lib/codeql/rust/elements/BlockExpr.qll index a87bbe472528..9e87d381525d 100644 --- a/rust/ql/lib/codeql/rust/elements/BlockExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/BlockExpr.qll @@ -5,8 +5,7 @@ private import internal.BlockExprImpl import codeql.rust.elements.Attr -import codeql.rust.elements.Expr -import codeql.rust.elements.Label +import codeql.rust.elements.LabelableExpr import codeql.rust.elements.StmtList /** diff --git a/rust/ql/lib/codeql/rust/elements/ForExpr.qll b/rust/ql/lib/codeql/rust/elements/ForExpr.qll index c4ef6f9faffc..cfb2586202ed 100644 --- a/rust/ql/lib/codeql/rust/elements/ForExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/ForExpr.qll @@ -5,9 +5,8 @@ private import internal.ForExprImpl import codeql.rust.elements.Attr -import codeql.rust.elements.BlockExpr import codeql.rust.elements.Expr -import codeql.rust.elements.Label +import codeql.rust.elements.LoopingExpr import codeql.rust.elements.Pat /** diff --git a/rust/ql/lib/codeql/rust/elements/Format.qll b/rust/ql/lib/codeql/rust/elements/Format.qll index 0c8b5d1c5413..f8b705be4fdb 100644 --- a/rust/ql/lib/codeql/rust/elements/Format.qll +++ b/rust/ql/lib/codeql/rust/elements/Format.qll @@ -5,6 +5,7 @@ private import internal.FormatImpl import codeql.rust.elements.FormatArgsExpr +import codeql.rust.elements.FormatArgument import codeql.rust.elements.Locatable /** diff --git a/rust/ql/lib/codeql/rust/elements/FormatArgsExpr.qll b/rust/ql/lib/codeql/rust/elements/FormatArgsExpr.qll index 226b4d211aae..419a48a53351 100644 --- a/rust/ql/lib/codeql/rust/elements/FormatArgsExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/FormatArgsExpr.qll @@ -6,12 +6,17 @@ private import internal.FormatArgsExprImpl import codeql.rust.elements.Attr import codeql.rust.elements.Expr +import codeql.rust.elements.Format import codeql.rust.elements.FormatArgsArg /** * A FormatArgsExpr. For example: * ```rust - * todo!() + * format_args!("no args"); + * format_args!("{} foo {:?}", 1, 2); + * format_args!("{b} foo {a:?}", a=1, b=2); + * let (x, y) = (1, 42); + * format_args!("{x}, {y}"); * ``` */ final class FormatArgsExpr = Impl::FormatArgsExpr; diff --git a/rust/ql/lib/codeql/rust/elements/FormatArgument.qll b/rust/ql/lib/codeql/rust/elements/FormatArgument.qll index 62313c523727..00e9007434bb 100644 --- a/rust/ql/lib/codeql/rust/elements/FormatArgument.qll +++ b/rust/ql/lib/codeql/rust/elements/FormatArgument.qll @@ -5,6 +5,7 @@ private import internal.FormatArgumentImpl import codeql.rust.elements.Format +import codeql.rust.elements.FormatTemplateVariableAccess import codeql.rust.elements.Locatable /** diff --git a/rust/ql/lib/codeql/rust/elements/Item.qll b/rust/ql/lib/codeql/rust/elements/Item.qll index 838ba32b964c..b95620551bad 100644 --- a/rust/ql/lib/codeql/rust/elements/Item.qll +++ b/rust/ql/lib/codeql/rust/elements/Item.qll @@ -4,6 +4,7 @@ */ private import internal.ItemImpl +import codeql.rust.elements.Addressable import codeql.rust.elements.Stmt /** diff --git a/rust/ql/lib/codeql/rust/elements/LabelableExpr.qll b/rust/ql/lib/codeql/rust/elements/LabelableExpr.qll new file mode 100644 index 000000000000..c2a042595a19 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/LabelableExpr.qll @@ -0,0 +1,13 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `LabelableExpr`. + */ + +private import internal.LabelableExprImpl +import codeql.rust.elements.Expr +import codeql.rust.elements.Label + +/** + * The base class for expressions that can be labeled (`LoopExpr`, `ForExpr`, `WhileExpr` or `BlockExpr`). + */ +final class LabelableExpr = Impl::LabelableExpr; diff --git a/rust/ql/lib/codeql/rust/elements/LoopExpr.qll b/rust/ql/lib/codeql/rust/elements/LoopExpr.qll index 6abc449c6261..cdb6d743b50f 100644 --- a/rust/ql/lib/codeql/rust/elements/LoopExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/LoopExpr.qll @@ -5,9 +5,7 @@ private import internal.LoopExprImpl import codeql.rust.elements.Attr -import codeql.rust.elements.BlockExpr -import codeql.rust.elements.Expr -import codeql.rust.elements.Label +import codeql.rust.elements.LoopingExpr /** * A loop expression. For example: diff --git a/rust/ql/lib/codeql/rust/elements/LoopingExpr.qll b/rust/ql/lib/codeql/rust/elements/LoopingExpr.qll new file mode 100644 index 000000000000..6078afdf762c --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/LoopingExpr.qll @@ -0,0 +1,13 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `LoopingExpr`. + */ + +private import internal.LoopingExprImpl +import codeql.rust.elements.BlockExpr +import codeql.rust.elements.LabelableExpr + +/** + * The base class for expressions that loop (`LoopExpr`, `ForExpr` or `WhileExpr`). + */ +final class LoopingExpr = Impl::LoopingExpr; diff --git a/rust/ql/lib/codeql/rust/elements/Param.qll b/rust/ql/lib/codeql/rust/elements/Param.qll index eb46d206ba48..74eda683740e 100644 --- a/rust/ql/lib/codeql/rust/elements/Param.qll +++ b/rust/ql/lib/codeql/rust/elements/Param.qll @@ -4,15 +4,15 @@ */ private import internal.ParamImpl -import codeql.rust.elements.AstNode -import codeql.rust.elements.Attr +import codeql.rust.elements.ParamBase import codeql.rust.elements.Pat -import codeql.rust.elements.TypeRef /** - * A Param. For example: + * A parameter in a function or method. For example `x` in: * ```rust - * todo!() + * fn new(x: T) -> Foo { + * // ... + * } * ``` */ final class Param = Impl::Param; diff --git a/rust/ql/lib/codeql/rust/elements/ParamBase.qll b/rust/ql/lib/codeql/rust/elements/ParamBase.qll new file mode 100644 index 000000000000..d3a031f4da5b --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/ParamBase.qll @@ -0,0 +1,14 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `ParamBase`. + */ + +private import internal.ParamBaseImpl +import codeql.rust.elements.AstNode +import codeql.rust.elements.Attr +import codeql.rust.elements.TypeRef + +/** + * A normal parameter, `Param`, or a self parameter `SelfParam`. + */ +final class ParamBase = Impl::ParamBase; diff --git a/rust/ql/lib/codeql/rust/elements/Path.qll b/rust/ql/lib/codeql/rust/elements/Path.qll index 530c40397c31..cb228373cf5a 100644 --- a/rust/ql/lib/codeql/rust/elements/Path.qll +++ b/rust/ql/lib/codeql/rust/elements/Path.qll @@ -10,6 +10,7 @@ import codeql.rust.elements.Resolvable /** * A path. For example: * ```rust + * use some_crate::some_module::some_item; * foo::bar; * ``` */ diff --git a/rust/ql/lib/codeql/rust/elements/PathSegment.qll b/rust/ql/lib/codeql/rust/elements/PathSegment.qll index 5566ba322b62..9edc7d6573f7 100644 --- a/rust/ql/lib/codeql/rust/elements/PathSegment.qll +++ b/rust/ql/lib/codeql/rust/elements/PathSegment.qll @@ -14,9 +14,6 @@ import codeql.rust.elements.ReturnTypeSyntax import codeql.rust.elements.TypeRef /** - * A PathSegment. For example: - * ```rust - * todo!() - * ``` + * A path segment, which is one part of a whole path. */ final class PathSegment = Impl::PathSegment; diff --git a/rust/ql/lib/codeql/rust/elements/PathType.qll b/rust/ql/lib/codeql/rust/elements/PathType.qll index e313b9d1b561..773fe910bfa3 100644 --- a/rust/ql/lib/codeql/rust/elements/PathType.qll +++ b/rust/ql/lib/codeql/rust/elements/PathType.qll @@ -8,9 +8,10 @@ import codeql.rust.elements.Path import codeql.rust.elements.TypeRef /** - * A PathType. For example: + * A type referring to a path. For example: * ```rust - * todo!() + * type X = std::collections::HashMap; + * type Y = X::Item; * ``` */ final class PathType = Impl::PathType; diff --git a/rust/ql/lib/codeql/rust/elements/SelfParam.qll b/rust/ql/lib/codeql/rust/elements/SelfParam.qll index 74d2fb5e2ebc..88c1a05d8371 100644 --- a/rust/ql/lib/codeql/rust/elements/SelfParam.qll +++ b/rust/ql/lib/codeql/rust/elements/SelfParam.qll @@ -4,16 +4,16 @@ */ private import internal.SelfParamImpl -import codeql.rust.elements.AstNode -import codeql.rust.elements.Attr import codeql.rust.elements.Lifetime import codeql.rust.elements.Name -import codeql.rust.elements.TypeRef +import codeql.rust.elements.ParamBase /** - * A SelfParam. For example: + * A `self` parameter. For example `self` in: * ```rust - * todo!() + * fn push(&mut self, value: T) { + * // ... + * } * ``` */ final class SelfParam = Impl::SelfParam; diff --git a/rust/ql/lib/codeql/rust/elements/Variant.qll b/rust/ql/lib/codeql/rust/elements/Variant.qll index 6100928696ea..658143dbfa21 100644 --- a/rust/ql/lib/codeql/rust/elements/Variant.qll +++ b/rust/ql/lib/codeql/rust/elements/Variant.qll @@ -4,7 +4,7 @@ */ private import internal.VariantImpl -import codeql.rust.elements.AstNode +import codeql.rust.elements.Addressable import codeql.rust.elements.Attr import codeql.rust.elements.Expr import codeql.rust.elements.FieldList diff --git a/rust/ql/lib/codeql/rust/elements/WhileExpr.qll b/rust/ql/lib/codeql/rust/elements/WhileExpr.qll index 9dcbe9c6346f..fc704d35095a 100644 --- a/rust/ql/lib/codeql/rust/elements/WhileExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/WhileExpr.qll @@ -5,9 +5,8 @@ private import internal.WhileExprImpl import codeql.rust.elements.Attr -import codeql.rust.elements.BlockExpr import codeql.rust.elements.Expr -import codeql.rust.elements.Label +import codeql.rust.elements.LoopingExpr /** * A WhileExpr. For example: diff --git a/rust/ql/lib/codeql/rust/elements/internal/AddressableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/AddressableImpl.qll new file mode 100644 index 000000000000..b3fe47b294a2 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/AddressableImpl.qll @@ -0,0 +1,21 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `Addressable`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.Addressable + +/** + * INTERNAL: This module contains the customizable definition of `Addressable` and should not + * be referenced directly. + */ +module Impl { + /** + * Something that can be addressed by a path. + * + * TODO: This does not yet include all possible cases. + */ + class Addressable extends Generated::Addressable { } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/ArrayExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ArrayExprImpl.qll index ff4ce2248209..8bda9a2d46e2 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ArrayExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ArrayExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ArrayExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.ArrayExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An array expression. For example: * ```rust @@ -19,5 +19,7 @@ module Impl { * [1; 10]; * ``` */ - class ArrayExpr extends Generated::ArrayExpr { } + class ArrayExpr extends Generated::ArrayExpr { + override string toString() { result = "[...]" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll index f2784d058ae7..c33b1f3dd6eb 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/AstNodeImpl.qll @@ -14,6 +14,7 @@ private import codeql.rust.controlflow.ControlFlowGraph module Impl { private import rust private import codeql.rust.elements.internal.generated.ParentChild + private import codeql.rust.controlflow.ControlFlowGraph /** * Gets the immediate parent of a non-`AstNode` element `e`. @@ -62,5 +63,37 @@ module Impl { or this.getParentNode().isInMacroExpansion() } + + /** + * Gets a control flow node for this AST node, if any. + * + * Note that because of _control flow splitting_, one `AstNode` node may correspond + * to multiple `CfgNode`s. Example: + * + * ```rust + * if a && b { + * // ... + * } + * ``` + * + * The CFG for the condition above looks like + * + * ```mermaid + * flowchart TD + * 1["a"] + * 2["b"] + * 3["[false] a && b"] + * 4["[true] a && b"] + * + * 1 -- false --> 3 + * 1 -- true --> 2 + * 2 -- false --> 3 + * 2 -- true --> 4 + * ``` + * + * That is, the AST node for `a && b` corresponds to _two_ CFG nodes (it is + * split into two). + */ + CfgNode getACfgNode() { this = result.getAstNode() } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/AwaitExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/AwaitExprImpl.qll index 39bbe3017df6..d9aa0f8bf448 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/AwaitExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/AwaitExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `AwaitExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.AwaitExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An `await` expression. For example: * ```rust @@ -21,5 +21,7 @@ module Impl { * } * ``` */ - class AwaitExpr extends Generated::AwaitExpr { } + class AwaitExpr extends Generated::AwaitExpr { + override string toString() { result = "await " + this.getExpr().toAbbreviatedString() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/BecomeExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BecomeExprImpl.qll index 748659cfdd32..ded01ec4ef83 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BecomeExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BecomeExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `BecomeExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.BecomeExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A `become` expression. For example: * ```rust @@ -24,5 +24,7 @@ module Impl { * } * ``` */ - class BecomeExpr extends Generated::BecomeExpr { } + class BecomeExpr extends Generated::BecomeExpr { + override string toString() { result = "become " + this.getExpr().toAbbreviatedString() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/BoxPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BoxPatImpl.qll index 06fb2c0fbfa2..45870d14297b 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BoxPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BoxPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `BoxPat`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.BoxPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A box pattern. For example: * ```rust @@ -21,5 +21,7 @@ module Impl { * }; * ``` */ - class BoxPat extends Generated::BoxPat { } + class BoxPat extends Generated::BoxPat { + override string toString() { result = "box " + this.getPat().toAbbreviatedString() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/BreakExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/BreakExprImpl.qll index 4b302674a444..d156e207150c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/BreakExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/BreakExprImpl.qll @@ -5,6 +5,7 @@ */ private import codeql.rust.elements.internal.generated.BreakExpr +import codeql.rust.elements.LabelableExpr /** * INTERNAL: This module contains the customizable definition of `BreakExpr` and should not @@ -102,5 +103,17 @@ module Impl { isLabelled(result, label) ) } + + override string toString() { + result = strictconcat(int i | | this.toStringPart(i), " " order by i) + } + + private string toStringPart(int index) { + index = 0 and result = "break" + or + index = 1 and result = this.getLifetime().toString() + or + index = 2 and result = this.getExpr().toAbbreviatedString() + } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/CallExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/CallExprImpl.qll index c03a7b9ac138..53e4c2de2ccf 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/CallExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/CallExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `CallExpr`. * @@ -6,12 +5,14 @@ */ private import codeql.rust.elements.internal.generated.CallExpr +private import codeql.rust.elements.PathExpr /** * INTERNAL: This module contains the customizable definition of `CallExpr` and should not * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A function call expression. For example: * ```rust @@ -21,5 +22,7 @@ module Impl { * foo(1) = 4; * ``` */ - class CallExpr extends Generated::CallExpr { } + class CallExpr extends Generated::CallExpr { + override string toString() { result = this.getFunction().toAbbreviatedString() + "(...)" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll index 308c321dfbd2..13270d1ca0b3 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/CastExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `CastExpr`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.CastExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A cast expression. For example: * ```rust * value as u64; * ``` */ - class CastExpr extends Generated::CastExpr { } + class CastExpr extends Generated::CastExpr { + override string toString() { + result = this.getExpr().toAbbreviatedString() + " as " + this.getTy().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ClosureExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ClosureExprImpl.qll index b1c6574b17f9..17e373290b50 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ClosureExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ClosureExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ClosureExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.ClosureExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A closure expression. For example: * ```rust @@ -24,5 +24,7 @@ module Impl { * static |x| yield x; * ``` */ - class ClosureExpr extends Generated::ClosureExpr { } + class ClosureExpr extends Generated::ClosureExpr { + override string toString() { result = "|...| " + this.getBody().toAbbreviatedString() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/CommentImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/CommentImpl.qll index 32a4f415ab7c..85b2a4d80d31 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/CommentImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/CommentImpl.qll @@ -20,11 +20,30 @@ module Impl { * ``` */ class Comment extends Generated::Comment { + override string toString() { + result = this.getCommentMarker() + "..." + this.getCommentEndMarker() + } + /** - * Gets the text of this comment, excluding the comment marker. + * Gets the text of this comment, excluding the comment markers. */ string getCommentText() { - exists(string s | s = this.getText() | result = s.regexpCapture("///?\\s*(.*)", 1)) + exists(string s | s = this.getText() | + result = + [ + s.regexpCapture("///?\\s*(.*)", 1), + s.regexpCapture("(?s)/\\*\\*?\\s*(.*?)\\s*\\*/", 1) + ] + ) + } + + /** + * Gets the marker of this comment, that is `"//"`, `"///"`, `"/*"` or `"/**"`. + */ + string getCommentMarker() { result = this.getText().regexpCapture("(?s)(///?|/\\*\\*?).*", 1) } + + private string getCommentEndMarker() { + if this.getCommentMarker() = ["//", "///"] then result = "" else result = "*/" } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ContinueExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ContinueExprImpl.qll index 4328fdfc9f93..ecfcd1a48429 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ContinueExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ContinueExprImpl.qll @@ -49,13 +49,23 @@ module Impl { * ``` */ class ContinueExpr extends Generated::ContinueExpr { + override string toString() { + result = strictconcat(int i | | this.toStringPart(i), " " order by i) + } + + private string toStringPart(int index) { + index = 0 and result = "continue" + or + index = 1 and result = this.getLifetime().getText() + } + /** * Gets the target of this `continue` expression. * * The target is either a `LoopExpr`, a `ForExpr`, or a `WhileExpr`. */ pragma[nomagic] - Expr getTarget() { + LoopingExpr getTarget() { exists(string label | result = getAContinueAncestor(this, label) and BreakExprImpl::isLabelledLoop(result, label) diff --git a/rust/ql/lib/codeql/rust/elements/internal/ElementImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ElementImpl.qll index 6f342c00fd3c..9307a567b6e1 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ElementImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ElementImpl.qll @@ -14,6 +14,14 @@ module Impl { class Element extends Generated::Element { override string toString() { result = this.getAPrimaryQlClass() } + /** + * Returns a string suitable to be inserted into the name of the parent. Typically `"..."`, + * but may be overridden by subclasses. + * + * INTERNAL: Do not use. + */ + string toAbbreviatedString() { result = "..." } + predicate isUnknown() { none() } // compatibility with test generation, to be fixed } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/EnumImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/EnumImpl.qll index bef9d3da903a..0299ce9f05e6 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/EnumImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/EnumImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Enum`. * @@ -12,11 +11,14 @@ private import codeql.rust.elements.internal.generated.Enum * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A Enum. For example: * ```rust * todo!() * ``` */ - class Enum extends Generated::Enum { } + class Enum extends Generated::Enum { + override string toString() { result = "enum " + this.getName().getText() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FieldExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FieldExprImpl.qll index 003d2789e683..b3cd63b79229 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FieldExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FieldExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `FieldExpr`. * @@ -12,11 +11,20 @@ private import codeql.rust.elements.internal.generated.FieldExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A field access expression. For example: * ```rust * x.foo * ``` */ - class FieldExpr extends Generated::FieldExpr { } + class FieldExpr extends Generated::FieldExpr { + override string toString() { + exists(string abbr, string name | + abbr = this.getExpr().toAbbreviatedString() and + name = this.getNameRef().getText() and + if abbr = "..." then result = "... ." + name else result = abbr + "." + name + ) + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ForExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ForExprImpl.qll index a196a6802e9a..b333702c9415 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ForExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ForExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ForExpr`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.ForExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A ForExpr. For example: * ```rust * todo!() * ``` */ - class ForExpr extends Generated::ForExpr { } + class ForExpr extends Generated::ForExpr { + override string toStringPrefix() { + result = "for " + this.getPat().toAbbreviatedString() + " in ..." + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll index 667439777b1a..6cc3aa114616 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll @@ -16,14 +16,15 @@ module Impl { /** * A FormatArgsExpr. For example: * ```rust - * todo!() + * format_args!("no args"); + * format_args!("{} foo {:?}", 1, 2); + * format_args!("{b} foo {a:?}", a=1, b=2); + * let (x, y) = (1, 42); + * format_args!("{x}, {y}"); * ``` */ class FormatArgsExpr extends Generated::FormatArgsExpr { - /** - * Gets the `index`th format of this `FormatArgsExpr`'s formatting template (0-based). - */ - Format getFormat(int index) { + override Format getFormat(int index) { result = rank[index + 1](Format f, int i | f.getParent() = this and f.getIndex() = i | f order by i) } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll index 7370939716d4..6719d9d8cb3c 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll @@ -39,6 +39,8 @@ module Impl { override string toString() { result = name } override Format getParent() { result = Synth::TFormat(parent, index, _, _) } + + override FormatTemplateVariableAccess getVariable() { result.getArgument() = this } } private class FormatSynthLocationImpl extends FormatArgument, LocatableImpl::SynthLocatable { diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll index 59c66768f05f..7cde91053e91 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll @@ -38,6 +38,8 @@ module Impl { override int getIndex() { result = index } + override FormatArgument getArgument() { result.getParent() = this } + /** * Gets the name or position reference of this format, if any. For example `name` and `0` in: * ```rust diff --git a/rust/ql/lib/codeql/rust/elements/internal/FunctionImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FunctionImpl.qll index bff68da5620b..791cf4f9d7fc 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FunctionImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FunctionImpl.qll @@ -25,6 +25,6 @@ module Impl { * ``` */ class Function extends Generated::Function { - override string toString() { result = this.getName().getText() } + override string toString() { result = "fn " + this.getName().getText() } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/GenericArgListImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/GenericArgListImpl.qll index 44d74bffbc6f..a701801b68cf 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/GenericArgListImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/GenericArgListImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `GenericArgList`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.GenericArgList * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * The base class for generic arguments. * ```rust * x.foo::(42); * ``` */ - class GenericArgList extends Generated::GenericArgList { } + class GenericArgList extends Generated::GenericArgList { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = "<...>" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/IfExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/IfExprImpl.qll index f9aec6faed35..c90ee6ccdc06 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/IfExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/IfExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `IfExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.IfExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An `if` expression. For example: * ```rust @@ -27,5 +27,17 @@ module Impl { * }; * ``` */ - class IfExpr extends Generated::IfExpr { } + class IfExpr extends Generated::IfExpr { + override string toString() { result = concat(int i | | this.toStringPart(i), " " order by i) } + + private string toStringPart(int index) { + index = 0 and result = "if" + or + index = 1 and result = this.getCondition().toAbbreviatedString() + or + index = 2 and result = "{...}" + or + index = 3 and this.hasElse() and result = "else {...}" + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplImpl.qll index b1918d16e56e..c75c36b280b9 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Impl`. * @@ -12,11 +11,23 @@ private import codeql.rust.elements.internal.generated.Impl * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A Impl. For example: * ```rust * todo!() * ``` */ - class Impl extends Generated::Impl { } + class Impl extends Generated::Impl { + override string toString() { + exists(string trait | + ( + trait = this.getTrait().toAbbreviatedString() + " for " + or + not this.hasTrait() and trait = "" + ) and + result = "impl " + trait + this.getSelfTy().toAbbreviatedString() + " { ... }" + ) + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/IndexExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/IndexExprImpl.qll index 94ff116cf1d4..2ace04fe3899 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/IndexExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/IndexExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `IndexExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.IndexExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An index expression. For example: * ```rust @@ -19,5 +19,10 @@ module Impl { * list[42] = 1; * ``` */ - class IndexExpr extends Generated::IndexExpr { } + class IndexExpr extends Generated::IndexExpr { + override string toString() { + result = + this.getBase().toAbbreviatedString() + "[" + this.getIndex().toAbbreviatedString() + "]" + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/InferTypeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/InferTypeImpl.qll index b29406661ba9..25c1a40701fd 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/InferTypeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/InferTypeImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `InferType`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.InferType * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A InferType. For example: * ```rust * todo!() * ``` */ - class InferType extends Generated::InferType { } + class InferType extends Generated::InferType { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = "_" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LabelImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LabelImpl.qll index 6740bb23ea88..822029bf3a73 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LabelImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LabelImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Label`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.Label * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A label. For example: * ```rust @@ -21,5 +21,14 @@ module Impl { * }; * ``` */ - class Label extends Generated::Label { } + class Label extends Generated::Label { + override string toString() { result = this.getText() } + + override string toAbbreviatedString() { result = this.getText() } + + /** + * Gets the name of the label, together with the leading `'`. + */ + string getText() { result = this.getLifetime().getText() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LabelableExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LabelableExprImpl.qll new file mode 100644 index 000000000000..070481817145 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/LabelableExprImpl.qll @@ -0,0 +1,38 @@ +/** + * This module provides a hand-modifiable wrapper around the generated class `LabelableExpr`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.LabelableExpr + +/** + * INTERNAL: This module contains the customizable definition of `LabelableExpr` and should not + * be referenced directly. + */ +module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file + /** + * The base class for expressions that can be labeled (`LoopExpr`, `ForExpr`, `WhileExpr` or `BlockExpr`). + */ + class LabelableExpr extends Generated::LabelableExpr { + final override string toString() { + result = strictconcat(int i | | this.toStringPart(i), " " order by i) + } + + private string toStringPart(int index) { + index = 0 and result = this.getLabel().getText() + ":" + or + index = 1 and result = this.toStringPrefix() + or + index = 2 and result = "{ ... }" + } + + /** + * Get the prefix for the string representation of this element. + * + * INTERNAL: Do not use. + */ + string toStringPrefix() { none() } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/LetElseImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LetElseImpl.qll index 2399964cf1af..0ca4e58fb850 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LetElseImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LetElseImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `LetElse`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.LetElse * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A LetElse. For example: * ```rust * todo!() * ``` */ - class LetElse extends Generated::LetElse { } + class LetElse extends Generated::LetElse { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = "else {...}" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LetExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LetExprImpl.qll index 4a99a43ba0fe..b690f2b044b7 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LetExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LetExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `LetExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.LetExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A `let` expression. For example: * ```rust @@ -20,5 +20,15 @@ module Impl { * } * ``` */ - class LetExpr extends Generated::LetExpr { } + class LetExpr extends Generated::LetExpr { + override string toString() { result = concat(int i | | this.toStringPart(i), " " order by i) } + + private string toStringPart(int index) { + index = 0 and result = "let" + or + index = 1 and result = this.getPat().toAbbreviatedString() + or + index = 2 and result = "= " + this.getScrutinee().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LetStmtImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LetStmtImpl.qll index 2bcaa6d7905c..d612c2082a64 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LetStmtImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LetStmtImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `LetStmt`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.LetStmt * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A let statement. For example: * ```rust @@ -25,5 +25,19 @@ module Impl { * }; * ``` */ - class LetStmt extends Generated::LetStmt { } + class LetStmt extends Generated::LetStmt { + override string toString() { + result = strictconcat(int i | | this.toStringPart(i), " " order by i) + } + + private string toStringPart(int index) { + index = 0 and result = "let" + or + index = 1 and result = this.getPat().toAbbreviatedString() + or + index = 2 and result = "= " + this.getInitializer().toAbbreviatedString() + or + index = 3 and result = this.getLetElse().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LifetimeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LifetimeImpl.qll index 3eb13ac87e5c..27b29f64cc9e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LifetimeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LifetimeImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Lifetime`. * @@ -12,11 +11,18 @@ private import codeql.rust.elements.internal.generated.Lifetime * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A Lifetime. For example: * ```rust * todo!() * ``` */ - class Lifetime extends Generated::Lifetime { } + class Lifetime extends Generated::Lifetime { + override string toString() { + result = "'" + this.getText() + or + not this.hasText() and result = "'_" + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll index 1b660b134c43..f68c79da16b1 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LiteralExprImpl.qll @@ -26,6 +26,20 @@ module Impl { * ``` */ class LiteralExpr extends Generated::LiteralExpr { - override string toString() { result = this.getTextValue() } + override string toString() { result = this.getTrimmedText() } + + override string toAbbreviatedString() { result = this.getTrimmedText() } + + /** + * Get the text of this literal, trimmed with `...` if it is too long. + * + * INTERNAL: Do not use. + */ + string getTrimmedText() { + exists(string v | + v = this.getTextValue() and + if v.length() > 30 then result = v.substring(0, 30) + "..." else result = v + ) + } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LiteralPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LiteralPatImpl.qll index a71d9b1bf848..1c59c3fa284a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LiteralPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LiteralPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `LiteralPat`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.LiteralPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A literal pattern. For example: * ```rust @@ -21,5 +21,9 @@ module Impl { * } * ``` */ - class LiteralPat extends Generated::LiteralPat { } + class LiteralPat extends Generated::LiteralPat { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = this.getLiteral().getTrimmedText() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LoopExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LoopExprImpl.qll index c56ea8770d48..732148717054 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LoopExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LoopExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `LoopExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.LoopExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A loop expression. For example: * ```rust @@ -36,5 +36,7 @@ module Impl { * }; * ``` */ - class LoopExpr extends Generated::LoopExpr { } + class LoopExpr extends Generated::LoopExpr { + override string toStringPrefix() { result = "loop" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/LoopingExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LoopingExprImpl.qll new file mode 100644 index 000000000000..45aa8f42e74b --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/LoopingExprImpl.qll @@ -0,0 +1,19 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `LoopingExpr`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.LoopingExpr + +/** + * INTERNAL: This module contains the customizable definition of `LoopingExpr` and should not + * be referenced directly. + */ +module Impl { + /** + * The base class for expressions that loop (`LoopExpr`, `ForExpr` or `WhileExpr`). + */ + class LoopingExpr extends Generated::LoopingExpr { } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/MacroCallImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/MacroCallImpl.qll index 76fcd7645a6f..a34d64c0735e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/MacroCallImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/MacroCallImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `MacroCall`. * @@ -12,11 +11,14 @@ private import codeql.rust.elements.internal.generated.MacroCall * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A MacroCall. For example: * ```rust * todo!() * ``` */ - class MacroCall extends Generated::MacroCall { } + class MacroCall extends Generated::MacroCall { + override string toString() { result = this.getPath().toAbbreviatedString() + "!..." } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/MatchArmImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/MatchArmImpl.qll index 117e6eb3498b..23ad2551bffc 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/MatchArmImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/MatchArmImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `MatchArm`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.MatchArm * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A match arm. For example: * ```rust @@ -27,5 +27,17 @@ module Impl { * }; * ``` */ - class MatchArm extends Generated::MatchArm { } + class MatchArm extends Generated::MatchArm { + override string toString() { result = concat(int i | | this.toStringPart(i), " " order by i) } + + private string toStringPart(int index) { + index = 0 and result = this.getPat().toAbbreviatedString() + or + index = 1 and result = "if " + this.getGuard().toAbbreviatedString() + or + index = 2 and result = "=>" + or + index = 3 and result = this.getExpr().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll index c8cb535b526d..15fdcf7e73fb 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/MatchExprImpl.qll @@ -28,6 +28,10 @@ module Impl { * ``` */ class MatchExpr extends Generated::MatchExpr { + override string toString() { + result = "match " + this.getScrutinee().toAbbreviatedString() + " { ... }" + } + /** * Gets the `index`th arm of this match expression. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/ModuleImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ModuleImpl.qll index 2e94fad609ca..505495862b7f 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ModuleImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ModuleImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Module`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.Module * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A module declaration. For example: * ```rust @@ -23,5 +23,7 @@ module Impl { * } * ``` */ - class Module extends Generated::Module { } + class Module extends Generated::Module { + override string toString() { result = "mod " + this.getName() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/NeverTypeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/NeverTypeImpl.qll index 9c04237f38c1..c1858fc9421a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/NeverTypeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/NeverTypeImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `NeverType`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.NeverType * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A NeverType. For example: * ```rust * todo!() * ``` */ - class NeverType extends Generated::NeverType { } + class NeverType extends Generated::NeverType { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = "!" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll index f29e3d1865fc..07cc59f0ddee 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/OrPatImpl.qll @@ -21,6 +21,10 @@ module Impl { * ``` */ class OrPat extends Generated::OrPat { + override string toString() { + result = concat(int i | | this.getPat(i).toAbbreviatedString(), " | " order by i) + } + /** Gets the last pattern in this or pattern. */ pragma[nomagic] Pat getLastPat() { result = this.getPat(this.getNumberOfPats() - 1) } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ParamBaseImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ParamBaseImpl.qll new file mode 100644 index 000000000000..3b0f82eb6c3d --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/ParamBaseImpl.qll @@ -0,0 +1,19 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `ParamBase`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.ParamBase + +/** + * INTERNAL: This module contains the customizable definition of `ParamBase` and should not + * be referenced directly. + */ +module Impl { + /** + * A normal parameter, `Param`, or a self parameter `SelfParam`. + */ + class ParamBase extends Generated::ParamBase { } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/ParamImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ParamImpl.qll index 7015d097e9f4..02d38d32c386 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ParamImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ParamImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Param`. * @@ -12,11 +11,22 @@ private import codeql.rust.elements.internal.generated.Param * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** - * A Param. For example: + * A parameter in a function or method. For example `x` in: * ```rust - * todo!() + * fn new(x: T) -> Foo { + * // ... + * } * ``` */ - class Param extends Generated::Param { } + class Param extends Generated::Param { + override string toString() { result = concat(int i | | this.toStringPart(i) order by i) } + + private string toStringPart(int index) { + index = 0 and result = this.getPat().toAbbreviatedString() + or + index = 1 and result = ": " + this.getTy().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ParamListImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ParamListImpl.qll index e31c2734355d..297b7f26fad5 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ParamListImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ParamListImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ParamList`. * @@ -12,11 +11,17 @@ private import codeql.rust.elements.internal.generated.ParamList * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A ParamList. For example: * ```rust * todo!() * ``` */ - class ParamList extends Generated::ParamList { } + class ParamList extends Generated::ParamList { + /** + * Gets any of the parameters of this parameter list. + */ + final ParamBase getAParamBase() { result = this.getParam(_) or result = this.getSelfParam() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ParenExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ParenExprImpl.qll index 98c3cab9267c..db9d19f5650b 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ParenExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ParenExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ParenExpr`. * @@ -12,11 +11,14 @@ private import codeql.rust.elements.internal.generated.ParenExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A ParenExpr. For example: * ```rust * todo!() * ``` */ - class ParenExpr extends Generated::ParenExpr { } + class ParenExpr extends Generated::ParenExpr { + override string toString() { result = "(" + this.getExpr().toAbbreviatedString() + ")" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ParenPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ParenPatImpl.qll index cdba455451c6..9d9016cff98e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ParenPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ParenPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ParenPat`. * @@ -12,11 +11,14 @@ private import codeql.rust.elements.internal.generated.ParenPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A ParenPat. For example: * ```rust * todo!() * ``` */ - class ParenPat extends Generated::ParenPat { } + class ParenPat extends Generated::ParenPat { + override string toString() { result = "(" + this.getPat().toAbbreviatedString() + ")" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ParenTypeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ParenTypeImpl.qll index ab49c9c4fcfc..916758b91333 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ParenTypeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ParenTypeImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ParenType`. * @@ -12,11 +11,14 @@ private import codeql.rust.elements.internal.generated.ParenType * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A ParenType. For example: * ```rust * todo!() * ``` */ - class ParenType extends Generated::ParenType { } + class ParenType extends Generated::ParenType { + override string toString() { result = "(" + this.getTy().toAbbreviatedString() + ")" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PathExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PathExprImpl.qll index c8a2af3de33b..19445493c889 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PathExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PathExprImpl.qll @@ -22,6 +22,8 @@ module Impl { * ``` */ class PathExpr extends Generated::PathExpr { - override string toString() { result = this.getPath().toString() } + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = this.getPath().toString() } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PathImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PathImpl.qll index b53c86559f0c..34cd16c144b4 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PathImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PathImpl.qll @@ -15,14 +15,17 @@ module Impl { /** * A path. For example: * ```rust + * use some_crate::some_module::some_item; * foo::bar; * ``` */ class Path extends Generated::Path { - override string toString() { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { if this.hasQualifier() - then result = this.getQualifier().toString() + "::" + this.getPart().toString() - else result = this.getPart().toString() + then result = "...::" + this.getPart().toAbbreviatedString() + else result = this.getPart().toAbbreviatedString() } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PathPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PathPatImpl.qll index 0acf7a588ba6..27914a8f4159 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PathPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PathPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `PathPat`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.PathPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A path pattern. For example: * ```rust @@ -21,5 +21,9 @@ module Impl { * } * ``` */ - class PathPat extends Generated::PathPat { } + class PathPat extends Generated::PathPat { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = this.getPath().toAbbreviatedString() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PathSegmentImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PathSegmentImpl.qll index 300a6c7d4a0c..7f586afa3755 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PathSegmentImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PathSegmentImpl.qll @@ -13,17 +13,22 @@ private import codeql.rust.elements.internal.generated.PathSegment module Impl { // the following QLdoc is generated: if you need to edit it, do it in the schema file /** - * A PathSegment. For example: - * ```rust - * todo!() - * ``` + * A path segment, which is one part of a whole path. */ class PathSegment extends Generated::PathSegment { - override string toString() { - // TODO: this does not cover everything - if this.hasGenericArgList() - then result = this.getNameRef().toString() + "::<...>" - else result = this.getNameRef().toString() + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { + result = strictconcat(int i | | this.toAbbreviatedStringPart(i), "::" order by i) + } + + private string toAbbreviatedStringPart(int index) { + index = 0 and + if this.hasPathType() or this.hasTy() + then result = "<...>" + else result = this.getNameRef().getText() + or + index = 1 and result = this.getGenericArgList().toAbbreviatedString() } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/PathTypeImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/PathTypeImpl.qll index 74fa536e08b5..02d8a98d42a3 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/PathTypeImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/PathTypeImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `PathType`. * @@ -12,11 +11,17 @@ private import codeql.rust.elements.internal.generated.PathType * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** - * A PathType. For example: + * A type referring to a path. For example: * ```rust - * todo!() + * type X = std::collections::HashMap; + * type Y = X::Item; * ``` */ - class PathType extends Generated::PathType { } + class PathType extends Generated::PathType { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = this.getPath().toAbbreviatedString() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RangeExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RangeExprImpl.qll index c015171253f7..3b8989af7821 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RangeExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RangeExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RangeExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.RangeExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A range expression. For example: * ```rust @@ -23,5 +23,29 @@ module Impl { * let x = ..; * ``` */ - class RangeExpr extends Generated::RangeExpr { } + class RangeExpr extends Generated::RangeExpr { + override string toString() { result = concat(int i | | this.toStringPart(i) order by i) } + + private string toStringPart(int index) { + index = 0 and result = this.getStartAbbreviation() + or + index = 1 and result = this.getOperatorName() + or + index = 2 and result = this.getEndAbbreviation() + } + + private string getStartAbbreviation() { + exists(string abbr | + abbr = this.getStart().toAbbreviatedString() and + if abbr = "..." then result = "... " else result = abbr + ) + } + + private string getEndAbbreviation() { + exists(string abbr | + abbr = this.getEnd().toAbbreviatedString() and + if abbr = "..." then result = " ..." else result = abbr + ) + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RecordExprFieldImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RecordExprFieldImpl.qll index 12b86bb1e4ab..fe898c82fea4 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RecordExprFieldImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RecordExprFieldImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RecordExprField`. * @@ -12,11 +11,20 @@ private import codeql.rust.elements.internal.generated.RecordExprField * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A field in a record expression. For example `a: 1` in: * ```rust * Foo { a: 1, b: 2 }; * ``` */ - class RecordExprField extends Generated::RecordExprField { } + class RecordExprField extends Generated::RecordExprField { + override string toString() { result = concat(int i | | this.toStringPart(i) order by i) } + + private string toStringPart(int index) { + index = 0 and result = this.getNameRef().getText() + or + index = 1 and result = ": " + this.getExpr().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RecordExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RecordExprImpl.qll index befc9b26ebbd..a59d3bc22e2e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RecordExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RecordExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RecordExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.RecordExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A record expression. For example: * ```rust @@ -21,5 +21,7 @@ module Impl { * Foo { .. } = second; * ``` */ - class RecordExpr extends Generated::RecordExpr { } + class RecordExpr extends Generated::RecordExpr { + override string toString() { result = this.getPath().toString() + " {...}" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RecordPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RecordPatImpl.qll index 6378e3220e0f..0bed25bb779f 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RecordPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RecordPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RecordPat`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.RecordPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A record pattern. For example: * ```rust @@ -21,5 +21,7 @@ module Impl { * } * ``` */ - class RecordPat extends Generated::RecordPat { } + class RecordPat extends Generated::RecordPat { + override string toString() { result = this.getPath().toAbbreviatedString() + " {...}" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RefExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RefExprImpl.qll index abc45e0d5c21..4ec593362d95 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RefExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RefExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RefExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.RefExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A reference expression. For example: * ```rust @@ -21,5 +21,19 @@ module Impl { * let raw_mut: &mut i32 = &raw mut foo; * ``` */ - class RefExpr extends Generated::RefExpr { } + class RefExpr extends Generated::RefExpr { + override string toString() { + result = "&" + concat(int i | | this.getSpecPart(i), " " order by i) + } + + private string getSpecPart(int index) { + index = 0 and this.isRaw() and result = "raw" + or + index = 1 and this.isConst() and result = "const" + or + index = 2 and this.isMut() and result = "mut" + or + index = 3 and result = this.getExpr().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RefPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RefPatImpl.qll index 03b1abf5a4f9..d6b1f4c27092 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RefPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RefPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RefPat`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.RefPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A reference pattern. For example: * ```rust @@ -21,5 +21,15 @@ module Impl { * }; * ``` */ - class RefPat extends Generated::RefPat { } + class RefPat extends Generated::RefPat { + override string toString() { + result = "&" + concat(int i | | this.getSpecPart(i), " " order by i) + } + + private string getSpecPart(int index) { + index = 0 and this.isMut() and result = "mut" + or + index = 1 and result = this.getPat().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/RestPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/RestPatImpl.qll index bd483e4ba9a6..ec7d48a4d9d7 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/RestPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/RestPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `RestPat`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.RestPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A RestPat. For example: * ```rust * todo!() * ``` */ - class RestPat extends Generated::RestPat { } + class RestPat extends Generated::RestPat { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = ".." } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ReturnExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ReturnExprImpl.qll index fd185c01b1df..1b632587867e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ReturnExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ReturnExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `ReturnExpr`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.ReturnExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A return expression. For example: * ```rust @@ -25,5 +25,13 @@ module Impl { * } * ``` */ - class ReturnExpr extends Generated::ReturnExpr { } + class ReturnExpr extends Generated::ReturnExpr { + override string toString() { result = concat(int i | | this.toStringPart(i), " " order by i) } + + private string toStringPart(int index) { + index = 0 and result = "return" + or + index = 1 and result = this.getExpr().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/SelfParamImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/SelfParamImpl.qll index 2be3b75ac47a..0d0d23a1e8c5 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/SelfParamImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/SelfParamImpl.qll @@ -13,9 +13,11 @@ private import codeql.rust.elements.internal.generated.SelfParam */ module Impl { /** - * A SelfParam. For example: + * A `self` parameter. For example `self` in: * ```rust - * todo!() + * fn push(&mut self, value: T) { + * // ... + * } * ``` */ class SelfParam extends Generated::SelfParam { } diff --git a/rust/ql/lib/codeql/rust/elements/internal/TraitImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/TraitImpl.qll index a6fa19517f41..564e54e78d64 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/TraitImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/TraitImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Trait`. * @@ -12,6 +11,7 @@ private import codeql.rust.elements.internal.generated.Trait * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A Trait. For example: * ``` @@ -24,5 +24,7 @@ module Impl { * pub trait Foo where T::Frobinator: Eq {} * ``` */ - class Trait extends Generated::Trait { } + class Trait extends Generated::Trait { + override string toString() { result = "trait " + this.getName().getText() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/UnderscoreExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/UnderscoreExprImpl.qll index 03709c54b545..620a09e8c3d9 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/UnderscoreExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/UnderscoreExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `UnderscoreExpr`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.UnderscoreExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * An underscore expression. For example: * ```rust * _ = 42; * ``` */ - class UnderscoreExpr extends Generated::UnderscoreExpr { } + class UnderscoreExpr extends Generated::UnderscoreExpr { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = "_" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/UnionImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/UnionImpl.qll index dc850eac4d19..15a793741172 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/UnionImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/UnionImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `Union`. * @@ -12,11 +11,14 @@ private import codeql.rust.elements.internal.generated.Union * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A Union. For example: * ```rust * todo!() * ``` */ - class Union extends Generated::Union { } + class Union extends Generated::Union { + override string toString() { result = "union " + this.getName().getText() } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll index 4b94546d8027..a9758c455b9b 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll @@ -73,24 +73,35 @@ module Impl { * where `definingNode` is the entire `Either::Left(x) | Either::Right(x)` * pattern. */ - private predicate variableDecl(AstNode definingNode, IdentPat p, string name) { - ( - definingNode = getOutermostEnclosingOrPat(p) - or - not exists(getOutermostEnclosingOrPat(p)) and - definingNode = p.getName() - ) and - name = p.getName().getText() and - // exclude for now anything starting with an uppercase character, which may be a reference to - // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE), - // which we don't appear to recognize yet anyway. This also assumes programmers follow the - // naming guidelines, which they generally do, but they're not enforced. - not name.charAt(0).isUppercase() and - // exclude parameters from functions without a body as these are trait method declarations - // without implementations - not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = p) and - // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`) - not exists(FnPtrType fp | fp.getParamList().getParam(_).getPat() = p) + private predicate variableDecl(AstNode definingNode, AstNode p, string name) { + p = + any(SelfParam sp | + definingNode = sp.getName() and + name = sp.getName().getText() and + // exclude self parameters from functions without a body as these are + // trait method declarations without implementations + not exists(Function f | not f.hasBody() and f.getParamList().getSelfParam() = sp) + ) + or + p = + any(IdentPat pat | + ( + definingNode = getOutermostEnclosingOrPat(pat) + or + not exists(getOutermostEnclosingOrPat(pat)) and definingNode = pat.getName() + ) and + name = pat.getName().getText() and + // exclude for now anything starting with an uppercase character, which may be a reference to + // an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE), + // which we don't appear to recognize yet anyway. This also assumes programmers follow the + // naming guidelines, which they generally do, but they're not enforced. + not name.charAt(0).isUppercase() and + // exclude parameters from functions without a body as these are trait method declarations + // without implementations + not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = pat) and + // exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`) + not exists(FnPtrType fp | fp.getParamList().getParam(_).getPat() = pat) + ) } /** A variable. */ @@ -112,8 +123,11 @@ module Impl { /** Gets an access to this variable. */ VariableAccess getAnAccess() { result.getVariable() = this } + /** Gets the `self` parameter that declares this variable, if one exists. */ + SelfParam getSelfParam() { variableDecl(definingNode, result, name) } + /** - * Gets the pattern that declares this variable. + * Gets the pattern that declares this variable, if any. * * Normally, the pattern is unique, except when introduced in an or pattern: * @@ -135,7 +149,9 @@ module Impl { predicate isCaptured() { this.getAnAccess().isCapture() } /** Gets the parameter that introduces this variable, if any. */ - Param getParameter() { parameterDeclInScope(result, this, _) } + ParamBase getParameter() { + result = this.getSelfParam() or result.(Param).getPat() = getAVariablePatAncestor(this) + } /** Hold is this variable is mutable. */ predicate isMutable() { this.getPat().isMut() } @@ -144,7 +160,11 @@ module Impl { predicate isImmutable() { not this.isMutable() } } - /** A path expression that may access a local variable. */ + /** + * A path expression that may access a local variable. These are paths that + * only consists of a simple name (i.e., without generic arguments, + * qualifiers, etc.). + */ private class VariableAccessCand extends PathExprBase { string name_; @@ -190,10 +210,7 @@ module Impl { private VariableScope getEnclosingScope(AstNode n) { result = getAnAncestorInVariableScope(n) } private Pat getAVariablePatAncestor(Variable v) { - exists(AstNode definingNode, string name | - v = MkVariable(definingNode, name) and - variableDecl(definingNode, result, name) - ) + result = v.getPat() or exists(Pat mid | mid = getAVariablePatAncestor(v) and @@ -202,23 +219,12 @@ module Impl { } /** - * Holds if parameter `p` introduces the variable `v` inside variable scope - * `scope`. + * Holds if a parameter declares the variable `v` inside variable scope `scope`. */ - private predicate parameterDeclInScope(Param p, Variable v, VariableScope scope) { - exists(Pat pat | - pat = getAVariablePatAncestor(v) and - p.getPat() = pat - | - exists(Function f | - f.getParamList().getAParam() = p and - scope = f.getBody() - ) - or - exists(ClosureExpr ce | - ce.getParamList().getAParam() = p and - scope = ce.getBody() - ) + private predicate parameterDeclInScope(Variable v, VariableScope scope) { + exists(Callable f | + v.getParameter() = f.getParamList().getAParamBase() and + scope = [f.(Function).getBody(), f.(ClosureExpr).getBody()] ) } @@ -231,7 +237,7 @@ module Impl { ) { name = v.getName() and ( - parameterDeclInScope(_, v, scope) and + parameterDeclInScope(v, scope) and scope.getLocation().hasLocationFileInfo(_, line, column, _, _) or exists(Pat pat | pat = getAVariablePatAncestor(v) | @@ -378,7 +384,7 @@ module Impl { } } - private module DenseRankInput implements DenseRankInputSig3 { + private module DenseRankInput implements DenseRankInputSig2 { class C1 = VariableScope; class C2 = string; @@ -401,7 +407,7 @@ module Impl { * to a variable named `name` in the variable scope `scope`. */ private int rankVariableOrAccess(VariableScope scope, string name, VariableOrAccessCand v) { - result = DenseRank3::denseRank(scope, name, v) - 1 + v = DenseRank2::denseRank(scope, name, result + 1) } /** diff --git a/rust/ql/lib/codeql/rust/elements/internal/WhileExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/WhileExprImpl.qll index 647864d46592..e41b6a684a1e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/WhileExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/WhileExprImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `WhileExpr`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.WhileExpr * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A WhileExpr. For example: * ```rust * todo!() * ``` */ - class WhileExpr extends Generated::WhileExpr { } + class WhileExpr extends Generated::WhileExpr { + override string toStringPrefix() { + result = "while " + this.getCondition().toAbbreviatedString() + } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/WildcardPatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/WildcardPatImpl.qll index d12e49e1daa9..f1a8fa1a72ee 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/WildcardPatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/WildcardPatImpl.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module provides a hand-modifiable wrapper around the generated class `WildcardPat`. * @@ -12,11 +11,16 @@ private import codeql.rust.elements.internal.generated.WildcardPat * be referenced directly. */ module Impl { + // the following QLdoc is generated: if you need to edit it, do it in the schema file /** * A wildcard pattern. For example: * ```rust * let _ = 42; * ``` */ - class WildcardPat extends Generated::WildcardPat { } + class WildcardPat extends Generated::WildcardPat { + override string toString() { result = this.toAbbreviatedString() } + + override string toAbbreviatedString() { result = "_" } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Addressable.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Addressable.qll new file mode 100644 index 000000000000..9d4ba1e976a3 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Addressable.qll @@ -0,0 +1,58 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `Addressable`. + * INTERNAL: Do not import directly. + */ + +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.generated.Raw +import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl + +/** + * INTERNAL: This module contains the fully generated definition of `Addressable` and should not + * be referenced directly. + */ +module Generated { + /** + * Something that can be addressed by a path. + * + * TODO: This does not yet include all possible cases. + * INTERNAL: Do not reference the `Generated::Addressable` class directly. + * Use the subclass `Addressable`, where the following predicates are available. + */ + class Addressable extends Synth::TAddressable, AstNodeImpl::AstNode { + /** + * Gets the extended canonical path of this addressable, if it exists. + * + * Either a canonical path (see https://doc.rust-lang.org/reference/paths.html#canonical-paths), + * or `{}::name` for addressable items defined in an anonymous block (and only + * addressable there-in). + * INTERNAL: Do not use. + */ + string getExtendedCanonicalPath() { + result = Synth::convertAddressableToRaw(this).(Raw::Addressable).getExtendedCanonicalPath() + } + + /** + * Holds if `getExtendedCanonicalPath()` exists. + * INTERNAL: Do not use. + */ + final predicate hasExtendedCanonicalPath() { exists(this.getExtendedCanonicalPath()) } + + /** + * Gets the crate origin of this addressable, if it exists. + * + * One of `rustc:`, `repo::` or `lang:`. + * INTERNAL: Do not use. + */ + string getCrateOrigin() { + result = Synth::convertAddressableToRaw(this).(Raw::Addressable).getCrateOrigin() + } + + /** + * Holds if `getCrateOrigin()` exists. + * INTERNAL: Do not use. + */ + final predicate hasCrateOrigin() { exists(this.getCrateOrigin()) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/BlockExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/BlockExpr.qll index c4f11fdd90c5..6a01a0c45880 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/BlockExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/BlockExpr.qll @@ -7,8 +7,7 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.Attr -import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -import codeql.rust.elements.Label +import codeql.rust.elements.internal.LabelableExprImpl::Impl as LabelableExprImpl import codeql.rust.elements.StmtList /** @@ -32,7 +31,7 @@ module Generated { * INTERNAL: Do not reference the `Generated::BlockExpr` class directly. * Use the subclass `BlockExpr`, where the following predicates are available. */ - class BlockExpr extends Synth::TBlockExpr, ExprImpl::Expr { + class BlockExpr extends Synth::TBlockExpr, LabelableExprImpl::LabelableExpr { override string getAPrimaryQlClass() { result = "BlockExpr" } /** @@ -83,19 +82,6 @@ module Generated { */ predicate isUnsafe() { Synth::convertBlockExprToRaw(this).(Raw::BlockExpr).isUnsafe() } - /** - * Gets the label of this block expression, if it exists. - */ - Label getLabel() { - result = - Synth::convertLabelFromRaw(Synth::convertBlockExprToRaw(this).(Raw::BlockExpr).getLabel()) - } - - /** - * Holds if `getLabel()` exists. - */ - final predicate hasLabel() { exists(this.getLabel()) } - /** * Gets the statement list of this block expression, if it exists. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/CallExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/CallExpr.qll index 2e41b664a4ee..829de70510be 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/CallExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/CallExpr.qll @@ -29,16 +29,16 @@ module Generated { override string getAPrimaryQlClass() { result = "CallExpr" } /** - * Gets the expression of this call expression, if it exists. + * Gets the function of this call expression, if it exists. */ - Expr getExpr() { + Expr getFunction() { result = - Synth::convertExprFromRaw(Synth::convertCallExprToRaw(this).(Raw::CallExpr).getExpr()) + Synth::convertExprFromRaw(Synth::convertCallExprToRaw(this).(Raw::CallExpr).getFunction()) } /** - * Holds if `getExpr()` exists. + * Holds if `getFunction()` exists. */ - final predicate hasExpr() { exists(this.getExpr()) } + final predicate hasFunction() { exists(this.getFunction()) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/ForExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/ForExpr.qll index dc5f2d34d3ee..202b1736fc49 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ForExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ForExpr.qll @@ -7,10 +7,8 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.Attr -import codeql.rust.elements.BlockExpr import codeql.rust.elements.Expr -import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -import codeql.rust.elements.Label +import codeql.rust.elements.internal.LoopingExprImpl::Impl as LoopingExprImpl import codeql.rust.elements.Pat /** @@ -26,7 +24,7 @@ module Generated { * INTERNAL: Do not reference the `Generated::ForExpr` class directly. * Use the subclass `ForExpr`, where the following predicates are available. */ - class ForExpr extends Synth::TForExpr, ExprImpl::Expr { + class ForExpr extends Synth::TForExpr, LoopingExprImpl::LoopingExpr { override string getAPrimaryQlClass() { result = "ForExpr" } /** @@ -60,32 +58,6 @@ module Generated { */ final predicate hasIterable() { exists(this.getIterable()) } - /** - * Gets the label of this for expression, if it exists. - */ - Label getLabel() { - result = - Synth::convertLabelFromRaw(Synth::convertForExprToRaw(this).(Raw::ForExpr).getLabel()) - } - - /** - * Holds if `getLabel()` exists. - */ - final predicate hasLabel() { exists(this.getLabel()) } - - /** - * Gets the loop body of this for expression, if it exists. - */ - BlockExpr getLoopBody() { - result = - Synth::convertBlockExprFromRaw(Synth::convertForExprToRaw(this).(Raw::ForExpr).getLoopBody()) - } - - /** - * Holds if `getLoopBody()` exists. - */ - final predicate hasLoopBody() { exists(this.getLoopBody()) } - /** * Gets the pat of this for expression, if it exists. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll index f2ade708ffaa..41c748d7fde3 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll @@ -7,6 +7,7 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.FormatArgsExpr +import codeql.rust.elements.FormatArgument import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl /** @@ -34,5 +35,15 @@ module Generated { * Gets the index of this format. */ int getIndex() { none() } + + /** + * Gets the argument of this format, if it exists. + */ + FormatArgument getArgument() { none() } + + /** + * Holds if `getArgument()` exists. + */ + final predicate hasArgument() { exists(this.getArgument()) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll index 7fe088e25411..38034779e053 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll @@ -9,6 +9,7 @@ private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.Attr import codeql.rust.elements.Expr import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl +import codeql.rust.elements.Format import codeql.rust.elements.FormatArgsArg /** @@ -19,7 +20,11 @@ module Generated { /** * A FormatArgsExpr. For example: * ```rust - * todo!() + * format_args!("no args"); + * format_args!("{} foo {:?}", 1, 2); + * format_args!("{b} foo {a:?}", a=1, b=2); + * let (x, y) = (1, 42); + * format_args!("{x}, {y}"); * ``` * INTERNAL: Do not reference the `Generated::FormatArgsExpr` class directly. * Use the subclass `FormatArgsExpr`, where the following predicates are available. @@ -81,5 +86,20 @@ module Generated { * Holds if `getTemplate()` exists. */ final predicate hasTemplate() { exists(this.getTemplate()) } + + /** + * Gets the `index`th format of this format arguments expression (0-based). + */ + Format getFormat(int index) { none() } + + /** + * Gets any of the formats of this format arguments expression. + */ + final Format getAFormat() { result = this.getFormat(_) } + + /** + * Gets the number of formats of this format arguments expression. + */ + final int getNumberOfFormats() { result = count(int i | exists(this.getFormat(i))) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll index 658d6b92e7a5..a1db224494b5 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll @@ -7,6 +7,7 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.Format +import codeql.rust.elements.FormatTemplateVariableAccess import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl /** @@ -33,5 +34,15 @@ module Generated { * Gets the parent of this format argument. */ Format getParent() { none() } + + /** + * Gets the variable of this format argument, if it exists. + */ + FormatTemplateVariableAccess getVariable() { none() } + + /** + * Holds if `getVariable()` exists. + */ + final predicate hasVariable() { exists(this.getVariable()) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Item.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Item.qll index 429221c7f18f..39149c252587 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Item.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Item.qll @@ -6,6 +6,7 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw +import codeql.rust.elements.internal.AddressableImpl::Impl as AddressableImpl import codeql.rust.elements.internal.StmtImpl::Impl as StmtImpl /** @@ -21,37 +22,5 @@ module Generated { * INTERNAL: Do not reference the `Generated::Item` class directly. * Use the subclass `Item`, where the following predicates are available. */ - class Item extends Synth::TItem, StmtImpl::Stmt { - /** - * Gets the extended canonical path of this item, if it exists. - * - * Either a canonical path (see https://doc.rust-lang.org/reference/paths.html#canonical-paths), - * or `{}::name` for addressable items defined in an anonymous block (and only - * addressable there-in). - * INTERNAL: Do not use. - */ - string getExtendedCanonicalPath() { - result = Synth::convertItemToRaw(this).(Raw::Item).getExtendedCanonicalPath() - } - - /** - * Holds if `getExtendedCanonicalPath()` exists. - * INTERNAL: Do not use. - */ - final predicate hasExtendedCanonicalPath() { exists(this.getExtendedCanonicalPath()) } - - /** - * Gets the crate origin of this item, if it exists. - * - * One of `rustc:`, `repo::` or `lang:`. - * INTERNAL: Do not use. - */ - string getCrateOrigin() { result = Synth::convertItemToRaw(this).(Raw::Item).getCrateOrigin() } - - /** - * Holds if `getCrateOrigin()` exists. - * INTERNAL: Do not use. - */ - final predicate hasCrateOrigin() { exists(this.getCrateOrigin()) } - } + class Item extends Synth::TItem, StmtImpl::Stmt, AddressableImpl::Addressable { } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/LabelableExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/LabelableExpr.qll new file mode 100644 index 000000000000..a0dfd03fb400 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/LabelableExpr.qll @@ -0,0 +1,38 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `LabelableExpr`. + * INTERNAL: Do not import directly. + */ + +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.generated.Raw +import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl +import codeql.rust.elements.Label + +/** + * INTERNAL: This module contains the fully generated definition of `LabelableExpr` and should not + * be referenced directly. + */ +module Generated { + /** + * The base class for expressions that can be labeled (`LoopExpr`, `ForExpr`, `WhileExpr` or `BlockExpr`). + * INTERNAL: Do not reference the `Generated::LabelableExpr` class directly. + * Use the subclass `LabelableExpr`, where the following predicates are available. + */ + class LabelableExpr extends Synth::TLabelableExpr, ExprImpl::Expr { + /** + * Gets the label of this labelable expression, if it exists. + */ + Label getLabel() { + result = + Synth::convertLabelFromRaw(Synth::convertLabelableExprToRaw(this) + .(Raw::LabelableExpr) + .getLabel()) + } + + /** + * Holds if `getLabel()` exists. + */ + final predicate hasLabel() { exists(this.getLabel()) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/LetExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/LetExpr.qll index b53dc1c8c67e..c887afa603d9 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/LetExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/LetExpr.qll @@ -48,16 +48,17 @@ module Generated { final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } /** - * Gets the expression of this let expression, if it exists. + * Gets the scrutinee of this let expression, if it exists. */ - Expr getExpr() { - result = Synth::convertExprFromRaw(Synth::convertLetExprToRaw(this).(Raw::LetExpr).getExpr()) + Expr getScrutinee() { + result = + Synth::convertExprFromRaw(Synth::convertLetExprToRaw(this).(Raw::LetExpr).getScrutinee()) } /** - * Holds if `getExpr()` exists. + * Holds if `getScrutinee()` exists. */ - final predicate hasExpr() { exists(this.getExpr()) } + final predicate hasScrutinee() { exists(this.getScrutinee()) } /** * Gets the pat of this let expression, if it exists. diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/LoopExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/LoopExpr.qll index eb943bf746aa..510c3dedb683 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/LoopExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/LoopExpr.qll @@ -7,9 +7,7 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.Attr -import codeql.rust.elements.BlockExpr -import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -import codeql.rust.elements.Label +import codeql.rust.elements.internal.LoopingExprImpl::Impl as LoopingExprImpl /** * INTERNAL: This module contains the fully generated definition of `LoopExpr` and should not @@ -42,7 +40,7 @@ module Generated { * INTERNAL: Do not reference the `Generated::LoopExpr` class directly. * Use the subclass `LoopExpr`, where the following predicates are available. */ - class LoopExpr extends Synth::TLoopExpr, ExprImpl::Expr { + class LoopExpr extends Synth::TLoopExpr, LoopingExprImpl::LoopingExpr { override string getAPrimaryQlClass() { result = "LoopExpr" } /** @@ -62,33 +60,5 @@ module Generated { * Gets the number of attrs of this loop expression. */ final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } - - /** - * Gets the label of this loop expression, if it exists. - */ - Label getLabel() { - result = - Synth::convertLabelFromRaw(Synth::convertLoopExprToRaw(this).(Raw::LoopExpr).getLabel()) - } - - /** - * Holds if `getLabel()` exists. - */ - final predicate hasLabel() { exists(this.getLabel()) } - - /** - * Gets the loop body of this loop expression, if it exists. - */ - BlockExpr getLoopBody() { - result = - Synth::convertBlockExprFromRaw(Synth::convertLoopExprToRaw(this) - .(Raw::LoopExpr) - .getLoopBody()) - } - - /** - * Holds if `getLoopBody()` exists. - */ - final predicate hasLoopBody() { exists(this.getLoopBody()) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/LoopingExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/LoopingExpr.qll new file mode 100644 index 000000000000..427ef05c2aba --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/LoopingExpr.qll @@ -0,0 +1,38 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `LoopingExpr`. + * INTERNAL: Do not import directly. + */ + +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.generated.Raw +import codeql.rust.elements.BlockExpr +import codeql.rust.elements.internal.LabelableExprImpl::Impl as LabelableExprImpl + +/** + * INTERNAL: This module contains the fully generated definition of `LoopingExpr` and should not + * be referenced directly. + */ +module Generated { + /** + * The base class for expressions that loop (`LoopExpr`, `ForExpr` or `WhileExpr`). + * INTERNAL: Do not reference the `Generated::LoopingExpr` class directly. + * Use the subclass `LoopingExpr`, where the following predicates are available. + */ + class LoopingExpr extends Synth::TLoopingExpr, LabelableExprImpl::LabelableExpr { + /** + * Gets the loop body of this looping expression, if it exists. + */ + BlockExpr getLoopBody() { + result = + Synth::convertBlockExprFromRaw(Synth::convertLoopingExprToRaw(this) + .(Raw::LoopingExpr) + .getLoopBody()) + } + + /** + * Holds if `getLoopBody()` exists. + */ + final predicate hasLoopBody() { exists(this.getLoopBody()) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/MatchExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/MatchExpr.qll index 5b48d8e18544..8f49407e5f9e 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/MatchExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/MatchExpr.qll @@ -55,17 +55,17 @@ module Generated { final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } /** - * Gets the expression of this match expression, if it exists. + * Gets the scrutinee (the expression being matched) of this match expression, if it exists. */ - Expr getExpr() { + Expr getScrutinee() { result = - Synth::convertExprFromRaw(Synth::convertMatchExprToRaw(this).(Raw::MatchExpr).getExpr()) + Synth::convertExprFromRaw(Synth::convertMatchExprToRaw(this).(Raw::MatchExpr).getScrutinee()) } /** - * Holds if `getExpr()` exists. + * Holds if `getScrutinee()` exists. */ - final predicate hasExpr() { exists(this.getExpr()) } + final predicate hasScrutinee() { exists(this.getScrutinee()) } /** * Gets the match arm list of this match expression, if it exists. diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Param.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Param.qll index 1ac10da37d35..2bbbc81b2c9f 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Param.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Param.qll @@ -6,10 +6,8 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw -import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl -import codeql.rust.elements.Attr +import codeql.rust.elements.internal.ParamBaseImpl::Impl as ParamBaseImpl import codeql.rust.elements.Pat -import codeql.rust.elements.TypeRef /** * INTERNAL: This module contains the fully generated definition of `Param` and should not @@ -17,33 +15,18 @@ import codeql.rust.elements.TypeRef */ module Generated { /** - * A Param. For example: + * A parameter in a function or method. For example `x` in: * ```rust - * todo!() + * fn new(x: T) -> Foo { + * // ... + * } * ``` * INTERNAL: Do not reference the `Generated::Param` class directly. * Use the subclass `Param`, where the following predicates are available. */ - class Param extends Synth::TParam, AstNodeImpl::AstNode { + class Param extends Synth::TParam, ParamBaseImpl::ParamBase { override string getAPrimaryQlClass() { result = "Param" } - /** - * Gets the `index`th attr of this parameter (0-based). - */ - Attr getAttr(int index) { - result = Synth::convertAttrFromRaw(Synth::convertParamToRaw(this).(Raw::Param).getAttr(index)) - } - - /** - * Gets any of the attrs of this parameter. - */ - final Attr getAnAttr() { result = this.getAttr(_) } - - /** - * Gets the number of attrs of this parameter. - */ - final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } - /** * Gets the pat of this parameter, if it exists. */ @@ -55,17 +38,5 @@ module Generated { * Holds if `getPat()` exists. */ final predicate hasPat() { exists(this.getPat()) } - - /** - * Gets the ty of this parameter, if it exists. - */ - TypeRef getTy() { - result = Synth::convertTypeRefFromRaw(Synth::convertParamToRaw(this).(Raw::Param).getTy()) - } - - /** - * Holds if `getTy()` exists. - */ - final predicate hasTy() { exists(this.getTy()) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/ParamBase.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/ParamBase.qll new file mode 100644 index 000000000000..ea5ef12a64f5 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParamBase.qll @@ -0,0 +1,55 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `ParamBase`. + * INTERNAL: Do not import directly. + */ + +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.generated.Raw +import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl +import codeql.rust.elements.Attr +import codeql.rust.elements.TypeRef + +/** + * INTERNAL: This module contains the fully generated definition of `ParamBase` and should not + * be referenced directly. + */ +module Generated { + /** + * A normal parameter, `Param`, or a self parameter `SelfParam`. + * INTERNAL: Do not reference the `Generated::ParamBase` class directly. + * Use the subclass `ParamBase`, where the following predicates are available. + */ + class ParamBase extends Synth::TParamBase, AstNodeImpl::AstNode { + /** + * Gets the `index`th attr of this parameter base (0-based). + */ + Attr getAttr(int index) { + result = + Synth::convertAttrFromRaw(Synth::convertParamBaseToRaw(this).(Raw::ParamBase).getAttr(index)) + } + + /** + * Gets any of the attrs of this parameter base. + */ + final Attr getAnAttr() { result = this.getAttr(_) } + + /** + * Gets the number of attrs of this parameter base. + */ + final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } + + /** + * Gets the ty of this parameter base, if it exists. + */ + TypeRef getTy() { + result = + Synth::convertTypeRefFromRaw(Synth::convertParamBaseToRaw(this).(Raw::ParamBase).getTy()) + } + + /** + * Holds if `getTy()` exists. + */ + final predicate hasTy() { exists(this.getTy()) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll index 470207683ae5..6709629e8b4f 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll @@ -52,14 +52,17 @@ private module Impl { } private Element getImmediateChildOfFormat(Format e, int index, string partialPredicateCall) { - exists(int b, int bLocatable, int n | + exists(int b, int bLocatable, int n, int nArgument | b = 0 and bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and n = bLocatable and + nArgument = n + 1 and ( none() or result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + or + index = n and result = e.getArgument() and partialPredicateCall = "Argument()" ) ) } @@ -67,14 +70,17 @@ private module Impl { private Element getImmediateChildOfFormatArgument( FormatArgument e, int index, string partialPredicateCall ) { - exists(int b, int bLocatable, int n | + exists(int b, int bLocatable, int n, int nVariable | b = 0 and bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and n = bLocatable and + nVariable = n + 1 and ( none() or result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + or + index = n and result = e.getVariable() and partialPredicateCall = "Variable()" ) ) } @@ -122,6 +128,21 @@ private module Impl { ) } + private Element getImmediateChildOfAddressable( + Addressable e, int index, string partialPredicateCall + ) { + exists(int b, int bAstNode, int n | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfArgList(ArgList e, int index, string partialPredicateCall) { exists(int b, int bAstNode, int n, int nArg | b = 0 and @@ -596,14 +617,13 @@ private module Impl { ) } - private Element getImmediateChildOfParam(Param e, int index, string partialPredicateCall) { - exists(int b, int bAstNode, int n, int nAttr, int nPat, int nTy | + private Element getImmediateChildOfParamBase(ParamBase e, int index, string partialPredicateCall) { + exists(int b, int bAstNode, int n, int nAttr, int nTy | b = 0 and bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and n = bAstNode and nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nPat = nAttr + 1 and - nTy = nPat + 1 and + nTy = nAttr + 1 and ( none() or @@ -612,9 +632,7 @@ private module Impl { result = e.getAttr(index - n) and partialPredicateCall = "Attr(" + (index - n).toString() + ")" or - index = nAttr and result = e.getPat() and partialPredicateCall = "Pat()" - or - index = nPat and result = e.getTy() and partialPredicateCall = "Ty()" + index = nAttr and result = e.getTy() and partialPredicateCall = "Ty()" ) ) } @@ -879,32 +897,6 @@ private module Impl { ) } - private Element getImmediateChildOfSelfParam(SelfParam e, int index, string partialPredicateCall) { - exists(int b, int bAstNode, int n, int nAttr, int nLifetime, int nName, int nTy | - b = 0 and - bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and - n = bAstNode and - nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nLifetime = nAttr + 1 and - nName = nLifetime + 1 and - nTy = nName + 1 and - ( - none() - or - result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) - or - result = e.getAttr(index - n) and - partialPredicateCall = "Attr(" + (index - n).toString() + ")" - or - index = nAttr and result = e.getLifetime() and partialPredicateCall = "Lifetime()" - or - index = nLifetime and result = e.getName() and partialPredicateCall = "Name()" - or - index = nName and result = e.getTy() and partialPredicateCall = "Ty()" - ) - ) - } - private Element getImmediateChildOfSourceFile(SourceFile e, int index, string partialPredicateCall) { exists(int b, int bAstNode, int n, int nAttr, int nItem | b = 0 and @@ -1111,37 +1103,6 @@ private module Impl { ) } - private Element getImmediateChildOfVariant(Variant e, int index, string partialPredicateCall) { - exists( - int b, int bAstNode, int n, int nAttr, int nExpr, int nFieldList, int nName, int nVisibility - | - b = 0 and - bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and - n = bAstNode and - nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nExpr = nAttr + 1 and - nFieldList = nExpr + 1 and - nName = nFieldList + 1 and - nVisibility = nName + 1 and - ( - none() - or - result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) - or - result = e.getAttr(index - n) and - partialPredicateCall = "Attr(" + (index - n).toString() + ")" - or - index = nAttr and result = e.getExpr() and partialPredicateCall = "Expr()" - or - index = nExpr and result = e.getFieldList() and partialPredicateCall = "FieldList()" - or - index = nFieldList and result = e.getName() and partialPredicateCall = "Name()" - or - index = nName and result = e.getVisibility() and partialPredicateCall = "Visibility()" - ) - ) - } - private Element getImmediateChildOfVariantList( VariantList e, int index, string partialPredicateCall ) { @@ -1397,29 +1358,6 @@ private module Impl { ) } - private Element getImmediateChildOfBlockExpr(BlockExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nAttr, int nLabel, int nStmtList | - b = 0 and - bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and - n = bExpr and - nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nLabel = nAttr + 1 and - nStmtList = nLabel + 1 and - ( - none() - or - result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) - or - result = e.getAttr(index - n) and - partialPredicateCall = "Attr(" + (index - n).toString() + ")" - or - index = nAttr and result = e.getLabel() and partialPredicateCall = "Label()" - or - index = nLabel and result = e.getStmtList() and partialPredicateCall = "StmtList()" - ) - ) - } - private Element getImmediateChildOfBoxPat(BoxPat e, int index, string partialPredicateCall) { exists(int b, int bPat, int n, int nPat | b = 0 and @@ -1708,35 +1646,6 @@ private module Impl { ) } - private Element getImmediateChildOfForExpr(ForExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nAttr, int nIterable, int nLabel, int nLoopBody, int nPat | - b = 0 and - bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and - n = bExpr and - nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nIterable = nAttr + 1 and - nLabel = nIterable + 1 and - nLoopBody = nLabel + 1 and - nPat = nLoopBody + 1 and - ( - none() - or - result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) - or - result = e.getAttr(index - n) and - partialPredicateCall = "Attr(" + (index - n).toString() + ")" - or - index = nAttr and result = e.getIterable() and partialPredicateCall = "Iterable()" - or - index = nIterable and result = e.getLabel() and partialPredicateCall = "Label()" - or - index = nLabel and result = e.getLoopBody() and partialPredicateCall = "LoopBody()" - or - index = nLoopBody and result = e.getPat() and partialPredicateCall = "Pat()" - ) - ) - } - private Element getImmediateChildOfForType(ForType e, int index, string partialPredicateCall) { exists(int b, int bTypeRef, int n, int nGenericParamList, int nTy | b = 0 and @@ -1761,13 +1670,14 @@ private module Impl { private Element getImmediateChildOfFormatArgsExpr( FormatArgsExpr e, int index, string partialPredicateCall ) { - exists(int b, int bExpr, int n, int nArg, int nAttr, int nTemplate | + exists(int b, int bExpr, int n, int nArg, int nAttr, int nTemplate, int nFormat | b = 0 and bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and n = bExpr and nArg = n + 1 + max(int i | i = -1 or exists(e.getArg(i)) | i) and nAttr = nArg + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and nTemplate = nAttr + 1 and + nFormat = nTemplate + 1 + max(int i | i = -1 or exists(e.getFormat(i)) | i) and ( none() or @@ -1780,6 +1690,9 @@ private module Impl { partialPredicateCall = "Attr(" + (index - nArg).toString() + ")" or index = nAttr and result = e.getTemplate() and partialPredicateCall = "Template()" + or + result = e.getFormat(index - nTemplate) and + partialPredicateCall = "Format(" + (index - nTemplate).toString() + ")" ) ) } @@ -1888,26 +1801,48 @@ private module Impl { } private Element getImmediateChildOfItem(Item e, int index, string partialPredicateCall) { - exists(int b, int bStmt, int n | + exists(int b, int bStmt, int bAddressable, int n | b = 0 and bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and - n = bStmt and + bAddressable = + bStmt + 1 + max(int i | i = -1 or exists(getImmediateChildOfAddressable(e, i, _)) | i) and + n = bAddressable and ( none() or result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfAddressable(e, index - bStmt, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLabelableExpr( + LabelableExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nLabel | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nLabel = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getLabel() and partialPredicateCall = "Label()" ) ) } private Element getImmediateChildOfLetExpr(LetExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nAttr, int nExpr, int nPat | + exists(int b, int bExpr, int n, int nAttr, int nScrutinee, int nPat | b = 0 and bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and n = bExpr and nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nExpr = nAttr + 1 and - nPat = nExpr + 1 and + nScrutinee = nAttr + 1 and + nPat = nScrutinee + 1 and ( none() or @@ -1916,9 +1851,9 @@ private module Impl { result = e.getAttr(index - n) and partialPredicateCall = "Attr(" + (index - n).toString() + ")" or - index = nAttr and result = e.getExpr() and partialPredicateCall = "Expr()" + index = nAttr and result = e.getScrutinee() and partialPredicateCall = "Scrutinee()" or - index = nExpr and result = e.getPat() and partialPredicateCall = "Pat()" + index = nScrutinee and result = e.getPat() and partialPredicateCall = "Pat()" ) ) } @@ -2034,29 +1969,6 @@ private module Impl { ) } - private Element getImmediateChildOfLoopExpr(LoopExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nAttr, int nLabel, int nLoopBody | - b = 0 and - bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and - n = bExpr and - nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nLabel = nAttr + 1 and - nLoopBody = nLabel + 1 and - ( - none() - or - result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) - or - result = e.getAttr(index - n) and - partialPredicateCall = "Attr(" + (index - n).toString() + ")" - or - index = nAttr and result = e.getLabel() and partialPredicateCall = "Label()" - or - index = nLabel and result = e.getLoopBody() and partialPredicateCall = "LoopBody()" - ) - ) - } - private Element getImmediateChildOfMacroExpr(MacroExpr e, int index, string partialPredicateCall) { exists(int b, int bExpr, int n, int nMacroCall | b = 0 and @@ -2106,13 +2018,13 @@ private module Impl { } private Element getImmediateChildOfMatchExpr(MatchExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nAttr, int nExpr, int nMatchArmList | + exists(int b, int bExpr, int n, int nAttr, int nScrutinee, int nMatchArmList | b = 0 and bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and n = bExpr and nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nExpr = nAttr + 1 and - nMatchArmList = nExpr + 1 and + nScrutinee = nAttr + 1 and + nMatchArmList = nScrutinee + 1 and ( none() or @@ -2121,9 +2033,11 @@ private module Impl { result = e.getAttr(index - n) and partialPredicateCall = "Attr(" + (index - n).toString() + ")" or - index = nAttr and result = e.getExpr() and partialPredicateCall = "Expr()" + index = nAttr and result = e.getScrutinee() and partialPredicateCall = "Scrutinee()" or - index = nExpr and result = e.getMatchArmList() and partialPredicateCall = "MatchArmList()" + index = nScrutinee and + result = e.getMatchArmList() and + partialPredicateCall = "MatchArmList()" ) ) } @@ -2184,6 +2098,22 @@ private module Impl { ) } + private Element getImmediateChildOfParam(Param e, int index, string partialPredicateCall) { + exists(int b, int bParamBase, int n, int nPat | + b = 0 and + bParamBase = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfParamBase(e, i, _)) | i) and + n = bParamBase and + nPat = n + 1 and + ( + none() + or + result = getImmediateChildOfParamBase(e, index - b, partialPredicateCall) + or + index = n and result = e.getPat() and partialPredicateCall = "Pat()" + ) + ) + } + private Element getImmediateChildOfParenExpr(ParenExpr e, int index, string partialPredicateCall) { exists(int b, int bExpr, int n, int nAttr, int nExpr | b = 0 and @@ -2534,6 +2464,25 @@ private module Impl { ) } + private Element getImmediateChildOfSelfParam(SelfParam e, int index, string partialPredicateCall) { + exists(int b, int bParamBase, int n, int nLifetime, int nName | + b = 0 and + bParamBase = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfParamBase(e, i, _)) | i) and + n = bParamBase and + nLifetime = n + 1 and + nName = nLifetime + 1 and + ( + none() + or + result = getImmediateChildOfParamBase(e, index - b, partialPredicateCall) + or + index = n and result = e.getLifetime() and partialPredicateCall = "Lifetime()" + or + index = nLifetime and result = e.getName() and partialPredicateCall = "Name()" + ) + ) + } + private Element getImmediateChildOfSlicePat(SlicePat e, int index, string partialPredicateCall) { exists(int b, int bPat, int n, int nPat | b = 0 and @@ -2748,28 +2697,35 @@ private module Impl { ) } - private Element getImmediateChildOfWhileExpr(WhileExpr e, int index, string partialPredicateCall) { - exists(int b, int bExpr, int n, int nAttr, int nCondition, int nLabel, int nLoopBody | + private Element getImmediateChildOfVariant(Variant e, int index, string partialPredicateCall) { + exists( + int b, int bAddressable, int n, int nAttr, int nExpr, int nFieldList, int nName, + int nVisibility + | b = 0 and - bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and - n = bExpr and + bAddressable = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAddressable(e, i, _)) | i) and + n = bAddressable and nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and - nCondition = nAttr + 1 and - nLabel = nCondition + 1 and - nLoopBody = nLabel + 1 and + nExpr = nAttr + 1 and + nFieldList = nExpr + 1 and + nName = nFieldList + 1 and + nVisibility = nName + 1 and ( none() or - result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + result = getImmediateChildOfAddressable(e, index - b, partialPredicateCall) or result = e.getAttr(index - n) and partialPredicateCall = "Attr(" + (index - n).toString() + ")" or - index = nAttr and result = e.getCondition() and partialPredicateCall = "Condition()" + index = nAttr and result = e.getExpr() and partialPredicateCall = "Expr()" or - index = nCondition and result = e.getLabel() and partialPredicateCall = "Label()" + index = nExpr and result = e.getFieldList() and partialPredicateCall = "FieldList()" + or + index = nFieldList and result = e.getName() and partialPredicateCall = "Name()" or - index = nLabel and result = e.getLoopBody() and partialPredicateCall = "LoopBody()" + index = nName and result = e.getVisibility() and partialPredicateCall = "Visibility()" ) ) } @@ -2829,19 +2785,40 @@ private module Impl { ) } + private Element getImmediateChildOfBlockExpr(BlockExpr e, int index, string partialPredicateCall) { + exists(int b, int bLabelableExpr, int n, int nAttr, int nStmtList | + b = 0 and + bLabelableExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabelableExpr(e, i, _)) | i) and + n = bLabelableExpr and + nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and + nStmtList = nAttr + 1 and + ( + none() + or + result = getImmediateChildOfLabelableExpr(e, index - b, partialPredicateCall) + or + result = e.getAttr(index - n) and + partialPredicateCall = "Attr(" + (index - n).toString() + ")" + or + index = nAttr and result = e.getStmtList() and partialPredicateCall = "StmtList()" + ) + ) + } + private Element getImmediateChildOfCallExpr(CallExpr e, int index, string partialPredicateCall) { - exists(int b, int bCallExprBase, int n, int nExpr | + exists(int b, int bCallExprBase, int n, int nFunction | b = 0 and bCallExprBase = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallExprBase(e, i, _)) | i) and n = bCallExprBase and - nExpr = n + 1 and + nFunction = n + 1 and ( none() or result = getImmediateChildOfCallExprBase(e, index - b, partialPredicateCall) or - index = n and result = e.getExpr() and partialPredicateCall = "Expr()" + index = n and result = e.getFunction() and partialPredicateCall = "Function()" ) ) } @@ -3087,6 +3064,25 @@ private module Impl { ) } + private Element getImmediateChildOfLoopingExpr( + LoopingExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLabelableExpr, int n, int nLoopBody | + b = 0 and + bLabelableExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabelableExpr(e, i, _)) | i) and + n = bLabelableExpr and + nLoopBody = n + 1 and + ( + none() + or + result = getImmediateChildOfLabelableExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getLoopBody() and partialPredicateCall = "LoopBody()" + ) + ) + } + private Element getImmediateChildOfMacroCall(MacroCall e, int index, string partialPredicateCall) { exists( int b, int bAssocItem, int bExternItem, int bItem, int n, int nAttr, int nPath, @@ -3535,6 +3531,69 @@ private module Impl { ) } + private Element getImmediateChildOfForExpr(ForExpr e, int index, string partialPredicateCall) { + exists(int b, int bLoopingExpr, int n, int nAttr, int nIterable, int nPat | + b = 0 and + bLoopingExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLoopingExpr(e, i, _)) | i) and + n = bLoopingExpr and + nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and + nIterable = nAttr + 1 and + nPat = nIterable + 1 and + ( + none() + or + result = getImmediateChildOfLoopingExpr(e, index - b, partialPredicateCall) + or + result = e.getAttr(index - n) and + partialPredicateCall = "Attr(" + (index - n).toString() + ")" + or + index = nAttr and result = e.getIterable() and partialPredicateCall = "Iterable()" + or + index = nIterable and result = e.getPat() and partialPredicateCall = "Pat()" + ) + ) + } + + private Element getImmediateChildOfLoopExpr(LoopExpr e, int index, string partialPredicateCall) { + exists(int b, int bLoopingExpr, int n, int nAttr | + b = 0 and + bLoopingExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLoopingExpr(e, i, _)) | i) and + n = bLoopingExpr and + nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and + ( + none() + or + result = getImmediateChildOfLoopingExpr(e, index - b, partialPredicateCall) + or + result = e.getAttr(index - n) and + partialPredicateCall = "Attr(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfWhileExpr(WhileExpr e, int index, string partialPredicateCall) { + exists(int b, int bLoopingExpr, int n, int nAttr, int nCondition | + b = 0 and + bLoopingExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLoopingExpr(e, i, _)) | i) and + n = bLoopingExpr and + nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and + nCondition = nAttr + 1 and + ( + none() + or + result = getImmediateChildOfLoopingExpr(e, index - b, partialPredicateCall) + or + result = e.getAttr(index - n) and + partialPredicateCall = "Attr(" + (index - n).toString() + ")" + or + index = nAttr and result = e.getCondition() and partialPredicateCall = "Condition()" + ) + ) + } + cached Element getImmediateChild(Element e, int index, string partialAccessor) { // why does this look more complicated than it should? @@ -3591,8 +3650,6 @@ private module Impl { or result = getImmediateChildOfNameRef(e, index, partialAccessor) or - result = getImmediateChildOfParam(e, index, partialAccessor) - or result = getImmediateChildOfParamList(e, index, partialAccessor) or result = getImmediateChildOfPathSegment(e, index, partialAccessor) @@ -3613,8 +3670,6 @@ private module Impl { or result = getImmediateChildOfReturnTypeSyntax(e, index, partialAccessor) or - result = getImmediateChildOfSelfParam(e, index, partialAccessor) - or result = getImmediateChildOfSourceFile(e, index, partialAccessor) or result = getImmediateChildOfStmtList(e, index, partialAccessor) @@ -3631,8 +3686,6 @@ private module Impl { or result = getImmediateChildOfUseTreeList(e, index, partialAccessor) or - result = getImmediateChildOfVariant(e, index, partialAccessor) - or result = getImmediateChildOfVariantList(e, index, partialAccessor) or result = getImmediateChildOfVisibility(e, index, partialAccessor) @@ -3655,8 +3708,6 @@ private module Impl { or result = getImmediateChildOfBinaryExpr(e, index, partialAccessor) or - result = getImmediateChildOfBlockExpr(e, index, partialAccessor) - or result = getImmediateChildOfBoxPat(e, index, partialAccessor) or result = getImmediateChildOfBreakExpr(e, index, partialAccessor) @@ -3683,8 +3734,6 @@ private module Impl { or result = getImmediateChildOfFnPtrType(e, index, partialAccessor) or - result = getImmediateChildOfForExpr(e, index, partialAccessor) - or result = getImmediateChildOfForType(e, index, partialAccessor) or result = getImmediateChildOfFormatArgsExpr(e, index, partialAccessor) @@ -3711,8 +3760,6 @@ private module Impl { or result = getImmediateChildOfLiteralPat(e, index, partialAccessor) or - result = getImmediateChildOfLoopExpr(e, index, partialAccessor) - or result = getImmediateChildOfMacroExpr(e, index, partialAccessor) or result = getImmediateChildOfMacroPat(e, index, partialAccessor) @@ -3727,6 +3774,8 @@ private module Impl { or result = getImmediateChildOfOrPat(e, index, partialAccessor) or + result = getImmediateChildOfParam(e, index, partialAccessor) + or result = getImmediateChildOfParenExpr(e, index, partialAccessor) or result = getImmediateChildOfParenPat(e, index, partialAccessor) @@ -3763,6 +3812,8 @@ private module Impl { or result = getImmediateChildOfReturnExpr(e, index, partialAccessor) or + result = getImmediateChildOfSelfParam(e, index, partialAccessor) + or result = getImmediateChildOfSlicePat(e, index, partialAccessor) or result = getImmediateChildOfSliceType(e, index, partialAccessor) @@ -3785,7 +3836,7 @@ private module Impl { or result = getImmediateChildOfUnderscoreExpr(e, index, partialAccessor) or - result = getImmediateChildOfWhileExpr(e, index, partialAccessor) + result = getImmediateChildOfVariant(e, index, partialAccessor) or result = getImmediateChildOfWildcardPat(e, index, partialAccessor) or @@ -3793,6 +3844,8 @@ private module Impl { or result = getImmediateChildOfYieldExpr(e, index, partialAccessor) or + result = getImmediateChildOfBlockExpr(e, index, partialAccessor) + or result = getImmediateChildOfCallExpr(e, index, partialAccessor) or result = getImmediateChildOfConst(e, index, partialAccessor) @@ -3834,6 +3887,12 @@ private module Impl { result = getImmediateChildOfUnion(e, index, partialAccessor) or result = getImmediateChildOfUse(e, index, partialAccessor) + or + result = getImmediateChildOfForExpr(e, index, partialAccessor) + or + result = getImmediateChildOfLoopExpr(e, index, partialAccessor) + or + result = getImmediateChildOfWhileExpr(e, index, partialAccessor) } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Path.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Path.qll index 58f7d891d263..36313ca9fe9a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Path.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Path.qll @@ -18,6 +18,7 @@ module Generated { /** * A path. For example: * ```rust + * use some_crate::some_module::some_item; * foo::bar; * ``` * INTERNAL: Do not reference the `Generated::Path` class directly. diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/PathSegment.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/PathSegment.qll index 0878635e7d17..a2c3b970df68 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/PathSegment.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/PathSegment.qll @@ -21,10 +21,7 @@ import codeql.rust.elements.TypeRef */ module Generated { /** - * A PathSegment. For example: - * ```rust - * todo!() - * ``` + * A path segment, which is one part of a whole path. * INTERNAL: Do not reference the `Generated::PathSegment` class directly. * Use the subclass `PathSegment`, where the following predicates are available. */ diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/PathType.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/PathType.qll index 3ac799108ccb..13d7957c40e0 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/PathType.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/PathType.qll @@ -15,9 +15,10 @@ import codeql.rust.elements.internal.TypeRefImpl::Impl as TypeRefImpl */ module Generated { /** - * A PathType. For example: + * A type referring to a path. For example: * ```rust - * todo!() + * type X = std::collections::HashMap; + * type Y = X::Item; * ``` * INTERNAL: Do not reference the `Generated::PathType` class directly. * Use the subclass `PathType`, where the following predicates are available. diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll index 25af8ddac644..1c85daa22cfa 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Raw.qll @@ -61,6 +61,30 @@ module Raw { string getAbiString() { abi_abi_strings(this, result) } } + /** + * INTERNAL: Do not use. + * Something that can be addressed by a path. + * + * TODO: This does not yet include all possible cases. + */ + class Addressable extends @addressable, AstNode { + /** + * Gets the extended canonical path of this addressable, if it exists. + * + * Either a canonical path (see https://doc.rust-lang.org/reference/paths.html#canonical-paths), + * or `{}::name` for addressable items defined in an anonymous block (and only + * addressable there-in). + */ + string getExtendedCanonicalPath() { addressable_extended_canonical_paths(this, result) } + + /** + * Gets the crate origin of this addressable, if it exists. + * + * One of `rustc:`, `repo::` or `lang:`. + */ + string getCrateOrigin() { addressable_crate_origins(this, result) } + } + /** * INTERNAL: Do not use. * A ArgList. For example: @@ -525,28 +549,18 @@ module Raw { /** * INTERNAL: Do not use. - * A Param. For example: - * ```rust - * todo!() - * ``` + * A normal parameter, `Param`, or a self parameter `SelfParam`. */ - class Param extends @param, AstNode { - override string toString() { result = "Param" } - + class ParamBase extends @param_base, AstNode { /** - * Gets the `index`th attr of this parameter (0-based). + * Gets the `index`th attr of this parameter base (0-based). */ - Attr getAttr(int index) { param_attrs(this, index, result) } + Attr getAttr(int index) { param_base_attrs(this, index, result) } /** - * Gets the pat of this parameter, if it exists. + * Gets the ty of this parameter base, if it exists. */ - Pat getPat() { param_pats(this, result) } - - /** - * Gets the ty of this parameter, if it exists. - */ - TypeRef getTy() { param_ties(this, result) } + TypeRef getTy() { param_base_ties(this, result) } } /** @@ -578,10 +592,7 @@ module Raw { /** * INTERNAL: Do not use. - * A PathSegment. For example: - * ```rust - * todo!() - * ``` + * A path segment, which is one part of a whole path. */ class PathSegment extends @path_segment, AstNode { override string toString() { result = "PathSegment" } @@ -811,42 +822,6 @@ module Raw { override string toString() { result = "ReturnTypeSyntax" } } - /** - * INTERNAL: Do not use. - * A SelfParam. For example: - * ```rust - * todo!() - * ``` - */ - class SelfParam extends @self_param, AstNode { - override string toString() { result = "SelfParam" } - - /** - * Gets the `index`th attr of this self parameter (0-based). - */ - Attr getAttr(int index) { self_param_attrs(this, index, result) } - - /** - * Holds if this self parameter is mut. - */ - predicate isMut() { self_param_is_mut(this) } - - /** - * Gets the lifetime of this self parameter, if it exists. - */ - Lifetime getLifetime() { self_param_lifetimes(this, result) } - - /** - * Gets the name of this self parameter, if it exists. - */ - Name getName() { self_param_names(this, result) } - - /** - * Gets the ty of this self parameter, if it exists. - */ - TypeRef getTy() { self_param_ties(this, result) } - } - /** * INTERNAL: Do not use. * A SourceFile. For example: @@ -1048,42 +1023,6 @@ module Raw { UseTree getUseTree(int index) { use_tree_list_use_trees(this, index, result) } } - /** - * INTERNAL: Do not use. - * A Variant. For example: - * ```rust - * todo!() - * ``` - */ - class Variant extends @variant, AstNode { - override string toString() { result = "Variant" } - - /** - * Gets the `index`th attr of this variant (0-based). - */ - Attr getAttr(int index) { variant_attrs(this, index, result) } - - /** - * Gets the expression of this variant, if it exists. - */ - Expr getExpr() { variant_exprs(this, result) } - - /** - * Gets the field list of this variant, if it exists. - */ - FieldList getFieldList() { variant_field_lists(this, result) } - - /** - * Gets the name of this variant, if it exists. - */ - Name getName() { variant_names(this, result) } - - /** - * Gets the visibility of this variant, if it exists. - */ - Visibility getVisibility() { variant_visibilities(this, result) } - } - /** * INTERNAL: Do not use. * A VariantList. For example: @@ -1366,70 +1305,6 @@ module Raw { Expr getRhs() { binary_expr_rhs(this, result) } } - /** - * INTERNAL: Do not use. - * A block expression. For example: - * ```rust - * { - * let x = 42; - * } - * ``` - * ```rust - * 'label: { - * let x = 42; - * x - * } - * ``` - */ - class BlockExpr extends @block_expr, Expr { - override string toString() { result = "BlockExpr" } - - /** - * Gets the `index`th attr of this block expression (0-based). - */ - Attr getAttr(int index) { block_expr_attrs(this, index, result) } - - /** - * Holds if this block expression is async. - */ - predicate isAsync() { block_expr_is_async(this) } - - /** - * Holds if this block expression is const. - */ - predicate isConst() { block_expr_is_const(this) } - - /** - * Holds if this block expression is gen. - */ - predicate isGen() { block_expr_is_gen(this) } - - /** - * Holds if this block expression is move. - */ - predicate isMove() { block_expr_is_move(this) } - - /** - * Holds if this block expression is try. - */ - predicate isTry() { block_expr_is_try(this) } - - /** - * Holds if this block expression is unsafe. - */ - predicate isUnsafe() { block_expr_is_unsafe(this) } - - /** - * Gets the label of this block expression, if it exists. - */ - Label getLabel() { block_expr_labels(this, result) } - - /** - * Gets the statement list of this block expression, if it exists. - */ - StmtList getStmtList() { block_expr_stmt_lists(this, result) } - } - /** * INTERNAL: Do not use. * A box pattern. For example: @@ -1824,42 +1699,6 @@ module Raw { RetType getRetType() { fn_ptr_type_ret_types(this, result) } } - /** - * INTERNAL: Do not use. - * A ForExpr. For example: - * ```rust - * todo!() - * ``` - */ - class ForExpr extends @for_expr, Expr { - override string toString() { result = "ForExpr" } - - /** - * Gets the `index`th attr of this for expression (0-based). - */ - Attr getAttr(int index) { for_expr_attrs(this, index, result) } - - /** - * Gets the iterable of this for expression, if it exists. - */ - Expr getIterable() { for_expr_iterables(this, result) } - - /** - * Gets the label of this for expression, if it exists. - */ - Label getLabel() { for_expr_labels(this, result) } - - /** - * Gets the loop body of this for expression, if it exists. - */ - BlockExpr getLoopBody() { for_expr_loop_bodies(this, result) } - - /** - * Gets the pat of this for expression, if it exists. - */ - Pat getPat() { for_expr_pats(this, result) } - } - /** * INTERNAL: Do not use. * A ForType. For example: @@ -1885,7 +1724,11 @@ module Raw { * INTERNAL: Do not use. * A FormatArgsExpr. For example: * ```rust - * todo!() + * format_args!("no args"); + * format_args!("{} foo {:?}", 1, 2); + * format_args!("{b} foo {a:?}", a=1, b=2); + * let (x, y) = (1, 42); + * format_args!("{x}, {y}"); * ``` */ class FormatArgsExpr extends @format_args_expr, Expr { @@ -2053,22 +1896,17 @@ module Raw { * todo!() * ``` */ - class Item extends @item, Stmt { - /** - * Gets the extended canonical path of this item, if it exists. - * - * Either a canonical path (see https://doc.rust-lang.org/reference/paths.html#canonical-paths), - * or `{}::name` for addressable items defined in an anonymous block (and only - * addressable there-in). - */ - string getExtendedCanonicalPath() { item_extended_canonical_paths(this, result) } + class Item extends @item, Stmt, Addressable { } + /** + * INTERNAL: Do not use. + * The base class for expressions that can be labeled (`LoopExpr`, `ForExpr`, `WhileExpr` or `BlockExpr`). + */ + class LabelableExpr extends @labelable_expr, Expr { /** - * Gets the crate origin of this item, if it exists. - * - * One of `rustc:`, `repo::` or `lang:`. + * Gets the label of this labelable expression, if it exists. */ - string getCrateOrigin() { item_crate_origins(this, result) } + Label getLabel() { labelable_expr_labels(this, result) } } /** @@ -2089,9 +1927,9 @@ module Raw { Attr getAttr(int index) { let_expr_attrs(this, index, result) } /** - * Gets the expression of this let expression, if it exists. + * Gets the scrutinee of this let expression, if it exists. */ - Expr getExpr() { let_expr_exprs(this, result) } + Expr getScrutinee() { let_expr_scrutinees(this, result) } /** * Gets the pat of this let expression, if it exists. @@ -2231,50 +2069,6 @@ module Raw { LiteralExpr getLiteral() { literal_pat_literals(this, result) } } - /** - * INTERNAL: Do not use. - * A loop expression. For example: - * ```rust - * loop { - * println!("Hello, world (again)!"); - * }; - * ``` - * ```rust - * 'label: loop { - * println!("Hello, world (once)!"); - * break 'label; - * }; - * ``` - * ```rust - * let mut x = 0; - * loop { - * if x < 10 { - * x += 1; - * } else { - * break; - * } - * }; - * ``` - */ - class LoopExpr extends @loop_expr, Expr { - override string toString() { result = "LoopExpr" } - - /** - * Gets the `index`th attr of this loop expression (0-based). - */ - Attr getAttr(int index) { loop_expr_attrs(this, index, result) } - - /** - * Gets the label of this loop expression, if it exists. - */ - Label getLabel() { loop_expr_labels(this, result) } - - /** - * Gets the loop body of this loop expression, if it exists. - */ - BlockExpr getLoopBody() { loop_expr_loop_bodies(this, result) } - } - /** * INTERNAL: Do not use. * A MacroExpr. For example: @@ -2348,9 +2142,9 @@ module Raw { Attr getAttr(int index) { match_expr_attrs(this, index, result) } /** - * Gets the expression of this match expression, if it exists. + * Gets the scrutinee (the expression being matched) of this match expression, if it exists. */ - Expr getExpr() { match_expr_exprs(this, result) } + Expr getScrutinee() { match_expr_scrutinees(this, result) } /** * Gets the match arm list of this match expression, if it exists. @@ -2413,6 +2207,24 @@ module Raw { Pat getPat(int index) { or_pat_pats(this, index, result) } } + /** + * INTERNAL: Do not use. + * A parameter in a function or method. For example `x` in: + * ```rust + * fn new(x: T) -> Foo { + * // ... + * } + * ``` + */ + class Param extends @param, ParamBase { + override string toString() { result = "Param" } + + /** + * Gets the pat of this parameter, if it exists. + */ + Pat getPat() { param_pats(this, result) } + } + /** * INTERNAL: Do not use. * A ParenExpr. For example: @@ -2470,6 +2282,7 @@ module Raw { * INTERNAL: Do not use. * A path. For example: * ```rust + * use some_crate::some_module::some_item; * foo::bar; * ``` */ @@ -2514,9 +2327,10 @@ module Raw { /** * INTERNAL: Do not use. - * A PathType. For example: + * A type referring to a path. For example: * ```rust - * todo!() + * type X = std::collections::HashMap; + * type Y = X::Item; * ``` */ class PathType extends @path_type, TypeRef { @@ -2847,6 +2661,34 @@ module Raw { Expr getExpr() { return_expr_exprs(this, result) } } + /** + * INTERNAL: Do not use. + * A `self` parameter. For example `self` in: + * ```rust + * fn push(&mut self, value: T) { + * // ... + * } + * ``` + */ + class SelfParam extends @self_param, ParamBase { + override string toString() { result = "SelfParam" } + + /** + * Holds if this self parameter is mut. + */ + predicate isMut() { self_param_is_mut(this) } + + /** + * Gets the lifetime of this self parameter, if it exists. + */ + Lifetime getLifetime() { self_param_lifetimes(this, result) } + + /** + * Gets the name of this self parameter, if it exists. + */ + Name getName() { self_param_names(this, result) } + } + /** * INTERNAL: Do not use. * A slice pattern. For example: @@ -3065,33 +2907,38 @@ module Raw { /** * INTERNAL: Do not use. - * A WhileExpr. For example: + * A Variant. For example: * ```rust * todo!() * ``` */ - class WhileExpr extends @while_expr, Expr { - override string toString() { result = "WhileExpr" } + class Variant extends @variant, Addressable { + override string toString() { result = "Variant" } /** - * Gets the `index`th attr of this while expression (0-based). + * Gets the `index`th attr of this variant (0-based). */ - Attr getAttr(int index) { while_expr_attrs(this, index, result) } + Attr getAttr(int index) { variant_attrs(this, index, result) } /** - * Gets the condition of this while expression, if it exists. + * Gets the expression of this variant, if it exists. */ - Expr getCondition() { while_expr_conditions(this, result) } + Expr getExpr() { variant_exprs(this, result) } + + /** + * Gets the field list of this variant, if it exists. + */ + FieldList getFieldList() { variant_field_lists(this, result) } /** - * Gets the label of this while expression, if it exists. + * Gets the name of this variant, if it exists. */ - Label getLabel() { while_expr_labels(this, result) } + Name getName() { variant_names(this, result) } /** - * Gets the loop body of this while expression, if it exists. + * Gets the visibility of this variant, if it exists. */ - BlockExpr getLoopBody() { while_expr_loop_bodies(this, result) } + Visibility getVisibility() { variant_visibilities(this, result) } } /** @@ -3152,6 +2999,65 @@ module Raw { Expr getExpr() { yield_expr_exprs(this, result) } } + /** + * INTERNAL: Do not use. + * A block expression. For example: + * ```rust + * { + * let x = 42; + * } + * ``` + * ```rust + * 'label: { + * let x = 42; + * x + * } + * ``` + */ + class BlockExpr extends @block_expr, LabelableExpr { + override string toString() { result = "BlockExpr" } + + /** + * Gets the `index`th attr of this block expression (0-based). + */ + Attr getAttr(int index) { block_expr_attrs(this, index, result) } + + /** + * Holds if this block expression is async. + */ + predicate isAsync() { block_expr_is_async(this) } + + /** + * Holds if this block expression is const. + */ + predicate isConst() { block_expr_is_const(this) } + + /** + * Holds if this block expression is gen. + */ + predicate isGen() { block_expr_is_gen(this) } + + /** + * Holds if this block expression is move. + */ + predicate isMove() { block_expr_is_move(this) } + + /** + * Holds if this block expression is try. + */ + predicate isTry() { block_expr_is_try(this) } + + /** + * Holds if this block expression is unsafe. + */ + predicate isUnsafe() { block_expr_is_unsafe(this) } + + /** + * Gets the statement list of this block expression, if it exists. + */ + StmtList getStmtList() { block_expr_stmt_lists(this, result) } + } + /** * INTERNAL: Do not use. * A function call expression. For example: @@ -3166,9 +3072,9 @@ module Raw { override string toString() { result = "CallExpr" } /** - * Gets the expression of this call expression, if it exists. + * Gets the function of this call expression, if it exists. */ - Expr getExpr() { call_expr_exprs(this, result) } + Expr getFunction() { call_expr_functions(this, result) } } /** @@ -3458,6 +3364,17 @@ module Raw { WhereClause getWhereClause() { impl_where_clauses(this, result) } } + /** + * INTERNAL: Do not use. + * The base class for expressions that loop (`LoopExpr`, `ForExpr` or `WhileExpr`). + */ + class LoopingExpr extends @looping_expr, LabelableExpr { + /** + * Gets the loop body of this looping expression, if it exists. + */ + BlockExpr getLoopBody() { looping_expr_loop_bodies(this, result) } + } + /** * INTERNAL: Do not use. * A MacroCall. For example: @@ -3950,4 +3867,85 @@ module Raw { */ Visibility getVisibility() { use_visibilities(this, result) } } + + /** + * INTERNAL: Do not use. + * A ForExpr. For example: + * ```rust + * todo!() + * ``` + */ + class ForExpr extends @for_expr, LoopingExpr { + override string toString() { result = "ForExpr" } + + /** + * Gets the `index`th attr of this for expression (0-based). + */ + Attr getAttr(int index) { for_expr_attrs(this, index, result) } + + /** + * Gets the iterable of this for expression, if it exists. + */ + Expr getIterable() { for_expr_iterables(this, result) } + + /** + * Gets the pat of this for expression, if it exists. + */ + Pat getPat() { for_expr_pats(this, result) } + } + + /** + * INTERNAL: Do not use. + * A loop expression. For example: + * ```rust + * loop { + * println!("Hello, world (again)!"); + * }; + * ``` + * ```rust + * 'label: loop { + * println!("Hello, world (once)!"); + * break 'label; + * }; + * ``` + * ```rust + * let mut x = 0; + * loop { + * if x < 10 { + * x += 1; + * } else { + * break; + * } + * }; + * ``` + */ + class LoopExpr extends @loop_expr, LoopingExpr { + override string toString() { result = "LoopExpr" } + + /** + * Gets the `index`th attr of this loop expression (0-based). + */ + Attr getAttr(int index) { loop_expr_attrs(this, index, result) } + } + + /** + * INTERNAL: Do not use. + * A WhileExpr. For example: + * ```rust + * todo!() + * ``` + */ + class WhileExpr extends @while_expr, LoopingExpr { + override string toString() { result = "WhileExpr" } + + /** + * Gets the `index`th attr of this while expression (0-based). + */ + Attr getAttr(int index) { while_expr_attrs(this, index, result) } + + /** + * Gets the condition of this while expression, if it exists. + */ + Expr getCondition() { while_expr_conditions(this, result) } + } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/SelfParam.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/SelfParam.qll index 243d04e9bb77..b2cc6e4b0c4a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/SelfParam.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/SelfParam.qll @@ -6,11 +6,9 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw -import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl -import codeql.rust.elements.Attr import codeql.rust.elements.Lifetime import codeql.rust.elements.Name -import codeql.rust.elements.TypeRef +import codeql.rust.elements.internal.ParamBaseImpl::Impl as ParamBaseImpl /** * INTERNAL: This module contains the fully generated definition of `SelfParam` and should not @@ -18,34 +16,18 @@ import codeql.rust.elements.TypeRef */ module Generated { /** - * A SelfParam. For example: + * A `self` parameter. For example `self` in: * ```rust - * todo!() + * fn push(&mut self, value: T) { + * // ... + * } * ``` * INTERNAL: Do not reference the `Generated::SelfParam` class directly. * Use the subclass `SelfParam`, where the following predicates are available. */ - class SelfParam extends Synth::TSelfParam, AstNodeImpl::AstNode { + class SelfParam extends Synth::TSelfParam, ParamBaseImpl::ParamBase { override string getAPrimaryQlClass() { result = "SelfParam" } - /** - * Gets the `index`th attr of this self parameter (0-based). - */ - Attr getAttr(int index) { - result = - Synth::convertAttrFromRaw(Synth::convertSelfParamToRaw(this).(Raw::SelfParam).getAttr(index)) - } - - /** - * Gets any of the attrs of this self parameter. - */ - final Attr getAnAttr() { result = this.getAttr(_) } - - /** - * Gets the number of attrs of this self parameter. - */ - final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) } - /** * Holds if this self parameter is mut. */ @@ -78,18 +60,5 @@ module Generated { * Holds if `getName()` exists. */ final predicate hasName() { exists(this.getName()) } - - /** - * Gets the ty of this self parameter, if it exists. - */ - TypeRef getTy() { - result = - Synth::convertTypeRefFromRaw(Synth::convertSelfParamToRaw(this).(Raw::SelfParam).getTy()) - } - - /** - * Holds if `getTy()` exists. - */ - final predicate hasTy() { exists(this.getTy()) } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll index 927ba1f238d8..0b4fa39cd848 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll @@ -611,6 +611,11 @@ module Synth { */ TYieldExpr(Raw::YieldExpr id) { constructYieldExpr(id) } + /** + * INTERNAL: Do not use. + */ + class TAddressable = TItem or TVariant; + /** * INTERNAL: Do not use. */ @@ -620,15 +625,15 @@ module Synth { * INTERNAL: Do not use. */ class TAstNode = - TAbi or TArgList or TAssocItem or TAssocItemList or TAttr or TCallable or TClosureBinder or - TExpr or TExternItem or TExternItemList or TFieldList or TFormatArgsArg or TGenericArg or - TGenericArgList or TGenericParam or TGenericParamList or TItemList or TLabel or TLetElse or - TLifetime or TMacroItems or TMacroStmts or TMatchArm or TMatchArmList or TMatchGuard or - TMeta or TName or TNameRef or TParam or TParamList or TPat or TPathSegment or - TRecordExprField or TRecordExprFieldList or TRecordField or TRecordPatField or - TRecordPatFieldList or TRename or TResolvable or TRetType or TReturnTypeSyntax or - TSelfParam or TSourceFile or TStmt or TStmtList or TToken or TTokenTree or TTupleField or - TTypeBound or TTypeBoundList or TTypeRef or TUseTree or TUseTreeList or TVariant or + TAbi or TAddressable or TArgList or TAssocItem or TAssocItemList or TAttr or TCallable or + TClosureBinder or TExpr or TExternItem or TExternItemList or TFieldList or TFormatArgsArg or + TGenericArg or TGenericArgList or TGenericParam or TGenericParamList or TItemList or + TLabel or TLetElse or TLifetime or TMacroItems or TMacroStmts or TMatchArm or + TMatchArmList or TMatchGuard or TMeta or TName or TNameRef or TParamBase or TParamList or + TPat or TPathSegment or TRecordExprField or TRecordExprFieldList or TRecordField or + TRecordPatField or TRecordPatFieldList or TRename or TResolvable or TRetType or + TReturnTypeSyntax or TSourceFile or TStmt or TStmtList or TToken or TTokenTree or + TTupleField or TTypeBound or TTypeBoundList or TTypeRef or TUseTree or TUseTreeList or TVariantList or TVisibility or TWhereClause or TWherePred; /** @@ -645,12 +650,12 @@ module Synth { * INTERNAL: Do not use. */ class TExpr = - TArrayExpr or TAsmExpr or TAwaitExpr or TBecomeExpr or TBinaryExpr or TBlockExpr or - TBreakExpr or TCallExprBase or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or - TForExpr or TFormatArgsExpr or TIfExpr or TIndexExpr or TLetExpr or TLiteralExpr or - TLoopExpr or TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExprBase or - TPrefixExpr or TRangeExpr or TRecordExpr or TRefExpr or TReturnExpr or TTryExpr or - TTupleExpr or TUnderscoreExpr or TWhileExpr or TYeetExpr or TYieldExpr; + TArrayExpr or TAsmExpr or TAwaitExpr or TBecomeExpr or TBinaryExpr or TBreakExpr or + TCallExprBase or TCastExpr or TClosureExpr or TContinueExpr or TFieldExpr or + TFormatArgsExpr or TIfExpr or TIndexExpr or TLabelableExpr or TLetExpr or TLiteralExpr or + TMacroExpr or TMatchExpr or TOffsetOfExpr or TParenExpr or TPathExprBase or TPrefixExpr or + TRangeExpr or TRecordExpr or TRefExpr or TReturnExpr or TTryExpr or TTupleExpr or + TUnderscoreExpr or TYeetExpr or TYieldExpr; /** * INTERNAL: Do not use. @@ -680,11 +685,26 @@ module Synth { TMacroDef or TMacroRules or TModule or TStatic or TStruct or TTrait or TTraitAlias or TTypeAlias or TUnion or TUse; + /** + * INTERNAL: Do not use. + */ + class TLabelableExpr = TBlockExpr or TLoopingExpr; + /** * INTERNAL: Do not use. */ class TLocatable = TAstNode or TFormat or TFormatArgument; + /** + * INTERNAL: Do not use. + */ + class TLoopingExpr = TForExpr or TLoopExpr or TWhileExpr; + + /** + * INTERNAL: Do not use. + */ + class TParamBase = TParam or TSelfParam; + /** * INTERNAL: Do not use. */ @@ -1614,6 +1634,16 @@ module Synth { */ TYieldExpr convertYieldExprFromRaw(Raw::Element e) { result = TYieldExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw DB element to a synthesized `TAddressable`, if possible. + */ + TAddressable convertAddressableFromRaw(Raw::Element e) { + result = convertItemFromRaw(e) + or + result = convertVariantFromRaw(e) + } + /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TAssocItem`, if possible. @@ -1635,6 +1665,8 @@ module Synth { TAstNode convertAstNodeFromRaw(Raw::Element e) { result = convertAbiFromRaw(e) or + result = convertAddressableFromRaw(e) + or result = convertArgListFromRaw(e) or result = convertAssocItemFromRaw(e) @@ -1689,7 +1721,7 @@ module Synth { or result = convertNameRefFromRaw(e) or - result = convertParamFromRaw(e) + result = convertParamBaseFromRaw(e) or result = convertParamListFromRaw(e) or @@ -1715,8 +1747,6 @@ module Synth { or result = convertReturnTypeSyntaxFromRaw(e) or - result = convertSelfParamFromRaw(e) - or result = convertSourceFileFromRaw(e) or result = convertStmtFromRaw(e) @@ -1739,8 +1769,6 @@ module Synth { or result = convertUseTreeListFromRaw(e) or - result = convertVariantFromRaw(e) - or result = convertVariantListFromRaw(e) or result = convertVisibilityFromRaw(e) @@ -1795,8 +1823,6 @@ module Synth { or result = convertBinaryExprFromRaw(e) or - result = convertBlockExprFromRaw(e) - or result = convertBreakExprFromRaw(e) or result = convertCallExprBaseFromRaw(e) @@ -1809,20 +1835,18 @@ module Synth { or result = convertFieldExprFromRaw(e) or - result = convertForExprFromRaw(e) - or result = convertFormatArgsExprFromRaw(e) or result = convertIfExprFromRaw(e) or result = convertIndexExprFromRaw(e) or + result = convertLabelableExprFromRaw(e) + or result = convertLetExprFromRaw(e) or result = convertLiteralExprFromRaw(e) or - result = convertLoopExprFromRaw(e) - or result = convertMacroExprFromRaw(e) or result = convertMatchExprFromRaw(e) @@ -1849,8 +1873,6 @@ module Synth { or result = convertUnderscoreExprFromRaw(e) or - result = convertWhileExprFromRaw(e) - or result = convertYeetExprFromRaw(e) or result = convertYieldExprFromRaw(e) @@ -1946,6 +1968,16 @@ module Synth { result = convertUseFromRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a raw DB element to a synthesized `TLabelableExpr`, if possible. + */ + TLabelableExpr convertLabelableExprFromRaw(Raw::Element e) { + result = convertBlockExprFromRaw(e) + or + result = convertLoopingExprFromRaw(e) + } + /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TLocatable`, if possible. @@ -1958,6 +1990,28 @@ module Synth { result = convertFormatArgumentFromRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a raw DB element to a synthesized `TLoopingExpr`, if possible. + */ + TLoopingExpr convertLoopingExprFromRaw(Raw::Element e) { + result = convertForExprFromRaw(e) + or + result = convertLoopExprFromRaw(e) + or + result = convertWhileExprFromRaw(e) + } + + /** + * INTERNAL: Do not use. + * Converts a raw DB element to a synthesized `TParamBase`, if possible. + */ + TParamBase convertParamBaseFromRaw(Raw::Element e) { + result = convertParamFromRaw(e) + or + result = convertSelfParamFromRaw(e) + } + /** * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TPat`, if possible. @@ -2964,6 +3018,16 @@ module Synth { */ Raw::Element convertYieldExprToRaw(TYieldExpr e) { e = TYieldExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TAddressable` to a raw DB element, if possible. + */ + Raw::Element convertAddressableToRaw(TAddressable e) { + result = convertItemToRaw(e) + or + result = convertVariantToRaw(e) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TAssocItem` to a raw DB element, if possible. @@ -2985,6 +3049,8 @@ module Synth { Raw::Element convertAstNodeToRaw(TAstNode e) { result = convertAbiToRaw(e) or + result = convertAddressableToRaw(e) + or result = convertArgListToRaw(e) or result = convertAssocItemToRaw(e) @@ -3039,7 +3105,7 @@ module Synth { or result = convertNameRefToRaw(e) or - result = convertParamToRaw(e) + result = convertParamBaseToRaw(e) or result = convertParamListToRaw(e) or @@ -3065,8 +3131,6 @@ module Synth { or result = convertReturnTypeSyntaxToRaw(e) or - result = convertSelfParamToRaw(e) - or result = convertSourceFileToRaw(e) or result = convertStmtToRaw(e) @@ -3089,8 +3153,6 @@ module Synth { or result = convertUseTreeListToRaw(e) or - result = convertVariantToRaw(e) - or result = convertVariantListToRaw(e) or result = convertVisibilityToRaw(e) @@ -3145,8 +3207,6 @@ module Synth { or result = convertBinaryExprToRaw(e) or - result = convertBlockExprToRaw(e) - or result = convertBreakExprToRaw(e) or result = convertCallExprBaseToRaw(e) @@ -3159,20 +3219,18 @@ module Synth { or result = convertFieldExprToRaw(e) or - result = convertForExprToRaw(e) - or result = convertFormatArgsExprToRaw(e) or result = convertIfExprToRaw(e) or result = convertIndexExprToRaw(e) or + result = convertLabelableExprToRaw(e) + or result = convertLetExprToRaw(e) or result = convertLiteralExprToRaw(e) or - result = convertLoopExprToRaw(e) - or result = convertMacroExprToRaw(e) or result = convertMatchExprToRaw(e) @@ -3199,8 +3257,6 @@ module Synth { or result = convertUnderscoreExprToRaw(e) or - result = convertWhileExprToRaw(e) - or result = convertYeetExprToRaw(e) or result = convertYieldExprToRaw(e) @@ -3296,6 +3352,16 @@ module Synth { result = convertUseToRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TLabelableExpr` to a raw DB element, if possible. + */ + Raw::Element convertLabelableExprToRaw(TLabelableExpr e) { + result = convertBlockExprToRaw(e) + or + result = convertLoopingExprToRaw(e) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TLocatable` to a raw DB element, if possible. @@ -3308,6 +3374,28 @@ module Synth { result = convertFormatArgumentToRaw(e) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TLoopingExpr` to a raw DB element, if possible. + */ + Raw::Element convertLoopingExprToRaw(TLoopingExpr e) { + result = convertForExprToRaw(e) + or + result = convertLoopExprToRaw(e) + or + result = convertWhileExprToRaw(e) + } + + /** + * INTERNAL: Do not use. + * Converts a synthesized `TParamBase` to a raw DB element, if possible. + */ + Raw::Element convertParamBaseToRaw(TParamBase e) { + result = convertParamToRaw(e) + or + result = convertSelfParamToRaw(e) + } + /** * INTERNAL: Do not use. * Converts a synthesized `TPat` to a raw DB element, if possible. diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Variant.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Variant.qll index ec57b2a03da2..b78043e09223 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Variant.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Variant.qll @@ -6,7 +6,7 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw -import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl +import codeql.rust.elements.internal.AddressableImpl::Impl as AddressableImpl import codeql.rust.elements.Attr import codeql.rust.elements.Expr import codeql.rust.elements.FieldList @@ -26,7 +26,7 @@ module Generated { * INTERNAL: Do not reference the `Generated::Variant` class directly. * Use the subclass `Variant`, where the following predicates are available. */ - class Variant extends Synth::TVariant, AstNodeImpl::AstNode { + class Variant extends Synth::TVariant, AddressableImpl::Addressable { override string getAPrimaryQlClass() { result = "Variant" } /** diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/WhileExpr.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/WhileExpr.qll index 5cd48bb25063..fa4a4aee65c5 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/WhileExpr.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/WhileExpr.qll @@ -7,10 +7,8 @@ private import codeql.rust.elements.internal.generated.Synth private import codeql.rust.elements.internal.generated.Raw import codeql.rust.elements.Attr -import codeql.rust.elements.BlockExpr import codeql.rust.elements.Expr -import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl -import codeql.rust.elements.Label +import codeql.rust.elements.internal.LoopingExprImpl::Impl as LoopingExprImpl /** * INTERNAL: This module contains the fully generated definition of `WhileExpr` and should not @@ -25,7 +23,7 @@ module Generated { * INTERNAL: Do not reference the `Generated::WhileExpr` class directly. * Use the subclass `WhileExpr`, where the following predicates are available. */ - class WhileExpr extends Synth::TWhileExpr, ExprImpl::Expr { + class WhileExpr extends Synth::TWhileExpr, LoopingExprImpl::LoopingExpr { override string getAPrimaryQlClass() { result = "WhileExpr" } /** @@ -58,33 +56,5 @@ module Generated { * Holds if `getCondition()` exists. */ final predicate hasCondition() { exists(this.getCondition()) } - - /** - * Gets the label of this while expression, if it exists. - */ - Label getLabel() { - result = - Synth::convertLabelFromRaw(Synth::convertWhileExprToRaw(this).(Raw::WhileExpr).getLabel()) - } - - /** - * Holds if `getLabel()` exists. - */ - final predicate hasLabel() { exists(this.getLabel()) } - - /** - * Gets the loop body of this while expression, if it exists. - */ - BlockExpr getLoopBody() { - result = - Synth::convertBlockExprFromRaw(Synth::convertWhileExprToRaw(this) - .(Raw::WhileExpr) - .getLoopBody()) - } - - /** - * Holds if `getLoopBody()` exists. - */ - final predicate hasLoopBody() { exists(this.getLoopBody()) } } } diff --git a/rust/ql/lib/codeql/rust/frameworks/Reqwest.qll b/rust/ql/lib/codeql/rust/frameworks/Reqwest.qll new file mode 100644 index 000000000000..f46c12feab93 --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/Reqwest.qll @@ -0,0 +1,20 @@ +/** + * Provides modeling for the `reqwest` library. + */ + +private import rust +private import codeql.rust.Concepts + +/** + * A call to `reqwest::get` or `reqwest::blocking::get`. + */ +private class ReqwestGet extends RemoteSource::Range { + ReqwestGet() { + exists(CallExpr ce | + this.asExpr().getExpr() = ce and + ce.getFunction().(PathExpr).getPath().getResolvedCrateOrigin().matches("%reqwest") and + ce.getFunction().(PathExpr).getPath().getResolvedPath() = + ["crate::get", "crate::blocking::get"] + ) + } +} diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/Env.qll b/rust/ql/lib/codeql/rust/frameworks/stdlib/Env.qll new file mode 100644 index 000000000000..3e769ae84d4f --- /dev/null +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/Env.qll @@ -0,0 +1,36 @@ +/** + * Provides modeling for the `std::env` library. + */ + +private import rust +private import codeql.rust.Concepts + +/** + * A call to `std::env::args` or `std::env::args_os`. + */ +private class StdEnvArgs extends CommandLineArgsSource::Range { + StdEnvArgs() { + this.asExpr().getExpr().(CallExpr).getFunction().(PathExpr).getPath().getResolvedPath() = + ["crate::env::args", "crate::env::args_os"] + } +} + +/** + * A call to `std::env::current_dir`, `std::env::current_exe` or `std::env::home_dir`. + */ +private class StdEnvDir extends CommandLineArgsSource::Range { + StdEnvDir() { + this.asExpr().getExpr().(CallExpr).getFunction().(PathExpr).getPath().getResolvedPath() = + ["crate::env::current_dir", "crate::env::current_exe", "crate::env::home_dir"] + } +} + +/** + * A call to `std::env::var`, `std::env::var_os`, `std::env::vars` or `std::env::vars_os`. + */ +private class StdEnvVar extends EnvironmentSource::Range { + StdEnvVar() { + this.asExpr().getExpr().(CallExpr).getFunction().(PathExpr).getPath().getResolvedPath() = + ["crate::env::var", "crate::env::var_os", "crate::env::vars", "crate::env::vars_os"] + } +} diff --git a/rust/ql/lib/codeql/rust/internal/CachedStages.qll b/rust/ql/lib/codeql/rust/internal/CachedStages.qll index 162853846f2d..1fdd3c2a9b85 100644 --- a/rust/ql/lib/codeql/rust/internal/CachedStages.qll +++ b/rust/ql/lib/codeql/rust/internal/CachedStages.qll @@ -71,6 +71,7 @@ module Stages { private import codeql.rust.controlflow.internal.Splitting private import codeql.rust.controlflow.internal.SuccessorType private import codeql.rust.controlflow.internal.ControlFlowGraphImpl + private import codeql.rust.controlflow.CfgNodes /** * Always holds. @@ -93,6 +94,8 @@ module Stages { exists(TNormalSuccessor()) or exists(AstCfgNode n) + or + exists(CallExprCfgNode n | exists(n.getFunction())) } } } diff --git a/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll b/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll new file mode 100644 index 000000000000..db6239d78110 --- /dev/null +++ b/rust/ql/lib/codeql/rust/security/SqlInjectionExtensions.qll @@ -0,0 +1,50 @@ +/** + * Provides classes and predicates for reasoning about database + * queries built from user-controlled sources (that is, SQL injection + * vulnerabilities). + */ + +import rust +private import codeql.rust.dataflow.DataFlow +private import codeql.rust.Concepts +private import codeql.util.Unit + +/** + * Provides default sources, sinks and barriers for detecting SQL injection + * vulnerabilities, as well as extension points for adding your own. + */ +module SqlInjection { + /** + * A data flow source for SQL injection vulnerabilities. + */ + abstract class Source extends DataFlow::Node { } + + /** + * A data flow sink for SQL injection vulnerabilities. + */ + abstract class Sink extends DataFlow::Node { } + + /** + * A barrier for SQL injection vulnerabilities. + */ + abstract class Barrier extends DataFlow::Node { } + + /** + * An active threat-model source, considered as a flow source. + */ + private class ActiveThreatModelSourceAsSource extends Source, ActiveThreatModelSource { } + + /** + * A flow sink that is the statement of an SQL construction. + */ + class SqlConstructionAsSink extends Sink { + SqlConstructionAsSink() { this = any(SqlConstruction c).getSql() } + } + + /** + * A flow sink that is the statement of an SQL execution. + */ + class SqlExecutionAsSink extends Sink { + SqlExecutionAsSink() { this = any(SqlExecution e).getSql() } + } +} diff --git a/rust/ql/lib/qlpack.yml b/rust/ql/lib/qlpack.yml index 649d02c8e3aa..53ccf6dfced4 100644 --- a/rust/ql/lib/qlpack.yml +++ b/rust/ql/lib/qlpack.yml @@ -8,6 +8,7 @@ dependencies: codeql/controlflow: ${workspace} codeql/dataflow: ${workspace} codeql/regex: ${workspace} + codeql/threat-models: ${workspace} codeql/mad: ${workspace} codeql/ssa: ${workspace} codeql/tutorial: ${workspace} diff --git a/rust/ql/lib/rust.dbscheme b/rust/ql/lib/rust.dbscheme index 666a1e2b0e16..fe0f5bc436c9 100644 --- a/rust/ql/lib/rust.dbscheme +++ b/rust/ql/lib/rust.dbscheme @@ -135,6 +135,7 @@ locatable_locations( @ast_node = @abi +| @addressable | @arg_list | @assoc_item | @assoc_item_list @@ -162,7 +163,7 @@ locatable_locations( | @meta | @name | @name_ref -| @param +| @param_base | @param_list | @pat | @path_segment @@ -175,7 +176,6 @@ locatable_locations( | @resolvable | @ret_type | @return_type_syntax -| @self_param | @source_file | @stmt | @stmt_list @@ -187,7 +187,6 @@ locatable_locations( | @type_ref | @use_tree | @use_tree_list -| @variant | @variant_list | @visibility | @where_clause @@ -212,6 +211,23 @@ abi_abi_strings( string abi_string: string ref ); +@addressable = + @item +| @variant +; + +#keyset[id] +addressable_extended_canonical_paths( + int id: @addressable ref, + string extended_canonical_path: string ref +); + +#keyset[id] +addressable_crate_origins( + int id: @addressable ref, + string crate_origin: string ref +); + arg_lists( unique int id: @arg_list ); @@ -292,20 +308,18 @@ closure_binder_generic_param_lists( | @await_expr | @become_expr | @binary_expr -| @block_expr | @break_expr | @call_expr_base | @cast_expr | @closure_expr | @continue_expr | @field_expr -| @for_expr | @format_args_expr | @if_expr | @index_expr +| @labelable_expr | @let_expr | @literal_expr -| @loop_expr | @macro_expr | @match_expr | @offset_of_expr @@ -319,7 +333,6 @@ closure_binder_generic_param_lists( | @try_expr | @tuple_expr | @underscore_expr -| @while_expr | @yeet_expr | @yield_expr ; @@ -585,26 +598,21 @@ name_ref_texts( string text: string ref ); -params( - unique int id: @param -); +@param_base = + @param +| @self_param +; #keyset[id, index] -param_attrs( - int id: @param ref, +param_base_attrs( + int id: @param_base ref, int index: int ref, int attr: @attr ref ); #keyset[id] -param_pats( - int id: @param ref, - int pat: @pat ref -); - -#keyset[id] -param_ties( - int id: @param ref, +param_base_ties( + int id: @param_base ref, int ty: @type_ref ref ); @@ -847,40 +855,6 @@ return_type_syntaxes( unique int id: @return_type_syntax ); -self_params( - unique int id: @self_param -); - -#keyset[id, index] -self_param_attrs( - int id: @self_param ref, - int index: int ref, - int attr: @attr ref -); - -#keyset[id] -self_param_is_mut( - int id: @self_param ref -); - -#keyset[id] -self_param_lifetimes( - int id: @self_param ref, - int lifetime: @lifetime ref -); - -#keyset[id] -self_param_names( - int id: @self_param ref, - int name: @name ref -); - -#keyset[id] -self_param_ties( - int id: @self_param ref, - int ty: @type_ref ref -); - source_files( unique int id: @source_file ); @@ -1053,41 +1027,6 @@ use_tree_list_use_trees( int use_tree: @use_tree ref ); -variants( - unique int id: @variant -); - -#keyset[id, index] -variant_attrs( - int id: @variant ref, - int index: int ref, - int attr: @attr ref -); - -#keyset[id] -variant_exprs( - int id: @variant ref, - int expr: @expr ref -); - -#keyset[id] -variant_field_lists( - int id: @variant ref, - int field_list: @field_list ref -); - -#keyset[id] -variant_names( - int id: @variant ref, - int name: @name ref -); - -#keyset[id] -variant_visibilities( - int id: @variant ref, - int visibility: @visibility ref -); - variant_lists( unique int id: @variant_list ); @@ -1314,59 +1253,6 @@ binary_expr_rhs( int rhs: @expr ref ); -block_exprs( - unique int id: @block_expr -); - -#keyset[id, index] -block_expr_attrs( - int id: @block_expr ref, - int index: int ref, - int attr: @attr ref -); - -#keyset[id] -block_expr_is_async( - int id: @block_expr ref -); - -#keyset[id] -block_expr_is_const( - int id: @block_expr ref -); - -#keyset[id] -block_expr_is_gen( - int id: @block_expr ref -); - -#keyset[id] -block_expr_is_move( - int id: @block_expr ref -); - -#keyset[id] -block_expr_is_try( - int id: @block_expr ref -); - -#keyset[id] -block_expr_is_unsafe( - int id: @block_expr ref -); - -#keyset[id] -block_expr_labels( - int id: @block_expr ref, - int label: @label ref -); - -#keyset[id] -block_expr_stmt_lists( - int id: @block_expr ref, - int stmt_list: @stmt_list ref -); - box_pats( unique int id: @box_pat ); @@ -1650,41 +1536,6 @@ fn_ptr_type_ret_types( int ret_type: @ret_type ref ); -for_exprs( - unique int id: @for_expr -); - -#keyset[id, index] -for_expr_attrs( - int id: @for_expr ref, - int index: int ref, - int attr: @attr ref -); - -#keyset[id] -for_expr_iterables( - int id: @for_expr ref, - int iterable: @expr ref -); - -#keyset[id] -for_expr_labels( - int id: @for_expr ref, - int label: @label ref -); - -#keyset[id] -for_expr_loop_bodies( - int id: @for_expr ref, - int loop_body: @block_expr ref -); - -#keyset[id] -for_expr_pats( - int id: @for_expr ref, - int pat: @pat ref -); - for_types( unique int id: @for_type ); @@ -1844,16 +1695,15 @@ infer_types( | @use ; -#keyset[id] -item_extended_canonical_paths( - int id: @item ref, - string extended_canonical_path: string ref -); +@labelable_expr = + @block_expr +| @looping_expr +; #keyset[id] -item_crate_origins( - int id: @item ref, - string crate_origin: string ref +labelable_expr_labels( + int id: @labelable_expr ref, + int label: @label ref ); let_exprs( @@ -1868,9 +1718,9 @@ let_expr_attrs( ); #keyset[id] -let_expr_exprs( +let_expr_scrutinees( int id: @let_expr ref, - int expr: @expr ref + int scrutinee: @expr ref ); #keyset[id] @@ -1974,29 +1824,6 @@ literal_pat_literals( int literal: @literal_expr ref ); -loop_exprs( - unique int id: @loop_expr -); - -#keyset[id, index] -loop_expr_attrs( - int id: @loop_expr ref, - int index: int ref, - int attr: @attr ref -); - -#keyset[id] -loop_expr_labels( - int id: @loop_expr ref, - int label: @label ref -); - -#keyset[id] -loop_expr_loop_bodies( - int id: @loop_expr ref, - int loop_body: @block_expr ref -); - macro_exprs( unique int id: @macro_expr ); @@ -2039,9 +1866,9 @@ match_expr_attrs( ); #keyset[id] -match_expr_exprs( +match_expr_scrutinees( int id: @match_expr ref, - int expr: @expr ref + int scrutinee: @expr ref ); #keyset[id] @@ -2089,6 +1916,16 @@ or_pat_pats( int pat: @pat ref ); +params( + unique int id: @param +); + +#keyset[id] +param_pats( + int id: @param ref, + int pat: @pat ref +); + paren_exprs( unique int id: @paren_expr ); @@ -2399,6 +2236,27 @@ return_expr_exprs( int expr: @expr ref ); +self_params( + unique int id: @self_param +); + +#keyset[id] +self_param_is_mut( + int id: @self_param ref +); + +#keyset[id] +self_param_lifetimes( + int id: @self_param ref, + int lifetime: @lifetime ref +); + +#keyset[id] +self_param_names( + int id: @self_param ref, + int name: @name ref +); + slice_pats( unique int id: @slice_pat ); @@ -2555,33 +2413,39 @@ underscore_expr_attrs( int attr: @attr ref ); -while_exprs( - unique int id: @while_expr +variants( + unique int id: @variant ); #keyset[id, index] -while_expr_attrs( - int id: @while_expr ref, +variant_attrs( + int id: @variant ref, int index: int ref, int attr: @attr ref ); #keyset[id] -while_expr_conditions( - int id: @while_expr ref, - int condition: @expr ref +variant_exprs( + int id: @variant ref, + int expr: @expr ref ); #keyset[id] -while_expr_labels( - int id: @while_expr ref, - int label: @label ref +variant_field_lists( + int id: @variant ref, + int field_list: @field_list ref ); #keyset[id] -while_expr_loop_bodies( - int id: @while_expr ref, - int loop_body: @block_expr ref +variant_names( + int id: @variant ref, + int name: @name ref +); + +#keyset[id] +variant_visibilities( + int id: @variant ref, + int visibility: @visibility ref ); wildcard_pats( @@ -2622,14 +2486,61 @@ yield_expr_exprs( int expr: @expr ref ); +block_exprs( + unique int id: @block_expr +); + +#keyset[id, index] +block_expr_attrs( + int id: @block_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +block_expr_is_async( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_const( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_gen( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_move( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_try( + int id: @block_expr ref +); + +#keyset[id] +block_expr_is_unsafe( + int id: @block_expr ref +); + +#keyset[id] +block_expr_stmt_lists( + int id: @block_expr ref, + int stmt_list: @stmt_list ref +); + call_exprs( unique int id: @call_expr ); #keyset[id] -call_expr_exprs( +call_expr_functions( int id: @call_expr ref, - int expr: @expr ref + int function: @expr ref ); consts( @@ -2908,6 +2819,18 @@ impl_where_clauses( int where_clause: @where_clause ref ); +@looping_expr = + @for_expr +| @loop_expr +| @while_expr +; + +#keyset[id] +looping_expr_loop_bodies( + int id: @looping_expr ref, + int loop_body: @block_expr ref +); + macro_calls( unique int id: @macro_call ); @@ -3368,3 +3291,54 @@ use_visibilities( int id: @use ref, int visibility: @visibility ref ); + +for_exprs( + unique int id: @for_expr +); + +#keyset[id, index] +for_expr_attrs( + int id: @for_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +for_expr_iterables( + int id: @for_expr ref, + int iterable: @expr ref +); + +#keyset[id] +for_expr_pats( + int id: @for_expr ref, + int pat: @pat ref +); + +loop_exprs( + unique int id: @loop_expr +); + +#keyset[id, index] +loop_expr_attrs( + int id: @loop_expr ref, + int index: int ref, + int attr: @attr ref +); + +while_exprs( + unique int id: @while_expr +); + +#keyset[id, index] +while_expr_attrs( + int id: @while_expr ref, + int index: int ref, + int attr: @attr ref +); + +#keyset[id] +while_expr_conditions( + int id: @while_expr ref, + int condition: @expr ref +); diff --git a/rust/ql/src/queries/diagnostics/UnextractedElements.ql b/rust/ql/src/queries/diagnostics/UnextractedElements.ql index dccf7d2ab09f..1a819e3f7847 100644 --- a/rust/ql/src/queries/diagnostics/UnextractedElements.ql +++ b/rust/ql/src/queries/diagnostics/UnextractedElements.ql @@ -1,6 +1,7 @@ /** * @name Unextracted Elements * @description List all elements that weren't extracted due to unimplemented features or parse errors. + * @kind diagnostic * @id rust/diagnostics/unextracted-elements */ diff --git a/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql b/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql new file mode 100644 index 000000000000..a20c5035b6ab --- /dev/null +++ b/rust/ql/src/queries/diagnostics/UnresolvedMacroCalls.ql @@ -0,0 +1,12 @@ +/** + * @name Unresolved Macro Calls + * @description List all macro calls that were not resolved to a target. + * @kind diagnostic + * @id rust/diagnostics/unresolved-macro-calls + */ + +import rust + +from MacroCall mc +where not mc.hasExpanded() +select mc, "Macro call was not resolved to a target." diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjection.qhelp b/rust/ql/src/queries/security/CWE-089/SqlInjection.qhelp new file mode 100644 index 000000000000..0b56ac54d0de --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjection.qhelp @@ -0,0 +1,39 @@ + + + + +

+If a database query (such as an SQL query) is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries. An attacker can craft the part of the query they control to change the overall meaning of the query. +

+ +
+ + +

+Most database connector libraries offer a way to safely embed untrusted data into a query using query parameters or prepared statements. You should use these features to build queries, rather than string concatenation or similar methods. You can also escape (sanitize) user-controlled strings so that they can be included directly in an SQL command. A library function should be used for escaping, because this approach is only safe if the escaping function is robust against all possible inputs. +

+ +
+ + +

+In the following examples, an SQL query is prepared using string formatting to directly include a user-controlled value remote_controlled_string. An attacker could craft remote_controlled_string to change the overall meaning of the SQL query. +

+ + + +

A better way to do this is with a prepared statement, binding remote_controlled_string to a parameter of that statement. An attacker who controls remote_controlled_string now cannot change the overall meaning of the query. +

+ + + +
+ + +
  • Wikipedia: SQL injection.
  • +
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • + +
    +
    diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjection.ql b/rust/ql/src/queries/security/CWE-089/SqlInjection.ql new file mode 100644 index 000000000000..ee2a3d144868 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjection.ql @@ -0,0 +1,35 @@ +/** + * @name Database query built from user-controlled sources + * @description Building a database query from user-controlled sources is vulnerable to insertion of malicious code by attackers. + * @kind path-problem + * @problem.severity error + * @security-severity 8.8 + * @precision high + * @id rust/sql-injection + * @tags security + * external/cwe/cwe-089 + */ + +import rust +import codeql.rust.dataflow.DataFlow +import codeql.rust.dataflow.TaintTracking +import codeql.rust.security.SqlInjectionExtensions +import SqlInjectionFlow::PathGraph + +/** + * A taint configuration for tainted data that reaches a SQL sink. + */ +module SqlInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof SqlInjection::Source } + + predicate isSink(DataFlow::Node node) { node instanceof SqlInjection::Sink } + + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof SqlInjection::Barrier } +} + +module SqlInjectionFlow = TaintTracking::Global; + +from SqlInjectionFlow::PathNode sourceNode, SqlInjectionFlow::PathNode sinkNode +where SqlInjectionFlow::flowPath(sourceNode, sinkNode) +select sinkNode.getNode(), sourceNode, sinkNode, "This query depends on a $@.", + sourceNode.getNode(), "user-provided value" diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjectionBad.rs b/rust/ql/src/queries/security/CWE-089/SqlInjectionBad.rs new file mode 100644 index 000000000000..4184399a4f18 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjectionBad.rs @@ -0,0 +1,7 @@ +// with SQLx + +let unsafe_query = format!("SELECT * FROM people WHERE firstname='{remote_controlled_string}'"); + +let _ = conn.execute(unsafe_query.as_str()).await?; // BAD (arbitrary SQL injection is possible) + +let _ = sqlx::query(unsafe_query.as_str()).fetch_all(&mut conn).await?; // BAD (arbitrary SQL injection is possible) diff --git a/rust/ql/src/queries/security/CWE-089/SqlInjectionGood.rs b/rust/ql/src/queries/security/CWE-089/SqlInjectionGood.rs new file mode 100644 index 000000000000..238665cc2739 --- /dev/null +++ b/rust/ql/src/queries/security/CWE-089/SqlInjectionGood.rs @@ -0,0 +1,5 @@ +// with SQLx + +let prepared_query = "SELECT * FROM people WHERE firstname=?"; + +let _ = sqlx::query(prepared_query_1).bind(&remote_controlled_string).fetch_all(&mut conn).await?; // GOOD (prepared statement with bound parameter) diff --git a/rust/ql/src/queries/summary/SummaryStats.ql b/rust/ql/src/queries/summary/SummaryStats.ql index 3f24eb50d196..09ee83fc5e64 100644 --- a/rust/ql/src/queries/summary/SummaryStats.ql +++ b/rust/ql/src/queries/summary/SummaryStats.ql @@ -7,6 +7,7 @@ */ import rust +import codeql.rust.Concepts import codeql.rust.Diagnostics import Stats @@ -37,4 +38,14 @@ where key = "Inconsistencies - CFG" and value = getTotalCfgInconsistencies() or key = "Inconsistencies - data flow" and value = getTotalDataFlowInconsistencies() -select key, value + or + key = "Macro calls - total" and value = count(MacroCall mc) + or + key = "Macro calls - resolved" and value = count(MacroCall mc | mc.hasExpanded()) + or + key = "Macro calls - unresolved" and value = count(MacroCall mc | not mc.hasExpanded()) + or + key = "Taint sources - total" and value = count(ThreatModelSource s) + or + key = "Taint sources - active" and value = count(ActiveThreatModelSource s) +select key, value order by key diff --git a/rust/ql/src/queries/summary/TaintSources.ql b/rust/ql/src/queries/summary/TaintSources.ql new file mode 100644 index 000000000000..9ac72b706efb --- /dev/null +++ b/rust/ql/src/queries/summary/TaintSources.ql @@ -0,0 +1,18 @@ +/** + * @name Taint Sources + * @description List all sources of untrusted input that have been idenfitied + * in the database. + * @kind problem + * @problem.severity info + * @id rust/summary/taint-sources + * @tags summary + */ + +import rust +import codeql.rust.Concepts + +from ThreatModelSource s, string defaultString +where + if s instanceof ActiveThreatModelSource then defaultString = " (DEFAULT)" else defaultString = "" +select s, + "Flow source '" + s.getSourceType() + "' of type " + s.getThreatModel() + defaultString + "." diff --git a/rust/ql/test/extractor-tests/canonical_path/anonymous.rs b/rust/ql/test/extractor-tests/canonical_path/anonymous.rs new file mode 100644 index 000000000000..81e32169bfb9 --- /dev/null +++ b/rust/ql/test/extractor-tests/canonical_path/anonymous.rs @@ -0,0 +1,36 @@ +use super::regular::Trait; + +fn canonicals() { + struct OtherStruct; + + trait OtherTrait { + fn g(&self); + } + + impl OtherTrait for OtherStruct { + fn g(&self) {} + } + + impl OtherTrait for crate::regular::Struct { + fn g(&self) {} + } + + impl crate::regular::Trait for OtherStruct { + fn f(&self) {} + } + + fn nested() { + struct OtherStruct; + } + + fn usage() { + let s = OtherStruct {}; + s.f(); + s.g(); + nested(); + } +} + +fn other() { + struct OtherStruct; +} diff --git a/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected b/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected index 622652e091f7..0b973174828c 100644 --- a/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected +++ b/rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected @@ -1,70 +1,89 @@ canonicalPaths -| canonical_paths.rs:1:1:34:1 | Module | repo::test | crate::canonical_paths::a | -| canonical_paths.rs:2:5:3:22 | Struct | repo::test | crate::canonical_paths::a::Struct | -| canonical_paths.rs:5:5:7:5 | Trait | repo::test | crate::canonical_paths::a::Trait | -| canonical_paths.rs:6:9:6:20 | f | repo::test | crate::canonical_paths::a::Trait::f | -| canonical_paths.rs:9:5:11:5 | Impl | None | None | -| canonical_paths.rs:10:9:10:22 | f | repo::test | ::f | -| canonical_paths.rs:13:5:15:5 | Impl | None | None | -| canonical_paths.rs:14:9:14:22 | g | repo::test | ::g | -| canonical_paths.rs:17:5:19:5 | Trait | repo::test | crate::canonical_paths::a::TraitWithBlanketImpl | -| canonical_paths.rs:18:9:18:20 | h | repo::test | crate::canonical_paths::a::TraitWithBlanketImpl::h | -| canonical_paths.rs:21:5:23:5 | Impl | None | None | -| canonical_paths.rs:22:9:22:22 | h | repo::test | <_ as crate::canonical_paths::a::TraitWithBlanketImpl>::h | -| canonical_paths.rs:25:5:25:16 | free | repo::test | crate::canonical_paths::a::free | -| canonical_paths.rs:27:5:33:5 | usage | repo::test | crate::canonical_paths::a::usage | -| canonical_paths.rs:36:1:73:1 | Module | repo::test | crate::canonical_paths::without | -| canonical_paths.rs:37:5:37:24 | Use | None | None | -| canonical_paths.rs:39:5:68:5 | canonicals | repo::test | crate::canonical_paths::without::canonicals | -| canonical_paths.rs:40:9:40:27 | Struct | repo::test | {34}::OtherStruct | -| canonical_paths.rs:42:9:44:9 | Trait | repo::test | {34}::OtherTrait | -| canonical_paths.rs:43:13:43:24 | g | repo::test | {34}::OtherTrait::g | -| canonical_paths.rs:46:9:48:9 | Impl | None | None | -| canonical_paths.rs:47:13:47:26 | g | repo::test | <{34}::OtherStruct as {34}::OtherTrait>::g | -| canonical_paths.rs:50:9:52:9 | Impl | None | None | -| canonical_paths.rs:51:13:51:26 | g | repo::test | ::g | -| canonical_paths.rs:54:9:56:9 | Impl | None | None | -| canonical_paths.rs:55:13:55:26 | f | repo::test | <{34}::OtherStruct as crate::canonical_paths::a::Trait>::f | -| canonical_paths.rs:58:9:60:9 | nested | repo::test | {34}::nested | -| canonical_paths.rs:59:13:59:31 | Struct | repo::test | {35}::OtherStruct | -| canonical_paths.rs:62:9:67:9 | usage | repo::test | {34}::usage | -| canonical_paths.rs:70:5:72:5 | other | repo::test | crate::canonical_paths::without::other | -| canonical_paths.rs:71:9:71:27 | Struct | repo::test | {36}::OtherStruct | -| lib.rs:1:1:1:20 | Module | repo::test | crate::canonical_paths | +| anonymous.rs:1:1:1:26 | Use | None | None | +| anonymous.rs:3:1:32:1 | fn canonicals | repo::test | crate::anonymous::canonicals | +| anonymous.rs:4:5:4:23 | Struct | repo::test | {0}::OtherStruct | +| anonymous.rs:6:5:8:5 | trait OtherTrait | repo::test | {0}::OtherTrait | +| anonymous.rs:7:9:7:20 | fn g | repo::test | {0}::OtherTrait::g | +| anonymous.rs:10:5:12:5 | impl OtherTrait for OtherStruct { ... } | None | None | +| anonymous.rs:11:9:11:22 | fn g | repo::test | <{0}::OtherStruct as {0}::OtherTrait>::g | +| anonymous.rs:14:5:16:5 | impl OtherTrait for ...::Struct { ... } | None | None | +| anonymous.rs:15:9:15:22 | fn g | repo::test | ::g | +| anonymous.rs:18:5:20:5 | impl ...::Trait for OtherStruct { ... } | None | None | +| anonymous.rs:19:9:19:22 | fn f | repo::test | <{0}::OtherStruct as crate::regular::Trait>::f | +| anonymous.rs:22:5:24:5 | fn nested | repo::test | {0}::nested | +| anonymous.rs:23:9:23:27 | Struct | repo::test | {1}::OtherStruct | +| anonymous.rs:26:5:31:5 | fn usage | repo::test | {0}::usage | +| anonymous.rs:34:1:36:1 | fn other | repo::test | crate::anonymous::other | +| anonymous.rs:35:5:35:23 | Struct | repo::test | {36}::OtherStruct | +| lib.rs:1:1:1:14 | mod anonymous | repo::test | crate::anonymous | +| lib.rs:2:1:2:12 | mod regular | repo::test | crate::regular | +| regular.rs:1:1:2:18 | Struct | repo::test | crate::regular::Struct | +| regular.rs:4:1:6:1 | trait Trait | repo::test | crate::regular::Trait | +| regular.rs:5:5:5:16 | fn f | repo::test | crate::regular::Trait::f | +| regular.rs:8:1:10:1 | impl Trait for Struct { ... } | None | None | +| regular.rs:9:5:9:18 | fn f | repo::test | ::f | +| regular.rs:12:1:14:1 | impl Struct { ... } | None | None | +| regular.rs:13:5:13:18 | fn g | repo::test | ::g | +| regular.rs:16:1:18:1 | trait TraitWithBlanketImpl | repo::test | crate::regular::TraitWithBlanketImpl | +| regular.rs:17:5:17:16 | fn h | repo::test | crate::regular::TraitWithBlanketImpl::h | +| regular.rs:20:1:22:1 | impl TraitWithBlanketImpl for T { ... } | None | None | +| regular.rs:21:5:21:18 | fn h | repo::test | <_ as crate::regular::TraitWithBlanketImpl>::h | +| regular.rs:24:1:24:12 | fn free | repo::test | crate::regular::free | +| regular.rs:26:1:32:1 | fn usage | repo::test | crate::regular::usage | +| regular.rs:34:1:38:1 | enum MyEnum | repo::test | crate::regular::MyEnum | +| regular.rs:40:1:46:1 | fn enum_qualified_usage | repo::test | crate::regular::enum_qualified_usage | +| regular.rs:48:1:55:1 | fn enum_unqualified_usage | repo::test | crate::regular::enum_unqualified_usage | +| regular.rs:51:5:51:18 | Use | None | None | resolvedPaths -| canonical_paths.rs:2:7:2:12 | derive | None | None | -| canonical_paths.rs:9:10:9:14 | Trait | repo::test | crate::canonical_paths::a::Trait | -| canonical_paths.rs:9:20:9:25 | Struct | repo::test | crate::canonical_paths::a::Struct | -| canonical_paths.rs:13:10:13:15 | Struct | repo::test | crate::canonical_paths::a::Struct | -| canonical_paths.rs:21:13:21:14 | Eq | lang:core | crate::cmp::Eq | -| canonical_paths.rs:21:17:21:36 | TraitWithBlanketImpl | repo::test | crate::canonical_paths::a::TraitWithBlanketImpl | -| canonical_paths.rs:21:42:21:42 | T | None | None | -| canonical_paths.rs:28:17:28:22 | Struct | repo::test | crate::canonical_paths::a::Struct | -| canonical_paths.rs:29:9:29:9 | s | None | None | -| canonical_paths.rs:29:9:29:13 | ... .f(...) | repo::test | ::f | -| canonical_paths.rs:30:9:30:9 | s | None | None | -| canonical_paths.rs:30:9:30:13 | ... .g(...) | repo::test | ::g | -| canonical_paths.rs:31:9:31:9 | s | None | None | -| canonical_paths.rs:31:9:31:13 | ... .h(...) | repo::test | <_ as crate::canonical_paths::a::TraitWithBlanketImpl>::h | -| canonical_paths.rs:32:9:32:12 | free | repo::test | crate::canonical_paths::a::free | -| canonical_paths.rs:37:9:37:13 | super | repo::test | crate::canonical_paths | -| canonical_paths.rs:37:9:37:16 | super::a | repo::test | crate::canonical_paths::a | -| canonical_paths.rs:37:9:37:23 | super::a::Trait | repo::test | crate::canonical_paths::a::Trait | -| canonical_paths.rs:46:14:46:23 | OtherTrait | repo::test | {34}::OtherTrait | -| canonical_paths.rs:46:29:46:39 | OtherStruct | repo::test | {34}::OtherStruct | -| canonical_paths.rs:50:14:50:23 | OtherTrait | repo::test | {34}::OtherTrait | -| canonical_paths.rs:50:29:50:33 | crate | None | None | -| canonical_paths.rs:50:29:50:50 | crate::canonical_paths | repo::test | crate::canonical_paths | -| canonical_paths.rs:50:29:50:53 | crate::canonical_paths::a | repo::test | crate::canonical_paths::a | -| canonical_paths.rs:50:29:50:61 | crate::canonical_paths::a::Struct | repo::test | crate::canonical_paths::a::Struct | -| canonical_paths.rs:54:14:54:18 | crate | None | None | -| canonical_paths.rs:54:14:54:35 | crate::canonical_paths | repo::test | crate::canonical_paths | -| canonical_paths.rs:54:14:54:38 | crate::canonical_paths::a | repo::test | crate::canonical_paths::a | -| canonical_paths.rs:54:14:54:45 | crate::canonical_paths::a::Trait | repo::test | crate::canonical_paths::a::Trait | -| canonical_paths.rs:54:51:54:61 | OtherStruct | repo::test | {34}::OtherStruct | -| canonical_paths.rs:63:21:63:31 | OtherStruct | repo::test | {34}::OtherStruct | -| canonical_paths.rs:64:13:64:13 | s | None | None | -| canonical_paths.rs:64:13:64:17 | ... .f(...) | repo::test | <{34}::OtherStruct as crate::canonical_paths::a::Trait>::f | -| canonical_paths.rs:65:13:65:13 | s | None | None | -| canonical_paths.rs:65:13:65:17 | ... .g(...) | repo::test | <{34}::OtherStruct as {34}::OtherTrait>::g | -| canonical_paths.rs:66:13:66:18 | nested | repo::test | {34}::nested | +| anonymous.rs:1:5:1:9 | super | None | None | +| anonymous.rs:1:5:1:18 | ...::regular | repo::test | crate::regular | +| anonymous.rs:1:5:1:25 | ...::Trait | repo::test | crate::regular::Trait | +| anonymous.rs:10:10:10:19 | OtherTrait | repo::test | {0}::OtherTrait | +| anonymous.rs:10:25:10:35 | OtherStruct | repo::test | {0}::OtherStruct | +| anonymous.rs:14:10:14:19 | OtherTrait | repo::test | {0}::OtherTrait | +| anonymous.rs:14:25:14:29 | crate | None | None | +| anonymous.rs:14:25:14:38 | ...::regular | repo::test | crate::regular | +| anonymous.rs:14:25:14:46 | ...::Struct | repo::test | crate::regular::Struct | +| anonymous.rs:18:10:18:14 | crate | None | None | +| anonymous.rs:18:10:18:23 | ...::regular | repo::test | crate::regular | +| anonymous.rs:18:10:18:30 | ...::Trait | repo::test | crate::regular::Trait | +| anonymous.rs:18:36:18:46 | OtherStruct | repo::test | {0}::OtherStruct | +| anonymous.rs:27:17:27:27 | OtherStruct | repo::test | {0}::OtherStruct | +| anonymous.rs:28:9:28:9 | s | None | None | +| anonymous.rs:28:9:28:13 | ... .f(...) | repo::test | <{0}::OtherStruct as crate::regular::Trait>::f | +| anonymous.rs:29:9:29:9 | s | None | None | +| anonymous.rs:29:9:29:13 | ... .g(...) | repo::test | <{0}::OtherStruct as {0}::OtherTrait>::g | +| anonymous.rs:30:9:30:14 | nested | repo::test | {0}::nested | +| regular.rs:1:3:1:8 | derive | None | None | +| regular.rs:8:6:8:10 | Trait | repo::test | crate::regular::Trait | +| regular.rs:8:16:8:21 | Struct | repo::test | crate::regular::Struct | +| regular.rs:12:6:12:11 | Struct | repo::test | crate::regular::Struct | +| regular.rs:20:9:20:10 | Eq | lang:core | crate::cmp::Eq | +| regular.rs:20:13:20:32 | TraitWithBlanketImpl | repo::test | crate::regular::TraitWithBlanketImpl | +| regular.rs:20:38:20:38 | T | None | None | +| regular.rs:27:13:27:18 | Struct | repo::test | crate::regular::Struct | +| regular.rs:28:5:28:5 | s | None | None | +| regular.rs:28:5:28:9 | ... .f(...) | repo::test | ::f | +| regular.rs:29:5:29:5 | s | None | None | +| regular.rs:29:5:29:9 | ... .g(...) | repo::test | ::g | +| regular.rs:30:5:30:5 | s | None | None | +| regular.rs:30:5:30:9 | ... .h(...) | repo::test | <_ as crate::regular::TraitWithBlanketImpl>::h | +| regular.rs:31:5:31:8 | free | repo::test | crate::regular::free | +| regular.rs:36:14:36:18 | usize | None | None | +| regular.rs:37:19:37:23 | usize | None | None | +| regular.rs:41:9:41:14 | Option | lang:core | crate::option::Option | +| regular.rs:41:9:41:26 | ...::None::<...> | lang:core | crate::option::Option::None | +| regular.rs:42:9:42:14 | Option | lang:core | crate::option::Option | +| regular.rs:42:9:42:20 | ...::Some | lang:core | crate::option::Option::Some | +| regular.rs:43:9:43:14 | MyEnum | repo::test | crate::regular::MyEnum | +| regular.rs:43:9:43:24 | ...::Variant1 | repo::test | crate::regular::MyEnum::Variant1 | +| regular.rs:44:9:44:14 | MyEnum | repo::test | crate::regular::MyEnum | +| regular.rs:44:9:44:24 | ...::Variant2 | repo::test | crate::regular::MyEnum::Variant2 | +| regular.rs:45:9:45:14 | MyEnum | repo::test | crate::regular::MyEnum | +| regular.rs:45:9:45:24 | ...::Variant3 | repo::test | crate::regular::MyEnum::Variant3 | +| regular.rs:49:9:49:18 | None::<...> | lang:core | crate::option::Option::None | +| regular.rs:50:9:50:12 | Some | lang:core | crate::option::Option::Some | +| regular.rs:51:9:51:14 | MyEnum | repo::test | crate::regular::MyEnum | +| regular.rs:52:9:52:16 | Variant1 | repo::test | crate::regular::MyEnum::Variant1 | +| regular.rs:53:9:53:16 | Variant2 | repo::test | crate::regular::MyEnum::Variant2 | +| regular.rs:54:9:54:16 | Variant3 | repo::test | crate::regular::MyEnum::Variant3 | diff --git a/rust/ql/test/extractor-tests/canonical_path/canonical_paths.rs b/rust/ql/test/extractor-tests/canonical_path/canonical_paths.rs deleted file mode 100644 index 7444903dc01f..000000000000 --- a/rust/ql/test/extractor-tests/canonical_path/canonical_paths.rs +++ /dev/null @@ -1,73 +0,0 @@ -mod a { - #[derive(Eq, PartialEq)] - pub struct Struct; - - pub trait Trait { - fn f(&self); - } - - impl Trait for Struct { - fn f(&self) {} - } - - impl Struct { - fn g(&self) {} - } - - trait TraitWithBlanketImpl { - fn h(&self); - } - - impl TraitWithBlanketImpl for T { - fn h(&self) {} - } - - fn free() {} - - fn usage() { - let s = Struct {}; - s.f(); - s.g(); - s.h(); - free(); - } -} - -mod without { - use super::a::Trait; - - fn canonicals() { - struct OtherStruct; - - trait OtherTrait { - fn g(&self); - } - - impl OtherTrait for OtherStruct { - fn g(&self) {} - } - - impl OtherTrait for crate::canonical_paths::a::Struct { - fn g(&self) {} - } - - impl crate::canonical_paths::a::Trait for OtherStruct { - fn f(&self) {} - } - - fn nested() { - struct OtherStruct; - } - - fn usage() { - let s = OtherStruct {}; - s.f(); - s.g(); - nested(); - } - } - - fn other() { - struct OtherStruct; - } -} diff --git a/rust/ql/test/extractor-tests/canonical_path/regular.rs b/rust/ql/test/extractor-tests/canonical_path/regular.rs new file mode 100644 index 000000000000..ac06a12d24aa --- /dev/null +++ b/rust/ql/test/extractor-tests/canonical_path/regular.rs @@ -0,0 +1,55 @@ +#[derive(Eq, PartialEq)] +pub struct Struct; + +pub trait Trait { + fn f(&self); +} + +impl Trait for Struct { + fn f(&self) {} +} + +impl Struct { + fn g(&self) {} +} + +trait TraitWithBlanketImpl { + fn h(&self); +} + +impl TraitWithBlanketImpl for T { + fn h(&self) {} +} + +fn free() {} + +fn usage() { + let s = Struct {}; + s.f(); + s.g(); + s.h(); + free(); +} + +enum MyEnum { + Variant1, + Variant2(usize), + Variant3 { x: usize }, +} + +fn enum_qualified_usage() { + _ = Option::None::<()>; + _ = Option::Some(0); + _ = MyEnum::Variant1; + _ = MyEnum::Variant2(0); + _ = MyEnum::Variant3 { x: 1 }; +} + +fn enum_unqualified_usage() { + _ = None::<()>; + _ = Some(0); + use MyEnum::*; + _ = Variant1; + _ = Variant2(0); + _ = Variant3 { x: 1 }; +} diff --git a/rust/ql/test/extractor-tests/generated/.generated_tests.list b/rust/ql/test/extractor-tests/generated/.generated_tests.list index b60779ebd86a..1fe8e805b268 100644 --- a/rust/ql/test/extractor-tests/generated/.generated_tests.list +++ b/rust/ql/test/extractor-tests/generated/.generated_tests.list @@ -31,8 +31,10 @@ FieldExpr/gen_field_expr.rs 9a70500d592e0a071b03d974a55558b3bc0df531ff11bce5898f FnPtrType/gen_fn_ptr_type.rs a7842d8c21636739d1be959e5ce5e0b23482d5ef6eab5c45b009895da8175932 a7842d8c21636739d1be959e5ce5e0b23482d5ef6eab5c45b009895da8175932 ForExpr/gen_for_expr.rs 67decf3073e1a9363d9df05a5a64a6059349e50b81356f480f7aeb352189136d 67decf3073e1a9363d9df05a5a64a6059349e50b81356f480f7aeb352189136d ForType/gen_for_type.rs 6cb447df02c61b192e283e019576c28225added02d167030d64ebd0bebb1b158 6cb447df02c61b192e283e019576c28225added02d167030d64ebd0bebb1b158 -FormatArgsArg/gen_format_args_arg.rs c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a -FormatArgsExpr/gen_format_args_expr.rs 7184dbb8833f970676e59fca3a40ec51d14a68e3151d8a6d637896494f2b4454 7184dbb8833f970676e59fca3a40ec51d14a68e3151d8a6d637896494f2b4454 +FormatArgsExpr/gen_format.rs bd009cb152c35e2aacd147b5520a42be31e66e9a8715ec1d0fd57b8e97c743ed bd009cb152c35e2aacd147b5520a42be31e66e9a8715ec1d0fd57b8e97c743ed +FormatArgsExpr/gen_format_args_arg.rs c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a c466f2fc2c0f9592061a159a217a87551d67f1ccb0e4d8f7f56a463a2aa4a73a +FormatArgsExpr/gen_format_args_expr.rs 72c806ed163e9dcce2d0c5c8664d409b2aa635c1022c91959f9e8ae084f05bf2 72c806ed163e9dcce2d0c5c8664d409b2aa635c1022c91959f9e8ae084f05bf2 +FormatArgsExpr/gen_format_argument.rs 350d370e6f1db03d756384a3dbdb294697d241ff7c28d159cf57748abe99cfe9 350d370e6f1db03d756384a3dbdb294697d241ff7c28d159cf57748abe99cfe9 Function/gen_function.rs ba6ecb9e0d89183295eb02f3c20ebbf5c209f89bd0172c73a3b4a6dacbf3a54c ba6ecb9e0d89183295eb02f3c20ebbf5c209f89bd0172c73a3b4a6dacbf3a54c GenericArgList/gen_generic_arg_list.rs cfb072d3b48f9dd568c23d4dfefba28766628678f66bbf9a436de9919ead35f5 cfb072d3b48f9dd568c23d4dfefba28766628678f66bbf9a436de9919ead35f5 GenericParamList/gen_generic_param_list.rs 4cc9b628f53e1a6c5781ad195b8648fa6dee0bb41b24007fbd986527374d3669 4cc9b628f53e1a6c5781ad195b8648fa6dee0bb41b24007fbd986527374d3669 @@ -73,16 +75,15 @@ NameRef/gen_name_ref.rs 41307c2f7ca82d28217129639e556bd4c91221cf3a4170250b313fd5 NeverType/gen_never_type.rs a5413fab6a45dcfc2ff0ec5c8308b6c515963212ec4aa9edb9a96ec9a7e96830 a5413fab6a45dcfc2ff0ec5c8308b6c515963212ec4aa9edb9a96ec9a7e96830 OffsetOfExpr/gen_offset_of_expr.rs 8e2077b4d7b85c91c17c3630511bc4f929950e9007261cbf0471c4a064c4b934 8e2077b4d7b85c91c17c3630511bc4f929950e9007261cbf0471c4a064c4b934 OrPat/gen_or_pat.rs 71feef6e056bfe4cc8c22c9eb54fa3fecef613606769061d0efd059adbbd6f56 71feef6e056bfe4cc8c22c9eb54fa3fecef613606769061d0efd059adbbd6f56 -Param/gen_param.rs 6c9e4a972b2dc0702dc29ebcbdcbe2c6a433b3cd372ad6924feedcea4698faba 6c9e4a972b2dc0702dc29ebcbdcbe2c6a433b3cd372ad6924feedcea4698faba +Param/gen_param.rs 39f3979d6cb10e4c43e0b5601af2a92b7520a75a104211955bbbb5e6f13e9db9 39f3979d6cb10e4c43e0b5601af2a92b7520a75a104211955bbbb5e6f13e9db9 ParamList/gen_param_list.rs ef2e83d0aed45b969fe78dd717e87ef3c1f848e6179cfb4dc3cb136f1836b998 ef2e83d0aed45b969fe78dd717e87ef3c1f848e6179cfb4dc3cb136f1836b998 ParenExpr/gen_paren_expr.rs dd0c4a21a92e54e8a6151145e013cbec9c9e1cad093d572e293b4f51d6c44aea dd0c4a21a92e54e8a6151145e013cbec9c9e1cad093d572e293b4f51d6c44aea ParenPat/gen_paren_pat.rs c8d18521b9a0b7d39841eb72e3895914aa652b7235dea42ed12a4eb280e3bf0e c8d18521b9a0b7d39841eb72e3895914aa652b7235dea42ed12a4eb280e3bf0e ParenType/gen_paren_type.rs ae1a945b56020eab14bb0ef75ae9ccb735d8e45d1213adee210a90e6dba8430f ae1a945b56020eab14bb0ef75ae9ccb735d8e45d1213adee210a90e6dba8430f -Path/gen_path.rs e32637d04445d5b9411086f3ad5d8b41de24327f7ad641d1a1a25c1d160121c8 e32637d04445d5b9411086f3ad5d8b41de24327f7ad641d1a1a25c1d160121c8 -PathExpr/gen_path_expr.rs a1e0ececfe62a63a43583c9bd8064a80a90c042c55bac29d86776c0c6559f33a a1e0ececfe62a63a43583c9bd8064a80a90c042c55bac29d86776c0c6559f33a -PathPat/gen_path_pat.rs fd7f941f8b33f19d3693be1fdb595c2fb2e85e8296702b82bf12bcd44632f371 fd7f941f8b33f19d3693be1fdb595c2fb2e85e8296702b82bf12bcd44632f371 -PathSegment/gen_path_segment.rs bc0c914821a70f9a7db23766f4d84e2d69fc76d5075a8bc3341f2ba59a8ce911 bc0c914821a70f9a7db23766f4d84e2d69fc76d5075a8bc3341f2ba59a8ce911 -PathType/gen_path_type.rs 710a5505615769da940202e7c6d9031edc23a4b05cd9fb25241c60affbba4027 710a5505615769da940202e7c6d9031edc23a4b05cd9fb25241c60affbba4027 +Path/gen_path.rs 490268d6bfb1635883b8bdefc683d59c4dd0e9c7f86c2e55954661efb3ab0253 490268d6bfb1635883b8bdefc683d59c4dd0e9c7f86c2e55954661efb3ab0253 +Path/gen_path_expr.rs a1e0ececfe62a63a43583c9bd8064a80a90c042c55bac29d86776c0c6559f33a a1e0ececfe62a63a43583c9bd8064a80a90c042c55bac29d86776c0c6559f33a +Path/gen_path_pat.rs fd7f941f8b33f19d3693be1fdb595c2fb2e85e8296702b82bf12bcd44632f371 fd7f941f8b33f19d3693be1fdb595c2fb2e85e8296702b82bf12bcd44632f371 +Path/gen_path_type.rs 210f2ce4000b59d2f908801c22c5497a0f0c9a3b1a5130e7dad0931430f49eb9 210f2ce4000b59d2f908801c22c5497a0f0c9a3b1a5130e7dad0931430f49eb9 PrefixExpr/gen_prefix_expr.rs c4b53e87f370713b9a9e257be26d082b0761497bac19b1d7401a31b22b30d1ab c4b53e87f370713b9a9e257be26d082b0761497bac19b1d7401a31b22b30d1ab PtrType/gen_ptr_type.rs dd7faad19454b92d7942ef664df1a5f26c01863e408b87249aa4d5d4f68c78b3 dd7faad19454b92d7942ef664df1a5f26c01863e408b87249aa4d5d4f68c78b3 RangeExpr/gen_range_expr.rs 3f27cff9cc76b2703beff622d1453b84121e1970a869e45f9428deac92c4ecb0 3f27cff9cc76b2703beff622d1453b84121e1970a869e45f9428deac92c4ecb0 @@ -103,7 +104,7 @@ RestPat/gen_rest_pat.rs e762bf7537225f97da751c5dca6a2cd3836ad7579b68c748b8c6cba6 RetType/gen_ret_type.rs 0947aed0974461b7a5b56bbc5fe36131663bde715c37302345d4eee23b71c825 0947aed0974461b7a5b56bbc5fe36131663bde715c37302345d4eee23b71c825 ReturnExpr/gen_return_expr.rs 4f6ef29d7b3c60d6d71d1a6034a0721671f517428ba21897361a92b01009d38f 4f6ef29d7b3c60d6d71d1a6034a0721671f517428ba21897361a92b01009d38f ReturnTypeSyntax/gen_return_type_syntax.rs 0b11a4cc400f9a2001996f99d61391bdb636e8aea036f587cf18ad6a957fe496 0b11a4cc400f9a2001996f99d61391bdb636e8aea036f587cf18ad6a957fe496 -SelfParam/gen_self_param.rs b7bf9f23fedad6f1a15f02e5fac33fc2c68ec3409b44f24142c2fdec1e5e6f1f b7bf9f23fedad6f1a15f02e5fac33fc2c68ec3409b44f24142c2fdec1e5e6f1f +SelfParam/gen_self_param.rs 9be528c454e2734292d54550f8850ae8e48e1558da46dcf7f06fc7a7a8c3e569 9be528c454e2734292d54550f8850ae8e48e1558da46dcf7f06fc7a7a8c3e569 SlicePat/gen_slice_pat.rs df4a6692f5100aa11dd777561400ce71e37b85f2363b0638c21975a1771b15d5 df4a6692f5100aa11dd777561400ce71e37b85f2363b0638c21975a1771b15d5 SliceType/gen_slice_type.rs 073282f4755994473933db7e4f1e4d34a80363d7e331299ec4ac1a2d6a235b86 073282f4755994473933db7e4f1e4d34a80363d7e331299ec4ac1a2d6a235b86 SourceFile/gen_source_file.rs a7a1d4fa77b53adb6fbc031bf7ab49cf7c8787728ba0a687c348b5eefbb5b9df a7a1d4fa77b53adb6fbc031bf7ab49cf7c8787728ba0a687c348b5eefbb5b9df diff --git a/rust/ql/test/extractor-tests/generated/.gitattributes b/rust/ql/test/extractor-tests/generated/.gitattributes index 8ea3a00a31f0..782715565d2f 100644 --- a/rust/ql/test/extractor-tests/generated/.gitattributes +++ b/rust/ql/test/extractor-tests/generated/.gitattributes @@ -33,8 +33,10 @@ /FnPtrType/gen_fn_ptr_type.rs linguist-generated /ForExpr/gen_for_expr.rs linguist-generated /ForType/gen_for_type.rs linguist-generated -/FormatArgsArg/gen_format_args_arg.rs linguist-generated +/FormatArgsExpr/gen_format.rs linguist-generated +/FormatArgsExpr/gen_format_args_arg.rs linguist-generated /FormatArgsExpr/gen_format_args_expr.rs linguist-generated +/FormatArgsExpr/gen_format_argument.rs linguist-generated /Function/gen_function.rs linguist-generated /GenericArgList/gen_generic_arg_list.rs linguist-generated /GenericParamList/gen_generic_param_list.rs linguist-generated @@ -81,10 +83,9 @@ /ParenPat/gen_paren_pat.rs linguist-generated /ParenType/gen_paren_type.rs linguist-generated /Path/gen_path.rs linguist-generated -/PathExpr/gen_path_expr.rs linguist-generated -/PathPat/gen_path_pat.rs linguist-generated -/PathSegment/gen_path_segment.rs linguist-generated -/PathType/gen_path_type.rs linguist-generated +/Path/gen_path_expr.rs linguist-generated +/Path/gen_path_pat.rs linguist-generated +/Path/gen_path_type.rs linguist-generated /PrefixExpr/gen_prefix_expr.rs linguist-generated /PtrType/gen_ptr_type.rs linguist-generated /RangeExpr/gen_range_expr.rs linguist-generated diff --git a/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr.expected b/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr.expected index 549f43fc9892..e1ab176fe514 100644 --- a/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr.expected @@ -1,2 +1,2 @@ -| gen_array_expr.rs:5:5:5:13 | ArrayExpr | getNumberOfAttrs: | 0 | getNumberOfExprs: | 3 | -| gen_array_expr.rs:6:5:6:11 | ArrayExpr | getNumberOfAttrs: | 0 | getNumberOfExprs: | 2 | +| gen_array_expr.rs:5:5:5:13 | [...] | getNumberOfAttrs: | 0 | getNumberOfExprs: | 3 | +| gen_array_expr.rs:6:5:6:11 | [...] | getNumberOfAttrs: | 0 | getNumberOfExprs: | 2 | diff --git a/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr_getExpr.expected index 97da5ba1c2af..393fb28f2bfa 100644 --- a/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ArrayExpr/ArrayExpr_getExpr.expected @@ -1,5 +1,5 @@ -| gen_array_expr.rs:5:5:5:13 | ArrayExpr | 0 | gen_array_expr.rs:5:6:5:6 | 1 | -| gen_array_expr.rs:5:5:5:13 | ArrayExpr | 1 | gen_array_expr.rs:5:9:5:9 | 2 | -| gen_array_expr.rs:5:5:5:13 | ArrayExpr | 2 | gen_array_expr.rs:5:12:5:12 | 3 | -| gen_array_expr.rs:6:5:6:11 | ArrayExpr | 0 | gen_array_expr.rs:6:6:6:6 | 1 | -| gen_array_expr.rs:6:5:6:11 | ArrayExpr | 1 | gen_array_expr.rs:6:9:6:10 | 10 | +| gen_array_expr.rs:5:5:5:13 | [...] | 0 | gen_array_expr.rs:5:6:5:6 | 1 | +| gen_array_expr.rs:5:5:5:13 | [...] | 1 | gen_array_expr.rs:5:9:5:9 | 2 | +| gen_array_expr.rs:5:5:5:13 | [...] | 2 | gen_array_expr.rs:5:12:5:12 | 3 | +| gen_array_expr.rs:6:5:6:11 | [...] | 0 | gen_array_expr.rs:6:6:6:6 | 1 | +| gen_array_expr.rs:6:5:6:11 | [...] | 1 | gen_array_expr.rs:6:9:6:10 | 10 | diff --git a/rust/ql/test/extractor-tests/generated/AsmExpr/AsmExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/AsmExpr/AsmExpr_getExpr.expected index 7a4af543f311..07aec8f5fe0d 100644 --- a/rust/ql/test/extractor-tests/generated/AsmExpr/AsmExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/AsmExpr/AsmExpr_getExpr.expected @@ -1 +1 @@ -| gen_asm_expr.rs:6:9:6:24 | AsmExpr | gen_asm_expr.rs:6:23:6:23 | UnderscoreExpr | +| gen_asm_expr.rs:6:9:6:24 | AsmExpr | gen_asm_expr.rs:6:23:6:23 | _ | diff --git a/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr.expected b/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr.expected index 2ed01b9058e1..9104ba77e5fe 100644 --- a/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr.expected +++ b/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr.expected @@ -1 +1 @@ -| gen_await_expr.rs:6:17:6:27 | AwaitExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | +| gen_await_expr.rs:6:17:6:27 | await ... | getNumberOfAttrs: | 0 | hasExpr: | yes | diff --git a/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr_getExpr.expected index c34a6012f4c3..a1ea7809bb01 100644 --- a/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/AwaitExpr/AwaitExpr_getExpr.expected @@ -1 +1 @@ -| gen_await_expr.rs:6:17:6:27 | AwaitExpr | gen_await_expr.rs:6:17:6:21 | CallExpr | +| gen_await_expr.rs:6:17:6:27 | await ... | gen_await_expr.rs:6:17:6:21 | foo(...) | diff --git a/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr.expected b/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr.expected index 75840ec81fed..ce3e6a096909 100644 --- a/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr.expected +++ b/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr.expected @@ -1 +1 @@ -| gen_become_expr.rs:8:10:8:36 | BecomeExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | +| gen_become_expr.rs:8:10:8:36 | become ... | getNumberOfAttrs: | 0 | hasExpr: | yes | diff --git a/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr_getExpr.expected index 8992c4868ca2..d0cb86a0303c 100644 --- a/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/BecomeExpr/BecomeExpr_getExpr.expected @@ -1 +1 @@ -| gen_become_expr.rs:8:10:8:36 | BecomeExpr | gen_become_expr.rs:8:17:8:36 | CallExpr | +| gen_become_expr.rs:8:10:8:36 | become ... | gen_become_expr.rs:8:17:8:36 | fact_a(...) | diff --git a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.expected b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.expected index 39ec1d6a7e1a..b6be24d0bb73 100644 --- a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.expected +++ b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.expected @@ -1,3 +1,3 @@ -| gen_block_expr.rs:3:28:12:1 | BlockExpr | getNumberOfAttrs: | 0 | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isTry: | no | isUnsafe: | no | hasLabel: | no | hasStmtList: | yes | -| gen_block_expr.rs:5:5:7:5 | BlockExpr | getNumberOfAttrs: | 0 | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isTry: | no | isUnsafe: | no | hasLabel: | no | hasStmtList: | yes | -| gen_block_expr.rs:8:5:11:5 | BlockExpr | getNumberOfAttrs: | 0 | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isTry: | no | isUnsafe: | no | hasLabel: | yes | hasStmtList: | yes | +| gen_block_expr.rs:3:28:12:1 | { ... } | hasLabel: | no | getNumberOfAttrs: | 0 | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isTry: | no | isUnsafe: | no | hasStmtList: | yes | +| gen_block_expr.rs:5:5:7:5 | { ... } | hasLabel: | no | getNumberOfAttrs: | 0 | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isTry: | no | isUnsafe: | no | hasStmtList: | yes | +| gen_block_expr.rs:8:5:11:5 | 'label: { ... } | hasLabel: | yes | getNumberOfAttrs: | 0 | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isTry: | no | isUnsafe: | no | hasStmtList: | yes | diff --git a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.ql b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.ql index 581070545155..992c06a605b6 100644 --- a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.ql +++ b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr.ql @@ -3,11 +3,12 @@ import codeql.rust.elements import TestUtils from - BlockExpr x, int getNumberOfAttrs, string isAsync, string isConst, string isGen, string isMove, - string isTry, string isUnsafe, string hasLabel, string hasStmtList + BlockExpr x, string hasLabel, int getNumberOfAttrs, string isAsync, string isConst, string isGen, + string isMove, string isTry, string isUnsafe, string hasStmtList where toBeTested(x) and not x.isUnknown() and + (if x.hasLabel() then hasLabel = "yes" else hasLabel = "no") and getNumberOfAttrs = x.getNumberOfAttrs() and (if x.isAsync() then isAsync = "yes" else isAsync = "no") and (if x.isConst() then isConst = "yes" else isConst = "no") and @@ -15,8 +16,7 @@ where (if x.isMove() then isMove = "yes" else isMove = "no") and (if x.isTry() then isTry = "yes" else isTry = "no") and (if x.isUnsafe() then isUnsafe = "yes" else isUnsafe = "no") and - (if x.hasLabel() then hasLabel = "yes" else hasLabel = "no") and if x.hasStmtList() then hasStmtList = "yes" else hasStmtList = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "isAsync:", isAsync, "isConst:", isConst, "isGen:", - isGen, "isMove:", isMove, "isTry:", isTry, "isUnsafe:", isUnsafe, "hasLabel:", hasLabel, +select x, "hasLabel:", hasLabel, "getNumberOfAttrs:", getNumberOfAttrs, "isAsync:", isAsync, + "isConst:", isConst, "isGen:", isGen, "isMove:", isMove, "isTry:", isTry, "isUnsafe:", isUnsafe, "hasStmtList:", hasStmtList diff --git a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getLabel.expected b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getLabel.expected index 3a935228e051..a6933d65b22b 100644 --- a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getLabel.expected +++ b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getLabel.expected @@ -1 +1 @@ -| gen_block_expr.rs:8:5:11:5 | BlockExpr | gen_block_expr.rs:8:5:8:11 | Label | +| gen_block_expr.rs:8:5:11:5 | 'label: { ... } | gen_block_expr.rs:8:5:8:11 | 'label | diff --git a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getStmtList.expected b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getStmtList.expected index 21eb195289a2..4863264491b3 100644 --- a/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getStmtList.expected +++ b/rust/ql/test/extractor-tests/generated/BlockExpr/BlockExpr_getStmtList.expected @@ -1,3 +1,3 @@ -| gen_block_expr.rs:3:28:12:1 | BlockExpr | gen_block_expr.rs:3:28:12:1 | StmtList | -| gen_block_expr.rs:5:5:7:5 | BlockExpr | gen_block_expr.rs:5:5:7:5 | StmtList | -| gen_block_expr.rs:8:5:11:5 | BlockExpr | gen_block_expr.rs:8:13:11:5 | StmtList | +| gen_block_expr.rs:3:28:12:1 | { ... } | gen_block_expr.rs:3:28:12:1 | StmtList | +| gen_block_expr.rs:5:5:7:5 | { ... } | gen_block_expr.rs:5:5:7:5 | StmtList | +| gen_block_expr.rs:8:5:11:5 | 'label: { ... } | gen_block_expr.rs:8:13:11:5 | StmtList | diff --git a/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat.expected b/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat.expected index 95c8bdebd47a..8ca2412e8ff5 100644 --- a/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat.expected +++ b/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat.expected @@ -1,2 +1,2 @@ -| gen_box_pat.rs:6:9:6:27 | BoxPat | hasPat: | yes | -| gen_box_pat.rs:7:9:7:24 | BoxPat | hasPat: | yes | +| gen_box_pat.rs:6:9:6:27 | box ... | hasPat: | yes | +| gen_box_pat.rs:7:9:7:24 | box ...::None | hasPat: | yes | diff --git a/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat_getPat.expected b/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat_getPat.expected index cac8ee05d3c4..4e12432652dc 100644 --- a/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/BoxPat/BoxPat_getPat.expected @@ -1,2 +1,2 @@ -| gen_box_pat.rs:6:9:6:27 | BoxPat | gen_box_pat.rs:6:13:6:27 | TupleStructPat | -| gen_box_pat.rs:7:9:7:24 | BoxPat | gen_box_pat.rs:7:13:7:24 | PathPat | +| gen_box_pat.rs:6:9:6:27 | box ... | gen_box_pat.rs:6:13:6:27 | TupleStructPat | +| gen_box_pat.rs:7:9:7:24 | box ...::None | gen_box_pat.rs:7:13:7:24 | ...::None | diff --git a/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr.expected b/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr.expected index 763fae60866a..30c734fd682d 100644 --- a/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr.expected +++ b/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr.expected @@ -1,3 +1,3 @@ -| gen_break_expr.rs:7:13:7:17 | BreakExpr | getNumberOfAttrs: | 0 | hasExpr: | no | hasLifetime: | no | -| gen_break_expr.rs:12:13:12:27 | BreakExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasLifetime: | yes | -| gen_break_expr.rs:17:13:17:27 | BreakExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasLifetime: | yes | +| gen_break_expr.rs:7:13:7:17 | break | getNumberOfAttrs: | 0 | hasExpr: | no | hasLifetime: | no | +| gen_break_expr.rs:12:13:12:27 | break ''label 42 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasLifetime: | yes | +| gen_break_expr.rs:17:13:17:27 | break ''label 42 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasLifetime: | yes | diff --git a/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getExpr.expected index 0bd373a4bbc1..20c5295354af 100644 --- a/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getExpr.expected @@ -1,2 +1,2 @@ -| gen_break_expr.rs:12:13:12:27 | BreakExpr | gen_break_expr.rs:12:26:12:27 | 42 | -| gen_break_expr.rs:17:13:17:27 | BreakExpr | gen_break_expr.rs:17:26:17:27 | 42 | +| gen_break_expr.rs:12:13:12:27 | break ''label 42 | gen_break_expr.rs:12:26:12:27 | 42 | +| gen_break_expr.rs:17:13:17:27 | break ''label 42 | gen_break_expr.rs:17:26:17:27 | 42 | diff --git a/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getLifetime.expected b/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getLifetime.expected index b993a2eebf5a..2e1a88017950 100644 --- a/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getLifetime.expected +++ b/rust/ql/test/extractor-tests/generated/BreakExpr/BreakExpr_getLifetime.expected @@ -1,2 +1,2 @@ -| gen_break_expr.rs:12:13:12:27 | BreakExpr | gen_break_expr.rs:12:19:12:24 | Lifetime | -| gen_break_expr.rs:17:13:17:27 | BreakExpr | gen_break_expr.rs:17:19:17:24 | Lifetime | +| gen_break_expr.rs:12:13:12:27 | break ''label 42 | gen_break_expr.rs:12:19:12:24 | ''label | +| gen_break_expr.rs:17:13:17:27 | break ''label 42 | gen_break_expr.rs:17:19:17:24 | ''label | diff --git a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.expected b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.expected index 5414108064cd..ebe6eeda1049 100644 --- a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.expected +++ b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.expected @@ -1,4 +1,4 @@ -| gen_call_expr.rs:5:5:5:11 | CallExpr | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes | -| gen_call_expr.rs:6:5:6:23 | CallExpr | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes | -| gen_call_expr.rs:7:5:7:14 | CallExpr | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes | -| gen_call_expr.rs:8:5:8:10 | CallExpr | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes | +| gen_call_expr.rs:5:5:5:11 | foo(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes | +| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes | +| gen_call_expr.rs:7:5:7:14 | ...(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes | +| gen_call_expr.rs:8:5:8:10 | foo(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes | diff --git a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.ql b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.ql index b44136c4942e..cd043e88d1dd 100644 --- a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.ql +++ b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr.ql @@ -2,11 +2,12 @@ import codeql.rust.elements import TestUtils -from CallExpr x, string hasArgList, int getNumberOfAttrs, string hasExpr +from CallExpr x, string hasArgList, int getNumberOfAttrs, string hasFunction where toBeTested(x) and not x.isUnknown() and (if x.hasArgList() then hasArgList = "yes" else hasArgList = "no") and getNumberOfAttrs = x.getNumberOfAttrs() and - if x.hasExpr() then hasExpr = "yes" else hasExpr = "no" -select x, "hasArgList:", hasArgList, "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr + if x.hasFunction() then hasFunction = "yes" else hasFunction = "no" +select x, "hasArgList:", hasArgList, "getNumberOfAttrs:", getNumberOfAttrs, "hasFunction:", + hasFunction diff --git a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getArgList.expected b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getArgList.expected index a42cc13bf39c..13c426db99d1 100644 --- a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getArgList.expected +++ b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getArgList.expected @@ -1,4 +1,4 @@ -| gen_call_expr.rs:5:5:5:11 | CallExpr | gen_call_expr.rs:5:8:5:11 | ArgList | -| gen_call_expr.rs:6:5:6:23 | CallExpr | gen_call_expr.rs:6:20:6:23 | ArgList | -| gen_call_expr.rs:7:5:7:14 | CallExpr | gen_call_expr.rs:7:11:7:14 | ArgList | -| gen_call_expr.rs:8:5:8:10 | CallExpr | gen_call_expr.rs:8:8:8:10 | ArgList | +| gen_call_expr.rs:5:5:5:11 | foo(...) | gen_call_expr.rs:5:8:5:11 | ArgList | +| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | gen_call_expr.rs:6:20:6:23 | ArgList | +| gen_call_expr.rs:7:5:7:14 | ...(...) | gen_call_expr.rs:7:11:7:14 | ArgList | +| gen_call_expr.rs:8:5:8:10 | foo(...) | gen_call_expr.rs:8:8:8:10 | ArgList | diff --git a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.expected index 544937866b78..ecaaf15cebbc 100644 --- a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.expected @@ -1,4 +1,4 @@ -| gen_call_expr.rs:5:5:5:11 | CallExpr | gen_call_expr.rs:5:5:5:7 | foo | -| gen_call_expr.rs:6:5:6:23 | CallExpr | gen_call_expr.rs:6:5:6:19 | foo::<...> | -| gen_call_expr.rs:7:5:7:14 | CallExpr | gen_call_expr.rs:7:5:7:10 | IndexExpr | -| gen_call_expr.rs:8:5:8:10 | CallExpr | gen_call_expr.rs:8:5:8:7 | foo | +| gen_call_expr.rs:5:5:5:11 | foo(...) | gen_call_expr.rs:5:5:5:7 | foo | +| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | gen_call_expr.rs:6:5:6:19 | foo::<...> | +| gen_call_expr.rs:7:5:7:14 | ...(...) | gen_call_expr.rs:7:5:7:10 | foo[0] | +| gen_call_expr.rs:8:5:8:10 | foo(...) | gen_call_expr.rs:8:5:8:7 | foo | diff --git a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.expected b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.expected new file mode 100644 index 000000000000..ecaaf15cebbc --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.expected @@ -0,0 +1,4 @@ +| gen_call_expr.rs:5:5:5:11 | foo(...) | gen_call_expr.rs:5:5:5:7 | foo | +| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | gen_call_expr.rs:6:5:6:19 | foo::<...> | +| gen_call_expr.rs:7:5:7:14 | ...(...) | gen_call_expr.rs:7:5:7:10 | foo[0] | +| gen_call_expr.rs:8:5:8:10 | foo(...) | gen_call_expr.rs:8:5:8:7 | foo | diff --git a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql similarity index 84% rename from rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql rename to rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql index d09819fc1fd8..61196bcd14df 100644 --- a/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql +++ b/rust/ql/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql @@ -4,4 +4,4 @@ import TestUtils from CallExpr x where toBeTested(x) and not x.isUnknown() -select x, x.getExpr() +select x, x.getFunction() diff --git a/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr.expected b/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr.expected index 6050eb022593..c85e41866313 100644 --- a/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr.expected +++ b/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr.expected @@ -1 +1 @@ -| gen_cast_expr.rs:5:5:5:16 | CastExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasTy: | yes | +| gen_cast_expr.rs:5:5:5:16 | value as u64 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasTy: | yes | diff --git a/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getExpr.expected index f3e1d4c7ec94..01a710bfb533 100644 --- a/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getExpr.expected @@ -1 +1 @@ -| gen_cast_expr.rs:5:5:5:16 | CastExpr | gen_cast_expr.rs:5:5:5:9 | value | +| gen_cast_expr.rs:5:5:5:16 | value as u64 | gen_cast_expr.rs:5:5:5:9 | value | diff --git a/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getTy.expected b/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getTy.expected index 29cc49cc3b9f..87c07babb021 100644 --- a/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getTy.expected +++ b/rust/ql/test/extractor-tests/generated/CastExpr/CastExpr_getTy.expected @@ -1 +1 @@ -| gen_cast_expr.rs:5:5:5:16 | CastExpr | gen_cast_expr.rs:5:14:5:16 | PathType | +| gen_cast_expr.rs:5:5:5:16 | value as u64 | gen_cast_expr.rs:5:14:5:16 | u64 | diff --git a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr.expected b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr.expected index fb665ca8f605..3ea9f463a00d 100644 --- a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr.expected @@ -1,5 +1,5 @@ -| gen_closure_expr.rs:5:5:5:13 | ClosureExpr | hasParamList: | yes | getNumberOfAttrs: | 0 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isStatic: | no | hasRetType: | no | -| gen_closure_expr.rs:6:5:6:34 | ClosureExpr | hasParamList: | yes | getNumberOfAttrs: | 0 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | yes | isStatic: | no | hasRetType: | yes | -| gen_closure_expr.rs:7:5:7:27 | ClosureExpr | hasParamList: | yes | getNumberOfAttrs: | 0 | hasBody: | yes | hasClosureBinder: | no | isAsync: | yes | isConst: | no | isGen: | no | isMove: | no | isStatic: | no | hasRetType: | no | -| gen_closure_expr.rs:8:6:9:15 | ClosureExpr | hasParamList: | yes | getNumberOfAttrs: | 1 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isStatic: | no | hasRetType: | no | -| gen_closure_expr.rs:10:6:11:23 | ClosureExpr | hasParamList: | yes | getNumberOfAttrs: | 1 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isStatic: | yes | hasRetType: | no | +| gen_closure_expr.rs:5:5:5:13 | \|...\| ... | hasParamList: | yes | getNumberOfAttrs: | 0 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isStatic: | no | hasRetType: | no | +| gen_closure_expr.rs:6:5:6:34 | \|...\| ... | hasParamList: | yes | getNumberOfAttrs: | 0 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | yes | isStatic: | no | hasRetType: | yes | +| gen_closure_expr.rs:7:5:7:27 | \|...\| ... | hasParamList: | yes | getNumberOfAttrs: | 0 | hasBody: | yes | hasClosureBinder: | no | isAsync: | yes | isConst: | no | isGen: | no | isMove: | no | isStatic: | no | hasRetType: | no | +| gen_closure_expr.rs:8:6:9:15 | \|...\| ... | hasParamList: | yes | getNumberOfAttrs: | 1 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isStatic: | no | hasRetType: | no | +| gen_closure_expr.rs:10:6:11:23 | \|...\| ... | hasParamList: | yes | getNumberOfAttrs: | 1 | hasBody: | yes | hasClosureBinder: | no | isAsync: | no | isConst: | no | isGen: | no | isMove: | no | isStatic: | yes | hasRetType: | no | diff --git a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getAttr.expected b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getAttr.expected index f1859d594d18..4de6e17d785a 100644 --- a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getAttr.expected +++ b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getAttr.expected @@ -1,2 +1,2 @@ -| gen_closure_expr.rs:8:6:9:15 | ClosureExpr | 0 | gen_closure_expr.rs:8:6:8:17 | Attr | -| gen_closure_expr.rs:10:6:11:23 | ClosureExpr | 0 | gen_closure_expr.rs:10:6:10:17 | Attr | +| gen_closure_expr.rs:8:6:9:15 | \|...\| ... | 0 | gen_closure_expr.rs:8:6:8:17 | Attr | +| gen_closure_expr.rs:10:6:11:23 | \|...\| ... | 0 | gen_closure_expr.rs:10:6:10:17 | Attr | diff --git a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getBody.expected b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getBody.expected index 71bc3cccda3c..d7b6180e63b2 100644 --- a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getBody.expected +++ b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getBody.expected @@ -1,5 +1,5 @@ -| gen_closure_expr.rs:5:5:5:13 | ClosureExpr | gen_closure_expr.rs:5:9:5:13 | ... + ... | -| gen_closure_expr.rs:6:5:6:34 | ClosureExpr | gen_closure_expr.rs:6:26:6:34 | BlockExpr | -| gen_closure_expr.rs:7:5:7:27 | ClosureExpr | gen_closure_expr.rs:7:23:7:27 | ... + ... | -| gen_closure_expr.rs:8:6:9:15 | ClosureExpr | gen_closure_expr.rs:9:9:9:15 | YieldExpr | -| gen_closure_expr.rs:10:6:11:23 | ClosureExpr | gen_closure_expr.rs:11:17:11:23 | YieldExpr | +| gen_closure_expr.rs:5:5:5:13 | \|...\| ... | gen_closure_expr.rs:5:9:5:13 | ... + ... | +| gen_closure_expr.rs:6:5:6:34 | \|...\| ... | gen_closure_expr.rs:6:26:6:34 | { ... } | +| gen_closure_expr.rs:7:5:7:27 | \|...\| ... | gen_closure_expr.rs:7:23:7:27 | ... + ... | +| gen_closure_expr.rs:8:6:9:15 | \|...\| ... | gen_closure_expr.rs:9:9:9:15 | YieldExpr | +| gen_closure_expr.rs:10:6:11:23 | \|...\| ... | gen_closure_expr.rs:11:17:11:23 | YieldExpr | diff --git a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getParamList.expected b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getParamList.expected index d0e6aaeac064..5945738433bd 100644 --- a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getParamList.expected +++ b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getParamList.expected @@ -1,5 +1,5 @@ -| gen_closure_expr.rs:5:5:5:13 | ClosureExpr | gen_closure_expr.rs:5:5:5:7 | ParamList | -| gen_closure_expr.rs:6:5:6:34 | ClosureExpr | gen_closure_expr.rs:6:10:6:17 | ParamList | -| gen_closure_expr.rs:7:5:7:27 | ClosureExpr | gen_closure_expr.rs:7:11:7:21 | ParamList | -| gen_closure_expr.rs:8:6:9:15 | ClosureExpr | gen_closure_expr.rs:9:5:9:7 | ParamList | -| gen_closure_expr.rs:10:6:11:23 | ClosureExpr | gen_closure_expr.rs:11:13:11:15 | ParamList | +| gen_closure_expr.rs:5:5:5:13 | \|...\| ... | gen_closure_expr.rs:5:5:5:7 | ParamList | +| gen_closure_expr.rs:6:5:6:34 | \|...\| ... | gen_closure_expr.rs:6:10:6:17 | ParamList | +| gen_closure_expr.rs:7:5:7:27 | \|...\| ... | gen_closure_expr.rs:7:11:7:21 | ParamList | +| gen_closure_expr.rs:8:6:9:15 | \|...\| ... | gen_closure_expr.rs:9:5:9:7 | ParamList | +| gen_closure_expr.rs:10:6:11:23 | \|...\| ... | gen_closure_expr.rs:11:13:11:15 | ParamList | diff --git a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getRetType.expected b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getRetType.expected index e018209cb53f..d7ec1024953c 100644 --- a/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getRetType.expected +++ b/rust/ql/test/extractor-tests/generated/ClosureExpr/ClosureExpr_getRetType.expected @@ -1 +1 @@ -| gen_closure_expr.rs:6:5:6:34 | ClosureExpr | gen_closure_expr.rs:6:19:6:24 | RetType | +| gen_closure_expr.rs:6:5:6:34 | \|...\| ... | gen_closure_expr.rs:6:19:6:24 | RetType | diff --git a/rust/ql/test/extractor-tests/generated/Comment/Comment.expected b/rust/ql/test/extractor-tests/generated/Comment/Comment.expected index 21861bb40bf9..24e95f123d8c 100644 --- a/rust/ql/test/extractor-tests/generated/Comment/Comment.expected +++ b/rust/ql/test/extractor-tests/generated/Comment/Comment.expected @@ -1,7 +1,7 @@ -| comments.rs:1:1:3:2 | Comment | getParent: | comments.rs:1:1:9:1 | foo | getText: | /** \n* A doc comment\n*/ | -| comments.rs:6:17:6:34 | Comment | getParent: | comments.rs:6:17:8:16 | nested | getText: | // print some text | -| comments.rs:7:3:7:31 | Comment | getParent: | comments.rs:6:17:8:16 | nested | getText: | /// This is a nested function | -| gen_comment.rs:1:1:1:36 | Comment | getParent: | gen_comment.rs:1:1:7:2 | SourceFile | getText: | // generated by codegen, do not edit | -| gen_comment.rs:4:5:4:30 | Comment | getParent: | gen_comment.rs:3:25:7:1 | StmtList | getText: | // A comment. For example: | -| gen_comment.rs:5:5:5:24 | Comment | getParent: | gen_comment.rs:3:25:7:1 | StmtList | getText: | // this is a comment | -| gen_comment.rs:6:5:6:29 | Comment | getParent: | gen_comment.rs:3:25:7:1 | StmtList | getText: | /// This is a doc comment | +| comments.rs:1:1:3:2 | /**...*/ | getParent: | comments.rs:1:1:9:1 | fn foo | getText: | /** \n* A doc comment\n*/ | +| comments.rs:6:17:6:34 | //... | getParent: | comments.rs:6:17:8:16 | fn nested | getText: | // print some text | +| comments.rs:7:3:7:31 | ///... | getParent: | comments.rs:6:17:8:16 | fn nested | getText: | /// This is a nested function | +| gen_comment.rs:1:1:1:36 | //... | getParent: | gen_comment.rs:1:1:7:2 | SourceFile | getText: | // generated by codegen, do not edit | +| gen_comment.rs:4:5:4:30 | //... | getParent: | gen_comment.rs:3:25:7:1 | StmtList | getText: | // A comment. For example: | +| gen_comment.rs:5:5:5:24 | //... | getParent: | gen_comment.rs:3:25:7:1 | StmtList | getText: | // this is a comment | +| gen_comment.rs:6:5:6:29 | ///... | getParent: | gen_comment.rs:3:25:7:1 | StmtList | getText: | /// This is a doc comment | diff --git a/rust/ql/test/extractor-tests/generated/ConstBlockPat/ConstBlockPat_getBlockExpr.expected b/rust/ql/test/extractor-tests/generated/ConstBlockPat/ConstBlockPat_getBlockExpr.expected index 58a885a48578..42cdb5ef4c30 100644 --- a/rust/ql/test/extractor-tests/generated/ConstBlockPat/ConstBlockPat_getBlockExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ConstBlockPat/ConstBlockPat_getBlockExpr.expected @@ -1 +1 @@ -| gen_const_block_pat.rs:6:9:6:27 | ConstBlockPat | gen_const_block_pat.rs:6:15:6:27 | BlockExpr | +| gen_const_block_pat.rs:6:9:6:27 | ConstBlockPat | gen_const_block_pat.rs:6:15:6:27 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr.expected b/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr.expected index ab921873d620..a09556b9a3ff 100644 --- a/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr.expected @@ -1,2 +1,2 @@ -| gen_continue_expr.rs:7:13:7:20 | ContinueExpr | getNumberOfAttrs: | 0 | hasLifetime: | no | -| gen_continue_expr.rs:12:13:12:27 | ContinueExpr | getNumberOfAttrs: | 0 | hasLifetime: | yes | +| gen_continue_expr.rs:7:13:7:20 | continue | getNumberOfAttrs: | 0 | hasLifetime: | no | +| gen_continue_expr.rs:12:13:12:27 | continue 'label | getNumberOfAttrs: | 0 | hasLifetime: | yes | diff --git a/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr_getLifetime.expected b/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr_getLifetime.expected index 525d2bb55a8e..d81d276ce0ae 100644 --- a/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr_getLifetime.expected +++ b/rust/ql/test/extractor-tests/generated/ContinueExpr/ContinueExpr_getLifetime.expected @@ -1 +1 @@ -| gen_continue_expr.rs:12:13:12:27 | ContinueExpr | gen_continue_expr.rs:12:22:12:27 | Lifetime | +| gen_continue_expr.rs:12:13:12:27 | continue 'label | gen_continue_expr.rs:12:22:12:27 | ''label | diff --git a/rust/ql/test/extractor-tests/generated/ExprStmt/ExprStmt_getExpr.expected b/rust/ql/test/extractor-tests/generated/ExprStmt/ExprStmt_getExpr.expected index f29a7f83d7d5..1cacf1e84241 100644 --- a/rust/ql/test/extractor-tests/generated/ExprStmt/ExprStmt_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ExprStmt/ExprStmt_getExpr.expected @@ -1,2 +1,2 @@ -| gen_expr_stmt.rs:5:5:5:12 | ExprStmt | gen_expr_stmt.rs:5:5:5:11 | CallExpr | -| gen_expr_stmt.rs:6:5:6:13 | ExprStmt | gen_expr_stmt.rs:6:5:6:12 | CallExpr | +| gen_expr_stmt.rs:5:5:5:12 | ExprStmt | gen_expr_stmt.rs:5:5:5:11 | start(...) | +| gen_expr_stmt.rs:6:5:6:13 | ExprStmt | gen_expr_stmt.rs:6:5:6:12 | finish(...) | diff --git a/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr.expected b/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr.expected index 22dcb3c92e11..c25a0633e402 100644 --- a/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr.expected +++ b/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr.expected @@ -1 +1 @@ -| gen_field_expr.rs:5:5:5:9 | FieldExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasNameRef: | yes | +| gen_field_expr.rs:5:5:5:9 | x.foo | getNumberOfAttrs: | 0 | hasExpr: | yes | hasNameRef: | yes | diff --git a/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getExpr.expected index 32b13c1cb2b0..7d21f7f7af81 100644 --- a/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getExpr.expected @@ -1 +1 @@ -| gen_field_expr.rs:5:5:5:9 | FieldExpr | gen_field_expr.rs:5:5:5:5 | x | +| gen_field_expr.rs:5:5:5:9 | x.foo | gen_field_expr.rs:5:5:5:5 | x | diff --git a/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getNameRef.expected b/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getNameRef.expected index 667f3130968c..0722ca1aaf28 100644 --- a/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getNameRef.expected +++ b/rust/ql/test/extractor-tests/generated/FieldExpr/FieldExpr_getNameRef.expected @@ -1 +1 @@ -| gen_field_expr.rs:5:5:5:9 | FieldExpr | gen_field_expr.rs:5:7:5:9 | foo | +| gen_field_expr.rs:5:5:5:9 | x.foo | gen_field_expr.rs:5:7:5:9 | foo | diff --git a/rust/ql/test/extractor-tests/generated/ForExpr/ForExpr.ql b/rust/ql/test/extractor-tests/generated/ForExpr/ForExpr.ql index ef1999ff4a9d..60f5ab1e0809 100644 --- a/rust/ql/test/extractor-tests/generated/ForExpr/ForExpr.ql +++ b/rust/ql/test/extractor-tests/generated/ForExpr/ForExpr.ql @@ -3,15 +3,15 @@ import codeql.rust.elements import TestUtils from - ForExpr x, int getNumberOfAttrs, string hasIterable, string hasLabel, string hasLoopBody, + ForExpr x, string hasLabel, string hasLoopBody, int getNumberOfAttrs, string hasIterable, string hasPat where toBeTested(x) and not x.isUnknown() and - getNumberOfAttrs = x.getNumberOfAttrs() and - (if x.hasIterable() then hasIterable = "yes" else hasIterable = "no") and (if x.hasLabel() then hasLabel = "yes" else hasLabel = "no") and (if x.hasLoopBody() then hasLoopBody = "yes" else hasLoopBody = "no") and + getNumberOfAttrs = x.getNumberOfAttrs() and + (if x.hasIterable() then hasIterable = "yes" else hasIterable = "no") and if x.hasPat() then hasPat = "yes" else hasPat = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasIterable:", hasIterable, "hasLabel:", hasLabel, - "hasLoopBody:", hasLoopBody, "hasPat:", hasPat +select x, "hasLabel:", hasLabel, "hasLoopBody:", hasLoopBody, "getNumberOfAttrs:", getNumberOfAttrs, + "hasIterable:", hasIterable, "hasPat:", hasPat diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format.expected new file mode 100644 index 000000000000..312f5a3b0712 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format.expected @@ -0,0 +1,9 @@ +| gen_format.rs:5:21:5:22 | {} | getParent: | gen_format.rs:5:14:5:32 | FormatArgsExpr | getIndex: | 1 | hasArgument: | no | +| gen_format_args_expr.rs:6:19:6:20 | {} | getParent: | gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | getIndex: | 1 | hasArgument: | no | +| gen_format_args_expr.rs:6:26:6:29 | {:?} | getParent: | gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | getIndex: | 3 | hasArgument: | no | +| gen_format_args_expr.rs:7:19:7:21 | {b} | getParent: | gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes | +| gen_format_args_expr.rs:7:27:7:31 | {a:?} | getParent: | gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | getIndex: | 3 | hasArgument: | yes | +| gen_format_args_expr.rs:9:19:9:21 | {x} | getParent: | gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes | +| gen_format_args_expr.rs:9:24:9:26 | {y} | getParent: | gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | getIndex: | 3 | hasArgument: | yes | +| gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | getParent: | gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes | +| gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | getParent: | gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | getIndex: | 1 | hasArgument: | yes | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format.ql new file mode 100644 index 000000000000..fa17b4294f7e --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format.ql @@ -0,0 +1,12 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from Format x, FormatArgsExpr getParent, int getIndex, string hasArgument +where + toBeTested(x) and + not x.isUnknown() and + getParent = x.getParent() and + getIndex = x.getIndex() and + if x.hasArgument() then hasArgument = "yes" else hasArgument = "no" +select x, "getParent:", getParent, "getIndex:", getIndex, "hasArgument:", hasArgument diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.expected new file mode 100644 index 000000000000..8e704471e02c --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.expected @@ -0,0 +1,8 @@ +| gen_format.rs:5:26:5:32 | FormatArgsArg | hasExpr: | yes | hasName: | no | +| gen_format_args_expr.rs:6:33:6:33 | FormatArgsArg | hasExpr: | yes | hasName: | no | +| gen_format_args_expr.rs:6:36:6:36 | FormatArgsArg | hasExpr: | yes | hasName: | no | +| gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | hasExpr: | yes | hasName: | yes | +| gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | hasExpr: | yes | hasName: | yes | +| gen_format_argument.rs:7:34:7:38 | FormatArgsArg | hasExpr: | yes | hasName: | no | +| gen_format_argument.rs:7:41:7:45 | FormatArgsArg | hasExpr: | yes | hasName: | no | +| gen_format_argument.rs:7:48:7:56 | FormatArgsArg | hasExpr: | yes | hasName: | no | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg.ql rename to rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg.ql diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.expected new file mode 100644 index 000000000000..90cf2cae221f --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.expected @@ -0,0 +1,8 @@ +| gen_format.rs:5:26:5:32 | FormatArgsArg | gen_format.rs:5:26:5:32 | "world" | +| gen_format_args_expr.rs:6:33:6:33 | FormatArgsArg | gen_format_args_expr.rs:6:33:6:33 | 1 | +| gen_format_args_expr.rs:6:36:6:36 | FormatArgsArg | gen_format_args_expr.rs:6:36:6:36 | 2 | +| gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | gen_format_args_expr.rs:7:37:7:37 | 1 | +| gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | gen_format_args_expr.rs:7:42:7:42 | 2 | +| gen_format_argument.rs:7:34:7:38 | FormatArgsArg | gen_format_argument.rs:7:34:7:38 | value | +| gen_format_argument.rs:7:41:7:45 | FormatArgsArg | gen_format_argument.rs:7:41:7:45 | width | +| gen_format_argument.rs:7:48:7:56 | FormatArgsArg | gen_format_argument.rs:7:48:7:56 | precision | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.ql rename to rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getExpr.ql diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.expected new file mode 100644 index 000000000000..ad5d7ab4ab22 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.expected @@ -0,0 +1,2 @@ +| gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | gen_format_args_expr.rs:7:35:7:35 | a | +| gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | gen_format_args_expr.rs:7:40:7:40 | b | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.ql rename to rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsArg_getName.ql diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.expected index e69de29bb2d1..bed19ed26d47 100644 --- a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.expected +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.expected @@ -0,0 +1,7 @@ +| gen_format.rs:5:14:5:32 | FormatArgsExpr | getNumberOfArgs: | 1 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 1 | +| gen_format_args_expr.rs:5:17:5:27 | FormatArgsExpr | getNumberOfArgs: | 0 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 0 | +| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | getNumberOfArgs: | 2 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 2 | +| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | getNumberOfArgs: | 2 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 2 | +| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | getNumberOfArgs: | 0 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 2 | +| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | getNumberOfArgs: | 0 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 1 | +| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | getNumberOfArgs: | 3 | getNumberOfAttrs: | 0 | hasTemplate: | yes | getNumberOfFormats: | 1 | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql index 4d5bcf051735..6a43bc1ea0a3 100644 --- a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr.ql @@ -2,12 +2,15 @@ import codeql.rust.elements import TestUtils -from FormatArgsExpr x, int getNumberOfArgs, int getNumberOfAttrs, string hasTemplate +from + FormatArgsExpr x, int getNumberOfArgs, int getNumberOfAttrs, string hasTemplate, + int getNumberOfFormats where toBeTested(x) and not x.isUnknown() and getNumberOfArgs = x.getNumberOfArgs() and getNumberOfAttrs = x.getNumberOfAttrs() and - if x.hasTemplate() then hasTemplate = "yes" else hasTemplate = "no" + (if x.hasTemplate() then hasTemplate = "yes" else hasTemplate = "no") and + getNumberOfFormats = x.getNumberOfFormats() select x, "getNumberOfArgs:", getNumberOfArgs, "getNumberOfAttrs:", getNumberOfAttrs, - "hasTemplate:", hasTemplate + "hasTemplate:", hasTemplate, "getNumberOfFormats:", getNumberOfFormats diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.expected index e69de29bb2d1..89fce13908fd 100644 --- a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.expected +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getArg.expected @@ -0,0 +1,8 @@ +| gen_format.rs:5:14:5:32 | FormatArgsExpr | 0 | gen_format.rs:5:26:5:32 | FormatArgsArg | +| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 0 | gen_format_args_expr.rs:6:33:6:33 | FormatArgsArg | +| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 1 | gen_format_args_expr.rs:6:36:6:36 | FormatArgsArg | +| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 0 | gen_format_args_expr.rs:7:35:7:37 | FormatArgsArg | +| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 1 | gen_format_args_expr.rs:7:40:7:42 | FormatArgsArg | +| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 0 | gen_format_argument.rs:7:34:7:38 | FormatArgsArg | +| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 1 | gen_format_argument.rs:7:41:7:45 | FormatArgsArg | +| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 2 | gen_format_argument.rs:7:48:7:56 | FormatArgsArg | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.expected new file mode 100644 index 000000000000..f0061b8dba46 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.expected @@ -0,0 +1,9 @@ +| gen_format.rs:5:14:5:32 | FormatArgsExpr | 0 | gen_format.rs:5:21:5:22 | {} | +| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 0 | gen_format_args_expr.rs:6:19:6:20 | {} | +| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | 1 | gen_format_args_expr.rs:6:26:6:29 | {:?} | +| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 0 | gen_format_args_expr.rs:7:19:7:21 | {b} | +| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | 1 | gen_format_args_expr.rs:7:27:7:31 | {a:?} | +| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 0 | gen_format_args_expr.rs:9:19:9:21 | {x} | +| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 1 | gen_format_args_expr.rs:9:24:9:26 | {y} | +| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 0 | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | +| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | 0 | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql new file mode 100644 index 000000000000..ca61ca2bebd9 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getFormat.ql @@ -0,0 +1,7 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from FormatArgsExpr x, int index +where toBeTested(x) and not x.isUnknown() +select x, index, x.getFormat(index) diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.expected index e69de29bb2d1..1b201bbf36f2 100644 --- a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.expected +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getTemplate.expected @@ -0,0 +1,7 @@ +| gen_format.rs:5:14:5:32 | FormatArgsExpr | gen_format.rs:5:14:5:23 | "Hello {}\\n" | +| gen_format_args_expr.rs:5:17:5:27 | FormatArgsExpr | gen_format_args_expr.rs:5:18:5:26 | "no args" | +| gen_format_args_expr.rs:6:17:6:37 | FormatArgsExpr | gen_format_args_expr.rs:6:18:6:30 | "{} foo {:?}" | +| gen_format_args_expr.rs:7:17:7:43 | FormatArgsExpr | gen_format_args_expr.rs:7:18:7:32 | "{b} foo {a:?}" | +| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | gen_format_args_expr.rs:9:18:9:27 | "{x}, {y}" | +| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | gen_format_argument.rs:5:14:5:47 | "Value {value:#width$.precisio... | +| gen_format_argument.rs:7:14:7:56 | FormatArgsExpr | gen_format_argument.rs:7:14:7:31 | "Value {0:#1$.2$}\\n" | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getVariable.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getVariable.expected new file mode 100644 index 000000000000..dca240710f7d --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgsExpr_getVariable.expected @@ -0,0 +1,5 @@ +| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 1 | gen_format_args_expr.rs:9:20:9:20 | x | +| gen_format_args_expr.rs:9:17:9:28 | FormatArgsExpr | 3 | gen_format_args_expr.rs:9:25:9:25 | y | +| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 1 | gen_format_argument.rs:5:22:5:26 | value | +| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 1 | gen_format_argument.rs:5:29:5:33 | width | +| gen_format_argument.rs:5:14:5:47 | FormatArgsExpr | 1 | gen_format_argument.rs:5:36:5:44 | precision | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.expected new file mode 100644 index 000000000000..e63b4b6558fc --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.expected @@ -0,0 +1,10 @@ +| gen_format_args_expr.rs:7:20:7:20 | b | getParent: | gen_format_args_expr.rs:7:19:7:21 | {b} | hasVariable: | no | +| gen_format_args_expr.rs:7:28:7:28 | a | getParent: | gen_format_args_expr.rs:7:27:7:31 | {a:?} | hasVariable: | no | +| gen_format_args_expr.rs:9:20:9:20 | x | getParent: | gen_format_args_expr.rs:9:19:9:21 | {x} | hasVariable: | yes | +| gen_format_args_expr.rs:9:25:9:25 | y | getParent: | gen_format_args_expr.rs:9:24:9:26 | {y} | hasVariable: | yes | +| gen_format_argument.rs:5:22:5:26 | value | getParent: | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | hasVariable: | yes | +| gen_format_argument.rs:5:29:5:33 | width | getParent: | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | hasVariable: | yes | +| gen_format_argument.rs:5:36:5:44 | precision | getParent: | gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | hasVariable: | yes | +| gen_format_argument.rs:7:22:7:22 | 0 | getParent: | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | hasVariable: | no | +| gen_format_argument.rs:7:25:7:25 | 1 | getParent: | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | hasVariable: | no | +| gen_format_argument.rs:7:28:7:28 | 2 | getParent: | gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | hasVariable: | no | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql new file mode 100644 index 000000000000..ed57154f7e82 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument.ql @@ -0,0 +1,11 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from FormatArgument x, Format getParent, string hasVariable +where + toBeTested(x) and + not x.isUnknown() and + getParent = x.getParent() and + if x.hasVariable() then hasVariable = "yes" else hasVariable = "no" +select x, "getParent:", getParent, "hasVariable:", hasVariable diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.expected new file mode 100644 index 000000000000..11db93ec06dd --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.expected @@ -0,0 +1,5 @@ +| gen_format_args_expr.rs:9:20:9:20 | x | gen_format_args_expr.rs:9:20:9:20 | x | +| gen_format_args_expr.rs:9:25:9:25 | y | gen_format_args_expr.rs:9:25:9:25 | y | +| gen_format_argument.rs:5:22:5:26 | value | gen_format_argument.rs:5:22:5:26 | value | +| gen_format_argument.rs:5:29:5:33 | width | gen_format_argument.rs:5:29:5:33 | width | +| gen_format_argument.rs:5:36:5:44 | precision | gen_format_argument.rs:5:36:5:44 | precision | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql new file mode 100644 index 000000000000..5d303bc4b6c6 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatArgument_getVariable.ql @@ -0,0 +1,7 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from FormatArgument x +where toBeTested(x) and not x.isUnknown() +select x, x.getVariable() diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.expected new file mode 100644 index 000000000000..df4fdad5c911 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.expected @@ -0,0 +1,5 @@ +| gen_format_args_expr.rs:9:20:9:20 | x | +| gen_format_args_expr.rs:9:25:9:25 | y | +| gen_format_argument.rs:5:22:5:26 | value | +| gen_format_argument.rs:5:29:5:33 | width | +| gen_format_argument.rs:5:36:5:44 | precision | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql new file mode 100644 index 000000000000..4f43ca11870a --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/FormatTemplateVariableAccess.ql @@ -0,0 +1,7 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from FormatTemplateVariableAccess x +where toBeTested(x) and not x.isUnknown() +select x diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.expected b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.expected new file mode 100644 index 000000000000..af9dd77578ce --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.expected @@ -0,0 +1,10 @@ +| gen_format_args_expr.rs:7:19:7:21 | {b} | gen_format_args_expr.rs:7:20:7:20 | b | +| gen_format_args_expr.rs:7:27:7:31 | {a:?} | gen_format_args_expr.rs:7:28:7:28 | a | +| gen_format_args_expr.rs:9:19:9:21 | {x} | gen_format_args_expr.rs:9:20:9:20 | x | +| gen_format_args_expr.rs:9:24:9:26 | {y} | gen_format_args_expr.rs:9:25:9:25 | y | +| gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | gen_format_argument.rs:5:22:5:26 | value | +| gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | gen_format_argument.rs:5:29:5:33 | width | +| gen_format_argument.rs:5:21:5:46 | {value:#width$.precision$} | gen_format_argument.rs:5:36:5:44 | precision | +| gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | gen_format_argument.rs:7:22:7:22 | 0 | +| gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | gen_format_argument.rs:7:25:7:25 | 1 | +| gen_format_argument.rs:7:21:7:30 | {0:#1$.2$} | gen_format_argument.rs:7:28:7:28 | 2 | diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql new file mode 100644 index 000000000000..e131365770b6 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/Format_getArgument.ql @@ -0,0 +1,7 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from Format x +where toBeTested(x) and not x.isUnknown() +select x, x.getArgument() diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format.rs b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format.rs new file mode 100644 index 000000000000..86b78256d403 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format.rs @@ -0,0 +1,6 @@ +// generated by codegen, do not edit + +fn test_format() -> () { + // A format element in a formatting template. For example the `{}` in: + println!("Hello {}", "world"); +} diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/gen_format_args_arg.rs b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_args_arg.rs similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/gen_format_args_arg.rs rename to rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_args_arg.rs diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_args_expr.rs b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_args_expr.rs index 7345a633ba5d..3c2acb387fc7 100644 --- a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_args_expr.rs +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_args_expr.rs @@ -2,5 +2,9 @@ fn test_format_args_expr() -> () { // A FormatArgsExpr. For example: - todo!() + format_args!("no args"); + format_args!("{} foo {:?}", 1, 2); + format_args!("{b} foo {a:?}", a=1, b=2); + let (x, y) = (1, 42); + format_args!("{x}, {y}"); } diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_argument.rs b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_argument.rs new file mode 100644 index 000000000000..32cb123f51d0 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/FormatArgsExpr/gen_format_argument.rs @@ -0,0 +1,8 @@ +// generated by codegen, do not edit + +fn test_format_argument() -> () { + // An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: + println!("Value {value:#width$.precision$}"); + // or the `0`, `1` and `2` in: + println!("Value {0:#1$.2$}", value, width, precision); +} diff --git a/rust/ql/test/extractor-tests/generated/Function/Function.expected b/rust/ql/test/extractor-tests/generated/Function/Function.expected index f93eb58b2ae4..b96996beef94 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function.expected @@ -1,2 +1,2 @@ -| gen_function.rs:3:1:4:38 | foo | hasParamList: | yes | getNumberOfAttrs: | 0 | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAbi: | no | hasBody: | yes | hasGenericParamList: | no | isAsync: | no | isConst: | no | isDefault: | no | isGen: | no | isUnsafe: | no | hasName: | yes | hasRetType: | yes | hasVisibility: | no | hasWhereClause: | no | -| gen_function.rs:7:5:7:13 | bar | hasParamList: | yes | getNumberOfAttrs: | 0 | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAbi: | no | hasBody: | no | hasGenericParamList: | no | isAsync: | no | isConst: | no | isDefault: | no | isGen: | no | isUnsafe: | no | hasName: | yes | hasRetType: | no | hasVisibility: | no | hasWhereClause: | no | +| gen_function.rs:3:1:4:38 | fn foo | hasParamList: | yes | getNumberOfAttrs: | 0 | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAbi: | no | hasBody: | yes | hasGenericParamList: | no | isAsync: | no | isConst: | no | isDefault: | no | isGen: | no | isUnsafe: | no | hasName: | yes | hasRetType: | yes | hasVisibility: | no | hasWhereClause: | no | +| gen_function.rs:7:5:7:13 | fn bar | hasParamList: | yes | getNumberOfAttrs: | 0 | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAbi: | no | hasBody: | no | hasGenericParamList: | no | isAsync: | no | isConst: | no | isDefault: | no | isGen: | no | isUnsafe: | no | hasName: | yes | hasRetType: | no | hasVisibility: | no | hasWhereClause: | no | diff --git a/rust/ql/test/extractor-tests/generated/Function/Function_getBody.expected b/rust/ql/test/extractor-tests/generated/Function/Function_getBody.expected index 996e8c1a27c3..894900b3eaa8 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function_getBody.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function_getBody.expected @@ -1 +1 @@ -| gen_function.rs:3:1:4:38 | foo | gen_function.rs:4:23:4:38 | BlockExpr | +| gen_function.rs:3:1:4:38 | fn foo | gen_function.rs:4:23:4:38 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/Function/Function_getCrateOrigin.expected b/rust/ql/test/extractor-tests/generated/Function/Function_getCrateOrigin.expected index 7c376ffaf1e6..eabc941bd5be 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function_getCrateOrigin.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function_getCrateOrigin.expected @@ -1,2 +1,2 @@ -| gen_function.rs:3:1:4:38 | foo | repo::test | -| gen_function.rs:7:5:7:13 | bar | repo::test | +| gen_function.rs:3:1:4:38 | fn foo | repo::test | +| gen_function.rs:7:5:7:13 | fn bar | repo::test | diff --git a/rust/ql/test/extractor-tests/generated/Function/Function_getExtendedCanonicalPath.expected b/rust/ql/test/extractor-tests/generated/Function/Function_getExtendedCanonicalPath.expected index d9b6255918f8..2c0059ebc2a5 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function_getExtendedCanonicalPath.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function_getExtendedCanonicalPath.expected @@ -1,2 +1,2 @@ -| gen_function.rs:3:1:4:38 | foo | crate::gen_function::foo | -| gen_function.rs:7:5:7:13 | bar | crate::gen_function::Trait::bar | +| gen_function.rs:3:1:4:38 | fn foo | crate::gen_function::foo | +| gen_function.rs:7:5:7:13 | fn bar | crate::gen_function::Trait::bar | diff --git a/rust/ql/test/extractor-tests/generated/Function/Function_getName.expected b/rust/ql/test/extractor-tests/generated/Function/Function_getName.expected index 62676019818d..7e889e82d284 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function_getName.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function_getName.expected @@ -1,2 +1,2 @@ -| gen_function.rs:3:1:4:38 | foo | gen_function.rs:4:4:4:6 | foo | -| gen_function.rs:7:5:7:13 | bar | gen_function.rs:7:8:7:10 | bar | +| gen_function.rs:3:1:4:38 | fn foo | gen_function.rs:4:4:4:6 | foo | +| gen_function.rs:7:5:7:13 | fn bar | gen_function.rs:7:8:7:10 | bar | diff --git a/rust/ql/test/extractor-tests/generated/Function/Function_getParamList.expected b/rust/ql/test/extractor-tests/generated/Function/Function_getParamList.expected index baa2734e86ac..df5810619191 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function_getParamList.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function_getParamList.expected @@ -1,2 +1,2 @@ -| gen_function.rs:3:1:4:38 | foo | gen_function.rs:4:7:4:14 | ParamList | -| gen_function.rs:7:5:7:13 | bar | gen_function.rs:7:11:7:12 | ParamList | +| gen_function.rs:3:1:4:38 | fn foo | gen_function.rs:4:7:4:14 | ParamList | +| gen_function.rs:7:5:7:13 | fn bar | gen_function.rs:7:11:7:12 | ParamList | diff --git a/rust/ql/test/extractor-tests/generated/Function/Function_getRetType.expected b/rust/ql/test/extractor-tests/generated/Function/Function_getRetType.expected index 7a5338705600..bd225b268e84 100644 --- a/rust/ql/test/extractor-tests/generated/Function/Function_getRetType.expected +++ b/rust/ql/test/extractor-tests/generated/Function/Function_getRetType.expected @@ -1 +1 @@ -| gen_function.rs:3:1:4:38 | foo | gen_function.rs:4:16:4:21 | RetType | +| gen_function.rs:3:1:4:38 | fn foo | gen_function.rs:4:16:4:21 | RetType | diff --git a/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList.expected b/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList.expected index 370ee8ce4d66..d2a5b7bcd8f0 100644 --- a/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList.expected +++ b/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList.expected @@ -1 +1 @@ -| gen_generic_arg_list.rs:5:10:5:21 | GenericArgList | getNumberOfGenericArgs: | 2 | +| gen_generic_arg_list.rs:5:10:5:21 | <...> | getNumberOfGenericArgs: | 2 | diff --git a/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList_getGenericArg.expected b/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList_getGenericArg.expected index b72d3035ed14..69e416a57ad7 100644 --- a/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList_getGenericArg.expected +++ b/rust/ql/test/extractor-tests/generated/GenericArgList/GenericArgList_getGenericArg.expected @@ -1,2 +1,2 @@ -| gen_generic_arg_list.rs:5:10:5:21 | GenericArgList | 0 | gen_generic_arg_list.rs:5:13:5:15 | TypeArg | -| gen_generic_arg_list.rs:5:10:5:21 | GenericArgList | 1 | gen_generic_arg_list.rs:5:18:5:20 | TypeArg | +| gen_generic_arg_list.rs:5:10:5:21 | <...> | 0 | gen_generic_arg_list.rs:5:13:5:15 | TypeArg | +| gen_generic_arg_list.rs:5:10:5:21 | <...> | 1 | gen_generic_arg_list.rs:5:18:5:20 | TypeArg | diff --git a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr.expected b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr.expected index a0e0ea15594f..d9a33ad74f79 100644 --- a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr.expected +++ b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr.expected @@ -1,2 +1,2 @@ -| gen_if_expr.rs:5:5:7:5 | IfExpr | getNumberOfAttrs: | 0 | hasCondition: | yes | hasElse: | no | hasThen: | yes | -| gen_if_expr.rs:8:13:12:5 | IfExpr | getNumberOfAttrs: | 0 | hasCondition: | yes | hasElse: | yes | hasThen: | yes | +| gen_if_expr.rs:5:5:7:5 | if ... {...} | getNumberOfAttrs: | 0 | hasCondition: | yes | hasElse: | no | hasThen: | yes | +| gen_if_expr.rs:8:13:12:5 | if ... {...} else {...} | getNumberOfAttrs: | 0 | hasCondition: | yes | hasElse: | yes | hasThen: | yes | diff --git a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getCondition.expected b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getCondition.expected index 7bdb262dd324..4990a47bc96e 100644 --- a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getCondition.expected +++ b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getCondition.expected @@ -1,2 +1,2 @@ -| gen_if_expr.rs:5:5:7:5 | IfExpr | gen_if_expr.rs:5:8:5:14 | ... == ... | -| gen_if_expr.rs:8:13:12:5 | IfExpr | gen_if_expr.rs:8:16:8:20 | ... > ... | +| gen_if_expr.rs:5:5:7:5 | if ... {...} | gen_if_expr.rs:5:8:5:14 | ... == ... | +| gen_if_expr.rs:8:13:12:5 | if ... {...} else {...} | gen_if_expr.rs:8:16:8:20 | ... > ... | diff --git a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getElse.expected b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getElse.expected index a857dbe2099a..a03626f5e5dd 100644 --- a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getElse.expected +++ b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getElse.expected @@ -1 +1 @@ -| gen_if_expr.rs:8:13:12:5 | IfExpr | gen_if_expr.rs:10:12:12:5 | BlockExpr | +| gen_if_expr.rs:8:13:12:5 | if ... {...} else {...} | gen_if_expr.rs:10:12:12:5 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getThen.expected b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getThen.expected index 0916c3f33916..6080b004f38f 100644 --- a/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getThen.expected +++ b/rust/ql/test/extractor-tests/generated/IfExpr/IfExpr_getThen.expected @@ -1,2 +1,2 @@ -| gen_if_expr.rs:5:5:7:5 | IfExpr | gen_if_expr.rs:5:16:7:5 | BlockExpr | -| gen_if_expr.rs:8:13:12:5 | IfExpr | gen_if_expr.rs:8:22:10:5 | BlockExpr | +| gen_if_expr.rs:5:5:7:5 | if ... {...} | gen_if_expr.rs:5:16:7:5 | { ... } | +| gen_if_expr.rs:8:13:12:5 | if ... {...} else {...} | gen_if_expr.rs:8:22:10:5 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr.expected b/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr.expected index c113934115d2..614afc3040f4 100644 --- a/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr.expected +++ b/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr.expected @@ -1,2 +1,2 @@ -| gen_index_expr.rs:5:5:5:12 | IndexExpr | getNumberOfAttrs: | 0 | hasBase: | yes | hasIndex: | yes | -| gen_index_expr.rs:6:5:6:12 | IndexExpr | getNumberOfAttrs: | 0 | hasBase: | yes | hasIndex: | yes | +| gen_index_expr.rs:5:5:5:12 | list[42] | getNumberOfAttrs: | 0 | hasBase: | yes | hasIndex: | yes | +| gen_index_expr.rs:6:5:6:12 | list[42] | getNumberOfAttrs: | 0 | hasBase: | yes | hasIndex: | yes | diff --git a/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getBase.expected b/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getBase.expected index c149597172b8..13fb9a2c6a6d 100644 --- a/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getBase.expected +++ b/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getBase.expected @@ -1,2 +1,2 @@ -| gen_index_expr.rs:5:5:5:12 | IndexExpr | gen_index_expr.rs:5:5:5:8 | list | -| gen_index_expr.rs:6:5:6:12 | IndexExpr | gen_index_expr.rs:6:5:6:8 | list | +| gen_index_expr.rs:5:5:5:12 | list[42] | gen_index_expr.rs:5:5:5:8 | list | +| gen_index_expr.rs:6:5:6:12 | list[42] | gen_index_expr.rs:6:5:6:8 | list | diff --git a/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getIndex.expected b/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getIndex.expected index 433afd85eb99..dfca82040881 100644 --- a/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getIndex.expected +++ b/rust/ql/test/extractor-tests/generated/IndexExpr/IndexExpr_getIndex.expected @@ -1,2 +1,2 @@ -| gen_index_expr.rs:5:5:5:12 | IndexExpr | gen_index_expr.rs:5:10:5:11 | 42 | -| gen_index_expr.rs:6:5:6:12 | IndexExpr | gen_index_expr.rs:6:10:6:11 | 42 | +| gen_index_expr.rs:5:5:5:12 | list[42] | gen_index_expr.rs:5:10:5:11 | 42 | +| gen_index_expr.rs:6:5:6:12 | list[42] | gen_index_expr.rs:6:10:6:11 | 42 | diff --git a/rust/ql/test/extractor-tests/generated/Label/Label.expected b/rust/ql/test/extractor-tests/generated/Label/Label.expected index 5cea4ef72221..7525044aaa25 100644 --- a/rust/ql/test/extractor-tests/generated/Label/Label.expected +++ b/rust/ql/test/extractor-tests/generated/Label/Label.expected @@ -1 +1 @@ -| gen_label.rs:5:5:5:11 | Label | hasLifetime: | yes | +| gen_label.rs:5:5:5:11 | 'label | hasLifetime: | yes | diff --git a/rust/ql/test/extractor-tests/generated/Label/Label_getLifetime.expected b/rust/ql/test/extractor-tests/generated/Label/Label_getLifetime.expected index 9c78f23307d2..73ebbe963e85 100644 --- a/rust/ql/test/extractor-tests/generated/Label/Label_getLifetime.expected +++ b/rust/ql/test/extractor-tests/generated/Label/Label_getLifetime.expected @@ -1 +1 @@ -| gen_label.rs:5:5:5:11 | Label | gen_label.rs:5:5:5:10 | Lifetime | +| gen_label.rs:5:5:5:11 | 'label | gen_label.rs:5:5:5:10 | ''label | diff --git a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.expected b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.expected index 26a968ef35b3..115493214ea5 100644 --- a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.expected +++ b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.expected @@ -1 +1 @@ -| gen_let_expr.rs:5:8:5:31 | LetExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasPat: | yes | +| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | getNumberOfAttrs: | 0 | hasScrutinee: | yes | hasPat: | yes | diff --git a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.ql b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.ql index 1b7648a56684..60aa8b90892c 100644 --- a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.ql +++ b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr.ql @@ -2,11 +2,11 @@ import codeql.rust.elements import TestUtils -from LetExpr x, int getNumberOfAttrs, string hasExpr, string hasPat +from LetExpr x, int getNumberOfAttrs, string hasScrutinee, string hasPat where toBeTested(x) and not x.isUnknown() and getNumberOfAttrs = x.getNumberOfAttrs() and - (if x.hasExpr() then hasExpr = "yes" else hasExpr = "no") and + (if x.hasScrutinee() then hasScrutinee = "yes" else hasScrutinee = "no") and if x.hasPat() then hasPat = "yes" else hasPat = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr, "hasPat:", hasPat +select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasScrutinee:", hasScrutinee, "hasPat:", hasPat diff --git a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.expected index f90fa5862299..0080ab4ee6e5 100644 --- a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.expected @@ -1 +1 @@ -| gen_let_expr.rs:5:8:5:31 | LetExpr | gen_let_expr.rs:5:22:5:31 | maybe_some | +| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | gen_let_expr.rs:5:22:5:31 | maybe_some | diff --git a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getPat.expected b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getPat.expected index 287200e610ff..7c31e314128d 100644 --- a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getPat.expected @@ -1 +1 @@ -| gen_let_expr.rs:5:8:5:31 | LetExpr | gen_let_expr.rs:5:12:5:18 | TupleStructPat | +| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | gen_let_expr.rs:5:12:5:18 | TupleStructPat | diff --git a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.expected b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.expected new file mode 100644 index 000000000000..0080ab4ee6e5 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.expected @@ -0,0 +1 @@ +| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | gen_let_expr.rs:5:22:5:31 | maybe_some | diff --git a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql similarity index 83% rename from rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql rename to rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql index 0f9e8088b461..2c144c2ac3c7 100644 --- a/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql +++ b/rust/ql/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql @@ -4,4 +4,4 @@ import TestUtils from LetExpr x where toBeTested(x) and not x.isUnknown() -select x, x.getExpr() +select x, x.getScrutinee() diff --git a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt.expected b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt.expected index 7c05e07e2f3e..847ff988ff0d 100644 --- a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt.expected +++ b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt.expected @@ -1,6 +1,6 @@ -| gen_let_stmt.rs:5:5:5:15 | LetStmt | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | no | hasPat: | yes | hasTy: | no | -| gen_let_stmt.rs:6:5:6:20 | LetStmt | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | no | hasPat: | yes | hasTy: | yes | -| gen_let_stmt.rs:7:5:7:15 | LetStmt | getNumberOfAttrs: | 0 | hasInitializer: | no | hasLetElse: | no | hasPat: | yes | hasTy: | yes | -| gen_let_stmt.rs:8:5:8:10 | LetStmt | getNumberOfAttrs: | 0 | hasInitializer: | no | hasLetElse: | no | hasPat: | yes | hasTy: | no | -| gen_let_stmt.rs:9:5:9:24 | LetStmt | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | no | hasPat: | yes | hasTy: | no | -| gen_let_stmt.rs:10:5:12:6 | LetStmt | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | yes | hasPat: | yes | hasTy: | no | +| gen_let_stmt.rs:5:5:5:15 | let ... = 42 | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | no | hasPat: | yes | hasTy: | no | +| gen_let_stmt.rs:6:5:6:20 | let ... = 42 | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | no | hasPat: | yes | hasTy: | yes | +| gen_let_stmt.rs:7:5:7:15 | let ... | getNumberOfAttrs: | 0 | hasInitializer: | no | hasLetElse: | no | hasPat: | yes | hasTy: | yes | +| gen_let_stmt.rs:8:5:8:10 | let ... | getNumberOfAttrs: | 0 | hasInitializer: | no | hasLetElse: | no | hasPat: | yes | hasTy: | no | +| gen_let_stmt.rs:9:5:9:24 | let ... = ... | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | no | hasPat: | yes | hasTy: | no | +| gen_let_stmt.rs:10:5:12:6 | let ... = ... else {...} | getNumberOfAttrs: | 0 | hasInitializer: | yes | hasLetElse: | yes | hasPat: | yes | hasTy: | no | diff --git a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.expected b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.expected index 5e79b98f8278..bd8368e351fb 100644 --- a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.expected +++ b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.expected @@ -1,4 +1,4 @@ -| gen_let_stmt.rs:5:5:5:15 | LetStmt | gen_let_stmt.rs:5:13:5:14 | 42 | -| gen_let_stmt.rs:6:5:6:20 | LetStmt | gen_let_stmt.rs:6:18:6:19 | 42 | -| gen_let_stmt.rs:9:5:9:24 | LetStmt | gen_let_stmt.rs:9:18:9:23 | TupleExpr | -| gen_let_stmt.rs:10:5:12:6 | LetStmt | gen_let_stmt.rs:10:19:10:38 | CallExpr | +| gen_let_stmt.rs:5:5:5:15 | let ... = 42 | gen_let_stmt.rs:5:13:5:14 | 42 | +| gen_let_stmt.rs:6:5:6:20 | let ... = 42 | gen_let_stmt.rs:6:18:6:19 | 42 | +| gen_let_stmt.rs:9:5:9:24 | let ... = ... | gen_let_stmt.rs:9:18:9:23 | TupleExpr | +| gen_let_stmt.rs:10:5:12:6 | let ... = ... else {...} | gen_let_stmt.rs:10:19:10:38 | ...::var(...) | diff --git a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getLetElse.expected b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getLetElse.expected index 8078ec669660..5e8090859af5 100644 --- a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getLetElse.expected +++ b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getLetElse.expected @@ -1 +1 @@ -| gen_let_stmt.rs:10:5:12:6 | LetStmt | gen_let_stmt.rs:10:40:12:5 | LetElse | +| gen_let_stmt.rs:10:5:12:6 | let ... = ... else {...} | gen_let_stmt.rs:10:40:12:5 | else {...} | diff --git a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getPat.expected b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getPat.expected index 93810df10e36..758837c946d1 100644 --- a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getPat.expected @@ -1,6 +1,6 @@ -| gen_let_stmt.rs:5:5:5:15 | LetStmt | gen_let_stmt.rs:5:9:5:9 | x | -| gen_let_stmt.rs:6:5:6:20 | LetStmt | gen_let_stmt.rs:6:9:6:9 | x | -| gen_let_stmt.rs:7:5:7:15 | LetStmt | gen_let_stmt.rs:7:9:7:9 | x | -| gen_let_stmt.rs:8:5:8:10 | LetStmt | gen_let_stmt.rs:8:9:8:9 | x | -| gen_let_stmt.rs:9:5:9:24 | LetStmt | gen_let_stmt.rs:9:9:9:14 | TuplePat | -| gen_let_stmt.rs:10:5:12:6 | LetStmt | gen_let_stmt.rs:10:9:10:15 | TupleStructPat | +| gen_let_stmt.rs:5:5:5:15 | let ... = 42 | gen_let_stmt.rs:5:9:5:9 | x | +| gen_let_stmt.rs:6:5:6:20 | let ... = 42 | gen_let_stmt.rs:6:9:6:9 | x | +| gen_let_stmt.rs:7:5:7:15 | let ... | gen_let_stmt.rs:7:9:7:9 | x | +| gen_let_stmt.rs:8:5:8:10 | let ... | gen_let_stmt.rs:8:9:8:9 | x | +| gen_let_stmt.rs:9:5:9:24 | let ... = ... | gen_let_stmt.rs:9:9:9:14 | TuplePat | +| gen_let_stmt.rs:10:5:12:6 | let ... = ... else {...} | gen_let_stmt.rs:10:9:10:15 | TupleStructPat | diff --git a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getTy.expected b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getTy.expected index 1cf6d1d2a513..489647f4793a 100644 --- a/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getTy.expected +++ b/rust/ql/test/extractor-tests/generated/LetStmt/LetStmt_getTy.expected @@ -1,2 +1,2 @@ -| gen_let_stmt.rs:6:5:6:20 | LetStmt | gen_let_stmt.rs:6:12:6:14 | PathType | -| gen_let_stmt.rs:7:5:7:15 | LetStmt | gen_let_stmt.rs:7:12:7:14 | PathType | +| gen_let_stmt.rs:6:5:6:20 | let ... = 42 | gen_let_stmt.rs:6:12:6:14 | i32 | +| gen_let_stmt.rs:7:5:7:15 | let ... | gen_let_stmt.rs:7:12:7:14 | i32 | diff --git a/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat.expected b/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat.expected index b7ac2ced75f8..d4734ef3dac3 100644 --- a/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat.expected +++ b/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat.expected @@ -1 +1 @@ -| gen_literal_pat.rs:6:9:6:10 | LiteralPat | hasLiteral: | yes | +| gen_literal_pat.rs:6:9:6:10 | 42 | hasLiteral: | yes | diff --git a/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat_getLiteral.expected b/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat_getLiteral.expected index ce74da0fb3a5..487f239737bc 100644 --- a/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat_getLiteral.expected +++ b/rust/ql/test/extractor-tests/generated/LiteralPat/LiteralPat_getLiteral.expected @@ -1 +1 @@ -| gen_literal_pat.rs:6:9:6:10 | LiteralPat | gen_literal_pat.rs:6:9:6:10 | 42 | +| gen_literal_pat.rs:6:9:6:10 | 42 | gen_literal_pat.rs:6:9:6:10 | 42 | diff --git a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.expected b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.expected index aae22652d645..b0adbe40897f 100644 --- a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.expected +++ b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.expected @@ -1,3 +1,3 @@ -| gen_loop_expr.rs:5:5:7:5 | LoopExpr | getNumberOfAttrs: | 0 | hasLabel: | no | hasLoopBody: | yes | -| gen_loop_expr.rs:8:5:11:5 | LoopExpr | getNumberOfAttrs: | 0 | hasLabel: | yes | hasLoopBody: | yes | -| gen_loop_expr.rs:13:5:19:5 | LoopExpr | getNumberOfAttrs: | 0 | hasLabel: | no | hasLoopBody: | yes | +| gen_loop_expr.rs:5:5:7:5 | loop { ... } | hasLabel: | no | hasLoopBody: | yes | getNumberOfAttrs: | 0 | +| gen_loop_expr.rs:8:5:11:5 | 'label: loop { ... } | hasLabel: | yes | hasLoopBody: | yes | getNumberOfAttrs: | 0 | +| gen_loop_expr.rs:13:5:19:5 | loop { ... } | hasLabel: | no | hasLoopBody: | yes | getNumberOfAttrs: | 0 | diff --git a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.ql b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.ql index c627fb16771a..92248ab5ec07 100644 --- a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.ql +++ b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr.ql @@ -2,11 +2,11 @@ import codeql.rust.elements import TestUtils -from LoopExpr x, int getNumberOfAttrs, string hasLabel, string hasLoopBody +from LoopExpr x, string hasLabel, string hasLoopBody, int getNumberOfAttrs where toBeTested(x) and not x.isUnknown() and - getNumberOfAttrs = x.getNumberOfAttrs() and (if x.hasLabel() then hasLabel = "yes" else hasLabel = "no") and - if x.hasLoopBody() then hasLoopBody = "yes" else hasLoopBody = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasLabel:", hasLabel, "hasLoopBody:", hasLoopBody + (if x.hasLoopBody() then hasLoopBody = "yes" else hasLoopBody = "no") and + getNumberOfAttrs = x.getNumberOfAttrs() +select x, "hasLabel:", hasLabel, "hasLoopBody:", hasLoopBody, "getNumberOfAttrs:", getNumberOfAttrs diff --git a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.expected b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.expected index 98a657f09832..e2dc2fdf8950 100644 --- a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.expected +++ b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLabel.expected @@ -1 +1 @@ -| gen_loop_expr.rs:8:5:11:5 | LoopExpr | gen_loop_expr.rs:8:5:8:11 | Label | +| gen_loop_expr.rs:8:5:11:5 | 'label: loop { ... } | gen_loop_expr.rs:8:5:8:11 | 'label | diff --git a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.expected b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.expected index 358fd7625b57..9cf0c64dd0b8 100644 --- a/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.expected +++ b/rust/ql/test/extractor-tests/generated/LoopExpr/LoopExpr_getLoopBody.expected @@ -1,3 +1,3 @@ -| gen_loop_expr.rs:5:5:7:5 | LoopExpr | gen_loop_expr.rs:5:10:7:5 | BlockExpr | -| gen_loop_expr.rs:8:5:11:5 | LoopExpr | gen_loop_expr.rs:8:18:11:5 | BlockExpr | -| gen_loop_expr.rs:13:5:19:5 | LoopExpr | gen_loop_expr.rs:13:10:19:5 | BlockExpr | +| gen_loop_expr.rs:5:5:7:5 | loop { ... } | gen_loop_expr.rs:5:10:7:5 | { ... } | +| gen_loop_expr.rs:8:5:11:5 | 'label: loop { ... } | gen_loop_expr.rs:8:18:11:5 | { ... } | +| gen_loop_expr.rs:13:5:19:5 | loop { ... } | gen_loop_expr.rs:13:10:19:5 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall.expected b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall.expected index 03bcc247a9d2..db69c4e068ab 100644 --- a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall.expected +++ b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall.expected @@ -1 +1 @@ -| gen_macro_call.rs:5:5:5:11 | MacroCall | hasExtendedCanonicalPath: | no | hasCrateOrigin: | no | getNumberOfAttrs: | 0 | hasPath: | yes | hasTokenTree: | yes | hasExpanded: | yes | +| gen_macro_call.rs:5:5:5:11 | todo!... | hasExtendedCanonicalPath: | no | hasCrateOrigin: | no | getNumberOfAttrs: | 0 | hasPath: | yes | hasTokenTree: | yes | hasExpanded: | yes | diff --git a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected index 7bdb564985f8..1b60df41f797 100644 --- a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected +++ b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getExpanded.expected @@ -1 +1 @@ -| gen_macro_call.rs:5:5:5:11 | MacroCall | gen_macro_call.rs:5:5:5:11 | MacroStmts | +| gen_macro_call.rs:5:5:5:11 | todo!... | gen_macro_call.rs:5:5:5:11 | MacroStmts | diff --git a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getPath.expected b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getPath.expected index 33685ad0aad9..23762715c9a2 100644 --- a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getPath.expected +++ b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getPath.expected @@ -1 +1 @@ -| gen_macro_call.rs:5:5:5:11 | MacroCall | gen_macro_call.rs:5:5:5:8 | todo | +| gen_macro_call.rs:5:5:5:11 | todo!... | gen_macro_call.rs:5:5:5:8 | todo | diff --git a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getTokenTree.expected b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getTokenTree.expected index 5f92a68536c1..d2ed004ecc43 100644 --- a/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getTokenTree.expected +++ b/rust/ql/test/extractor-tests/generated/MacroCall/MacroCall_getTokenTree.expected @@ -1 +1 @@ -| gen_macro_call.rs:5:5:5:11 | MacroCall | gen_macro_call.rs:5:10:5:11 | TokenTree | +| gen_macro_call.rs:5:5:5:11 | todo!... | gen_macro_call.rs:5:10:5:11 | TokenTree | diff --git a/rust/ql/test/extractor-tests/generated/MacroExpr/MacroExpr_getMacroCall.expected b/rust/ql/test/extractor-tests/generated/MacroExpr/MacroExpr_getMacroCall.expected index 5a635cabcbe1..c1815adac090 100644 --- a/rust/ql/test/extractor-tests/generated/MacroExpr/MacroExpr_getMacroCall.expected +++ b/rust/ql/test/extractor-tests/generated/MacroExpr/MacroExpr_getMacroCall.expected @@ -1 +1 @@ -| gen_macro_expr.rs:5:5:5:11 | MacroExpr | gen_macro_expr.rs:5:5:5:11 | MacroCall | +| gen_macro_expr.rs:5:5:5:11 | MacroExpr | gen_macro_expr.rs:5:5:5:11 | todo!... | diff --git a/rust/ql/test/extractor-tests/generated/MacroItems/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/extractor-tests/generated/MacroItems/CONSISTENCY/DataFlowConsistency.expected index 02210855a69c..28012e97348f 100644 --- a/rust/ql/test/extractor-tests/generated/MacroItems/CONSISTENCY/DataFlowConsistency.expected +++ b/rust/ql/test/extractor-tests/generated/MacroItems/CONSISTENCY/DataFlowConsistency.expected @@ -1,9 +1,11 @@ uniqueNodeLocation | file://:0:0:0:0 | ... .parent(...) | Node should have one location but has 0. | +| file://:0:0:0:0 | ... .parent(...) | Node should have one location but has 0. | | file://:0:0:0:0 | ... .unwrap(...) | Node should have one location but has 0. | -| file://:0:0:0:0 | BlockExpr | Node should have one location but has 0. | -| file://:0:0:0:0 | Param | Node should have one location but has 0. | +| file://:0:0:0:0 | ...: ... | Node should have one location but has 0. | +| file://:0:0:0:0 | path | Node should have one location but has 0. | | file://:0:0:0:0 | path | Node should have one location but has 0. | | file://:0:0:0:0 | path | Node should have one location but has 0. | +| file://:0:0:0:0 | { ... } | Node should have one location but has 0. | missingLocation -| Nodes without location: 6 | +| Nodes without location: 8 | diff --git a/rust/ql/test/extractor-tests/generated/MacroItems/MacroItems_getItem.expected b/rust/ql/test/extractor-tests/generated/MacroItems/MacroItems_getItem.expected index a66e6bcca5ec..5940fb61696a 100644 --- a/rust/ql/test/extractor-tests/generated/MacroItems/MacroItems_getItem.expected +++ b/rust/ql/test/extractor-tests/generated/MacroItems/MacroItems_getItem.expected @@ -1,2 +1,2 @@ | file://:0:0:0:0 | MacroItems | 0 | file://:0:0:0:0 | Use | -| file://:0:0:0:0 | MacroItems | 1 | file://:0:0:0:0 | get_parent | +| file://:0:0:0:0 | MacroItems | 1 | file://:0:0:0:0 | fn get_parent | diff --git a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected b/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected index 7d30926c1528..d1390595304e 100644 --- a/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/MacroStmts/MacroStmts_getExpr.expected @@ -1 +1 @@ -| gen_macro_stmts.rs:5:14:5:28 | MacroStmts | gen_macro_stmts.rs:5:14:5:28 | BlockExpr | +| gen_macro_stmts.rs:5:14:5:28 | MacroStmts | gen_macro_stmts.rs:5:14:5:28 | { ... } | diff --git a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm.expected b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm.expected index b685f8823628..b3eb4c178b26 100644 --- a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm.expected +++ b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm.expected @@ -1,4 +1,4 @@ -| gen_match_arm.rs:6:9:6:29 | MatchArm | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | no | hasPat: | yes | -| gen_match_arm.rs:7:9:7:26 | MatchArm | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | no | hasPat: | yes | -| gen_match_arm.rs:10:9:10:35 | MatchArm | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | yes | hasPat: | yes | -| gen_match_arm.rs:11:9:11:15 | MatchArm | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | no | hasPat: | yes | +| gen_match_arm.rs:6:9:6:29 | ... => y | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | no | hasPat: | yes | +| gen_match_arm.rs:7:9:7:26 | ...::None => 0 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | no | hasPat: | yes | +| gen_match_arm.rs:10:9:10:35 | ... if ... => ... | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | yes | hasPat: | yes | +| gen_match_arm.rs:11:9:11:15 | _ => 0 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasGuard: | no | hasPat: | yes | diff --git a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getExpr.expected b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getExpr.expected index 493ea8d9bb03..95d4a7fc2f22 100644 --- a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getExpr.expected @@ -1,4 +1,4 @@ -| gen_match_arm.rs:6:9:6:29 | MatchArm | gen_match_arm.rs:6:28:6:28 | y | -| gen_match_arm.rs:7:9:7:26 | MatchArm | gen_match_arm.rs:7:25:7:25 | 0 | -| gen_match_arm.rs:10:9:10:35 | MatchArm | gen_match_arm.rs:10:30:10:34 | ... / ... | -| gen_match_arm.rs:11:9:11:15 | MatchArm | gen_match_arm.rs:11:14:11:14 | 0 | +| gen_match_arm.rs:6:9:6:29 | ... => y | gen_match_arm.rs:6:28:6:28 | y | +| gen_match_arm.rs:7:9:7:26 | ...::None => 0 | gen_match_arm.rs:7:25:7:25 | 0 | +| gen_match_arm.rs:10:9:10:35 | ... if ... => ... | gen_match_arm.rs:10:30:10:34 | ... / ... | +| gen_match_arm.rs:11:9:11:15 | _ => 0 | gen_match_arm.rs:11:14:11:14 | 0 | diff --git a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getGuard.expected b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getGuard.expected index 4e5da9874740..002917455476 100644 --- a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getGuard.expected +++ b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getGuard.expected @@ -1 +1 @@ -| gen_match_arm.rs:10:9:10:35 | MatchArm | gen_match_arm.rs:10:17:10:25 | MatchGuard | +| gen_match_arm.rs:10:9:10:35 | ... if ... => ... | gen_match_arm.rs:10:17:10:25 | MatchGuard | diff --git a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getPat.expected b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getPat.expected index 41f79ed16c9e..9928555fc324 100644 --- a/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/MatchArm/MatchArm_getPat.expected @@ -1,4 +1,4 @@ -| gen_match_arm.rs:6:9:6:29 | MatchArm | gen_match_arm.rs:6:9:6:23 | TupleStructPat | -| gen_match_arm.rs:7:9:7:26 | MatchArm | gen_match_arm.rs:7:9:7:20 | PathPat | -| gen_match_arm.rs:10:9:10:35 | MatchArm | gen_match_arm.rs:10:9:10:15 | TupleStructPat | -| gen_match_arm.rs:11:9:11:15 | MatchArm | gen_match_arm.rs:11:9:11:9 | WildcardPat | +| gen_match_arm.rs:6:9:6:29 | ... => y | gen_match_arm.rs:6:9:6:23 | TupleStructPat | +| gen_match_arm.rs:7:9:7:26 | ...::None => 0 | gen_match_arm.rs:7:9:7:20 | ...::None | +| gen_match_arm.rs:10:9:10:35 | ... if ... => ... | gen_match_arm.rs:10:9:10:15 | TupleStructPat | +| gen_match_arm.rs:11:9:11:15 | _ => 0 | gen_match_arm.rs:11:9:11:9 | _ | diff --git a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.expected b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.expected index 4591d8a57c36..8c5b0a32a8fa 100644 --- a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.expected +++ b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.expected @@ -1,2 +1,2 @@ -| gen_match_expr.rs:5:5:8:5 | MatchExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasMatchArmList: | yes | -| gen_match_expr.rs:9:5:12:5 | MatchExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | hasMatchArmList: | yes | +| gen_match_expr.rs:5:5:8:5 | match x { ... } | getNumberOfAttrs: | 0 | hasScrutinee: | yes | hasMatchArmList: | yes | +| gen_match_expr.rs:9:5:12:5 | match x { ... } | getNumberOfAttrs: | 0 | hasScrutinee: | yes | hasMatchArmList: | yes | diff --git a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.ql b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.ql index b29e333d3304..0847933e937c 100644 --- a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.ql +++ b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr.ql @@ -2,12 +2,12 @@ import codeql.rust.elements import TestUtils -from MatchExpr x, int getNumberOfAttrs, string hasExpr, string hasMatchArmList +from MatchExpr x, int getNumberOfAttrs, string hasScrutinee, string hasMatchArmList where toBeTested(x) and not x.isUnknown() and getNumberOfAttrs = x.getNumberOfAttrs() and - (if x.hasExpr() then hasExpr = "yes" else hasExpr = "no") and + (if x.hasScrutinee() then hasScrutinee = "yes" else hasScrutinee = "no") and if x.hasMatchArmList() then hasMatchArmList = "yes" else hasMatchArmList = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr, "hasMatchArmList:", +select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasScrutinee:", hasScrutinee, "hasMatchArmList:", hasMatchArmList diff --git a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.expected index 924eb3f807fa..427af7c6ed0c 100644 --- a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.expected @@ -1,2 +1,2 @@ -| gen_match_expr.rs:5:5:8:5 | MatchExpr | gen_match_expr.rs:5:11:5:11 | x | -| gen_match_expr.rs:9:5:12:5 | MatchExpr | gen_match_expr.rs:9:11:9:11 | x | +| gen_match_expr.rs:5:5:8:5 | match x { ... } | gen_match_expr.rs:5:11:5:11 | x | +| gen_match_expr.rs:9:5:12:5 | match x { ... } | gen_match_expr.rs:9:11:9:11 | x | diff --git a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getMatchArmList.expected b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getMatchArmList.expected index db83ecb1c535..f5e25db5b39d 100644 --- a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getMatchArmList.expected +++ b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getMatchArmList.expected @@ -1,2 +1,2 @@ -| gen_match_expr.rs:5:5:8:5 | MatchExpr | gen_match_expr.rs:5:13:8:5 | MatchArmList | -| gen_match_expr.rs:9:5:12:5 | MatchExpr | gen_match_expr.rs:9:13:12:5 | MatchArmList | +| gen_match_expr.rs:5:5:8:5 | match x { ... } | gen_match_expr.rs:5:13:8:5 | MatchArmList | +| gen_match_expr.rs:9:5:12:5 | match x { ... } | gen_match_expr.rs:9:13:12:5 | MatchArmList | diff --git a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.expected b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.expected new file mode 100644 index 000000000000..427af7c6ed0c --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.expected @@ -0,0 +1,2 @@ +| gen_match_expr.rs:5:5:8:5 | match x { ... } | gen_match_expr.rs:5:11:5:11 | x | +| gen_match_expr.rs:9:5:12:5 | match x { ... } | gen_match_expr.rs:9:11:9:11 | x | diff --git a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.ql b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.ql similarity index 84% rename from rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.ql rename to rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.ql index 40dd65afcbcd..4d29f21fbfba 100644 --- a/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getExpr.ql +++ b/rust/ql/test/extractor-tests/generated/MatchExpr/MatchExpr_getScrutinee.ql @@ -4,4 +4,4 @@ import TestUtils from MatchExpr x where toBeTested(x) and not x.isUnknown() -select x, x.getExpr() +select x, x.getScrutinee() diff --git a/rust/ql/test/extractor-tests/generated/MethodCallExpr/MethodCallExpr_getGenericArgList.expected b/rust/ql/test/extractor-tests/generated/MethodCallExpr/MethodCallExpr_getGenericArgList.expected index 8b2622f09abe..dd1ed8c03041 100644 --- a/rust/ql/test/extractor-tests/generated/MethodCallExpr/MethodCallExpr_getGenericArgList.expected +++ b/rust/ql/test/extractor-tests/generated/MethodCallExpr/MethodCallExpr_getGenericArgList.expected @@ -1 +1 @@ -| gen_method_call_expr.rs:6:5:6:25 | ... .foo(...) | gen_method_call_expr.rs:6:10:6:21 | GenericArgList | +| gen_method_call_expr.rs:6:5:6:25 | ... .foo(...) | gen_method_call_expr.rs:6:10:6:21 | <...> | diff --git a/rust/ql/test/extractor-tests/generated/Module/Module.expected b/rust/ql/test/extractor-tests/generated/Module/Module.expected index d7c04f7c1180..11b6d9e1e9bd 100644 --- a/rust/ql/test/extractor-tests/generated/Module/Module.expected +++ b/rust/ql/test/extractor-tests/generated/Module/Module.expected @@ -1,3 +1,3 @@ -| gen_module.rs:3:1:4:8 | Module | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | getNumberOfAttrs: | 0 | hasItemList: | no | hasName: | yes | hasVisibility: | no | -| gen_module.rs:5:1:7:1 | Module | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | getNumberOfAttrs: | 0 | hasItemList: | yes | hasName: | yes | hasVisibility: | no | -| lib.rs:1:1:1:15 | Module | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | getNumberOfAttrs: | 0 | hasItemList: | no | hasName: | yes | hasVisibility: | no | +| gen_module.rs:3:1:4:8 | mod foo | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | getNumberOfAttrs: | 0 | hasItemList: | no | hasName: | yes | hasVisibility: | no | +| gen_module.rs:5:1:7:1 | mod bar | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | getNumberOfAttrs: | 0 | hasItemList: | yes | hasName: | yes | hasVisibility: | no | +| lib.rs:1:1:1:15 | mod gen_module | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | getNumberOfAttrs: | 0 | hasItemList: | no | hasName: | yes | hasVisibility: | no | diff --git a/rust/ql/test/extractor-tests/generated/Module/Module_getCrateOrigin.expected b/rust/ql/test/extractor-tests/generated/Module/Module_getCrateOrigin.expected index e2e58c030ef7..0164fbb8e29b 100644 --- a/rust/ql/test/extractor-tests/generated/Module/Module_getCrateOrigin.expected +++ b/rust/ql/test/extractor-tests/generated/Module/Module_getCrateOrigin.expected @@ -1,3 +1,3 @@ -| gen_module.rs:3:1:4:8 | Module | repo::test | -| gen_module.rs:5:1:7:1 | Module | repo::test | -| lib.rs:1:1:1:15 | Module | repo::test | +| gen_module.rs:3:1:4:8 | mod foo | repo::test | +| gen_module.rs:5:1:7:1 | mod bar | repo::test | +| lib.rs:1:1:1:15 | mod gen_module | repo::test | diff --git a/rust/ql/test/extractor-tests/generated/Module/Module_getExtendedCanonicalPath.expected b/rust/ql/test/extractor-tests/generated/Module/Module_getExtendedCanonicalPath.expected index 19eadfdafd54..c573ef164ebe 100644 --- a/rust/ql/test/extractor-tests/generated/Module/Module_getExtendedCanonicalPath.expected +++ b/rust/ql/test/extractor-tests/generated/Module/Module_getExtendedCanonicalPath.expected @@ -1,3 +1,3 @@ -| gen_module.rs:3:1:4:8 | Module | crate::gen_module::foo | -| gen_module.rs:5:1:7:1 | Module | crate::gen_module::bar | -| lib.rs:1:1:1:15 | Module | crate::gen_module | +| gen_module.rs:3:1:4:8 | mod foo | crate::gen_module::foo | +| gen_module.rs:5:1:7:1 | mod bar | crate::gen_module::bar | +| lib.rs:1:1:1:15 | mod gen_module | crate::gen_module | diff --git a/rust/ql/test/extractor-tests/generated/Module/Module_getItemList.expected b/rust/ql/test/extractor-tests/generated/Module/Module_getItemList.expected index 04fd8d4a81a0..8edc36efa738 100644 --- a/rust/ql/test/extractor-tests/generated/Module/Module_getItemList.expected +++ b/rust/ql/test/extractor-tests/generated/Module/Module_getItemList.expected @@ -1 +1 @@ -| gen_module.rs:5:1:7:1 | Module | gen_module.rs:5:9:7:1 | ItemList | +| gen_module.rs:5:1:7:1 | mod bar | gen_module.rs:5:9:7:1 | ItemList | diff --git a/rust/ql/test/extractor-tests/generated/Module/Module_getName.expected b/rust/ql/test/extractor-tests/generated/Module/Module_getName.expected index cc295b1da89a..1874862befe5 100644 --- a/rust/ql/test/extractor-tests/generated/Module/Module_getName.expected +++ b/rust/ql/test/extractor-tests/generated/Module/Module_getName.expected @@ -1,3 +1,3 @@ -| gen_module.rs:3:1:4:8 | Module | gen_module.rs:4:5:4:7 | foo | -| gen_module.rs:5:1:7:1 | Module | gen_module.rs:5:5:5:7 | bar | -| lib.rs:1:1:1:15 | Module | lib.rs:1:5:1:14 | gen_module | +| gen_module.rs:3:1:4:8 | mod foo | gen_module.rs:4:5:4:7 | foo | +| gen_module.rs:5:1:7:1 | mod bar | gen_module.rs:5:5:5:7 | bar | +| lib.rs:1:1:1:15 | mod gen_module | lib.rs:1:5:1:14 | gen_module | diff --git a/rust/ql/test/extractor-tests/generated/OffsetOfExpr/OffsetOfExpr_getTy.expected b/rust/ql/test/extractor-tests/generated/OffsetOfExpr/OffsetOfExpr_getTy.expected index c7d0f2ee6afc..e2e11abb6a0f 100644 --- a/rust/ql/test/extractor-tests/generated/OffsetOfExpr/OffsetOfExpr_getTy.expected +++ b/rust/ql/test/extractor-tests/generated/OffsetOfExpr/OffsetOfExpr_getTy.expected @@ -1 +1 @@ -| gen_offset_of_expr.rs:5:5:5:38 | OffsetOfExpr | gen_offset_of_expr.rs:5:25:5:30 | PathType | +| gen_offset_of_expr.rs:5:5:5:38 | OffsetOfExpr | gen_offset_of_expr.rs:5:25:5:30 | Struct | diff --git a/rust/ql/test/extractor-tests/generated/OrPat/OrPat.expected b/rust/ql/test/extractor-tests/generated/OrPat/OrPat.expected index 786a00180935..1d67a8509b91 100644 --- a/rust/ql/test/extractor-tests/generated/OrPat/OrPat.expected +++ b/rust/ql/test/extractor-tests/generated/OrPat/OrPat.expected @@ -1 +1 @@ -| gen_or_pat.rs:6:9:6:38 | OrPat | getNumberOfPats: | 2 | +| gen_or_pat.rs:6:9:6:38 | ... \| ...::None | getNumberOfPats: | 2 | diff --git a/rust/ql/test/extractor-tests/generated/OrPat/OrPat_getPat.expected b/rust/ql/test/extractor-tests/generated/OrPat/OrPat_getPat.expected index a701548b2345..22ebce5dde55 100644 --- a/rust/ql/test/extractor-tests/generated/OrPat/OrPat_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/OrPat/OrPat_getPat.expected @@ -1,2 +1,2 @@ -| gen_or_pat.rs:6:9:6:38 | OrPat | 0 | gen_or_pat.rs:6:9:6:23 | TupleStructPat | -| gen_or_pat.rs:6:9:6:38 | OrPat | 1 | gen_or_pat.rs:6:27:6:38 | PathPat | +| gen_or_pat.rs:6:9:6:38 | ... \| ...::None | 0 | gen_or_pat.rs:6:9:6:23 | TupleStructPat | +| gen_or_pat.rs:6:9:6:38 | ... \| ...::None | 1 | gen_or_pat.rs:6:27:6:38 | ...::None | diff --git a/rust/ql/test/extractor-tests/generated/Param/Param.expected b/rust/ql/test/extractor-tests/generated/Param/Param.expected index e69de29bb2d1..e0f54f135831 100644 --- a/rust/ql/test/extractor-tests/generated/Param/Param.expected +++ b/rust/ql/test/extractor-tests/generated/Param/Param.expected @@ -0,0 +1 @@ +| gen_param.rs:5:12:5:15 | ...: T | getNumberOfAttrs: | 0 | hasTy: | yes | hasPat: | yes | diff --git a/rust/ql/test/extractor-tests/generated/Param/Param.ql b/rust/ql/test/extractor-tests/generated/Param/Param.ql index 6e022c29db92..1e744bae58b6 100644 --- a/rust/ql/test/extractor-tests/generated/Param/Param.ql +++ b/rust/ql/test/extractor-tests/generated/Param/Param.ql @@ -2,11 +2,11 @@ import codeql.rust.elements import TestUtils -from Param x, int getNumberOfAttrs, string hasPat, string hasTy +from Param x, int getNumberOfAttrs, string hasTy, string hasPat where toBeTested(x) and not x.isUnknown() and getNumberOfAttrs = x.getNumberOfAttrs() and - (if x.hasPat() then hasPat = "yes" else hasPat = "no") and - if x.hasTy() then hasTy = "yes" else hasTy = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasPat:", hasPat, "hasTy:", hasTy + (if x.hasTy() then hasTy = "yes" else hasTy = "no") and + if x.hasPat() then hasPat = "yes" else hasPat = "no" +select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasTy:", hasTy, "hasPat:", hasPat diff --git a/rust/ql/test/extractor-tests/generated/Param/Param_getPat.expected b/rust/ql/test/extractor-tests/generated/Param/Param_getPat.expected index e69de29bb2d1..c42d7ce0b9f2 100644 --- a/rust/ql/test/extractor-tests/generated/Param/Param_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/Param/Param_getPat.expected @@ -0,0 +1 @@ +| gen_param.rs:5:12:5:15 | ...: T | gen_param.rs:5:12:5:12 | x | diff --git a/rust/ql/test/extractor-tests/generated/Param/Param_getTy.expected b/rust/ql/test/extractor-tests/generated/Param/Param_getTy.expected index e69de29bb2d1..10bf906af5da 100644 --- a/rust/ql/test/extractor-tests/generated/Param/Param_getTy.expected +++ b/rust/ql/test/extractor-tests/generated/Param/Param_getTy.expected @@ -0,0 +1 @@ +| gen_param.rs:5:12:5:15 | ...: T | gen_param.rs:5:15:5:15 | T | diff --git a/rust/ql/test/extractor-tests/generated/Param/gen_param.rs b/rust/ql/test/extractor-tests/generated/Param/gen_param.rs index 5bc96d632198..679943f8aa7f 100644 --- a/rust/ql/test/extractor-tests/generated/Param/gen_param.rs +++ b/rust/ql/test/extractor-tests/generated/Param/gen_param.rs @@ -1,6 +1,8 @@ // generated by codegen, do not edit fn test_param() -> () { - // A Param. For example: - todo!() + // A parameter in a function or method. For example `x` in: + fn new(x: T) -> Foo { + // ... + } } diff --git a/rust/ql/test/extractor-tests/generated/Path/Path.expected b/rust/ql/test/extractor-tests/generated/Path/Path.expected index db093224b76b..dfc303c3293c 100644 --- a/rust/ql/test/extractor-tests/generated/Path/Path.expected +++ b/rust/ql/test/extractor-tests/generated/Path/Path.expected @@ -1,2 +1,26 @@ -| gen_path.rs:5:5:5:7 | foo | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | -| gen_path.rs:5:5:5:12 | foo::bar | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path.rs:5:9:5:18 | some_crate | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path.rs:5:9:5:31 | ...::some_module | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path.rs:5:9:5:42 | ...::some_item | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path.rs:6:5:6:7 | foo | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path.rs:6:5:6:12 | ...::bar | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path_expr.rs:5:13:5:20 | variable | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:6:13:6:15 | foo | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:6:13:6:20 | ...::bar | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path_expr.rs:7:13:7:15 | <...> | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:7:13:7:20 | ...::foo | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path_expr.rs:7:14:7:14 | T | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:7:14:7:14 | T | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:8:13:8:30 | <...> | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:8:13:8:35 | ...::foo | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path_expr.rs:8:14:8:20 | TypeRef | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_expr.rs:8:14:8:20 | TypeRef | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_pat.rs:5:11:5:11 | x | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_pat.rs:6:9:6:11 | Foo | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_pat.rs:6:9:6:16 | ...::Bar | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | +| gen_path_type.rs:5:14:5:16 | std | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_type.rs:5:14:5:29 | ...::collections | hasResolvedPath: | yes | hasResolvedCrateOrigin: | yes | hasQualifier: | yes | hasPart: | yes | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | hasResolvedPath: | yes | hasResolvedCrateOrigin: | yes | hasQualifier: | yes | hasPart: | yes | +| gen_path_type.rs:5:40:5:42 | i32 | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_type.rs:5:45:5:47 | i32 | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_type.rs:6:14:6:14 | X | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | no | hasPart: | yes | +| gen_path_type.rs:6:14:6:20 | ...::Item | hasResolvedPath: | no | hasResolvedCrateOrigin: | no | hasQualifier: | yes | hasPart: | yes | diff --git a/rust/ql/test/extractor-tests/generated/Path/PathExpr.expected b/rust/ql/test/extractor-tests/generated/Path/PathExpr.expected new file mode 100644 index 000000000000..4f6def5dd438 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathExpr.expected @@ -0,0 +1,6 @@ +| gen_path.rs:6:5:6:12 | ...::bar | getNumberOfAttrs: | 0 | hasPath: | yes | +| gen_path_expr.rs:5:13:5:20 | variable | getNumberOfAttrs: | 0 | hasPath: | yes | +| gen_path_expr.rs:6:13:6:20 | ...::bar | getNumberOfAttrs: | 0 | hasPath: | yes | +| gen_path_expr.rs:7:13:7:20 | ...::foo | getNumberOfAttrs: | 0 | hasPath: | yes | +| gen_path_expr.rs:8:13:8:35 | ...::foo | getNumberOfAttrs: | 0 | hasPath: | yes | +| gen_path_pat.rs:5:11:5:11 | x | getNumberOfAttrs: | 0 | hasPath: | yes | diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr.ql b/rust/ql/test/extractor-tests/generated/Path/PathExpr.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathExpr/PathExpr.ql rename to rust/ql/test/extractor-tests/generated/Path/PathExpr.ql diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getAttr.expected b/rust/ql/test/extractor-tests/generated/Path/PathExpr_getAttr.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getAttr.expected rename to rust/ql/test/extractor-tests/generated/Path/PathExpr_getAttr.expected diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getAttr.ql b/rust/ql/test/extractor-tests/generated/Path/PathExpr_getAttr.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getAttr.ql rename to rust/ql/test/extractor-tests/generated/Path/PathExpr_getAttr.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathExpr_getPath.expected b/rust/ql/test/extractor-tests/generated/Path/PathExpr_getPath.expected new file mode 100644 index 000000000000..31b98a6a8ecf --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathExpr_getPath.expected @@ -0,0 +1,6 @@ +| gen_path.rs:6:5:6:12 | ...::bar | gen_path.rs:6:5:6:12 | ...::bar | +| gen_path_expr.rs:5:13:5:20 | variable | gen_path_expr.rs:5:13:5:20 | variable | +| gen_path_expr.rs:6:13:6:20 | ...::bar | gen_path_expr.rs:6:13:6:20 | ...::bar | +| gen_path_expr.rs:7:13:7:20 | ...::foo | gen_path_expr.rs:7:13:7:20 | ...::foo | +| gen_path_expr.rs:8:13:8:35 | ...::foo | gen_path_expr.rs:8:13:8:35 | ...::foo | +| gen_path_pat.rs:5:11:5:11 | x | gen_path_pat.rs:5:11:5:11 | x | diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getPath.ql b/rust/ql/test/extractor-tests/generated/Path/PathExpr_getPath.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getPath.ql rename to rust/ql/test/extractor-tests/generated/Path/PathExpr_getPath.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathPat.expected b/rust/ql/test/extractor-tests/generated/Path/PathPat.expected new file mode 100644 index 000000000000..159f006eecb1 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathPat.expected @@ -0,0 +1 @@ +| gen_path_pat.rs:6:9:6:16 | ...::Bar | hasPath: | yes | diff --git a/rust/ql/test/extractor-tests/generated/PathPat/PathPat.ql b/rust/ql/test/extractor-tests/generated/Path/PathPat.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathPat/PathPat.ql rename to rust/ql/test/extractor-tests/generated/Path/PathPat.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathPat_getPath.expected b/rust/ql/test/extractor-tests/generated/Path/PathPat_getPath.expected new file mode 100644 index 000000000000..3a601023f3f9 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathPat_getPath.expected @@ -0,0 +1 @@ +| gen_path_pat.rs:6:9:6:16 | ...::Bar | gen_path_pat.rs:6:9:6:16 | ...::Bar | diff --git a/rust/ql/test/extractor-tests/generated/PathPat/PathPat_getPath.ql b/rust/ql/test/extractor-tests/generated/Path/PathPat_getPath.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathPat/PathPat_getPath.ql rename to rust/ql/test/extractor-tests/generated/Path/PathPat_getPath.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathSegment.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment.expected new file mode 100644 index 000000000000..8278d7685dc3 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathSegment.expected @@ -0,0 +1,26 @@ +| gen_path.rs:5:9:5:18 | some_crate | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path.rs:5:21:5:31 | some_module | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path.rs:5:34:5:42 | some_item | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path.rs:6:5:6:7 | foo | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path.rs:6:10:6:12 | bar | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:5:13:5:20 | variable | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:6:13:6:15 | foo | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:6:18:6:20 | bar | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:7:13:7:15 | <...> | hasGenericArgList: | no | hasNameRef: | no | hasParamList: | no | hasPathType: | yes | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | yes | +| gen_path_expr.rs:7:14:7:14 | T | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:7:14:7:14 | T | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:7:18:7:20 | foo | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:8:13:8:30 | <...> | hasGenericArgList: | no | hasNameRef: | no | hasParamList: | no | hasPathType: | yes | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | yes | +| gen_path_expr.rs:8:14:8:20 | TypeRef | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:8:14:8:20 | TypeRef | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_expr.rs:8:33:8:35 | foo | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_pat.rs:5:11:5:11 | x | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_pat.rs:6:9:6:11 | Foo | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_pat.rs:6:14:6:16 | Bar | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:5:14:5:16 | std | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:5:19:5:29 | collections | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:5:32:5:48 | HashMap::<...> | hasGenericArgList: | yes | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:5:40:5:42 | i32 | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:5:45:5:47 | i32 | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:6:14:6:14 | X | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | +| gen_path_type.rs:6:17:6:20 | Item | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathSegment_getGenericArgList.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getGenericArgList.expected new file mode 100644 index 000000000000..7487eb65c84c --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getGenericArgList.expected @@ -0,0 +1 @@ +| gen_path_type.rs:5:32:5:48 | HashMap::<...> | gen_path_type.rs:5:39:5:48 | <...> | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getGenericArgList.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getGenericArgList.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getGenericArgList.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getGenericArgList.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathSegment_getNameRef.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getNameRef.expected new file mode 100644 index 000000000000..8778f6b4aefd --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getNameRef.expected @@ -0,0 +1,24 @@ +| gen_path.rs:5:9:5:18 | some_crate | gen_path.rs:5:9:5:18 | some_crate | +| gen_path.rs:5:21:5:31 | some_module | gen_path.rs:5:21:5:31 | some_module | +| gen_path.rs:5:34:5:42 | some_item | gen_path.rs:5:34:5:42 | some_item | +| gen_path.rs:6:5:6:7 | foo | gen_path.rs:6:5:6:7 | foo | +| gen_path.rs:6:10:6:12 | bar | gen_path.rs:6:10:6:12 | bar | +| gen_path_expr.rs:5:13:5:20 | variable | gen_path_expr.rs:5:13:5:20 | variable | +| gen_path_expr.rs:6:13:6:15 | foo | gen_path_expr.rs:6:13:6:15 | foo | +| gen_path_expr.rs:6:18:6:20 | bar | gen_path_expr.rs:6:18:6:20 | bar | +| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:7:18:7:20 | foo | gen_path_expr.rs:7:18:7:20 | foo | +| gen_path_expr.rs:8:14:8:20 | TypeRef | gen_path_expr.rs:8:14:8:20 | TypeRef | +| gen_path_expr.rs:8:14:8:20 | TypeRef | gen_path_expr.rs:8:14:8:20 | TypeRef | +| gen_path_expr.rs:8:33:8:35 | foo | gen_path_expr.rs:8:33:8:35 | foo | +| gen_path_pat.rs:5:11:5:11 | x | gen_path_pat.rs:5:11:5:11 | x | +| gen_path_pat.rs:6:9:6:11 | Foo | gen_path_pat.rs:6:9:6:11 | Foo | +| gen_path_pat.rs:6:14:6:16 | Bar | gen_path_pat.rs:6:14:6:16 | Bar | +| gen_path_type.rs:5:14:5:16 | std | gen_path_type.rs:5:14:5:16 | std | +| gen_path_type.rs:5:19:5:29 | collections | gen_path_type.rs:5:19:5:29 | collections | +| gen_path_type.rs:5:32:5:48 | HashMap::<...> | gen_path_type.rs:5:32:5:38 | HashMap | +| gen_path_type.rs:5:40:5:42 | i32 | gen_path_type.rs:5:40:5:42 | i32 | +| gen_path_type.rs:5:45:5:47 | i32 | gen_path_type.rs:5:45:5:47 | i32 | +| gen_path_type.rs:6:14:6:14 | X | gen_path_type.rs:6:14:6:14 | X | +| gen_path_type.rs:6:17:6:20 | Item | gen_path_type.rs:6:17:6:20 | Item | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getNameRef.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getNameRef.ql diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getParamList.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getParamList.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getParamList.expected rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getParamList.expected diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getParamList.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getParamList.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getParamList.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getParamList.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathSegment_getPathType.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getPathType.expected new file mode 100644 index 000000000000..db25db90b83e --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getPathType.expected @@ -0,0 +1,2 @@ +| gen_path_expr.rs:7:13:7:15 | <...> | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:8:13:8:30 | <...> | gen_path_expr.rs:8:14:8:20 | TypeRef | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getPathType.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getPathType.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getPathType.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getPathType.ql diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getRetType.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getRetType.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getRetType.expected rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getRetType.expected diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getRetType.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getRetType.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getRetType.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getRetType.ql diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getReturnTypeSyntax.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getReturnTypeSyntax.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getReturnTypeSyntax.expected rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getReturnTypeSyntax.expected diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getReturnTypeSyntax.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getReturnTypeSyntax.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getReturnTypeSyntax.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getReturnTypeSyntax.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathSegment_getTy.expected b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getTy.expected new file mode 100644 index 000000000000..db25db90b83e --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getTy.expected @@ -0,0 +1,2 @@ +| gen_path_expr.rs:7:13:7:15 | <...> | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:8:13:8:30 | <...> | gen_path_expr.rs:8:14:8:20 | TypeRef | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getTy.ql b/rust/ql/test/extractor-tests/generated/Path/PathSegment_getTy.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getTy.ql rename to rust/ql/test/extractor-tests/generated/Path/PathSegment_getTy.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathType.expected b/rust/ql/test/extractor-tests/generated/Path/PathType.expected new file mode 100644 index 000000000000..7d876dc4fa8d --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathType.expected @@ -0,0 +1,8 @@ +| gen_path_expr.rs:7:14:7:14 | T | hasPath: | yes | +| gen_path_expr.rs:7:14:7:14 | T | hasPath: | yes | +| gen_path_expr.rs:8:14:8:20 | TypeRef | hasPath: | yes | +| gen_path_expr.rs:8:14:8:20 | TypeRef | hasPath: | yes | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | hasPath: | yes | +| gen_path_type.rs:5:40:5:42 | i32 | hasPath: | yes | +| gen_path_type.rs:5:45:5:47 | i32 | hasPath: | yes | +| gen_path_type.rs:6:14:6:20 | ...::Item | hasPath: | yes | diff --git a/rust/ql/test/extractor-tests/generated/PathType/PathType.ql b/rust/ql/test/extractor-tests/generated/Path/PathType.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathType/PathType.ql rename to rust/ql/test/extractor-tests/generated/Path/PathType.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/PathType_getPath.expected b/rust/ql/test/extractor-tests/generated/Path/PathType_getPath.expected new file mode 100644 index 000000000000..879ed298b93f --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/PathType_getPath.expected @@ -0,0 +1,8 @@ +| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:8:14:8:20 | TypeRef | gen_path_expr.rs:8:14:8:20 | TypeRef | +| gen_path_expr.rs:8:14:8:20 | TypeRef | gen_path_expr.rs:8:14:8:20 | TypeRef | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | +| gen_path_type.rs:5:40:5:42 | i32 | gen_path_type.rs:5:40:5:42 | i32 | +| gen_path_type.rs:5:45:5:47 | i32 | gen_path_type.rs:5:45:5:47 | i32 | +| gen_path_type.rs:6:14:6:20 | ...::Item | gen_path_type.rs:6:14:6:20 | ...::Item | diff --git a/rust/ql/test/extractor-tests/generated/PathType/PathType_getPath.ql b/rust/ql/test/extractor-tests/generated/Path/PathType_getPath.ql similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathType/PathType_getPath.ql rename to rust/ql/test/extractor-tests/generated/Path/PathType_getPath.ql diff --git a/rust/ql/test/extractor-tests/generated/Path/Path_getPart.expected b/rust/ql/test/extractor-tests/generated/Path/Path_getPart.expected index 0e05956ea897..99ed98b3f521 100644 --- a/rust/ql/test/extractor-tests/generated/Path/Path_getPart.expected +++ b/rust/ql/test/extractor-tests/generated/Path/Path_getPart.expected @@ -1,2 +1,26 @@ -| gen_path.rs:5:5:5:7 | foo | gen_path.rs:5:5:5:7 | foo | -| gen_path.rs:5:5:5:12 | foo::bar | gen_path.rs:5:10:5:12 | bar | +| gen_path.rs:5:9:5:18 | some_crate | gen_path.rs:5:9:5:18 | some_crate | +| gen_path.rs:5:9:5:31 | ...::some_module | gen_path.rs:5:21:5:31 | some_module | +| gen_path.rs:5:9:5:42 | ...::some_item | gen_path.rs:5:34:5:42 | some_item | +| gen_path.rs:6:5:6:7 | foo | gen_path.rs:6:5:6:7 | foo | +| gen_path.rs:6:5:6:12 | ...::bar | gen_path.rs:6:10:6:12 | bar | +| gen_path_expr.rs:5:13:5:20 | variable | gen_path_expr.rs:5:13:5:20 | variable | +| gen_path_expr.rs:6:13:6:15 | foo | gen_path_expr.rs:6:13:6:15 | foo | +| gen_path_expr.rs:6:13:6:20 | ...::bar | gen_path_expr.rs:6:18:6:20 | bar | +| gen_path_expr.rs:7:13:7:15 | <...> | gen_path_expr.rs:7:13:7:15 | <...> | +| gen_path_expr.rs:7:13:7:20 | ...::foo | gen_path_expr.rs:7:18:7:20 | foo | +| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:7:14:7:14 | T | gen_path_expr.rs:7:14:7:14 | T | +| gen_path_expr.rs:8:13:8:30 | <...> | gen_path_expr.rs:8:13:8:30 | <...> | +| gen_path_expr.rs:8:13:8:35 | ...::foo | gen_path_expr.rs:8:33:8:35 | foo | +| gen_path_expr.rs:8:14:8:20 | TypeRef | gen_path_expr.rs:8:14:8:20 | TypeRef | +| gen_path_expr.rs:8:14:8:20 | TypeRef | gen_path_expr.rs:8:14:8:20 | TypeRef | +| gen_path_pat.rs:5:11:5:11 | x | gen_path_pat.rs:5:11:5:11 | x | +| gen_path_pat.rs:6:9:6:11 | Foo | gen_path_pat.rs:6:9:6:11 | Foo | +| gen_path_pat.rs:6:9:6:16 | ...::Bar | gen_path_pat.rs:6:14:6:16 | Bar | +| gen_path_type.rs:5:14:5:16 | std | gen_path_type.rs:5:14:5:16 | std | +| gen_path_type.rs:5:14:5:29 | ...::collections | gen_path_type.rs:5:19:5:29 | collections | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | gen_path_type.rs:5:32:5:48 | HashMap::<...> | +| gen_path_type.rs:5:40:5:42 | i32 | gen_path_type.rs:5:40:5:42 | i32 | +| gen_path_type.rs:5:45:5:47 | i32 | gen_path_type.rs:5:45:5:47 | i32 | +| gen_path_type.rs:6:14:6:14 | X | gen_path_type.rs:6:14:6:14 | X | +| gen_path_type.rs:6:14:6:20 | ...::Item | gen_path_type.rs:6:17:6:20 | Item | diff --git a/rust/ql/test/extractor-tests/generated/Path/Path_getQualifier.expected b/rust/ql/test/extractor-tests/generated/Path/Path_getQualifier.expected index 44aa2ca5a006..162efd4b1870 100644 --- a/rust/ql/test/extractor-tests/generated/Path/Path_getQualifier.expected +++ b/rust/ql/test/extractor-tests/generated/Path/Path_getQualifier.expected @@ -1 +1,10 @@ -| gen_path.rs:5:5:5:12 | foo::bar | gen_path.rs:5:5:5:7 | foo | +| gen_path.rs:5:9:5:31 | ...::some_module | gen_path.rs:5:9:5:18 | some_crate | +| gen_path.rs:5:9:5:42 | ...::some_item | gen_path.rs:5:9:5:31 | ...::some_module | +| gen_path.rs:6:5:6:12 | ...::bar | gen_path.rs:6:5:6:7 | foo | +| gen_path_expr.rs:6:13:6:20 | ...::bar | gen_path_expr.rs:6:13:6:15 | foo | +| gen_path_expr.rs:7:13:7:20 | ...::foo | gen_path_expr.rs:7:13:7:15 | <...> | +| gen_path_expr.rs:8:13:8:35 | ...::foo | gen_path_expr.rs:8:13:8:30 | <...> | +| gen_path_pat.rs:6:9:6:16 | ...::Bar | gen_path_pat.rs:6:9:6:11 | Foo | +| gen_path_type.rs:5:14:5:29 | ...::collections | gen_path_type.rs:5:14:5:16 | std | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | gen_path_type.rs:5:14:5:29 | ...::collections | +| gen_path_type.rs:6:14:6:20 | ...::Item | gen_path_type.rs:6:14:6:14 | X | diff --git a/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedCrateOrigin.expected b/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedCrateOrigin.expected index e69de29bb2d1..df80e22f7446 100644 --- a/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedCrateOrigin.expected +++ b/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedCrateOrigin.expected @@ -0,0 +1,2 @@ +| gen_path_type.rs:5:14:5:29 | ...::collections | lang:std | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | lang:std | diff --git a/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedPath.expected b/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedPath.expected index e69de29bb2d1..7d1c698b0ce5 100644 --- a/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedPath.expected +++ b/rust/ql/test/extractor-tests/generated/Path/Path_getResolvedPath.expected @@ -0,0 +1,2 @@ +| gen_path_type.rs:5:14:5:29 | ...::collections | crate::collections | +| gen_path_type.rs:5:14:5:48 | ...::HashMap::<...> | crate::collections::hash::map::HashMap | diff --git a/rust/ql/test/extractor-tests/generated/Path/gen_path.rs b/rust/ql/test/extractor-tests/generated/Path/gen_path.rs index 3b3f054875a9..de58e6978afe 100644 --- a/rust/ql/test/extractor-tests/generated/Path/gen_path.rs +++ b/rust/ql/test/extractor-tests/generated/Path/gen_path.rs @@ -2,5 +2,6 @@ fn test_path() -> () { // A path. For example: + use some_crate::some_module::some_item; foo::bar; } diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/gen_path_expr.rs b/rust/ql/test/extractor-tests/generated/Path/gen_path_expr.rs similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathExpr/gen_path_expr.rs rename to rust/ql/test/extractor-tests/generated/Path/gen_path_expr.rs diff --git a/rust/ql/test/extractor-tests/generated/PathPat/gen_path_pat.rs b/rust/ql/test/extractor-tests/generated/Path/gen_path_pat.rs similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathPat/gen_path_pat.rs rename to rust/ql/test/extractor-tests/generated/Path/gen_path_pat.rs diff --git a/rust/ql/test/extractor-tests/generated/Path/gen_path_type.rs b/rust/ql/test/extractor-tests/generated/Path/gen_path_type.rs new file mode 100644 index 000000000000..62797d756779 --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Path/gen_path_type.rs @@ -0,0 +1,7 @@ +// generated by codegen, do not edit + +fn test_path_type() -> () { + // A type referring to a path. For example: + type X = std::collections::HashMap; + type Y = X::Item; +} diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/extractor-tests/generated/PathExpr/CONSISTENCY/DataFlowConsistency.expected deleted file mode 100644 index c54360f7361b..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathExpr/CONSISTENCY/DataFlowConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -uniqueNodeToString -| gen_path_expr.rs:7:13:7:20 | (no string representation) | Node should have one toString but has 0. | -| gen_path_expr.rs:8:13:8:35 | (no string representation) | Node should have one toString but has 0. | diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr.expected b/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr.expected deleted file mode 100644 index a676396a2f9b..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr.expected +++ /dev/null @@ -1,4 +0,0 @@ -| gen_path_expr.rs:5:13:5:20 | variable | getNumberOfAttrs: | 0 | hasPath: | yes | -| gen_path_expr.rs:6:13:6:20 | foo::bar | getNumberOfAttrs: | 0 | hasPath: | yes | -| gen_path_expr.rs:7:13:7:20 | (no string representation) | getNumberOfAttrs: | 0 | hasPath: | yes | -| gen_path_expr.rs:8:13:8:35 | (no string representation) | getNumberOfAttrs: | 0 | hasPath: | yes | diff --git a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getPath.expected b/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getPath.expected deleted file mode 100644 index a5765b5be60b..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathExpr/PathExpr_getPath.expected +++ /dev/null @@ -1,4 +0,0 @@ -| gen_path_expr.rs:5:13:5:20 | variable | gen_path_expr.rs:5:13:5:20 | variable | -| gen_path_expr.rs:6:13:6:20 | foo::bar | gen_path_expr.rs:6:13:6:20 | foo::bar | -| gen_path_expr.rs:7:13:7:20 | (no string representation) | gen_path_expr.rs:7:13:7:20 | (no string representation) | -| gen_path_expr.rs:8:13:8:35 | (no string representation) | gen_path_expr.rs:8:13:8:35 | (no string representation) | diff --git a/rust/ql/test/extractor-tests/generated/PathPat/PathPat.expected b/rust/ql/test/extractor-tests/generated/PathPat/PathPat.expected deleted file mode 100644 index 54845a7565c4..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathPat/PathPat.expected +++ /dev/null @@ -1 +0,0 @@ -| gen_path_pat.rs:6:9:6:16 | PathPat | hasPath: | yes | diff --git a/rust/ql/test/extractor-tests/generated/PathPat/PathPat_getPath.expected b/rust/ql/test/extractor-tests/generated/PathPat/PathPat_getPath.expected deleted file mode 100644 index d48ba6549dba..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathPat/PathPat_getPath.expected +++ /dev/null @@ -1 +0,0 @@ -| gen_path_pat.rs:6:9:6:16 | PathPat | gen_path_pat.rs:6:9:6:16 | Foo::Bar | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment.expected b/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment.expected deleted file mode 100644 index 32042fc6a59d..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment.expected +++ /dev/null @@ -1,4 +0,0 @@ -| gen_path_segment.rs:5:5:5:8 | todo | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | -| gen_path_segment.rs:5:5:5:11 | $crate | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | -| gen_path_segment.rs:5:5:5:11 | panic | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | -| gen_path_segment.rs:5:5:5:11 | panicking | hasGenericArgList: | no | hasNameRef: | yes | hasParamList: | no | hasPathType: | no | hasRetType: | no | hasReturnTypeSyntax: | no | hasTy: | no | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.expected b/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.expected deleted file mode 100644 index 28346240d296..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getNameRef.expected +++ /dev/null @@ -1,4 +0,0 @@ -| gen_path_segment.rs:5:5:5:8 | todo | gen_path_segment.rs:5:5:5:8 | todo | -| gen_path_segment.rs:5:5:5:11 | $crate | gen_path_segment.rs:5:5:5:11 | $crate | -| gen_path_segment.rs:5:5:5:11 | panic | gen_path_segment.rs:5:5:5:11 | panic | -| gen_path_segment.rs:5:5:5:11 | panicking | gen_path_segment.rs:5:5:5:11 | panicking | diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getPathType.expected b/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getPathType.expected deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getTy.expected b/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getTy.expected deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/gen_path_segment.rs b/rust/ql/test/extractor-tests/generated/PathSegment/gen_path_segment.rs deleted file mode 100644 index 0ab008b6a685..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathSegment/gen_path_segment.rs +++ /dev/null @@ -1,6 +0,0 @@ -// generated by codegen, do not edit - -fn test_path_segment() -> () { - // A PathSegment. For example: - todo!() -} diff --git a/rust/ql/test/extractor-tests/generated/PathType/PathType.expected b/rust/ql/test/extractor-tests/generated/PathType/PathType.expected deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/rust/ql/test/extractor-tests/generated/PathType/PathType_getPath.expected b/rust/ql/test/extractor-tests/generated/PathType/PathType_getPath.expected deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/rust/ql/test/extractor-tests/generated/PathType/gen_path_type.rs b/rust/ql/test/extractor-tests/generated/PathType/gen_path_type.rs deleted file mode 100644 index e7666e2128a6..000000000000 --- a/rust/ql/test/extractor-tests/generated/PathType/gen_path_type.rs +++ /dev/null @@ -1,6 +0,0 @@ -// generated by codegen, do not edit - -fn test_path_type() -> () { - // A PathType. For example: - todo!() -} diff --git a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr.expected b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr.expected index 6f222c18f03b..7d8aeff6dfa9 100644 --- a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr.expected +++ b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr.expected @@ -1,6 +1,6 @@ -| gen_range_expr.rs:5:13:5:18 | RangeExpr | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | yes | -| gen_range_expr.rs:6:13:6:17 | RangeExpr | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | yes | -| gen_range_expr.rs:7:13:7:16 | RangeExpr | getNumberOfAttrs: | 0 | hasEnd: | no | hasOperatorName: | yes | hasStart: | yes | -| gen_range_expr.rs:8:13:8:16 | RangeExpr | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | no | -| gen_range_expr.rs:9:13:9:17 | RangeExpr | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | no | -| gen_range_expr.rs:10:13:10:14 | RangeExpr | getNumberOfAttrs: | 0 | hasEnd: | no | hasOperatorName: | yes | hasStart: | no | +| gen_range_expr.rs:5:13:5:18 | 1..=10 | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | yes | +| gen_range_expr.rs:6:13:6:17 | 1..10 | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | yes | +| gen_range_expr.rs:7:13:7:16 | 10.. | getNumberOfAttrs: | 0 | hasEnd: | no | hasOperatorName: | yes | hasStart: | yes | +| gen_range_expr.rs:8:13:8:16 | ..10 | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | no | +| gen_range_expr.rs:9:13:9:17 | ..=10 | getNumberOfAttrs: | 0 | hasEnd: | yes | hasOperatorName: | yes | hasStart: | no | +| gen_range_expr.rs:10:13:10:14 | .. | getNumberOfAttrs: | 0 | hasEnd: | no | hasOperatorName: | yes | hasStart: | no | diff --git a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getEnd.expected b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getEnd.expected index 101ae46138a4..46f5dba778c5 100644 --- a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getEnd.expected +++ b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getEnd.expected @@ -1,4 +1,4 @@ -| gen_range_expr.rs:5:13:5:18 | RangeExpr | gen_range_expr.rs:5:17:5:18 | 10 | -| gen_range_expr.rs:6:13:6:17 | RangeExpr | gen_range_expr.rs:6:16:6:17 | 10 | -| gen_range_expr.rs:8:13:8:16 | RangeExpr | gen_range_expr.rs:8:15:8:16 | 10 | -| gen_range_expr.rs:9:13:9:17 | RangeExpr | gen_range_expr.rs:9:16:9:17 | 10 | +| gen_range_expr.rs:5:13:5:18 | 1..=10 | gen_range_expr.rs:5:17:5:18 | 10 | +| gen_range_expr.rs:6:13:6:17 | 1..10 | gen_range_expr.rs:6:16:6:17 | 10 | +| gen_range_expr.rs:8:13:8:16 | ..10 | gen_range_expr.rs:8:15:8:16 | 10 | +| gen_range_expr.rs:9:13:9:17 | ..=10 | gen_range_expr.rs:9:16:9:17 | 10 | diff --git a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getOperatorName.expected b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getOperatorName.expected index b0d778eb7bb2..ee9172ac1ced 100644 --- a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getOperatorName.expected +++ b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getOperatorName.expected @@ -1,6 +1,6 @@ -| gen_range_expr.rs:5:13:5:18 | RangeExpr | ..= | -| gen_range_expr.rs:6:13:6:17 | RangeExpr | .. | -| gen_range_expr.rs:7:13:7:16 | RangeExpr | .. | -| gen_range_expr.rs:8:13:8:16 | RangeExpr | .. | -| gen_range_expr.rs:9:13:9:17 | RangeExpr | ..= | -| gen_range_expr.rs:10:13:10:14 | RangeExpr | .. | +| gen_range_expr.rs:5:13:5:18 | 1..=10 | ..= | +| gen_range_expr.rs:6:13:6:17 | 1..10 | .. | +| gen_range_expr.rs:7:13:7:16 | 10.. | .. | +| gen_range_expr.rs:8:13:8:16 | ..10 | .. | +| gen_range_expr.rs:9:13:9:17 | ..=10 | ..= | +| gen_range_expr.rs:10:13:10:14 | .. | .. | diff --git a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getStart.expected b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getStart.expected index 79b34397efe4..7f58ee5299fb 100644 --- a/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getStart.expected +++ b/rust/ql/test/extractor-tests/generated/RangeExpr/RangeExpr_getStart.expected @@ -1,3 +1,3 @@ -| gen_range_expr.rs:5:13:5:18 | RangeExpr | gen_range_expr.rs:5:13:5:13 | 1 | -| gen_range_expr.rs:6:13:6:17 | RangeExpr | gen_range_expr.rs:6:13:6:13 | 1 | -| gen_range_expr.rs:7:13:7:16 | RangeExpr | gen_range_expr.rs:7:13:7:14 | 10 | +| gen_range_expr.rs:5:13:5:18 | 1..=10 | gen_range_expr.rs:5:13:5:13 | 1 | +| gen_range_expr.rs:6:13:6:17 | 1..10 | gen_range_expr.rs:6:13:6:13 | 1 | +| gen_range_expr.rs:7:13:7:16 | 10.. | gen_range_expr.rs:7:13:7:14 | 10 | diff --git a/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getEnd.expected b/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getEnd.expected index 591b8d9093e1..38ded3fb940d 100644 --- a/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getEnd.expected +++ b/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getEnd.expected @@ -1,2 +1,2 @@ -| gen_range_pat.rs:6:9:6:12 | RangePat | gen_range_pat.rs:6:11:6:12 | LiteralPat | -| gen_range_pat.rs:7:9:7:15 | RangePat | gen_range_pat.rs:7:14:7:15 | LiteralPat | +| gen_range_pat.rs:6:9:6:12 | RangePat | gen_range_pat.rs:6:11:6:12 | 15 | +| gen_range_pat.rs:7:9:7:15 | RangePat | gen_range_pat.rs:7:14:7:15 | 25 | diff --git a/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getStart.expected b/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getStart.expected index ef6a8ea21216..ac6eadaf08c0 100644 --- a/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getStart.expected +++ b/rust/ql/test/extractor-tests/generated/RangePat/RangePat_getStart.expected @@ -1,2 +1,2 @@ -| gen_range_pat.rs:7:9:7:15 | RangePat | gen_range_pat.rs:7:9:7:10 | LiteralPat | -| gen_range_pat.rs:8:9:8:12 | RangePat | gen_range_pat.rs:8:9:8:10 | LiteralPat | +| gen_range_pat.rs:7:9:7:15 | RangePat | gen_range_pat.rs:7:9:7:10 | 16 | +| gen_range_pat.rs:8:9:8:12 | RangePat | gen_range_pat.rs:8:9:8:10 | 26 | diff --git a/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr.expected b/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr.expected index d30c4ef70e5d..445b906bf88b 100644 --- a/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr.expected +++ b/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr.expected @@ -1,4 +1,4 @@ -| gen_record_expr.rs:5:17:5:34 | RecordExpr | hasPath: | yes | hasRecordExprFieldList: | yes | -| gen_record_expr.rs:6:18:6:38 | RecordExpr | hasPath: | yes | hasRecordExprFieldList: | yes | -| gen_record_expr.rs:7:5:7:22 | RecordExpr | hasPath: | yes | hasRecordExprFieldList: | yes | -| gen_record_expr.rs:8:5:8:14 | RecordExpr | hasPath: | yes | hasRecordExprFieldList: | yes | +| gen_record_expr.rs:5:17:5:34 | Foo {...} | hasPath: | yes | hasRecordExprFieldList: | yes | +| gen_record_expr.rs:6:18:6:38 | Foo {...} | hasPath: | yes | hasRecordExprFieldList: | yes | +| gen_record_expr.rs:7:5:7:22 | Foo {...} | hasPath: | yes | hasRecordExprFieldList: | yes | +| gen_record_expr.rs:8:5:8:14 | Foo {...} | hasPath: | yes | hasRecordExprFieldList: | yes | diff --git a/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getPath.expected b/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getPath.expected index 91d4f5cb0b56..5aad8aad60c9 100644 --- a/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getPath.expected +++ b/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getPath.expected @@ -1,4 +1,4 @@ -| gen_record_expr.rs:5:17:5:34 | RecordExpr | gen_record_expr.rs:5:17:5:19 | Foo | -| gen_record_expr.rs:6:18:6:38 | RecordExpr | gen_record_expr.rs:6:18:6:20 | Foo | -| gen_record_expr.rs:7:5:7:22 | RecordExpr | gen_record_expr.rs:7:5:7:7 | Foo | -| gen_record_expr.rs:8:5:8:14 | RecordExpr | gen_record_expr.rs:8:5:8:7 | Foo | +| gen_record_expr.rs:5:17:5:34 | Foo {...} | gen_record_expr.rs:5:17:5:19 | Foo | +| gen_record_expr.rs:6:18:6:38 | Foo {...} | gen_record_expr.rs:6:18:6:20 | Foo | +| gen_record_expr.rs:7:5:7:22 | Foo {...} | gen_record_expr.rs:7:5:7:7 | Foo | +| gen_record_expr.rs:8:5:8:14 | Foo {...} | gen_record_expr.rs:8:5:8:7 | Foo | diff --git a/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getRecordExprFieldList.expected b/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getRecordExprFieldList.expected index d00bf3935d3e..79d18cac3b0d 100644 --- a/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getRecordExprFieldList.expected +++ b/rust/ql/test/extractor-tests/generated/RecordExpr/RecordExpr_getRecordExprFieldList.expected @@ -1,4 +1,4 @@ -| gen_record_expr.rs:5:17:5:34 | RecordExpr | gen_record_expr.rs:5:21:5:34 | RecordExprFieldList | -| gen_record_expr.rs:6:18:6:38 | RecordExpr | gen_record_expr.rs:6:22:6:38 | RecordExprFieldList | -| gen_record_expr.rs:7:5:7:22 | RecordExpr | gen_record_expr.rs:7:9:7:22 | RecordExprFieldList | -| gen_record_expr.rs:8:5:8:14 | RecordExpr | gen_record_expr.rs:8:9:8:14 | RecordExprFieldList | +| gen_record_expr.rs:5:17:5:34 | Foo {...} | gen_record_expr.rs:5:21:5:34 | RecordExprFieldList | +| gen_record_expr.rs:6:18:6:38 | Foo {...} | gen_record_expr.rs:6:22:6:38 | RecordExprFieldList | +| gen_record_expr.rs:7:5:7:22 | Foo {...} | gen_record_expr.rs:7:9:7:22 | RecordExprFieldList | +| gen_record_expr.rs:8:5:8:14 | Foo {...} | gen_record_expr.rs:8:9:8:14 | RecordExprFieldList | diff --git a/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField.expected b/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField.expected index 79ed38759180..46e7ce811bb7 100644 --- a/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField.expected +++ b/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField.expected @@ -1,2 +1,2 @@ -| gen_record_expr_field.rs:5:11:5:14 | RecordExprField | getNumberOfAttrs: | 0 | hasExpr: | yes | hasNameRef: | yes | -| gen_record_expr_field.rs:5:17:5:20 | RecordExprField | getNumberOfAttrs: | 0 | hasExpr: | yes | hasNameRef: | yes | +| gen_record_expr_field.rs:5:11:5:14 | a: 1 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasNameRef: | yes | +| gen_record_expr_field.rs:5:17:5:20 | b: 2 | getNumberOfAttrs: | 0 | hasExpr: | yes | hasNameRef: | yes | diff --git a/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getExpr.expected b/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getExpr.expected index ec096d00a314..cfb892424494 100644 --- a/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getExpr.expected @@ -1,2 +1,2 @@ -| gen_record_expr_field.rs:5:11:5:14 | RecordExprField | gen_record_expr_field.rs:5:14:5:14 | 1 | -| gen_record_expr_field.rs:5:17:5:20 | RecordExprField | gen_record_expr_field.rs:5:20:5:20 | 2 | +| gen_record_expr_field.rs:5:11:5:14 | a: 1 | gen_record_expr_field.rs:5:14:5:14 | 1 | +| gen_record_expr_field.rs:5:17:5:20 | b: 2 | gen_record_expr_field.rs:5:20:5:20 | 2 | diff --git a/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getNameRef.expected b/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getNameRef.expected index 081e3ccac566..d0a3f82cd9d2 100644 --- a/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getNameRef.expected +++ b/rust/ql/test/extractor-tests/generated/RecordExprField/RecordExprField_getNameRef.expected @@ -1,2 +1,2 @@ -| gen_record_expr_field.rs:5:11:5:14 | RecordExprField | gen_record_expr_field.rs:5:11:5:11 | a | -| gen_record_expr_field.rs:5:17:5:20 | RecordExprField | gen_record_expr_field.rs:5:17:5:17 | b | +| gen_record_expr_field.rs:5:11:5:14 | a: 1 | gen_record_expr_field.rs:5:11:5:11 | a | +| gen_record_expr_field.rs:5:17:5:20 | b: 2 | gen_record_expr_field.rs:5:17:5:17 | b | diff --git a/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat.expected b/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat.expected index 62cd3eb3c37d..8d7f96229ad7 100644 --- a/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat.expected +++ b/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat.expected @@ -1,2 +1,2 @@ -| gen_record_pat.rs:6:9:6:26 | RecordPat | hasPath: | yes | hasRecordPatFieldList: | yes | -| gen_record_pat.rs:7:9:7:18 | RecordPat | hasPath: | yes | hasRecordPatFieldList: | yes | +| gen_record_pat.rs:6:9:6:26 | Foo {...} | hasPath: | yes | hasRecordPatFieldList: | yes | +| gen_record_pat.rs:7:9:7:18 | Foo {...} | hasPath: | yes | hasRecordPatFieldList: | yes | diff --git a/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getPath.expected b/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getPath.expected index a9e0be01d5b5..7cd2f51d9eb6 100644 --- a/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getPath.expected +++ b/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getPath.expected @@ -1,2 +1,2 @@ -| gen_record_pat.rs:6:9:6:26 | RecordPat | gen_record_pat.rs:6:9:6:11 | Foo | -| gen_record_pat.rs:7:9:7:18 | RecordPat | gen_record_pat.rs:7:9:7:11 | Foo | +| gen_record_pat.rs:6:9:6:26 | Foo {...} | gen_record_pat.rs:6:9:6:11 | Foo | +| gen_record_pat.rs:7:9:7:18 | Foo {...} | gen_record_pat.rs:7:9:7:11 | Foo | diff --git a/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getRecordPatFieldList.expected b/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getRecordPatFieldList.expected index 86ba10ed9a3c..bad0003c07bd 100644 --- a/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getRecordPatFieldList.expected +++ b/rust/ql/test/extractor-tests/generated/RecordPat/RecordPat_getRecordPatFieldList.expected @@ -1,2 +1,2 @@ -| gen_record_pat.rs:6:9:6:26 | RecordPat | gen_record_pat.rs:6:13:6:26 | RecordPatFieldList | -| gen_record_pat.rs:7:9:7:18 | RecordPat | gen_record_pat.rs:7:13:7:18 | RecordPatFieldList | +| gen_record_pat.rs:6:9:6:26 | Foo {...} | gen_record_pat.rs:6:13:6:26 | RecordPatFieldList | +| gen_record_pat.rs:7:9:7:18 | Foo {...} | gen_record_pat.rs:7:13:7:18 | RecordPatFieldList | diff --git a/rust/ql/test/extractor-tests/generated/RecordPatField/RecordPatField_getPat.expected b/rust/ql/test/extractor-tests/generated/RecordPatField/RecordPatField_getPat.expected index a3ac24ec52be..1fa8a0f8bb7f 100644 --- a/rust/ql/test/extractor-tests/generated/RecordPatField/RecordPatField_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/RecordPatField/RecordPatField_getPat.expected @@ -1,2 +1,2 @@ -| gen_record_pat_field.rs:5:15:5:18 | RecordPatField | gen_record_pat_field.rs:5:18:5:18 | LiteralPat | -| gen_record_pat_field.rs:5:21:5:24 | RecordPatField | gen_record_pat_field.rs:5:24:5:24 | LiteralPat | +| gen_record_pat_field.rs:5:15:5:18 | RecordPatField | gen_record_pat_field.rs:5:18:5:18 | 1 | +| gen_record_pat_field.rs:5:21:5:24 | RecordPatField | gen_record_pat_field.rs:5:24:5:24 | 2 | diff --git a/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr.expected b/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr.expected index d4c75d9a79a0..412f82142060 100644 --- a/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr.expected +++ b/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr.expected @@ -1,4 +1,4 @@ -| gen_ref_expr.rs:5:25:5:28 | RefExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | no | isMut: | no | isRaw: | no | -| gen_ref_expr.rs:6:23:6:30 | RefExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | no | isMut: | yes | isRaw: | no | -| gen_ref_expr.rs:7:35:7:48 | RefExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | yes | isMut: | no | isRaw: | yes | -| gen_ref_expr.rs:8:33:8:44 | RefExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | no | isMut: | yes | isRaw: | yes | +| gen_ref_expr.rs:5:25:5:28 | &foo | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | no | isMut: | no | isRaw: | no | +| gen_ref_expr.rs:6:23:6:30 | &mut foo | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | no | isMut: | yes | isRaw: | no | +| gen_ref_expr.rs:7:35:7:48 | &raw const foo | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | yes | isMut: | no | isRaw: | yes | +| gen_ref_expr.rs:8:33:8:44 | &raw mut foo | getNumberOfAttrs: | 0 | hasExpr: | yes | isConst: | no | isMut: | yes | isRaw: | yes | diff --git a/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr_getExpr.expected index 571986ecf102..7709668f6fd8 100644 --- a/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/RefExpr/RefExpr_getExpr.expected @@ -1,4 +1,4 @@ -| gen_ref_expr.rs:5:25:5:28 | RefExpr | gen_ref_expr.rs:5:26:5:28 | foo | -| gen_ref_expr.rs:6:23:6:30 | RefExpr | gen_ref_expr.rs:6:28:6:30 | foo | -| gen_ref_expr.rs:7:35:7:48 | RefExpr | gen_ref_expr.rs:7:46:7:48 | foo | -| gen_ref_expr.rs:8:33:8:44 | RefExpr | gen_ref_expr.rs:8:42:8:44 | foo | +| gen_ref_expr.rs:5:25:5:28 | &foo | gen_ref_expr.rs:5:26:5:28 | foo | +| gen_ref_expr.rs:6:23:6:30 | &mut foo | gen_ref_expr.rs:6:28:6:30 | foo | +| gen_ref_expr.rs:7:35:7:48 | &raw const foo | gen_ref_expr.rs:7:46:7:48 | foo | +| gen_ref_expr.rs:8:33:8:44 | &raw mut foo | gen_ref_expr.rs:8:42:8:44 | foo | diff --git a/rust/ql/test/extractor-tests/generated/RefPat/RefPat.expected b/rust/ql/test/extractor-tests/generated/RefPat/RefPat.expected index c2fc3416297a..a9dfaf874561 100644 --- a/rust/ql/test/extractor-tests/generated/RefPat/RefPat.expected +++ b/rust/ql/test/extractor-tests/generated/RefPat/RefPat.expected @@ -1,2 +1,2 @@ -| gen_ref_pat.rs:6:9:6:28 | RefPat | isMut: | yes | hasPat: | yes | -| gen_ref_pat.rs:7:9:7:21 | RefPat | isMut: | no | hasPat: | yes | +| gen_ref_pat.rs:6:9:6:28 | &mut ... | isMut: | yes | hasPat: | yes | +| gen_ref_pat.rs:7:9:7:21 | &...::None | isMut: | no | hasPat: | yes | diff --git a/rust/ql/test/extractor-tests/generated/RefPat/RefPat_getPat.expected b/rust/ql/test/extractor-tests/generated/RefPat/RefPat_getPat.expected index 891c3c8216e6..d4f78daeb829 100644 --- a/rust/ql/test/extractor-tests/generated/RefPat/RefPat_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/RefPat/RefPat_getPat.expected @@ -1,2 +1,2 @@ -| gen_ref_pat.rs:6:9:6:28 | RefPat | gen_ref_pat.rs:6:14:6:28 | TupleStructPat | -| gen_ref_pat.rs:7:9:7:21 | RefPat | gen_ref_pat.rs:7:10:7:21 | PathPat | +| gen_ref_pat.rs:6:9:6:28 | &mut ... | gen_ref_pat.rs:6:14:6:28 | TupleStructPat | +| gen_ref_pat.rs:7:9:7:21 | &...::None | gen_ref_pat.rs:7:10:7:21 | ...::None | diff --git a/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr.expected b/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr.expected index dbf54e0f49bd..83220773989e 100644 --- a/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr.expected @@ -1,2 +1,2 @@ -| gen_return_expr.rs:5:5:5:13 | ReturnExpr | getNumberOfAttrs: | 0 | hasExpr: | yes | -| gen_return_expr.rs:8:5:8:10 | ReturnExpr | getNumberOfAttrs: | 0 | hasExpr: | no | +| gen_return_expr.rs:5:5:5:13 | return 42 | getNumberOfAttrs: | 0 | hasExpr: | yes | +| gen_return_expr.rs:8:5:8:10 | return | getNumberOfAttrs: | 0 | hasExpr: | no | diff --git a/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr_getExpr.expected b/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr_getExpr.expected index 2e1a4a8f8cec..c75ecd0b23c5 100644 --- a/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr_getExpr.expected +++ b/rust/ql/test/extractor-tests/generated/ReturnExpr/ReturnExpr_getExpr.expected @@ -1 +1 @@ -| gen_return_expr.rs:5:5:5:13 | ReturnExpr | gen_return_expr.rs:5:12:5:13 | 42 | +| gen_return_expr.rs:5:5:5:13 | return 42 | gen_return_expr.rs:5:12:5:13 | 42 | diff --git a/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.expected b/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.expected index e69de29bb2d1..41c5e89e83d0 100644 --- a/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.expected +++ b/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.expected @@ -0,0 +1 @@ +| gen_self_param.rs:5:13:5:21 | SelfParam | getNumberOfAttrs: | 0 | hasTy: | no | isMut: | yes | hasLifetime: | no | hasName: | yes | diff --git a/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.ql b/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.ql index af2fa064a724..579ec7ffa2ad 100644 --- a/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.ql +++ b/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam.ql @@ -3,14 +3,14 @@ import codeql.rust.elements import TestUtils from - SelfParam x, int getNumberOfAttrs, string isMut, string hasLifetime, string hasName, string hasTy + SelfParam x, int getNumberOfAttrs, string hasTy, string isMut, string hasLifetime, string hasName where toBeTested(x) and not x.isUnknown() and getNumberOfAttrs = x.getNumberOfAttrs() and + (if x.hasTy() then hasTy = "yes" else hasTy = "no") and (if x.isMut() then isMut = "yes" else isMut = "no") and (if x.hasLifetime() then hasLifetime = "yes" else hasLifetime = "no") and - (if x.hasName() then hasName = "yes" else hasName = "no") and - if x.hasTy() then hasTy = "yes" else hasTy = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "isMut:", isMut, "hasLifetime:", hasLifetime, - "hasName:", hasName, "hasTy:", hasTy + if x.hasName() then hasName = "yes" else hasName = "no" +select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasTy:", hasTy, "isMut:", isMut, "hasLifetime:", + hasLifetime, "hasName:", hasName diff --git a/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam_getName.expected b/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam_getName.expected index e69de29bb2d1..70a9a4a06596 100644 --- a/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam_getName.expected +++ b/rust/ql/test/extractor-tests/generated/SelfParam/SelfParam_getName.expected @@ -0,0 +1 @@ +| gen_self_param.rs:5:13:5:21 | SelfParam | gen_self_param.rs:5:18:5:21 | self | diff --git a/rust/ql/test/extractor-tests/generated/SelfParam/gen_self_param.rs b/rust/ql/test/extractor-tests/generated/SelfParam/gen_self_param.rs index 36f8ffd8baf5..6278147a8783 100644 --- a/rust/ql/test/extractor-tests/generated/SelfParam/gen_self_param.rs +++ b/rust/ql/test/extractor-tests/generated/SelfParam/gen_self_param.rs @@ -1,6 +1,8 @@ // generated by codegen, do not edit fn test_self_param() -> () { - // A SelfParam. For example: - todo!() + // A `self` parameter. For example `self` in: + fn push(&mut self, value: T) { + // ... + } } diff --git a/rust/ql/test/extractor-tests/generated/SlicePat/SlicePat_getPat.expected b/rust/ql/test/extractor-tests/generated/SlicePat/SlicePat_getPat.expected index e874d3a22ee4..0725988f37fd 100644 --- a/rust/ql/test/extractor-tests/generated/SlicePat/SlicePat_getPat.expected +++ b/rust/ql/test/extractor-tests/generated/SlicePat/SlicePat_getPat.expected @@ -1,13 +1,13 @@ -| gen_slice_pat.rs:6:9:6:23 | SlicePat | 0 | gen_slice_pat.rs:6:10:6:10 | LiteralPat | -| gen_slice_pat.rs:6:9:6:23 | SlicePat | 1 | gen_slice_pat.rs:6:13:6:13 | LiteralPat | -| gen_slice_pat.rs:6:9:6:23 | SlicePat | 2 | gen_slice_pat.rs:6:16:6:16 | LiteralPat | -| gen_slice_pat.rs:6:9:6:23 | SlicePat | 3 | gen_slice_pat.rs:6:19:6:19 | LiteralPat | -| gen_slice_pat.rs:6:9:6:23 | SlicePat | 4 | gen_slice_pat.rs:6:22:6:22 | LiteralPat | -| gen_slice_pat.rs:7:9:7:18 | SlicePat | 0 | gen_slice_pat.rs:7:10:7:10 | LiteralPat | -| gen_slice_pat.rs:7:9:7:18 | SlicePat | 1 | gen_slice_pat.rs:7:13:7:13 | LiteralPat | -| gen_slice_pat.rs:7:9:7:18 | SlicePat | 2 | gen_slice_pat.rs:7:16:7:17 | RestPat | +| gen_slice_pat.rs:6:9:6:23 | SlicePat | 0 | gen_slice_pat.rs:6:10:6:10 | 1 | +| gen_slice_pat.rs:6:9:6:23 | SlicePat | 1 | gen_slice_pat.rs:6:13:6:13 | 2 | +| gen_slice_pat.rs:6:9:6:23 | SlicePat | 2 | gen_slice_pat.rs:6:16:6:16 | 3 | +| gen_slice_pat.rs:6:9:6:23 | SlicePat | 3 | gen_slice_pat.rs:6:19:6:19 | 4 | +| gen_slice_pat.rs:6:9:6:23 | SlicePat | 4 | gen_slice_pat.rs:6:22:6:22 | 5 | +| gen_slice_pat.rs:7:9:7:18 | SlicePat | 0 | gen_slice_pat.rs:7:10:7:10 | 1 | +| gen_slice_pat.rs:7:9:7:18 | SlicePat | 1 | gen_slice_pat.rs:7:13:7:13 | 2 | +| gen_slice_pat.rs:7:9:7:18 | SlicePat | 2 | gen_slice_pat.rs:7:16:7:17 | .. | | gen_slice_pat.rs:8:9:8:24 | SlicePat | 0 | gen_slice_pat.rs:8:10:8:10 | x | | gen_slice_pat.rs:8:9:8:24 | SlicePat | 1 | gen_slice_pat.rs:8:13:8:13 | y | -| gen_slice_pat.rs:8:9:8:24 | SlicePat | 2 | gen_slice_pat.rs:8:16:8:17 | RestPat | +| gen_slice_pat.rs:8:9:8:24 | SlicePat | 2 | gen_slice_pat.rs:8:16:8:17 | .. | | gen_slice_pat.rs:8:9:8:24 | SlicePat | 3 | gen_slice_pat.rs:8:20:8:20 | z | -| gen_slice_pat.rs:8:9:8:24 | SlicePat | 4 | gen_slice_pat.rs:8:23:8:23 | LiteralPat | +| gen_slice_pat.rs:8:9:8:24 | SlicePat | 4 | gen_slice_pat.rs:8:23:8:23 | 7 | diff --git a/rust/ql/test/extractor-tests/generated/SourceFile/SourceFile_getItem.expected b/rust/ql/test/extractor-tests/generated/SourceFile/SourceFile_getItem.expected index a256c2b84b20..981f445201e0 100644 --- a/rust/ql/test/extractor-tests/generated/SourceFile/SourceFile_getItem.expected +++ b/rust/ql/test/extractor-tests/generated/SourceFile/SourceFile_getItem.expected @@ -1,2 +1,2 @@ -| gen_source_file.rs:1:1:6:2 | SourceFile | 0 | gen_source_file.rs:3:1:6:1 | test_source_file | -| lib.rs:1:1:1:20 | SourceFile | 0 | lib.rs:1:1:1:20 | Module | +| gen_source_file.rs:1:1:6:2 | SourceFile | 0 | gen_source_file.rs:3:1:6:1 | fn test_source_file | +| lib.rs:1:1:1:20 | SourceFile | 0 | lib.rs:1:1:1:20 | mod gen_source_file | diff --git a/rust/ql/test/extractor-tests/generated/Trait/AssocItemList_getAssocItem.expected b/rust/ql/test/extractor-tests/generated/Trait/AssocItemList_getAssocItem.expected index 0f70039583a8..c7337ca090ae 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/AssocItemList_getAssocItem.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/AssocItemList_getAssocItem.expected @@ -1,3 +1,3 @@ | gen_trait.rs:4:20:8:1 | AssocItemList | 0 | gen_trait.rs:5:3:5:18 | TypeAlias | | gen_trait.rs:4:20:8:1 | AssocItemList | 1 | gen_trait.rs:6:3:6:20 | TypeAlias | -| gen_trait.rs:4:20:8:1 | AssocItemList | 2 | gen_trait.rs:7:3:7:72 | frobinize_with | +| gen_trait.rs:4:20:8:1 | AssocItemList | 2 | gen_trait.rs:7:3:7:72 | fn frobinize_with | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait.expected index ba06219a2d4c..451422d330ab 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait.expected @@ -1,2 +1,2 @@ -| gen_trait.rs:3:1:8:1 | Trait | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAssocItemList: | yes | getNumberOfAttrs: | 0 | hasGenericParamList: | no | isAuto: | no | isUnsafe: | no | hasName: | yes | hasTypeBoundList: | no | hasVisibility: | no | hasWhereClause: | no | -| gen_trait.rs:10:1:10:57 | Trait | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAssocItemList: | yes | getNumberOfAttrs: | 0 | hasGenericParamList: | yes | isAuto: | no | isUnsafe: | no | hasName: | yes | hasTypeBoundList: | no | hasVisibility: | yes | hasWhereClause: | yes | +| gen_trait.rs:3:1:8:1 | trait Frobinizable | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAssocItemList: | yes | getNumberOfAttrs: | 0 | hasGenericParamList: | no | isAuto: | no | isUnsafe: | no | hasName: | yes | hasTypeBoundList: | no | hasVisibility: | no | hasWhereClause: | no | +| gen_trait.rs:10:1:10:57 | trait Foo | hasExtendedCanonicalPath: | yes | hasCrateOrigin: | yes | hasAssocItemList: | yes | getNumberOfAttrs: | 0 | hasGenericParamList: | yes | isAuto: | no | isUnsafe: | no | hasName: | yes | hasTypeBoundList: | no | hasVisibility: | yes | hasWhereClause: | yes | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getAssocItemList.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getAssocItemList.expected index fc16a774800e..b60c89c8d3fe 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getAssocItemList.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getAssocItemList.expected @@ -1,2 +1,2 @@ -| gen_trait.rs:3:1:8:1 | Trait | gen_trait.rs:4:20:8:1 | AssocItemList | -| gen_trait.rs:10:1:10:57 | Trait | gen_trait.rs:10:56:10:57 | AssocItemList | +| gen_trait.rs:3:1:8:1 | trait Frobinizable | gen_trait.rs:4:20:8:1 | AssocItemList | +| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:56:10:57 | AssocItemList | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getCrateOrigin.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getCrateOrigin.expected index 36106a58ae0c..1e42bb437317 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getCrateOrigin.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getCrateOrigin.expected @@ -1,2 +1,2 @@ -| gen_trait.rs:3:1:8:1 | Trait | repo::test | -| gen_trait.rs:10:1:10:57 | Trait | repo::test | +| gen_trait.rs:3:1:8:1 | trait Frobinizable | repo::test | +| gen_trait.rs:10:1:10:57 | trait Foo | repo::test | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getExtendedCanonicalPath.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getExtendedCanonicalPath.expected index d89c9f23757d..6a5e82036739 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getExtendedCanonicalPath.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getExtendedCanonicalPath.expected @@ -1,2 +1,2 @@ -| gen_trait.rs:3:1:8:1 | Trait | crate::gen_trait::Frobinizable | -| gen_trait.rs:10:1:10:57 | Trait | crate::gen_trait::Foo | +| gen_trait.rs:3:1:8:1 | trait Frobinizable | crate::gen_trait::Frobinizable | +| gen_trait.rs:10:1:10:57 | trait Foo | crate::gen_trait::Foo | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getGenericParamList.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getGenericParamList.expected index 85a848355f12..1ea7592a5973 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getGenericParamList.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getGenericParamList.expected @@ -1 +1 @@ -| gen_trait.rs:10:1:10:57 | Trait | gen_trait.rs:10:14:10:30 | GenericParamList | +| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:14:10:30 | GenericParamList | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getName.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getName.expected index cc60a2ab9386..1c087cdea895 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getName.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getName.expected @@ -1,2 +1,2 @@ -| gen_trait.rs:3:1:8:1 | Trait | gen_trait.rs:4:7:4:18 | Frobinizable | -| gen_trait.rs:10:1:10:57 | Trait | gen_trait.rs:10:11:10:13 | Foo | +| gen_trait.rs:3:1:8:1 | trait Frobinizable | gen_trait.rs:4:7:4:18 | Frobinizable | +| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:11:10:13 | Foo | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getVisibility.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getVisibility.expected index 67d505acda7e..56576624e47f 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getVisibility.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getVisibility.expected @@ -1 +1 @@ -| gen_trait.rs:10:1:10:57 | Trait | gen_trait.rs:10:1:10:3 | Visibility | +| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:1:10:3 | Visibility | diff --git a/rust/ql/test/extractor-tests/generated/Trait/Trait_getWhereClause.expected b/rust/ql/test/extractor-tests/generated/Trait/Trait_getWhereClause.expected index a1ae3161e79d..d46ac2d04cd9 100644 --- a/rust/ql/test/extractor-tests/generated/Trait/Trait_getWhereClause.expected +++ b/rust/ql/test/extractor-tests/generated/Trait/Trait_getWhereClause.expected @@ -1 +1 @@ -| gen_trait.rs:10:1:10:57 | Trait | gen_trait.rs:10:32:10:54 | WhereClause | +| gen_trait.rs:10:1:10:57 | trait Foo | gen_trait.rs:10:32:10:54 | WhereClause | diff --git a/rust/ql/test/extractor-tests/generated/TuplePat/TuplePat_getField.expected b/rust/ql/test/extractor-tests/generated/TuplePat/TuplePat_getField.expected index 59d028b43ca9..78e00f39c92b 100644 --- a/rust/ql/test/extractor-tests/generated/TuplePat/TuplePat_getField.expected +++ b/rust/ql/test/extractor-tests/generated/TuplePat/TuplePat_getField.expected @@ -2,5 +2,5 @@ | gen_tuple_pat.rs:5:9:5:14 | TuplePat | 1 | gen_tuple_pat.rs:5:13:5:13 | y | | gen_tuple_pat.rs:6:9:6:22 | TuplePat | 0 | gen_tuple_pat.rs:6:10:6:10 | a | | gen_tuple_pat.rs:6:9:6:22 | TuplePat | 1 | gen_tuple_pat.rs:6:13:6:13 | b | -| gen_tuple_pat.rs:6:9:6:22 | TuplePat | 2 | gen_tuple_pat.rs:6:16:6:17 | RestPat | +| gen_tuple_pat.rs:6:9:6:22 | TuplePat | 2 | gen_tuple_pat.rs:6:16:6:17 | .. | | gen_tuple_pat.rs:6:9:6:22 | TuplePat | 3 | gen_tuple_pat.rs:6:21:6:21 | z | diff --git a/rust/ql/test/extractor-tests/generated/TupleStructPat/TupleStructPat_getField.expected b/rust/ql/test/extractor-tests/generated/TupleStructPat/TupleStructPat_getField.expected index 7a009a0818b7..5885cbcea3e3 100644 --- a/rust/ql/test/extractor-tests/generated/TupleStructPat/TupleStructPat_getField.expected +++ b/rust/ql/test/extractor-tests/generated/TupleStructPat/TupleStructPat_getField.expected @@ -1,7 +1,7 @@ -| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 0 | gen_tuple_struct_pat.rs:6:15:6:17 | LiteralPat | -| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 1 | gen_tuple_struct_pat.rs:6:20:6:20 | LiteralPat | -| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 2 | gen_tuple_struct_pat.rs:6:23:6:23 | LiteralPat | -| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 3 | gen_tuple_struct_pat.rs:6:26:6:26 | LiteralPat | -| gen_tuple_struct_pat.rs:7:9:7:20 | TupleStructPat | 0 | gen_tuple_struct_pat.rs:7:15:7:16 | RestPat | -| gen_tuple_struct_pat.rs:7:9:7:20 | TupleStructPat | 1 | gen_tuple_struct_pat.rs:7:19:7:19 | LiteralPat | -| gen_tuple_struct_pat.rs:8:9:8:17 | TupleStructPat | 0 | gen_tuple_struct_pat.rs:8:15:8:16 | RestPat | +| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 0 | gen_tuple_struct_pat.rs:6:15:6:17 | "a" | +| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 1 | gen_tuple_struct_pat.rs:6:20:6:20 | 1 | +| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 2 | gen_tuple_struct_pat.rs:6:23:6:23 | 2 | +| gen_tuple_struct_pat.rs:6:9:6:27 | TupleStructPat | 3 | gen_tuple_struct_pat.rs:6:26:6:26 | 3 | +| gen_tuple_struct_pat.rs:7:9:7:20 | TupleStructPat | 0 | gen_tuple_struct_pat.rs:7:15:7:16 | .. | +| gen_tuple_struct_pat.rs:7:9:7:20 | TupleStructPat | 1 | gen_tuple_struct_pat.rs:7:19:7:19 | 3 | +| gen_tuple_struct_pat.rs:8:9:8:17 | TupleStructPat | 0 | gen_tuple_struct_pat.rs:8:15:8:16 | .. | diff --git a/rust/ql/test/extractor-tests/generated/UnderscoreExpr/UnderscoreExpr.expected b/rust/ql/test/extractor-tests/generated/UnderscoreExpr/UnderscoreExpr.expected index 3b2effb788e1..ea89e8b29b4e 100644 --- a/rust/ql/test/extractor-tests/generated/UnderscoreExpr/UnderscoreExpr.expected +++ b/rust/ql/test/extractor-tests/generated/UnderscoreExpr/UnderscoreExpr.expected @@ -1 +1 @@ -| gen_underscore_expr.rs:5:5:5:5 | UnderscoreExpr | getNumberOfAttrs: | 0 | +| gen_underscore_expr.rs:5:5:5:5 | _ | getNumberOfAttrs: | 0 | diff --git a/rust/ql/test/extractor-tests/generated/Variant/Variant.ql b/rust/ql/test/extractor-tests/generated/Variant/Variant.ql index 2cbcd20cbf06..92ebcbe55eed 100644 --- a/rust/ql/test/extractor-tests/generated/Variant/Variant.ql +++ b/rust/ql/test/extractor-tests/generated/Variant/Variant.ql @@ -3,15 +3,22 @@ import codeql.rust.elements import TestUtils from - Variant x, int getNumberOfAttrs, string hasExpr, string hasFieldList, string hasName, - string hasVisibility + Variant x, string hasExtendedCanonicalPath, string hasCrateOrigin, int getNumberOfAttrs, + string hasExpr, string hasFieldList, string hasName, string hasVisibility where toBeTested(x) and not x.isUnknown() and + ( + if x.hasExtendedCanonicalPath() + then hasExtendedCanonicalPath = "yes" + else hasExtendedCanonicalPath = "no" + ) and + (if x.hasCrateOrigin() then hasCrateOrigin = "yes" else hasCrateOrigin = "no") and getNumberOfAttrs = x.getNumberOfAttrs() and (if x.hasExpr() then hasExpr = "yes" else hasExpr = "no") and (if x.hasFieldList() then hasFieldList = "yes" else hasFieldList = "no") and (if x.hasName() then hasName = "yes" else hasName = "no") and if x.hasVisibility() then hasVisibility = "yes" else hasVisibility = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr, "hasFieldList:", hasFieldList, +select x, "hasExtendedCanonicalPath:", hasExtendedCanonicalPath, "hasCrateOrigin:", hasCrateOrigin, + "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr, "hasFieldList:", hasFieldList, "hasName:", hasName, "hasVisibility:", hasVisibility diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.expected b/rust/ql/test/extractor-tests/generated/Variant/Variant_getCrateOrigin.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getExpr.expected rename to rust/ql/test/extractor-tests/generated/Variant/Variant_getCrateOrigin.expected diff --git a/rust/ql/test/extractor-tests/generated/Variant/Variant_getCrateOrigin.ql b/rust/ql/test/extractor-tests/generated/Variant/Variant_getCrateOrigin.ql new file mode 100644 index 000000000000..0acfd9827fee --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Variant/Variant_getCrateOrigin.ql @@ -0,0 +1,7 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from Variant x +where toBeTested(x) and not x.isUnknown() +select x, x.getCrateOrigin() diff --git a/rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.expected b/rust/ql/test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/FormatArgsArg/FormatArgsArg_getName.expected rename to rust/ql/test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.expected diff --git a/rust/ql/test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.ql b/rust/ql/test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.ql new file mode 100644 index 000000000000..ad8aaf86a5cf --- /dev/null +++ b/rust/ql/test/extractor-tests/generated/Variant/Variant_getExtendedCanonicalPath.ql @@ -0,0 +1,7 @@ +// generated by codegen, do not edit +import codeql.rust.elements +import TestUtils + +from Variant x +where toBeTested(x) and not x.isUnknown() +select x, x.getExtendedCanonicalPath() diff --git a/rust/ql/test/extractor-tests/generated/WhileExpr/WhileExpr.ql b/rust/ql/test/extractor-tests/generated/WhileExpr/WhileExpr.ql index ceb095e9d201..8544014e571a 100644 --- a/rust/ql/test/extractor-tests/generated/WhileExpr/WhileExpr.ql +++ b/rust/ql/test/extractor-tests/generated/WhileExpr/WhileExpr.ql @@ -2,13 +2,13 @@ import codeql.rust.elements import TestUtils -from WhileExpr x, int getNumberOfAttrs, string hasCondition, string hasLabel, string hasLoopBody +from WhileExpr x, string hasLabel, string hasLoopBody, int getNumberOfAttrs, string hasCondition where toBeTested(x) and not x.isUnknown() and - getNumberOfAttrs = x.getNumberOfAttrs() and - (if x.hasCondition() then hasCondition = "yes" else hasCondition = "no") and (if x.hasLabel() then hasLabel = "yes" else hasLabel = "no") and - if x.hasLoopBody() then hasLoopBody = "yes" else hasLoopBody = "no" -select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasCondition:", hasCondition, "hasLabel:", - hasLabel, "hasLoopBody:", hasLoopBody + (if x.hasLoopBody() then hasLoopBody = "yes" else hasLoopBody = "no") and + getNumberOfAttrs = x.getNumberOfAttrs() and + if x.hasCondition() then hasCondition = "yes" else hasCondition = "no" +select x, "hasLabel:", hasLabel, "hasLoopBody:", hasLoopBody, "getNumberOfAttrs:", getNumberOfAttrs, + "hasCondition:", hasCondition diff --git a/rust/ql/test/extractor-tests/generated/WildcardPat/WildcardPat.expected b/rust/ql/test/extractor-tests/generated/WildcardPat/WildcardPat.expected index ceb155671b7f..b8ac989ee1c0 100644 --- a/rust/ql/test/extractor-tests/generated/WildcardPat/WildcardPat.expected +++ b/rust/ql/test/extractor-tests/generated/WildcardPat/WildcardPat.expected @@ -1 +1 @@ -| gen_wildcard_pat.rs:5:9:5:9 | WildcardPat | +| gen_wildcard_pat.rs:5:9:5:9 | _ | diff --git a/rust/ql/test/extractor-tests/utf8/ast.expected b/rust/ql/test/extractor-tests/utf8/ast.expected index dfc20f5ab58b..560f834766e3 100644 --- a/rust/ql/test/extractor-tests/utf8/ast.expected +++ b/rust/ql/test/extractor-tests/utf8/ast.expected @@ -1,33 +1,33 @@ -| lib.rs:1:1:1:21 | Module | | lib.rs:1:1:1:21 | SourceFile | +| lib.rs:1:1:1:21 | mod utf8_identifiers | | lib.rs:1:5:1:20 | utf8_identifiers | -| utf8_identifiers.rs:1:1:4:6 | foo | +| utf8_identifiers.rs:1:1:4:6 | fn foo | | utf8_identifiers.rs:1:1:12:2 | SourceFile | | utf8_identifiers.rs:1:4:1:6 | foo | | utf8_identifiers.rs:1:7:4:1 | GenericParamList | -| utf8_identifiers.rs:2:5:2:6 | Lifetime | +| utf8_identifiers.rs:2:5:2:6 | ''\u03b2 | | utf8_identifiers.rs:2:5:2:6 | LifetimeParam | | utf8_identifiers.rs:3:5:3:5 | TypeParam | | utf8_identifiers.rs:3:5:3:5 | \u03b3 | | utf8_identifiers.rs:4:2:4:3 | ParamList | -| utf8_identifiers.rs:4:5:4:6 | BlockExpr | | utf8_identifiers.rs:4:5:4:6 | StmtList | +| utf8_identifiers.rs:4:5:4:6 | { ... } | | utf8_identifiers.rs:6:1:8:1 | Struct | | utf8_identifiers.rs:6:8:6:8 | X | | utf8_identifiers.rs:6:10:8:1 | RecordFieldList | | utf8_identifiers.rs:7:5:7:5 | \u03b4 | | utf8_identifiers.rs:7:5:7:13 | RecordField | -| utf8_identifiers.rs:7:9:7:13 | PathType | +| utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:7:9:7:13 | usize | | utf8_identifiers.rs:10:1:10:3 | Visibility | -| utf8_identifiers.rs:10:1:12:1 | main | +| utf8_identifiers.rs:10:1:12:1 | fn main | | utf8_identifiers.rs:10:8:10:11 | main | | utf8_identifiers.rs:10:12:10:13 | ParamList | -| utf8_identifiers.rs:10:15:12:1 | BlockExpr | | utf8_identifiers.rs:10:15:12:1 | StmtList | -| utf8_identifiers.rs:11:5:11:24 | LetStmt | +| utf8_identifiers.rs:10:15:12:1 | { ... } | +| utf8_identifiers.rs:11:5:11:24 | let ... = 0.00001f64 | | utf8_identifiers.rs:11:9:11:9 | \u03b1 | | utf8_identifiers.rs:11:9:11:9 | \u03b1 | | utf8_identifiers.rs:11:14:11:23 | 0.00001f64 | diff --git a/rust/ql/test/library-tests/controlflow-unstable/Cfg.expected b/rust/ql/test/library-tests/controlflow-unstable/Cfg.expected index 05851289a35f..4260e2384c8f 100644 --- a/rust/ql/test/library-tests/controlflow-unstable/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow-unstable/Cfg.expected @@ -1,53 +1,53 @@ edges -| test.rs:5:5:11:5 | enter test_and_if_let | test.rs:5:24:5:24 | a | | -| test.rs:5:5:11:5 | exit test_and_if_let (normal) | test.rs:5:5:11:5 | exit test_and_if_let | | -| test.rs:5:24:5:24 | a | test.rs:5:24:5:30 | Param | match | -| test.rs:5:24:5:30 | Param | test.rs:5:33:5:33 | b | | -| test.rs:5:33:5:33 | b | test.rs:5:33:5:47 | Param | match | -| test.rs:5:33:5:47 | Param | test.rs:5:50:5:50 | c | | -| test.rs:5:50:5:50 | c | test.rs:5:50:5:56 | Param | match | -| test.rs:5:50:5:56 | Param | test.rs:6:12:6:12 | a | | -| test.rs:5:67:11:5 | BlockExpr | test.rs:5:5:11:5 | exit test_and_if_let (normal) | | -| test.rs:6:9:10:9 | IfExpr | test.rs:5:67:11:5 | BlockExpr | | +| test.rs:5:5:11:5 | enter fn test_and_if_let | test.rs:5:24:5:24 | a | | +| test.rs:5:5:11:5 | exit fn test_and_if_let (normal) | test.rs:5:5:11:5 | exit fn test_and_if_let | | +| test.rs:5:24:5:24 | a | test.rs:5:24:5:30 | ...: bool | match | +| test.rs:5:24:5:30 | ...: bool | test.rs:5:33:5:33 | b | | +| test.rs:5:33:5:33 | b | test.rs:5:33:5:47 | ...: Option::<...> | match | +| test.rs:5:33:5:47 | ...: Option::<...> | test.rs:5:50:5:50 | c | | +| test.rs:5:50:5:50 | c | test.rs:5:50:5:56 | ...: bool | match | +| test.rs:5:50:5:56 | ...: bool | test.rs:6:12:6:12 | a | | +| test.rs:5:67:11:5 | { ... } | test.rs:5:5:11:5 | exit fn test_and_if_let (normal) | | +| test.rs:6:9:10:9 | if ... {...} else {...} | test.rs:5:67:11:5 | { ... } | | | test.rs:6:12:6:12 | a | test.rs:6:12:6:31 | [boolean(false)] ... && ... | false | -| test.rs:6:12:6:12 | a | test.rs:6:17:6:31 | LetExpr | true | +| test.rs:6:12:6:12 | a | test.rs:6:17:6:31 | let ... = b | true | | test.rs:6:12:6:31 | [boolean(false)] ... && ... | test.rs:9:13:9:17 | false | false | | test.rs:6:12:6:31 | [boolean(true)] ... && ... | test.rs:7:13:7:13 | d | true | -| test.rs:6:17:6:31 | LetExpr | test.rs:6:31:6:31 | b | | +| test.rs:6:17:6:31 | let ... = b | test.rs:6:31:6:31 | b | | | test.rs:6:21:6:27 | TupleStructPat | test.rs:6:12:6:31 | [boolean(false)] ... && ... | no-match | | test.rs:6:21:6:27 | TupleStructPat | test.rs:6:26:6:26 | d | match | | test.rs:6:26:6:26 | d | test.rs:6:12:6:31 | [boolean(true)] ... && ... | match | | test.rs:6:31:6:31 | b | test.rs:6:21:6:27 | TupleStructPat | | -| test.rs:6:33:8:9 | BlockExpr | test.rs:6:9:10:9 | IfExpr | | -| test.rs:7:13:7:13 | d | test.rs:6:33:8:9 | BlockExpr | | -| test.rs:8:16:10:9 | BlockExpr | test.rs:6:9:10:9 | IfExpr | | -| test.rs:9:13:9:17 | false | test.rs:8:16:10:9 | BlockExpr | | -| test.rs:13:5:21:5 | enter test_and_if_let2 | test.rs:13:25:13:25 | a | | -| test.rs:13:5:21:5 | exit test_and_if_let2 (normal) | test.rs:13:5:21:5 | exit test_and_if_let2 | | -| test.rs:13:25:13:25 | a | test.rs:13:25:13:31 | Param | match | -| test.rs:13:25:13:31 | Param | test.rs:13:34:13:34 | b | | -| test.rs:13:34:13:34 | b | test.rs:13:34:13:39 | Param | match | -| test.rs:13:34:13:39 | Param | test.rs:13:42:13:42 | c | | -| test.rs:13:42:13:42 | c | test.rs:13:42:13:48 | Param | match | -| test.rs:13:42:13:48 | Param | test.rs:14:12:14:12 | a | | -| test.rs:13:59:21:5 | BlockExpr | test.rs:13:5:21:5 | exit test_and_if_let2 (normal) | | -| test.rs:14:9:20:9 | IfExpr | test.rs:13:59:21:5 | BlockExpr | | +| test.rs:6:33:8:9 | { ... } | test.rs:6:9:10:9 | if ... {...} else {...} | | +| test.rs:7:13:7:13 | d | test.rs:6:33:8:9 | { ... } | | +| test.rs:8:16:10:9 | { ... } | test.rs:6:9:10:9 | if ... {...} else {...} | | +| test.rs:9:13:9:17 | false | test.rs:8:16:10:9 | { ... } | | +| test.rs:13:5:21:5 | enter fn test_and_if_let2 | test.rs:13:25:13:25 | a | | +| test.rs:13:5:21:5 | exit fn test_and_if_let2 (normal) | test.rs:13:5:21:5 | exit fn test_and_if_let2 | | +| test.rs:13:25:13:25 | a | test.rs:13:25:13:31 | ...: bool | match | +| test.rs:13:25:13:31 | ...: bool | test.rs:13:34:13:34 | b | | +| test.rs:13:34:13:34 | b | test.rs:13:34:13:39 | ...: i64 | match | +| test.rs:13:34:13:39 | ...: i64 | test.rs:13:42:13:42 | c | | +| test.rs:13:42:13:42 | c | test.rs:13:42:13:48 | ...: bool | match | +| test.rs:13:42:13:48 | ...: bool | test.rs:14:12:14:12 | a | | +| test.rs:13:59:21:5 | { ... } | test.rs:13:5:21:5 | exit fn test_and_if_let2 (normal) | | +| test.rs:14:9:20:9 | if ... {...} else {...} | test.rs:13:59:21:5 | { ... } | | | test.rs:14:12:14:12 | a | test.rs:14:12:14:25 | [boolean(false)] ... && ... | false | -| test.rs:14:12:14:12 | a | test.rs:14:17:14:25 | LetExpr | true | +| test.rs:14:12:14:12 | a | test.rs:14:17:14:25 | let ... = b | true | | test.rs:14:12:14:25 | [boolean(false)] ... && ... | test.rs:14:12:15:16 | [boolean(false)] ... && ... | false | | test.rs:14:12:14:25 | [boolean(true)] ... && ... | test.rs:15:16:15:16 | c | true | | test.rs:14:12:15:16 | [boolean(false)] ... && ... | test.rs:19:13:19:17 | false | false | | test.rs:14:12:15:16 | [boolean(true)] ... && ... | test.rs:17:13:17:13 | d | true | -| test.rs:14:17:14:25 | LetExpr | test.rs:14:25:14:25 | b | | +| test.rs:14:17:14:25 | let ... = b | test.rs:14:25:14:25 | b | | | test.rs:14:21:14:21 | d | test.rs:14:12:14:25 | [boolean(true)] ... && ... | match | | test.rs:14:25:14:25 | b | test.rs:14:21:14:21 | d | | | test.rs:15:16:15:16 | c | test.rs:14:12:15:16 | [boolean(false)] ... && ... | false | | test.rs:15:16:15:16 | c | test.rs:14:12:15:16 | [boolean(true)] ... && ... | true | -| test.rs:16:9:18:9 | BlockExpr | test.rs:14:9:20:9 | IfExpr | | +| test.rs:16:9:18:9 | { ... } | test.rs:14:9:20:9 | if ... {...} else {...} | | | test.rs:17:13:17:13 | d | test.rs:17:17:17:17 | 0 | | -| test.rs:17:13:17:17 | ... > ... | test.rs:16:9:18:9 | BlockExpr | | +| test.rs:17:13:17:17 | ... > ... | test.rs:16:9:18:9 | { ... } | | | test.rs:17:17:17:17 | 0 | test.rs:17:13:17:17 | ... > ... | | -| test.rs:18:16:20:9 | BlockExpr | test.rs:14:9:20:9 | IfExpr | | -| test.rs:19:13:19:17 | false | test.rs:18:16:20:9 | BlockExpr | | +| test.rs:18:16:20:9 | { ... } | test.rs:14:9:20:9 | if ... {...} else {...} | | +| test.rs:19:13:19:17 | false | test.rs:18:16:20:9 | { ... } | | breakTarget continueTarget diff --git a/rust/ql/test/library-tests/controlflow/Cfg.expected b/rust/ql/test/library-tests/controlflow/Cfg.expected index 620837abc826..5137e2f8b89c 100644 --- a/rust/ql/test/library-tests/controlflow/Cfg.expected +++ b/rust/ql/test/library-tests/controlflow/Cfg.expected @@ -1,479 +1,479 @@ edges -| test.rs:5:5:8:5 | enter function_call | test.rs:6:9:6:64 | ExprStmt | | -| test.rs:5:5:8:5 | exit function_call (normal) | test.rs:5:5:8:5 | exit function_call | | -| test.rs:5:24:8:5 | BlockExpr | test.rs:5:5:8:5 | exit function_call (normal) | | -| test.rs:6:9:6:44 | logical_operators::test_and_operator | test.rs:6:46:6:49 | true | | -| test.rs:6:9:6:63 | CallExpr | test.rs:7:9:7:22 | ExprStmt | | -| test.rs:6:9:6:64 | ExprStmt | test.rs:6:9:6:44 | logical_operators::test_and_operator | | +| test.rs:5:5:8:5 | enter fn function_call | test.rs:6:9:6:64 | ExprStmt | | +| test.rs:5:5:8:5 | exit fn function_call (normal) | test.rs:5:5:8:5 | exit fn function_call | | +| test.rs:5:24:8:5 | { ... } | test.rs:5:5:8:5 | exit fn function_call (normal) | | +| test.rs:6:9:6:44 | ...::test_and_operator | test.rs:6:46:6:49 | true | | +| test.rs:6:9:6:63 | ...::test_and_operator(...) | test.rs:7:9:7:22 | ExprStmt | | +| test.rs:6:9:6:64 | ExprStmt | test.rs:6:9:6:44 | ...::test_and_operator | | | test.rs:6:46:6:49 | true | test.rs:6:52:6:56 | false | | | test.rs:6:52:6:56 | false | test.rs:6:59:6:62 | true | | -| test.rs:6:59:6:62 | true | test.rs:6:9:6:63 | CallExpr | | -| test.rs:7:9:7:19 | method_call | test.rs:7:9:7:21 | CallExpr | | -| test.rs:7:9:7:21 | CallExpr | test.rs:5:24:8:5 | BlockExpr | | +| test.rs:6:59:6:62 | true | test.rs:6:9:6:63 | ...::test_and_operator(...) | | +| test.rs:7:9:7:19 | method_call | test.rs:7:9:7:21 | method_call(...) | | +| test.rs:7:9:7:21 | method_call(...) | test.rs:5:24:8:5 | { ... } | | | test.rs:7:9:7:22 | ExprStmt | test.rs:7:9:7:19 | method_call | | -| test.rs:10:5:13:5 | enter method_call | test.rs:11:9:11:37 | LetStmt | | -| test.rs:10:5:13:5 | exit method_call (normal) | test.rs:10:5:13:5 | exit method_call | | -| test.rs:10:22:13:5 | BlockExpr | test.rs:10:5:13:5 | exit method_call (normal) | | -| test.rs:11:9:11:37 | LetStmt | test.rs:11:23:11:34 | HashMap::new | | +| test.rs:10:5:13:5 | enter fn method_call | test.rs:11:9:11:37 | let ... = ... | | +| test.rs:10:5:13:5 | exit fn method_call (normal) | test.rs:10:5:13:5 | exit fn method_call | | +| test.rs:10:22:13:5 | { ... } | test.rs:10:5:13:5 | exit fn method_call (normal) | | +| test.rs:11:9:11:37 | let ... = ... | test.rs:11:23:11:34 | ...::new | | | test.rs:11:13:11:19 | map | test.rs:12:9:12:28 | ExprStmt | match | -| test.rs:11:23:11:34 | HashMap::new | test.rs:11:23:11:36 | CallExpr | | -| test.rs:11:23:11:36 | CallExpr | test.rs:11:13:11:19 | map | | +| test.rs:11:23:11:34 | ...::new | test.rs:11:23:11:36 | ...::new(...) | | +| test.rs:11:23:11:36 | ...::new(...) | test.rs:11:13:11:19 | map | | | test.rs:12:9:12:11 | map | test.rs:12:20:12:21 | 37 | | -| test.rs:12:9:12:27 | ... .insert(...) | test.rs:10:22:13:5 | BlockExpr | | +| test.rs:12:9:12:27 | ... .insert(...) | test.rs:10:22:13:5 | { ... } | | | test.rs:12:9:12:28 | ExprStmt | test.rs:12:9:12:11 | map | | | test.rs:12:20:12:21 | 37 | test.rs:12:24:12:26 | "a" | | | test.rs:12:24:12:26 | "a" | test.rs:12:9:12:27 | ... .insert(...) | | -| test.rs:18:5:24:5 | enter next | test.rs:18:13:18:13 | n | | -| test.rs:18:5:24:5 | exit next (normal) | test.rs:18:5:24:5 | exit next | | -| test.rs:18:13:18:13 | n | test.rs:18:13:18:18 | Param | match | -| test.rs:18:13:18:18 | Param | test.rs:19:12:19:12 | n | | -| test.rs:18:28:24:5 | BlockExpr | test.rs:18:5:24:5 | exit next (normal) | | -| test.rs:19:9:23:9 | IfExpr | test.rs:18:28:24:5 | BlockExpr | | +| test.rs:18:5:24:5 | enter fn next | test.rs:18:13:18:13 | n | | +| test.rs:18:5:24:5 | exit fn next (normal) | test.rs:18:5:24:5 | exit fn next | | +| test.rs:18:13:18:13 | n | test.rs:18:13:18:18 | ...: i64 | match | +| test.rs:18:13:18:18 | ...: i64 | test.rs:19:12:19:12 | n | | +| test.rs:18:28:24:5 | { ... } | test.rs:18:5:24:5 | exit fn next (normal) | | +| test.rs:19:9:23:9 | if ... {...} else {...} | test.rs:18:28:24:5 | { ... } | | | test.rs:19:12:19:12 | n | test.rs:19:16:19:16 | 2 | | | test.rs:19:12:19:16 | ... % ... | test.rs:19:21:19:21 | 0 | | | test.rs:19:12:19:21 | ... == ... | test.rs:20:13:20:13 | n | true | | test.rs:19:12:19:21 | ... == ... | test.rs:22:13:22:13 | 3 | false | | test.rs:19:16:19:16 | 2 | test.rs:19:12:19:16 | ... % ... | | | test.rs:19:21:19:21 | 0 | test.rs:19:12:19:21 | ... == ... | | -| test.rs:19:23:21:9 | BlockExpr | test.rs:19:9:23:9 | IfExpr | | +| test.rs:19:23:21:9 | { ... } | test.rs:19:9:23:9 | if ... {...} else {...} | | | test.rs:20:13:20:13 | n | test.rs:20:17:20:17 | 2 | | -| test.rs:20:13:20:17 | ... / ... | test.rs:19:23:21:9 | BlockExpr | | +| test.rs:20:13:20:17 | ... / ... | test.rs:19:23:21:9 | { ... } | | | test.rs:20:17:20:17 | 2 | test.rs:20:13:20:17 | ... / ... | | -| test.rs:21:16:23:9 | BlockExpr | test.rs:19:9:23:9 | IfExpr | | +| test.rs:21:16:23:9 | { ... } | test.rs:19:9:23:9 | if ... {...} else {...} | | | test.rs:22:13:22:13 | 3 | test.rs:22:17:22:17 | n | | | test.rs:22:13:22:17 | ... * ... | test.rs:22:21:22:21 | 1 | | -| test.rs:22:13:22:21 | ... + ... | test.rs:21:16:23:9 | BlockExpr | | +| test.rs:22:13:22:21 | ... + ... | test.rs:21:16:23:9 | { ... } | | | test.rs:22:17:22:17 | n | test.rs:22:13:22:17 | ... * ... | | | test.rs:22:21:22:21 | 1 | test.rs:22:13:22:21 | ... + ... | | -| test.rs:26:5:42:5 | enter test_break_and_continue | test.rs:26:32:26:32 | n | | -| test.rs:26:5:42:5 | exit test_break_and_continue (normal) | test.rs:26:5:42:5 | exit test_break_and_continue | | -| test.rs:26:32:26:32 | n | test.rs:26:32:26:37 | Param | match | -| test.rs:26:32:26:37 | Param | test.rs:27:9:27:22 | LetStmt | | -| test.rs:27:9:27:22 | LetStmt | test.rs:27:21:27:21 | n | | +| test.rs:26:5:42:5 | enter fn test_break_and_continue | test.rs:26:32:26:32 | n | | +| test.rs:26:5:42:5 | exit fn test_break_and_continue (normal) | test.rs:26:5:42:5 | exit fn test_break_and_continue | | +| test.rs:26:32:26:32 | n | test.rs:26:32:26:37 | ...: i64 | match | +| test.rs:26:32:26:37 | ...: i64 | test.rs:27:9:27:22 | let ... = n | | +| test.rs:27:9:27:22 | let ... = n | test.rs:27:21:27:21 | n | | | test.rs:27:13:27:17 | i | test.rs:28:9:40:9 | ExprStmt | match | | test.rs:27:21:27:21 | n | test.rs:27:13:27:17 | i | | | test.rs:28:9:40:9 | ExprStmt | test.rs:29:13:29:24 | ExprStmt | | -| test.rs:28:9:40:9 | LoopExpr | test.rs:41:9:41:20 | ExprStmt | | -| test.rs:28:14:40:9 | BlockExpr | test.rs:29:13:29:24 | ExprStmt | | +| test.rs:28:9:40:9 | loop { ... } | test.rs:41:9:41:20 | ExprStmt | | +| test.rs:28:14:40:9 | { ... } | test.rs:29:13:29:24 | ExprStmt | | | test.rs:29:13:29:13 | i | test.rs:29:17:29:20 | next | | | test.rs:29:13:29:23 | ... = ... | test.rs:30:13:32:13 | ExprStmt | | | test.rs:29:13:29:24 | ExprStmt | test.rs:29:13:29:13 | i | | | test.rs:29:17:29:20 | next | test.rs:29:22:29:22 | i | | -| test.rs:29:17:29:23 | CallExpr | test.rs:29:13:29:23 | ... = ... | | -| test.rs:29:22:29:22 | i | test.rs:29:17:29:23 | CallExpr | | +| test.rs:29:17:29:23 | next(...) | test.rs:29:13:29:23 | ... = ... | | +| test.rs:29:22:29:22 | i | test.rs:29:17:29:23 | next(...) | | | test.rs:30:13:32:13 | ExprStmt | test.rs:30:16:30:16 | i | | -| test.rs:30:13:32:13 | IfExpr | test.rs:33:13:35:13 | ExprStmt | | +| test.rs:30:13:32:13 | if ... {...} | test.rs:33:13:35:13 | ExprStmt | | | test.rs:30:16:30:16 | i | test.rs:30:20:30:24 | 10000 | | -| test.rs:30:16:30:24 | ... > ... | test.rs:30:13:32:13 | IfExpr | false | +| test.rs:30:16:30:24 | ... > ... | test.rs:30:13:32:13 | if ... {...} | false | | test.rs:30:16:30:24 | ... > ... | test.rs:31:17:31:29 | ExprStmt | true | | test.rs:30:20:30:24 | 10000 | test.rs:30:16:30:24 | ... > ... | | -| test.rs:31:17:31:28 | ReturnExpr | test.rs:26:5:42:5 | exit test_break_and_continue (normal) | return | +| test.rs:31:17:31:28 | return false | test.rs:26:5:42:5 | exit fn test_break_and_continue (normal) | return | | test.rs:31:17:31:29 | ExprStmt | test.rs:31:24:31:28 | false | | -| test.rs:31:24:31:28 | false | test.rs:31:17:31:28 | ReturnExpr | | +| test.rs:31:24:31:28 | false | test.rs:31:17:31:28 | return false | | | test.rs:33:13:35:13 | ExprStmt | test.rs:33:16:33:16 | i | | -| test.rs:33:13:35:13 | IfExpr | test.rs:36:13:38:13 | ExprStmt | | +| test.rs:33:13:35:13 | if ... {...} | test.rs:36:13:38:13 | ExprStmt | | | test.rs:33:16:33:16 | i | test.rs:33:21:33:21 | 1 | | -| test.rs:33:16:33:21 | ... == ... | test.rs:33:13:35:13 | IfExpr | false | +| test.rs:33:16:33:21 | ... == ... | test.rs:33:13:35:13 | if ... {...} | false | | test.rs:33:16:33:21 | ... == ... | test.rs:34:17:34:22 | ExprStmt | true | | test.rs:33:21:33:21 | 1 | test.rs:33:16:33:21 | ... == ... | | -| test.rs:34:17:34:21 | BreakExpr | test.rs:28:9:40:9 | LoopExpr | break | -| test.rs:34:17:34:22 | ExprStmt | test.rs:34:17:34:21 | BreakExpr | | +| test.rs:34:17:34:21 | break | test.rs:28:9:40:9 | loop { ... } | break | +| test.rs:34:17:34:22 | ExprStmt | test.rs:34:17:34:21 | break | | | test.rs:36:13:38:13 | ExprStmt | test.rs:36:16:36:16 | i | | -| test.rs:36:13:38:13 | IfExpr | test.rs:39:13:39:13 | i | | +| test.rs:36:13:38:13 | if ... {...} | test.rs:39:13:39:13 | i | | | test.rs:36:16:36:16 | i | test.rs:36:20:36:20 | 2 | | | test.rs:36:16:36:20 | ... % ... | test.rs:36:25:36:25 | 0 | | -| test.rs:36:16:36:25 | ... != ... | test.rs:36:13:38:13 | IfExpr | false | +| test.rs:36:16:36:25 | ... != ... | test.rs:36:13:38:13 | if ... {...} | false | | test.rs:36:16:36:25 | ... != ... | test.rs:37:17:37:25 | ExprStmt | true | | test.rs:36:20:36:20 | 2 | test.rs:36:16:36:20 | ... % ... | | | test.rs:36:25:36:25 | 0 | test.rs:36:16:36:25 | ... != ... | | -| test.rs:37:17:37:24 | ContinueExpr | test.rs:29:13:29:24 | ExprStmt | continue | -| test.rs:37:17:37:25 | ExprStmt | test.rs:37:17:37:24 | ContinueExpr | | +| test.rs:37:17:37:24 | continue | test.rs:29:13:29:24 | ExprStmt | continue | +| test.rs:37:17:37:25 | ExprStmt | test.rs:37:17:37:24 | continue | | | test.rs:39:13:39:13 | i | test.rs:39:17:39:17 | i | | -| test.rs:39:13:39:21 | ... = ... | test.rs:28:14:40:9 | BlockExpr | | +| test.rs:39:13:39:21 | ... = ... | test.rs:28:14:40:9 | { ... } | | | test.rs:39:17:39:17 | i | test.rs:39:21:39:21 | 2 | | | test.rs:39:17:39:21 | ... / ... | test.rs:39:13:39:21 | ... = ... | | | test.rs:39:21:39:21 | 2 | test.rs:39:17:39:21 | ... / ... | | -| test.rs:41:9:41:19 | ReturnExpr | test.rs:26:5:42:5 | exit test_break_and_continue (normal) | return | +| test.rs:41:9:41:19 | return true | test.rs:26:5:42:5 | exit fn test_break_and_continue (normal) | return | | test.rs:41:9:41:20 | ExprStmt | test.rs:41:16:41:19 | true | | -| test.rs:41:16:41:19 | true | test.rs:41:9:41:19 | ReturnExpr | | -| test.rs:44:5:56:5 | enter test_break_with_labels | test.rs:44:31:44:31 | b | | -| test.rs:44:5:56:5 | exit test_break_with_labels (normal) | test.rs:44:5:56:5 | exit test_break_with_labels | | -| test.rs:44:31:44:31 | b | test.rs:44:31:44:37 | Param | match | -| test.rs:44:31:44:37 | Param | test.rs:45:9:54:9 | ExprStmt | | -| test.rs:44:48:56:5 | BlockExpr | test.rs:44:5:56:5 | exit test_break_with_labels (normal) | | +| test.rs:41:16:41:19 | true | test.rs:41:9:41:19 | return true | | +| test.rs:44:5:56:5 | enter fn test_break_with_labels | test.rs:44:31:44:31 | b | | +| test.rs:44:5:56:5 | exit fn test_break_with_labels (normal) | test.rs:44:5:56:5 | exit fn test_break_with_labels | | +| test.rs:44:31:44:31 | b | test.rs:44:31:44:37 | ...: bool | match | +| test.rs:44:31:44:37 | ...: bool | test.rs:45:9:54:9 | ExprStmt | | +| test.rs:44:48:56:5 | { ... } | test.rs:44:5:56:5 | exit fn test_break_with_labels (normal) | | +| test.rs:45:9:54:9 | 'outer: loop { ... } | test.rs:55:9:55:12 | true | | | test.rs:45:9:54:9 | ExprStmt | test.rs:47:17:51:17 | ExprStmt | | -| test.rs:45:9:54:9 | LoopExpr | test.rs:55:9:55:12 | true | | -| test.rs:45:22:54:9 | BlockExpr | test.rs:47:17:51:17 | ExprStmt | | -| test.rs:46:13:53:13 | LoopExpr | test.rs:45:22:54:9 | BlockExpr | | +| test.rs:45:22:54:9 | { ... } | test.rs:47:17:51:17 | ExprStmt | | +| test.rs:46:13:53:13 | 'inner: loop { ... } | test.rs:45:22:54:9 | { ... } | | | test.rs:47:17:51:17 | ExprStmt | test.rs:47:20:47:20 | b | | -| test.rs:47:17:51:17 | IfExpr | test.rs:52:17:52:29 | ExprStmt | | +| test.rs:47:17:51:17 | if b {...} else {...} | test.rs:52:17:52:29 | ExprStmt | | | test.rs:47:20:47:20 | b | test.rs:48:21:48:26 | ExprStmt | true | | test.rs:47:20:47:20 | b | test.rs:49:27:49:27 | b | false | -| test.rs:48:21:48:25 | BreakExpr | test.rs:46:13:53:13 | LoopExpr | break | -| test.rs:48:21:48:26 | ExprStmt | test.rs:48:21:48:25 | BreakExpr | | -| test.rs:49:24:51:17 | IfExpr | test.rs:47:17:51:17 | IfExpr | | -| test.rs:49:27:49:27 | b | test.rs:49:24:51:17 | IfExpr | false | +| test.rs:48:21:48:25 | break | test.rs:46:13:53:13 | 'inner: loop { ... } | break | +| test.rs:48:21:48:26 | ExprStmt | test.rs:48:21:48:25 | break | | +| test.rs:49:24:51:17 | if b {...} | test.rs:47:17:51:17 | if b {...} else {...} | | +| test.rs:49:27:49:27 | b | test.rs:49:24:51:17 | if b {...} | false | | test.rs:49:27:49:27 | b | test.rs:50:21:50:33 | ExprStmt | true | -| test.rs:50:21:50:32 | BreakExpr | test.rs:45:9:54:9 | LoopExpr | break | -| test.rs:50:21:50:33 | ExprStmt | test.rs:50:21:50:32 | BreakExpr | | -| test.rs:52:17:52:28 | BreakExpr | test.rs:46:13:53:13 | LoopExpr | break | -| test.rs:52:17:52:29 | ExprStmt | test.rs:52:17:52:28 | BreakExpr | | -| test.rs:55:9:55:12 | true | test.rs:44:48:56:5 | BlockExpr | | -| test.rs:58:5:70:5 | enter test_continue_with_labels | test.rs:58:34:58:34 | b | | -| test.rs:58:34:58:34 | b | test.rs:58:34:58:40 | Param | match | -| test.rs:58:34:58:40 | Param | test.rs:60:13:60:14 | ExprStmt | | +| test.rs:50:21:50:32 | break ''outer | test.rs:45:9:54:9 | 'outer: loop { ... } | break | +| test.rs:50:21:50:33 | ExprStmt | test.rs:50:21:50:32 | break ''outer | | +| test.rs:52:17:52:28 | break ''inner | test.rs:46:13:53:13 | 'inner: loop { ... } | break | +| test.rs:52:17:52:29 | ExprStmt | test.rs:52:17:52:28 | break ''inner | | +| test.rs:55:9:55:12 | true | test.rs:44:48:56:5 | { ... } | | +| test.rs:58:5:70:5 | enter fn test_continue_with_labels | test.rs:58:34:58:34 | b | | +| test.rs:58:34:58:34 | b | test.rs:58:34:58:40 | ...: bool | match | +| test.rs:58:34:58:40 | ...: bool | test.rs:60:13:60:14 | ExprStmt | | | test.rs:60:13:60:13 | 1 | test.rs:62:17:66:17 | ExprStmt | | | test.rs:60:13:60:14 | ExprStmt | test.rs:60:13:60:13 | 1 | | | test.rs:62:17:66:17 | ExprStmt | test.rs:62:20:62:20 | b | | -| test.rs:62:17:66:17 | IfExpr | test.rs:67:17:67:32 | ExprStmt | | +| test.rs:62:17:66:17 | if b {...} else {...} | test.rs:67:17:67:32 | ExprStmt | | | test.rs:62:20:62:20 | b | test.rs:63:21:63:29 | ExprStmt | true | | test.rs:62:20:62:20 | b | test.rs:64:27:64:27 | b | false | -| test.rs:63:21:63:28 | ContinueExpr | test.rs:62:17:66:17 | ExprStmt | continue | -| test.rs:63:21:63:29 | ExprStmt | test.rs:63:21:63:28 | ContinueExpr | | -| test.rs:64:24:66:17 | IfExpr | test.rs:62:17:66:17 | IfExpr | | -| test.rs:64:27:64:27 | b | test.rs:64:24:66:17 | IfExpr | false | +| test.rs:63:21:63:28 | continue | test.rs:62:17:66:17 | ExprStmt | continue | +| test.rs:63:21:63:29 | ExprStmt | test.rs:63:21:63:28 | continue | | +| test.rs:64:24:66:17 | if b {...} | test.rs:62:17:66:17 | if b {...} else {...} | | +| test.rs:64:27:64:27 | b | test.rs:64:24:66:17 | if b {...} | false | | test.rs:64:27:64:27 | b | test.rs:65:21:65:36 | ExprStmt | true | -| test.rs:65:21:65:35 | ContinueExpr | test.rs:60:13:60:14 | ExprStmt | continue | -| test.rs:65:21:65:36 | ExprStmt | test.rs:65:21:65:35 | ContinueExpr | | -| test.rs:67:17:67:31 | ContinueExpr | test.rs:62:17:66:17 | ExprStmt | continue | -| test.rs:67:17:67:32 | ExprStmt | test.rs:67:17:67:31 | ContinueExpr | | -| test.rs:72:5:84:5 | enter test_loop_label_shadowing | test.rs:72:34:72:34 | b | | -| test.rs:72:34:72:34 | b | test.rs:72:34:72:40 | Param | match | -| test.rs:72:34:72:40 | Param | test.rs:74:13:74:14 | ExprStmt | | +| test.rs:65:21:65:35 | continue 'outer | test.rs:60:13:60:14 | ExprStmt | continue | +| test.rs:65:21:65:36 | ExprStmt | test.rs:65:21:65:35 | continue 'outer | | +| test.rs:67:17:67:31 | continue 'inner | test.rs:62:17:66:17 | ExprStmt | continue | +| test.rs:67:17:67:32 | ExprStmt | test.rs:67:17:67:31 | continue 'inner | | +| test.rs:72:5:84:5 | enter fn test_loop_label_shadowing | test.rs:72:34:72:34 | b | | +| test.rs:72:34:72:34 | b | test.rs:72:34:72:40 | ...: bool | match | +| test.rs:72:34:72:40 | ...: bool | test.rs:74:13:74:14 | ExprStmt | | | test.rs:74:13:74:13 | 1 | test.rs:76:17:80:17 | ExprStmt | | | test.rs:74:13:74:14 | ExprStmt | test.rs:74:13:74:13 | 1 | | | test.rs:76:17:80:17 | ExprStmt | test.rs:76:20:76:20 | b | | -| test.rs:76:17:80:17 | IfExpr | test.rs:81:17:81:32 | ExprStmt | | +| test.rs:76:17:80:17 | if b {...} else {...} | test.rs:81:17:81:32 | ExprStmt | | | test.rs:76:20:76:20 | b | test.rs:77:21:77:29 | ExprStmt | true | | test.rs:76:20:76:20 | b | test.rs:78:27:78:27 | b | false | -| test.rs:77:21:77:28 | ContinueExpr | test.rs:76:17:80:17 | ExprStmt | continue | -| test.rs:77:21:77:29 | ExprStmt | test.rs:77:21:77:28 | ContinueExpr | | -| test.rs:78:24:80:17 | IfExpr | test.rs:76:17:80:17 | IfExpr | | -| test.rs:78:27:78:27 | b | test.rs:78:24:80:17 | IfExpr | false | +| test.rs:77:21:77:28 | continue | test.rs:76:17:80:17 | ExprStmt | continue | +| test.rs:77:21:77:29 | ExprStmt | test.rs:77:21:77:28 | continue | | +| test.rs:78:24:80:17 | if b {...} | test.rs:76:17:80:17 | if b {...} else {...} | | +| test.rs:78:27:78:27 | b | test.rs:78:24:80:17 | if b {...} | false | | test.rs:78:27:78:27 | b | test.rs:79:21:79:36 | ExprStmt | true | -| test.rs:79:21:79:35 | ContinueExpr | test.rs:76:17:80:17 | ExprStmt | continue | -| test.rs:79:21:79:36 | ExprStmt | test.rs:79:21:79:35 | ContinueExpr | | -| test.rs:81:17:81:31 | ContinueExpr | test.rs:76:17:80:17 | ExprStmt | continue | -| test.rs:81:17:81:32 | ExprStmt | test.rs:81:17:81:31 | ContinueExpr | | -| test.rs:86:5:95:5 | enter test_while | test.rs:86:19:86:19 | i | | -| test.rs:86:5:95:5 | exit test_while (normal) | test.rs:86:5:95:5 | exit test_while | | -| test.rs:86:19:86:19 | i | test.rs:86:19:86:24 | Param | match | -| test.rs:86:19:86:24 | Param | test.rs:87:9:87:25 | LetStmt | | -| test.rs:86:27:95:5 | BlockExpr | test.rs:86:5:95:5 | exit test_while (normal) | | -| test.rs:87:9:87:25 | LetStmt | test.rs:87:21:87:24 | true | | +| test.rs:79:21:79:35 | continue 'label | test.rs:76:17:80:17 | ExprStmt | continue | +| test.rs:79:21:79:36 | ExprStmt | test.rs:79:21:79:35 | continue 'label | | +| test.rs:81:17:81:31 | continue 'label | test.rs:76:17:80:17 | ExprStmt | continue | +| test.rs:81:17:81:32 | ExprStmt | test.rs:81:17:81:31 | continue 'label | | +| test.rs:86:5:95:5 | enter fn test_while | test.rs:86:19:86:19 | i | | +| test.rs:86:5:95:5 | exit fn test_while (normal) | test.rs:86:5:95:5 | exit fn test_while | | +| test.rs:86:19:86:19 | i | test.rs:86:19:86:24 | ...: i64 | match | +| test.rs:86:19:86:24 | ...: i64 | test.rs:87:9:87:25 | let ... = true | | +| test.rs:86:27:95:5 | { ... } | test.rs:86:5:95:5 | exit fn test_while (normal) | | +| test.rs:87:9:87:25 | let ... = true | test.rs:87:21:87:24 | true | | | test.rs:87:13:87:17 | b | test.rs:88:15:88:15 | b | match | | test.rs:87:21:87:24 | true | test.rs:87:13:87:17 | b | | -| test.rs:88:9:94:9 | WhileExpr | test.rs:86:27:95:5 | BlockExpr | | -| test.rs:88:15:88:15 | b | test.rs:88:9:94:9 | WhileExpr | false | +| test.rs:88:9:94:9 | while b { ... } | test.rs:86:27:95:5 | { ... } | | +| test.rs:88:15:88:15 | b | test.rs:88:9:94:9 | while b { ... } | false | | test.rs:88:15:88:15 | b | test.rs:89:13:89:14 | ExprStmt | true | -| test.rs:88:17:94:9 | BlockExpr | test.rs:88:15:88:15 | b | | +| test.rs:88:17:94:9 | { ... } | test.rs:88:15:88:15 | b | | | test.rs:89:13:89:13 | 1 | test.rs:90:13:92:13 | ExprStmt | | | test.rs:89:13:89:14 | ExprStmt | test.rs:89:13:89:13 | 1 | | | test.rs:90:13:92:13 | ExprStmt | test.rs:90:17:90:17 | i | | -| test.rs:90:13:92:13 | IfExpr | test.rs:93:13:93:22 | ExprStmt | | +| test.rs:90:13:92:13 | if ... {...} | test.rs:93:13:93:22 | ExprStmt | | | test.rs:90:17:90:17 | i | test.rs:90:21:90:21 | 0 | | -| test.rs:90:17:90:21 | ... > ... | test.rs:90:13:92:13 | IfExpr | false | +| test.rs:90:17:90:21 | ... > ... | test.rs:90:13:92:13 | if ... {...} | false | | test.rs:90:17:90:21 | ... > ... | test.rs:91:17:91:22 | ExprStmt | true | | test.rs:90:21:90:21 | 0 | test.rs:90:17:90:21 | ... > ... | | -| test.rs:91:17:91:21 | BreakExpr | test.rs:88:9:94:9 | WhileExpr | break | -| test.rs:91:17:91:22 | ExprStmt | test.rs:91:17:91:21 | BreakExpr | | +| test.rs:91:17:91:21 | break | test.rs:88:9:94:9 | while b { ... } | break | +| test.rs:91:17:91:22 | ExprStmt | test.rs:91:17:91:21 | break | | | test.rs:93:13:93:13 | b | test.rs:93:17:93:21 | false | | -| test.rs:93:13:93:21 | ... = ... | test.rs:88:17:94:9 | BlockExpr | | +| test.rs:93:13:93:21 | ... = ... | test.rs:88:17:94:9 | { ... } | | | test.rs:93:13:93:22 | ExprStmt | test.rs:93:13:93:13 | b | | | test.rs:93:17:93:21 | false | test.rs:93:13:93:21 | ... = ... | | -| test.rs:97:5:104:5 | enter test_while_let | test.rs:98:9:98:29 | LetStmt | | -| test.rs:97:5:104:5 | exit test_while_let (normal) | test.rs:97:5:104:5 | exit test_while_let | | -| test.rs:97:25:104:5 | BlockExpr | test.rs:97:5:104:5 | exit test_while_let (normal) | | -| test.rs:98:9:98:29 | LetStmt | test.rs:98:24:98:24 | 1 | | -| test.rs:98:13:98:20 | iter | test.rs:99:15:99:39 | LetExpr | match | +| test.rs:97:5:104:5 | enter fn test_while_let | test.rs:98:9:98:29 | let ... = ... | | +| test.rs:97:5:104:5 | exit fn test_while_let (normal) | test.rs:97:5:104:5 | exit fn test_while_let | | +| test.rs:97:25:104:5 | { ... } | test.rs:97:5:104:5 | exit fn test_while_let (normal) | | +| test.rs:98:9:98:29 | let ... = ... | test.rs:98:24:98:24 | 1 | | +| test.rs:98:13:98:20 | iter | test.rs:99:15:99:39 | let ... = ... | match | | test.rs:98:24:98:24 | 1 | test.rs:98:27:98:28 | 10 | | -| test.rs:98:24:98:28 | RangeExpr | test.rs:98:13:98:20 | iter | | -| test.rs:98:27:98:28 | 10 | test.rs:98:24:98:28 | RangeExpr | | -| test.rs:99:9:103:9 | WhileExpr | test.rs:97:25:104:5 | BlockExpr | | -| test.rs:99:15:99:39 | LetExpr | test.rs:99:29:99:32 | iter | | -| test.rs:99:19:99:25 | TupleStructPat | test.rs:99:9:103:9 | WhileExpr | no-match | +| test.rs:98:24:98:28 | 1..10 | test.rs:98:13:98:20 | iter | | +| test.rs:98:27:98:28 | 10 | test.rs:98:24:98:28 | 1..10 | | +| test.rs:99:9:103:9 | while ... { ... } | test.rs:97:25:104:5 | { ... } | | +| test.rs:99:15:99:39 | let ... = ... | test.rs:99:29:99:32 | iter | | +| test.rs:99:19:99:25 | TupleStructPat | test.rs:99:9:103:9 | while ... { ... } | no-match | | test.rs:99:19:99:25 | TupleStructPat | test.rs:99:24:99:24 | x | match | | test.rs:99:24:99:24 | x | test.rs:100:17:100:17 | x | match | | test.rs:99:29:99:32 | iter | test.rs:99:29:99:39 | ... .next(...) | | | test.rs:99:29:99:39 | ... .next(...) | test.rs:99:19:99:25 | TupleStructPat | | -| test.rs:99:41:103:9 | BlockExpr | test.rs:99:15:99:39 | LetExpr | | -| test.rs:100:13:102:13 | IfExpr | test.rs:99:41:103:9 | BlockExpr | | +| test.rs:99:41:103:9 | { ... } | test.rs:99:15:99:39 | let ... = ... | | +| test.rs:100:13:102:13 | if ... {...} | test.rs:99:41:103:9 | { ... } | | | test.rs:100:17:100:17 | x | test.rs:100:22:100:22 | 5 | | -| test.rs:100:17:100:22 | ... == ... | test.rs:100:13:102:13 | IfExpr | false | +| test.rs:100:17:100:22 | ... == ... | test.rs:100:13:102:13 | if ... {...} | false | | test.rs:100:17:100:22 | ... == ... | test.rs:101:17:101:22 | ExprStmt | true | | test.rs:100:22:100:22 | 5 | test.rs:100:17:100:22 | ... == ... | | -| test.rs:101:17:101:21 | BreakExpr | test.rs:99:9:103:9 | WhileExpr | break | -| test.rs:101:17:101:22 | ExprStmt | test.rs:101:17:101:21 | BreakExpr | | -| test.rs:106:5:113:5 | enter test_for | test.rs:106:17:106:17 | j | | -| test.rs:106:5:113:5 | exit test_for (normal) | test.rs:106:5:113:5 | exit test_for | | -| test.rs:106:17:106:17 | j | test.rs:106:17:106:22 | Param | match | -| test.rs:106:17:106:22 | Param | test.rs:107:18:107:18 | 0 | | -| test.rs:106:25:113:5 | BlockExpr | test.rs:106:5:113:5 | exit test_for (normal) | | -| test.rs:107:9:112:9 | ForExpr | test.rs:106:25:113:5 | BlockExpr | | -| test.rs:107:13:107:13 | i | test.rs:107:9:112:9 | ForExpr | no-match | +| test.rs:101:17:101:21 | break | test.rs:99:9:103:9 | while ... { ... } | break | +| test.rs:101:17:101:22 | ExprStmt | test.rs:101:17:101:21 | break | | +| test.rs:106:5:113:5 | enter fn test_for | test.rs:106:17:106:17 | j | | +| test.rs:106:5:113:5 | exit fn test_for (normal) | test.rs:106:5:113:5 | exit fn test_for | | +| test.rs:106:17:106:17 | j | test.rs:106:17:106:22 | ...: i64 | match | +| test.rs:106:17:106:22 | ...: i64 | test.rs:107:18:107:18 | 0 | | +| test.rs:106:25:113:5 | { ... } | test.rs:106:5:113:5 | exit fn test_for (normal) | | +| test.rs:107:9:112:9 | for ... in ... { ... } | test.rs:106:25:113:5 | { ... } | | +| test.rs:107:13:107:13 | i | test.rs:107:9:112:9 | for ... in ... { ... } | no-match | | test.rs:107:13:107:13 | i | test.rs:108:13:110:13 | ExprStmt | match | | test.rs:107:18:107:18 | 0 | test.rs:107:21:107:22 | 10 | | -| test.rs:107:18:107:22 | RangeExpr | test.rs:107:13:107:13 | i | | -| test.rs:107:21:107:22 | 10 | test.rs:107:18:107:22 | RangeExpr | | -| test.rs:107:24:112:9 | BlockExpr | test.rs:107:13:107:13 | i | | +| test.rs:107:18:107:22 | 0..10 | test.rs:107:13:107:13 | i | | +| test.rs:107:21:107:22 | 10 | test.rs:107:18:107:22 | 0..10 | | +| test.rs:107:24:112:9 | { ... } | test.rs:107:13:107:13 | i | | | test.rs:108:13:110:13 | ExprStmt | test.rs:108:17:108:17 | i | | -| test.rs:108:13:110:13 | IfExpr | test.rs:111:13:111:14 | ExprStmt | | +| test.rs:108:13:110:13 | if ... {...} | test.rs:111:13:111:14 | ExprStmt | | | test.rs:108:17:108:17 | i | test.rs:108:22:108:22 | j | | -| test.rs:108:17:108:22 | ... == ... | test.rs:108:13:110:13 | IfExpr | false | +| test.rs:108:17:108:22 | ... == ... | test.rs:108:13:110:13 | if ... {...} | false | | test.rs:108:17:108:22 | ... == ... | test.rs:109:17:109:22 | ExprStmt | true | | test.rs:108:22:108:22 | j | test.rs:108:17:108:22 | ... == ... | | -| test.rs:109:17:109:21 | BreakExpr | test.rs:107:9:112:9 | ForExpr | break | -| test.rs:109:17:109:22 | ExprStmt | test.rs:109:17:109:21 | BreakExpr | | -| test.rs:111:13:111:13 | 1 | test.rs:107:24:112:9 | BlockExpr | | +| test.rs:109:17:109:21 | break | test.rs:107:9:112:9 | for ... in ... { ... } | break | +| test.rs:109:17:109:22 | ExprStmt | test.rs:109:17:109:21 | break | | +| test.rs:111:13:111:13 | 1 | test.rs:107:24:112:9 | { ... } | | | test.rs:111:13:111:14 | ExprStmt | test.rs:111:13:111:13 | 1 | | -| test.rs:115:5:119:5 | enter break_with_return | test.rs:117:13:117:27 | ExprStmt | | -| test.rs:115:5:119:5 | exit break_with_return (normal) | test.rs:115:5:119:5 | exit break_with_return | | +| test.rs:115:5:119:5 | enter fn break_with_return | test.rs:117:13:117:27 | ExprStmt | | +| test.rs:115:5:119:5 | exit fn break_with_return (normal) | test.rs:115:5:119:5 | exit fn break_with_return | | | test.rs:117:13:117:27 | ExprStmt | test.rs:117:26:117:26 | 1 | | -| test.rs:117:19:117:26 | ReturnExpr | test.rs:115:5:119:5 | exit break_with_return (normal) | return | -| test.rs:117:26:117:26 | 1 | test.rs:117:19:117:26 | ReturnExpr | | -| test.rs:122:1:125:1 | enter test_nested_function | test.rs:122:25:122:25 | n | | -| test.rs:122:1:125:1 | exit test_nested_function (normal) | test.rs:122:1:125:1 | exit test_nested_function | | -| test.rs:122:25:122:25 | n | test.rs:122:25:122:30 | Param | match | -| test.rs:122:25:122:30 | Param | test.rs:123:5:123:28 | LetStmt | | -| test.rs:122:40:125:1 | BlockExpr | test.rs:122:1:125:1 | exit test_nested_function (normal) | | -| test.rs:123:5:123:28 | LetStmt | test.rs:123:19:123:27 | ClosureExpr | | +| test.rs:117:19:117:26 | return 1 | test.rs:115:5:119:5 | exit fn break_with_return (normal) | return | +| test.rs:117:26:117:26 | 1 | test.rs:117:19:117:26 | return 1 | | +| test.rs:122:1:125:1 | enter fn test_nested_function | test.rs:122:25:122:25 | n | | +| test.rs:122:1:125:1 | exit fn test_nested_function (normal) | test.rs:122:1:125:1 | exit fn test_nested_function | | +| test.rs:122:25:122:25 | n | test.rs:122:25:122:30 | ...: i64 | match | +| test.rs:122:25:122:30 | ...: i64 | test.rs:123:5:123:28 | let ... = ... | | +| test.rs:122:40:125:1 | { ... } | test.rs:122:1:125:1 | exit fn test_nested_function (normal) | | +| test.rs:123:5:123:28 | let ... = ... | test.rs:123:19:123:27 | \|...\| ... | | | test.rs:123:9:123:15 | add_one | test.rs:124:5:124:11 | add_one | match | -| test.rs:123:19:123:27 | ClosureExpr | test.rs:123:9:123:15 | add_one | | -| test.rs:123:19:123:27 | enter ClosureExpr | test.rs:123:20:123:20 | i | | -| test.rs:123:19:123:27 | exit ClosureExpr (normal) | test.rs:123:19:123:27 | exit ClosureExpr | | -| test.rs:123:20:123:20 | Param | test.rs:123:23:123:23 | i | | -| test.rs:123:20:123:20 | i | test.rs:123:20:123:20 | Param | match | +| test.rs:123:19:123:27 | \|...\| ... | test.rs:123:9:123:15 | add_one | | +| test.rs:123:19:123:27 | enter \|...\| ... | test.rs:123:20:123:20 | i | | +| test.rs:123:19:123:27 | exit \|...\| ... (normal) | test.rs:123:19:123:27 | exit \|...\| ... | | +| test.rs:123:20:123:20 | ... | test.rs:123:23:123:23 | i | | +| test.rs:123:20:123:20 | i | test.rs:123:20:123:20 | ... | match | | test.rs:123:23:123:23 | i | test.rs:123:27:123:27 | 1 | | -| test.rs:123:23:123:27 | ... + ... | test.rs:123:19:123:27 | exit ClosureExpr (normal) | | +| test.rs:123:23:123:27 | ... + ... | test.rs:123:19:123:27 | exit \|...\| ... (normal) | | | test.rs:123:27:123:27 | 1 | test.rs:123:23:123:27 | ... + ... | | | test.rs:124:5:124:11 | add_one | test.rs:124:13:124:19 | add_one | | -| test.rs:124:5:124:23 | CallExpr | test.rs:122:40:125:1 | BlockExpr | | +| test.rs:124:5:124:23 | add_one(...) | test.rs:122:40:125:1 | { ... } | | | test.rs:124:13:124:19 | add_one | test.rs:124:21:124:21 | n | | -| test.rs:124:13:124:22 | CallExpr | test.rs:124:5:124:23 | CallExpr | | -| test.rs:124:21:124:21 | n | test.rs:124:13:124:22 | CallExpr | | -| test.rs:129:5:135:5 | enter test_if_else | test.rs:129:21:129:21 | n | | -| test.rs:129:5:135:5 | exit test_if_else (normal) | test.rs:129:5:135:5 | exit test_if_else | | -| test.rs:129:21:129:21 | n | test.rs:129:21:129:26 | Param | match | -| test.rs:129:21:129:26 | Param | test.rs:130:12:130:12 | n | | -| test.rs:129:36:135:5 | BlockExpr | test.rs:129:5:135:5 | exit test_if_else (normal) | | -| test.rs:130:9:134:9 | IfExpr | test.rs:129:36:135:5 | BlockExpr | | +| test.rs:124:13:124:22 | add_one(...) | test.rs:124:5:124:23 | add_one(...) | | +| test.rs:124:21:124:21 | n | test.rs:124:13:124:22 | add_one(...) | | +| test.rs:129:5:135:5 | enter fn test_if_else | test.rs:129:21:129:21 | n | | +| test.rs:129:5:135:5 | exit fn test_if_else (normal) | test.rs:129:5:135:5 | exit fn test_if_else | | +| test.rs:129:21:129:21 | n | test.rs:129:21:129:26 | ...: i64 | match | +| test.rs:129:21:129:26 | ...: i64 | test.rs:130:12:130:12 | n | | +| test.rs:129:36:135:5 | { ... } | test.rs:129:5:135:5 | exit fn test_if_else (normal) | | +| test.rs:130:9:134:9 | if ... {...} else {...} | test.rs:129:36:135:5 | { ... } | | | test.rs:130:12:130:12 | n | test.rs:130:17:130:17 | 0 | | | test.rs:130:12:130:17 | ... <= ... | test.rs:131:13:131:13 | 0 | true | | test.rs:130:12:130:17 | ... <= ... | test.rs:133:13:133:13 | n | false | | test.rs:130:17:130:17 | 0 | test.rs:130:12:130:17 | ... <= ... | | -| test.rs:130:19:132:9 | BlockExpr | test.rs:130:9:134:9 | IfExpr | | -| test.rs:131:13:131:13 | 0 | test.rs:130:19:132:9 | BlockExpr | | -| test.rs:132:16:134:9 | BlockExpr | test.rs:130:9:134:9 | IfExpr | | +| test.rs:130:19:132:9 | { ... } | test.rs:130:9:134:9 | if ... {...} else {...} | | +| test.rs:131:13:131:13 | 0 | test.rs:130:19:132:9 | { ... } | | +| test.rs:132:16:134:9 | { ... } | test.rs:130:9:134:9 | if ... {...} else {...} | | | test.rs:133:13:133:13 | n | test.rs:133:17:133:17 | 1 | | -| test.rs:133:13:133:17 | ... - ... | test.rs:132:16:134:9 | BlockExpr | | +| test.rs:133:13:133:17 | ... - ... | test.rs:132:16:134:9 | { ... } | | | test.rs:133:17:133:17 | 1 | test.rs:133:13:133:17 | ... - ... | | -| test.rs:137:5:143:5 | enter test_if_let_else | test.rs:137:25:137:25 | a | | -| test.rs:137:5:143:5 | exit test_if_let_else (normal) | test.rs:137:5:143:5 | exit test_if_let_else | | -| test.rs:137:25:137:25 | a | test.rs:137:25:137:38 | Param | match | -| test.rs:137:25:137:38 | Param | test.rs:138:12:138:26 | LetExpr | | -| test.rs:137:48:143:5 | BlockExpr | test.rs:137:5:143:5 | exit test_if_let_else (normal) | | -| test.rs:138:9:142:9 | IfExpr | test.rs:137:48:143:5 | BlockExpr | | -| test.rs:138:12:138:26 | LetExpr | test.rs:138:26:138:26 | a | | +| test.rs:137:5:143:5 | enter fn test_if_let_else | test.rs:137:25:137:25 | a | | +| test.rs:137:5:143:5 | exit fn test_if_let_else (normal) | test.rs:137:5:143:5 | exit fn test_if_let_else | | +| test.rs:137:25:137:25 | a | test.rs:137:25:137:38 | ...: Option::<...> | match | +| test.rs:137:25:137:38 | ...: Option::<...> | test.rs:138:12:138:26 | let ... = a | | +| test.rs:137:48:143:5 | { ... } | test.rs:137:5:143:5 | exit fn test_if_let_else (normal) | | +| test.rs:138:9:142:9 | if ... {...} else {...} | test.rs:137:48:143:5 | { ... } | | +| test.rs:138:12:138:26 | let ... = a | test.rs:138:26:138:26 | a | | | test.rs:138:16:138:22 | TupleStructPat | test.rs:138:21:138:21 | n | match | | test.rs:138:16:138:22 | TupleStructPat | test.rs:141:13:141:13 | 0 | no-match | | test.rs:138:21:138:21 | n | test.rs:139:13:139:13 | n | match | | test.rs:138:26:138:26 | a | test.rs:138:16:138:22 | TupleStructPat | | -| test.rs:138:28:140:9 | BlockExpr | test.rs:138:9:142:9 | IfExpr | | -| test.rs:139:13:139:13 | n | test.rs:138:28:140:9 | BlockExpr | | -| test.rs:140:16:142:9 | BlockExpr | test.rs:138:9:142:9 | IfExpr | | -| test.rs:141:13:141:13 | 0 | test.rs:140:16:142:9 | BlockExpr | | -| test.rs:145:5:150:5 | enter test_if_let | test.rs:145:20:145:20 | a | | -| test.rs:145:5:150:5 | exit test_if_let (normal) | test.rs:145:5:150:5 | exit test_if_let | | -| test.rs:145:20:145:20 | a | test.rs:145:20:145:33 | Param | match | -| test.rs:145:20:145:33 | Param | test.rs:146:9:148:9 | ExprStmt | | -| test.rs:145:43:150:5 | BlockExpr | test.rs:145:5:150:5 | exit test_if_let (normal) | | -| test.rs:146:9:148:9 | ExprStmt | test.rs:146:12:146:26 | LetExpr | | -| test.rs:146:9:148:9 | IfExpr | test.rs:149:9:149:9 | 0 | | -| test.rs:146:12:146:26 | LetExpr | test.rs:146:26:146:26 | a | | -| test.rs:146:16:146:22 | TupleStructPat | test.rs:146:9:148:9 | IfExpr | no-match | +| test.rs:138:28:140:9 | { ... } | test.rs:138:9:142:9 | if ... {...} else {...} | | +| test.rs:139:13:139:13 | n | test.rs:138:28:140:9 | { ... } | | +| test.rs:140:16:142:9 | { ... } | test.rs:138:9:142:9 | if ... {...} else {...} | | +| test.rs:141:13:141:13 | 0 | test.rs:140:16:142:9 | { ... } | | +| test.rs:145:5:150:5 | enter fn test_if_let | test.rs:145:20:145:20 | a | | +| test.rs:145:5:150:5 | exit fn test_if_let (normal) | test.rs:145:5:150:5 | exit fn test_if_let | | +| test.rs:145:20:145:20 | a | test.rs:145:20:145:33 | ...: Option::<...> | match | +| test.rs:145:20:145:33 | ...: Option::<...> | test.rs:146:9:148:9 | ExprStmt | | +| test.rs:145:43:150:5 | { ... } | test.rs:145:5:150:5 | exit fn test_if_let (normal) | | +| test.rs:146:9:148:9 | ExprStmt | test.rs:146:12:146:26 | let ... = a | | +| test.rs:146:9:148:9 | if ... {...} | test.rs:149:9:149:9 | 0 | | +| test.rs:146:12:146:26 | let ... = a | test.rs:146:26:146:26 | a | | +| test.rs:146:16:146:22 | TupleStructPat | test.rs:146:9:148:9 | if ... {...} | no-match | | test.rs:146:16:146:22 | TupleStructPat | test.rs:146:21:146:21 | n | match | | test.rs:146:21:146:21 | n | test.rs:147:13:147:21 | ExprStmt | match | | test.rs:146:26:146:26 | a | test.rs:146:16:146:22 | TupleStructPat | | -| test.rs:147:13:147:20 | ReturnExpr | test.rs:145:5:150:5 | exit test_if_let (normal) | return | +| test.rs:147:13:147:20 | return n | test.rs:145:5:150:5 | exit fn test_if_let (normal) | return | | test.rs:147:13:147:21 | ExprStmt | test.rs:147:20:147:20 | n | | -| test.rs:147:20:147:20 | n | test.rs:147:13:147:20 | ReturnExpr | | -| test.rs:149:9:149:9 | 0 | test.rs:145:43:150:5 | BlockExpr | | -| test.rs:152:5:158:5 | enter test_nested_if | test.rs:152:23:152:23 | a | | -| test.rs:152:5:158:5 | exit test_nested_if (normal) | test.rs:152:5:158:5 | exit test_nested_if | | -| test.rs:152:23:152:23 | a | test.rs:152:23:152:28 | Param | match | -| test.rs:152:23:152:28 | Param | test.rs:153:16:153:16 | a | | -| test.rs:152:38:158:5 | BlockExpr | test.rs:152:5:158:5 | exit test_nested_if (normal) | | -| test.rs:153:9:157:9 | IfExpr | test.rs:152:38:158:5 | BlockExpr | | -| test.rs:153:13:153:48 | [boolean(false)] IfExpr | test.rs:156:13:156:13 | 0 | false | -| test.rs:153:13:153:48 | [boolean(true)] IfExpr | test.rs:154:13:154:13 | 1 | true | +| test.rs:147:20:147:20 | n | test.rs:147:13:147:20 | return n | | +| test.rs:149:9:149:9 | 0 | test.rs:145:43:150:5 | { ... } | | +| test.rs:152:5:158:5 | enter fn test_nested_if | test.rs:152:23:152:23 | a | | +| test.rs:152:5:158:5 | exit fn test_nested_if (normal) | test.rs:152:5:158:5 | exit fn test_nested_if | | +| test.rs:152:23:152:23 | a | test.rs:152:23:152:28 | ...: i64 | match | +| test.rs:152:23:152:28 | ...: i64 | test.rs:153:16:153:16 | a | | +| test.rs:152:38:158:5 | { ... } | test.rs:152:5:158:5 | exit fn test_nested_if (normal) | | +| test.rs:153:9:157:9 | if ... {...} else {...} | test.rs:152:38:158:5 | { ... } | | +| test.rs:153:13:153:48 | [boolean(false)] if ... {...} else {...} | test.rs:156:13:156:13 | 0 | false | +| test.rs:153:13:153:48 | [boolean(true)] if ... {...} else {...} | test.rs:154:13:154:13 | 1 | true | | test.rs:153:16:153:16 | a | test.rs:153:20:153:20 | 0 | | | test.rs:153:16:153:20 | ... < ... | test.rs:153:24:153:24 | a | true | | test.rs:153:16:153:20 | ... < ... | test.rs:153:41:153:41 | a | false | | test.rs:153:20:153:20 | 0 | test.rs:153:16:153:20 | ... < ... | | -| test.rs:153:22:153:32 | [boolean(false)] BlockExpr | test.rs:153:13:153:48 | [boolean(false)] IfExpr | false | -| test.rs:153:22:153:32 | [boolean(true)] BlockExpr | test.rs:153:13:153:48 | [boolean(true)] IfExpr | true | +| test.rs:153:22:153:32 | [boolean(false)] { ... } | test.rs:153:13:153:48 | [boolean(false)] if ... {...} else {...} | false | +| test.rs:153:22:153:32 | [boolean(true)] { ... } | test.rs:153:13:153:48 | [boolean(true)] if ... {...} else {...} | true | | test.rs:153:24:153:24 | a | test.rs:153:29:153:30 | 10 | | -| test.rs:153:24:153:30 | ... < ... | test.rs:153:22:153:32 | [boolean(false)] BlockExpr | false | -| test.rs:153:24:153:30 | ... < ... | test.rs:153:22:153:32 | [boolean(true)] BlockExpr | true | +| test.rs:153:24:153:30 | ... < ... | test.rs:153:22:153:32 | [boolean(false)] { ... } | false | +| test.rs:153:24:153:30 | ... < ... | test.rs:153:22:153:32 | [boolean(true)] { ... } | true | | test.rs:153:28:153:30 | - ... | test.rs:153:24:153:30 | ... < ... | | | test.rs:153:29:153:30 | 10 | test.rs:153:28:153:30 | - ... | | -| test.rs:153:39:153:48 | [boolean(false)] BlockExpr | test.rs:153:13:153:48 | [boolean(false)] IfExpr | false | -| test.rs:153:39:153:48 | [boolean(true)] BlockExpr | test.rs:153:13:153:48 | [boolean(true)] IfExpr | true | +| test.rs:153:39:153:48 | [boolean(false)] { ... } | test.rs:153:13:153:48 | [boolean(false)] if ... {...} else {...} | false | +| test.rs:153:39:153:48 | [boolean(true)] { ... } | test.rs:153:13:153:48 | [boolean(true)] if ... {...} else {...} | true | | test.rs:153:41:153:41 | a | test.rs:153:45:153:46 | 10 | | -| test.rs:153:41:153:46 | ... > ... | test.rs:153:39:153:48 | [boolean(false)] BlockExpr | false | -| test.rs:153:41:153:46 | ... > ... | test.rs:153:39:153:48 | [boolean(true)] BlockExpr | true | +| test.rs:153:41:153:46 | ... > ... | test.rs:153:39:153:48 | [boolean(false)] { ... } | false | +| test.rs:153:41:153:46 | ... > ... | test.rs:153:39:153:48 | [boolean(true)] { ... } | true | | test.rs:153:45:153:46 | 10 | test.rs:153:41:153:46 | ... > ... | | -| test.rs:153:51:155:9 | BlockExpr | test.rs:153:9:157:9 | IfExpr | | -| test.rs:154:13:154:13 | 1 | test.rs:153:51:155:9 | BlockExpr | | -| test.rs:155:16:157:9 | BlockExpr | test.rs:153:9:157:9 | IfExpr | | -| test.rs:156:13:156:13 | 0 | test.rs:155:16:157:9 | BlockExpr | | -| test.rs:160:5:169:5 | enter test_nested_if_match | test.rs:160:29:160:29 | a | | -| test.rs:160:5:169:5 | exit test_nested_if_match (normal) | test.rs:160:5:169:5 | exit test_nested_if_match | | -| test.rs:160:29:160:29 | a | test.rs:160:29:160:34 | Param | match | -| test.rs:160:29:160:34 | Param | test.rs:161:19:161:19 | a | | -| test.rs:160:44:169:5 | BlockExpr | test.rs:160:5:169:5 | exit test_nested_if_match (normal) | | -| test.rs:161:9:168:9 | IfExpr | test.rs:160:44:169:5 | BlockExpr | | -| test.rs:161:13:164:9 | [boolean(false)] MatchExpr | test.rs:167:13:167:13 | 0 | false | -| test.rs:161:13:164:9 | [boolean(true)] MatchExpr | test.rs:165:13:165:13 | 1 | true | +| test.rs:153:51:155:9 | { ... } | test.rs:153:9:157:9 | if ... {...} else {...} | | +| test.rs:154:13:154:13 | 1 | test.rs:153:51:155:9 | { ... } | | +| test.rs:155:16:157:9 | { ... } | test.rs:153:9:157:9 | if ... {...} else {...} | | +| test.rs:156:13:156:13 | 0 | test.rs:155:16:157:9 | { ... } | | +| test.rs:160:5:169:5 | enter fn test_nested_if_match | test.rs:160:29:160:29 | a | | +| test.rs:160:5:169:5 | exit fn test_nested_if_match (normal) | test.rs:160:5:169:5 | exit fn test_nested_if_match | | +| test.rs:160:29:160:29 | a | test.rs:160:29:160:34 | ...: i64 | match | +| test.rs:160:29:160:34 | ...: i64 | test.rs:161:19:161:19 | a | | +| test.rs:160:44:169:5 | { ... } | test.rs:160:5:169:5 | exit fn test_nested_if_match (normal) | | +| test.rs:161:9:168:9 | if ... {...} else {...} | test.rs:160:44:169:5 | { ... } | | +| test.rs:161:13:164:9 | [boolean(false)] match a { ... } | test.rs:167:13:167:13 | 0 | false | +| test.rs:161:13:164:9 | [boolean(true)] match a { ... } | test.rs:165:13:165:13 | 1 | true | | test.rs:161:19:161:19 | a | test.rs:162:13:162:13 | 0 | | -| test.rs:162:13:162:13 | 0 | test.rs:162:13:162:13 | LiteralPat | | -| test.rs:162:13:162:13 | LiteralPat | test.rs:162:18:162:21 | true | match | -| test.rs:162:13:162:13 | LiteralPat | test.rs:163:13:163:13 | WildcardPat | no-match | -| test.rs:162:18:162:21 | true | test.rs:161:13:164:9 | [boolean(true)] MatchExpr | true | -| test.rs:163:13:163:13 | WildcardPat | test.rs:163:18:163:22 | false | match | -| test.rs:163:18:163:22 | false | test.rs:161:13:164:9 | [boolean(false)] MatchExpr | false | -| test.rs:164:12:166:9 | BlockExpr | test.rs:161:9:168:9 | IfExpr | | -| test.rs:165:13:165:13 | 1 | test.rs:164:12:166:9 | BlockExpr | | -| test.rs:166:16:168:9 | BlockExpr | test.rs:161:9:168:9 | IfExpr | | -| test.rs:167:13:167:13 | 0 | test.rs:166:16:168:9 | BlockExpr | | -| test.rs:171:5:180:5 | enter test_nested_if_block | test.rs:171:29:171:29 | a | | -| test.rs:171:5:180:5 | exit test_nested_if_block (normal) | test.rs:171:5:180:5 | exit test_nested_if_block | | -| test.rs:171:29:171:29 | a | test.rs:171:29:171:34 | Param | match | -| test.rs:171:29:171:34 | Param | test.rs:173:13:173:15 | ExprStmt | | -| test.rs:171:44:180:5 | BlockExpr | test.rs:171:5:180:5 | exit test_nested_if_block (normal) | | -| test.rs:172:9:179:9 | IfExpr | test.rs:171:44:180:5 | BlockExpr | | -| test.rs:172:12:175:9 | [boolean(false)] BlockExpr | test.rs:178:13:178:13 | 0 | false | -| test.rs:172:12:175:9 | [boolean(true)] BlockExpr | test.rs:176:13:176:13 | 1 | true | +| test.rs:162:13:162:13 | 0 | test.rs:162:13:162:13 | 0 | | +| test.rs:162:13:162:13 | 0 | test.rs:162:18:162:21 | true | match | +| test.rs:162:13:162:13 | 0 | test.rs:163:13:163:13 | _ | no-match | +| test.rs:162:18:162:21 | true | test.rs:161:13:164:9 | [boolean(true)] match a { ... } | true | +| test.rs:163:13:163:13 | _ | test.rs:163:18:163:22 | false | match | +| test.rs:163:18:163:22 | false | test.rs:161:13:164:9 | [boolean(false)] match a { ... } | false | +| test.rs:164:12:166:9 | { ... } | test.rs:161:9:168:9 | if ... {...} else {...} | | +| test.rs:165:13:165:13 | 1 | test.rs:164:12:166:9 | { ... } | | +| test.rs:166:16:168:9 | { ... } | test.rs:161:9:168:9 | if ... {...} else {...} | | +| test.rs:167:13:167:13 | 0 | test.rs:166:16:168:9 | { ... } | | +| test.rs:171:5:180:5 | enter fn test_nested_if_block | test.rs:171:29:171:29 | a | | +| test.rs:171:5:180:5 | exit fn test_nested_if_block (normal) | test.rs:171:5:180:5 | exit fn test_nested_if_block | | +| test.rs:171:29:171:29 | a | test.rs:171:29:171:34 | ...: i64 | match | +| test.rs:171:29:171:34 | ...: i64 | test.rs:173:13:173:15 | ExprStmt | | +| test.rs:171:44:180:5 | { ... } | test.rs:171:5:180:5 | exit fn test_nested_if_block (normal) | | +| test.rs:172:9:179:9 | if ... {...} else {...} | test.rs:171:44:180:5 | { ... } | | +| test.rs:172:12:175:9 | [boolean(false)] { ... } | test.rs:178:13:178:13 | 0 | false | +| test.rs:172:12:175:9 | [boolean(true)] { ... } | test.rs:176:13:176:13 | 1 | true | | test.rs:173:13:173:14 | TupleExpr | test.rs:174:13:174:13 | a | | | test.rs:173:13:173:15 | ExprStmt | test.rs:173:13:173:14 | TupleExpr | | | test.rs:174:13:174:13 | a | test.rs:174:17:174:17 | 0 | | -| test.rs:174:13:174:17 | ... > ... | test.rs:172:12:175:9 | [boolean(false)] BlockExpr | false | -| test.rs:174:13:174:17 | ... > ... | test.rs:172:12:175:9 | [boolean(true)] BlockExpr | true | +| test.rs:174:13:174:17 | ... > ... | test.rs:172:12:175:9 | [boolean(false)] { ... } | false | +| test.rs:174:13:174:17 | ... > ... | test.rs:172:12:175:9 | [boolean(true)] { ... } | true | | test.rs:174:17:174:17 | 0 | test.rs:174:13:174:17 | ... > ... | | -| test.rs:175:11:177:9 | BlockExpr | test.rs:172:9:179:9 | IfExpr | | -| test.rs:176:13:176:13 | 1 | test.rs:175:11:177:9 | BlockExpr | | -| test.rs:177:16:179:9 | BlockExpr | test.rs:172:9:179:9 | IfExpr | | -| test.rs:178:13:178:13 | 0 | test.rs:177:16:179:9 | BlockExpr | | -| test.rs:182:5:192:5 | enter test_if_assignment | test.rs:182:27:182:27 | a | | -| test.rs:182:5:192:5 | exit test_if_assignment (normal) | test.rs:182:5:192:5 | exit test_if_assignment | | -| test.rs:182:27:182:27 | a | test.rs:182:27:182:32 | Param | match | -| test.rs:182:27:182:32 | Param | test.rs:183:9:183:26 | LetStmt | | -| test.rs:182:42:192:5 | BlockExpr | test.rs:182:5:192:5 | exit test_if_assignment (normal) | | -| test.rs:183:9:183:26 | LetStmt | test.rs:183:21:183:25 | false | | +| test.rs:175:11:177:9 | { ... } | test.rs:172:9:179:9 | if ... {...} else {...} | | +| test.rs:176:13:176:13 | 1 | test.rs:175:11:177:9 | { ... } | | +| test.rs:177:16:179:9 | { ... } | test.rs:172:9:179:9 | if ... {...} else {...} | | +| test.rs:178:13:178:13 | 0 | test.rs:177:16:179:9 | { ... } | | +| test.rs:182:5:192:5 | enter fn test_if_assignment | test.rs:182:27:182:27 | a | | +| test.rs:182:5:192:5 | exit fn test_if_assignment (normal) | test.rs:182:5:192:5 | exit fn test_if_assignment | | +| test.rs:182:27:182:27 | a | test.rs:182:27:182:32 | ...: i64 | match | +| test.rs:182:27:182:32 | ...: i64 | test.rs:183:9:183:26 | let ... = false | | +| test.rs:182:42:192:5 | { ... } | test.rs:182:5:192:5 | exit fn test_if_assignment (normal) | | +| test.rs:183:9:183:26 | let ... = false | test.rs:183:21:183:25 | false | | | test.rs:183:13:183:17 | x | test.rs:185:13:185:21 | ExprStmt | match | | test.rs:183:21:183:25 | false | test.rs:183:13:183:17 | x | | -| test.rs:184:9:191:9 | IfExpr | test.rs:182:42:192:5 | BlockExpr | | -| test.rs:184:12:187:9 | [boolean(false)] BlockExpr | test.rs:190:13:190:13 | 0 | false | -| test.rs:184:12:187:9 | [boolean(true)] BlockExpr | test.rs:188:13:188:13 | 1 | true | +| test.rs:184:9:191:9 | if ... {...} else {...} | test.rs:182:42:192:5 | { ... } | | +| test.rs:184:12:187:9 | [boolean(false)] { ... } | test.rs:190:13:190:13 | 0 | false | +| test.rs:184:12:187:9 | [boolean(true)] { ... } | test.rs:188:13:188:13 | 1 | true | | test.rs:185:13:185:13 | x | test.rs:185:17:185:20 | true | | | test.rs:185:13:185:20 | ... = ... | test.rs:186:13:186:13 | x | | | test.rs:185:13:185:21 | ExprStmt | test.rs:185:13:185:13 | x | | | test.rs:185:17:185:20 | true | test.rs:185:13:185:20 | ... = ... | | -| test.rs:186:13:186:13 | x | test.rs:184:12:187:9 | [boolean(false)] BlockExpr | false | -| test.rs:186:13:186:13 | x | test.rs:184:12:187:9 | [boolean(true)] BlockExpr | true | -| test.rs:187:11:189:9 | BlockExpr | test.rs:184:9:191:9 | IfExpr | | -| test.rs:188:13:188:13 | 1 | test.rs:187:11:189:9 | BlockExpr | | -| test.rs:189:16:191:9 | BlockExpr | test.rs:184:9:191:9 | IfExpr | | -| test.rs:190:13:190:13 | 0 | test.rs:189:16:191:9 | BlockExpr | | -| test.rs:194:5:205:5 | enter test_if_loop1 | test.rs:194:22:194:22 | a | | -| test.rs:194:5:205:5 | exit test_if_loop1 (normal) | test.rs:194:5:205:5 | exit test_if_loop1 | | -| test.rs:194:22:194:22 | a | test.rs:194:22:194:27 | Param | match | -| test.rs:194:22:194:27 | Param | test.rs:196:13:198:14 | ExprStmt | | -| test.rs:194:37:205:5 | BlockExpr | test.rs:194:5:205:5 | exit test_if_loop1 (normal) | | -| test.rs:195:9:204:9 | IfExpr | test.rs:194:37:205:5 | BlockExpr | | -| test.rs:195:13:200:9 | [boolean(false)] LoopExpr | test.rs:203:13:203:13 | 0 | false | -| test.rs:195:13:200:9 | [boolean(true)] LoopExpr | test.rs:201:13:201:13 | 1 | true | -| test.rs:195:18:200:9 | BlockExpr | test.rs:196:13:198:14 | ExprStmt | | -| test.rs:196:13:198:13 | IfExpr | test.rs:199:13:199:19 | ExprStmt | | +| test.rs:186:13:186:13 | x | test.rs:184:12:187:9 | [boolean(false)] { ... } | false | +| test.rs:186:13:186:13 | x | test.rs:184:12:187:9 | [boolean(true)] { ... } | true | +| test.rs:187:11:189:9 | { ... } | test.rs:184:9:191:9 | if ... {...} else {...} | | +| test.rs:188:13:188:13 | 1 | test.rs:187:11:189:9 | { ... } | | +| test.rs:189:16:191:9 | { ... } | test.rs:184:9:191:9 | if ... {...} else {...} | | +| test.rs:190:13:190:13 | 0 | test.rs:189:16:191:9 | { ... } | | +| test.rs:194:5:205:5 | enter fn test_if_loop1 | test.rs:194:22:194:22 | a | | +| test.rs:194:5:205:5 | exit fn test_if_loop1 (normal) | test.rs:194:5:205:5 | exit fn test_if_loop1 | | +| test.rs:194:22:194:22 | a | test.rs:194:22:194:27 | ...: i64 | match | +| test.rs:194:22:194:27 | ...: i64 | test.rs:196:13:198:14 | ExprStmt | | +| test.rs:194:37:205:5 | { ... } | test.rs:194:5:205:5 | exit fn test_if_loop1 (normal) | | +| test.rs:195:9:204:9 | if ... {...} else {...} | test.rs:194:37:205:5 | { ... } | | +| test.rs:195:13:200:9 | [boolean(false)] loop { ... } | test.rs:203:13:203:13 | 0 | false | +| test.rs:195:13:200:9 | [boolean(true)] loop { ... } | test.rs:201:13:201:13 | 1 | true | +| test.rs:195:18:200:9 | { ... } | test.rs:196:13:198:14 | ExprStmt | | +| test.rs:196:13:198:13 | if ... {...} | test.rs:199:13:199:19 | ExprStmt | | | test.rs:196:13:198:14 | ExprStmt | test.rs:196:16:196:16 | a | | | test.rs:196:16:196:16 | a | test.rs:196:20:196:20 | 0 | | -| test.rs:196:16:196:20 | ... > ... | test.rs:196:13:198:13 | IfExpr | false | +| test.rs:196:16:196:20 | ... > ... | test.rs:196:13:198:13 | if ... {...} | false | | test.rs:196:16:196:20 | ... > ... | test.rs:197:17:197:29 | ExprStmt | true | | test.rs:196:20:196:20 | 0 | test.rs:196:16:196:20 | ... > ... | | -| test.rs:197:17:197:28 | [boolean(false)] BreakExpr | test.rs:195:13:200:9 | [boolean(false)] LoopExpr | break | -| test.rs:197:17:197:28 | [boolean(true)] BreakExpr | test.rs:195:13:200:9 | [boolean(true)] LoopExpr | break | +| test.rs:197:17:197:28 | [boolean(false)] break ... | test.rs:195:13:200:9 | [boolean(false)] loop { ... } | break | +| test.rs:197:17:197:28 | [boolean(true)] break ... | test.rs:195:13:200:9 | [boolean(true)] loop { ... } | break | | test.rs:197:17:197:29 | ExprStmt | test.rs:197:23:197:23 | a | | | test.rs:197:23:197:23 | a | test.rs:197:27:197:28 | 10 | | -| test.rs:197:23:197:28 | ... > ... | test.rs:197:17:197:28 | [boolean(false)] BreakExpr | false | -| test.rs:197:23:197:28 | ... > ... | test.rs:197:17:197:28 | [boolean(true)] BreakExpr | true | +| test.rs:197:23:197:28 | ... > ... | test.rs:197:17:197:28 | [boolean(false)] break ... | false | +| test.rs:197:23:197:28 | ... > ... | test.rs:197:17:197:28 | [boolean(true)] break ... | true | | test.rs:197:27:197:28 | 10 | test.rs:197:23:197:28 | ... > ... | | | test.rs:199:13:199:13 | a | test.rs:199:17:199:18 | 10 | | -| test.rs:199:13:199:18 | ... < ... | test.rs:195:18:200:9 | BlockExpr | | +| test.rs:199:13:199:18 | ... < ... | test.rs:195:18:200:9 | { ... } | | | test.rs:199:13:199:19 | ExprStmt | test.rs:199:13:199:13 | a | | | test.rs:199:17:199:18 | 10 | test.rs:199:13:199:18 | ... < ... | | -| test.rs:200:12:202:9 | BlockExpr | test.rs:195:9:204:9 | IfExpr | | -| test.rs:201:13:201:13 | 1 | test.rs:200:12:202:9 | BlockExpr | | -| test.rs:202:16:204:9 | BlockExpr | test.rs:195:9:204:9 | IfExpr | | -| test.rs:203:13:203:13 | 0 | test.rs:202:16:204:9 | BlockExpr | | -| test.rs:207:5:218:5 | enter test_if_loop2 | test.rs:207:22:207:22 | a | | -| test.rs:207:5:218:5 | exit test_if_loop2 (normal) | test.rs:207:5:218:5 | exit test_if_loop2 | | -| test.rs:207:22:207:22 | a | test.rs:207:22:207:27 | Param | match | -| test.rs:207:22:207:27 | Param | test.rs:209:13:211:14 | ExprStmt | | -| test.rs:207:37:218:5 | BlockExpr | test.rs:207:5:218:5 | exit test_if_loop2 (normal) | | -| test.rs:208:9:217:9 | IfExpr | test.rs:207:37:218:5 | BlockExpr | | -| test.rs:208:13:213:9 | [boolean(false)] LoopExpr | test.rs:216:13:216:13 | 0 | false | -| test.rs:208:13:213:9 | [boolean(true)] LoopExpr | test.rs:214:13:214:13 | 1 | true | -| test.rs:208:26:213:9 | BlockExpr | test.rs:209:13:211:14 | ExprStmt | | -| test.rs:209:13:211:13 | IfExpr | test.rs:212:13:212:19 | ExprStmt | | +| test.rs:200:12:202:9 | { ... } | test.rs:195:9:204:9 | if ... {...} else {...} | | +| test.rs:201:13:201:13 | 1 | test.rs:200:12:202:9 | { ... } | | +| test.rs:202:16:204:9 | { ... } | test.rs:195:9:204:9 | if ... {...} else {...} | | +| test.rs:203:13:203:13 | 0 | test.rs:202:16:204:9 | { ... } | | +| test.rs:207:5:218:5 | enter fn test_if_loop2 | test.rs:207:22:207:22 | a | | +| test.rs:207:5:218:5 | exit fn test_if_loop2 (normal) | test.rs:207:5:218:5 | exit fn test_if_loop2 | | +| test.rs:207:22:207:22 | a | test.rs:207:22:207:27 | ...: i64 | match | +| test.rs:207:22:207:27 | ...: i64 | test.rs:209:13:211:14 | ExprStmt | | +| test.rs:207:37:218:5 | { ... } | test.rs:207:5:218:5 | exit fn test_if_loop2 (normal) | | +| test.rs:208:9:217:9 | if ... {...} else {...} | test.rs:207:37:218:5 | { ... } | | +| test.rs:208:13:213:9 | [boolean(false)] 'label: loop { ... } | test.rs:216:13:216:13 | 0 | false | +| test.rs:208:13:213:9 | [boolean(true)] 'label: loop { ... } | test.rs:214:13:214:13 | 1 | true | +| test.rs:208:26:213:9 | { ... } | test.rs:209:13:211:14 | ExprStmt | | +| test.rs:209:13:211:13 | if ... {...} | test.rs:212:13:212:19 | ExprStmt | | | test.rs:209:13:211:14 | ExprStmt | test.rs:209:16:209:16 | a | | | test.rs:209:16:209:16 | a | test.rs:209:20:209:20 | 0 | | -| test.rs:209:16:209:20 | ... > ... | test.rs:209:13:211:13 | IfExpr | false | +| test.rs:209:16:209:20 | ... > ... | test.rs:209:13:211:13 | if ... {...} | false | | test.rs:209:16:209:20 | ... > ... | test.rs:210:17:210:36 | ExprStmt | true | | test.rs:209:20:209:20 | 0 | test.rs:209:16:209:20 | ... > ... | | -| test.rs:210:17:210:35 | [boolean(false)] BreakExpr | test.rs:208:13:213:9 | [boolean(false)] LoopExpr | break | -| test.rs:210:17:210:35 | [boolean(true)] BreakExpr | test.rs:208:13:213:9 | [boolean(true)] LoopExpr | break | +| test.rs:210:17:210:35 | [boolean(false)] break ''label ... | test.rs:208:13:213:9 | [boolean(false)] 'label: loop { ... } | break | +| test.rs:210:17:210:35 | [boolean(true)] break ''label ... | test.rs:208:13:213:9 | [boolean(true)] 'label: loop { ... } | break | | test.rs:210:17:210:36 | ExprStmt | test.rs:210:30:210:30 | a | | | test.rs:210:30:210:30 | a | test.rs:210:34:210:35 | 10 | | -| test.rs:210:30:210:35 | ... > ... | test.rs:210:17:210:35 | [boolean(false)] BreakExpr | false | -| test.rs:210:30:210:35 | ... > ... | test.rs:210:17:210:35 | [boolean(true)] BreakExpr | true | +| test.rs:210:30:210:35 | ... > ... | test.rs:210:17:210:35 | [boolean(false)] break ''label ... | false | +| test.rs:210:30:210:35 | ... > ... | test.rs:210:17:210:35 | [boolean(true)] break ''label ... | true | | test.rs:210:34:210:35 | 10 | test.rs:210:30:210:35 | ... > ... | | | test.rs:212:13:212:13 | a | test.rs:212:17:212:18 | 10 | | -| test.rs:212:13:212:18 | ... < ... | test.rs:208:26:213:9 | BlockExpr | | +| test.rs:212:13:212:18 | ... < ... | test.rs:208:26:213:9 | { ... } | | | test.rs:212:13:212:19 | ExprStmt | test.rs:212:13:212:13 | a | | | test.rs:212:17:212:18 | 10 | test.rs:212:13:212:18 | ... < ... | | -| test.rs:213:12:215:9 | BlockExpr | test.rs:208:9:217:9 | IfExpr | | -| test.rs:214:13:214:13 | 1 | test.rs:213:12:215:9 | BlockExpr | | -| test.rs:215:16:217:9 | BlockExpr | test.rs:208:9:217:9 | IfExpr | | -| test.rs:216:13:216:13 | 0 | test.rs:215:16:217:9 | BlockExpr | | -| test.rs:220:5:228:5 | enter test_labelled_block | test.rs:220:28:220:28 | a | | -| test.rs:220:5:228:5 | exit test_labelled_block (normal) | test.rs:220:5:228:5 | exit test_labelled_block | | -| test.rs:220:28:220:28 | a | test.rs:220:28:220:33 | Param | match | -| test.rs:220:28:220:33 | Param | test.rs:222:13:222:31 | ExprStmt | | -| test.rs:220:43:228:5 | BlockExpr | test.rs:220:5:228:5 | exit test_labelled_block (normal) | | -| test.rs:221:9:227:9 | IfExpr | test.rs:220:43:228:5 | BlockExpr | | -| test.rs:221:13:223:9 | [boolean(false)] BlockExpr | test.rs:226:13:226:13 | 0 | false | -| test.rs:221:13:223:9 | [boolean(true)] BlockExpr | test.rs:224:13:224:13 | 1 | true | -| test.rs:222:13:222:30 | [boolean(false)] BreakExpr | test.rs:221:13:223:9 | [boolean(false)] BlockExpr | break | -| test.rs:222:13:222:30 | [boolean(true)] BreakExpr | test.rs:221:13:223:9 | [boolean(true)] BlockExpr | break | +| test.rs:213:12:215:9 | { ... } | test.rs:208:9:217:9 | if ... {...} else {...} | | +| test.rs:214:13:214:13 | 1 | test.rs:213:12:215:9 | { ... } | | +| test.rs:215:16:217:9 | { ... } | test.rs:208:9:217:9 | if ... {...} else {...} | | +| test.rs:216:13:216:13 | 0 | test.rs:215:16:217:9 | { ... } | | +| test.rs:220:5:228:5 | enter fn test_labelled_block | test.rs:220:28:220:28 | a | | +| test.rs:220:5:228:5 | exit fn test_labelled_block (normal) | test.rs:220:5:228:5 | exit fn test_labelled_block | | +| test.rs:220:28:220:28 | a | test.rs:220:28:220:33 | ...: i64 | match | +| test.rs:220:28:220:33 | ...: i64 | test.rs:222:13:222:31 | ExprStmt | | +| test.rs:220:43:228:5 | { ... } | test.rs:220:5:228:5 | exit fn test_labelled_block (normal) | | +| test.rs:221:9:227:9 | if ... {...} else {...} | test.rs:220:43:228:5 | { ... } | | +| test.rs:221:13:223:9 | [boolean(false)] 'block: { ... } | test.rs:226:13:226:13 | 0 | false | +| test.rs:221:13:223:9 | [boolean(true)] 'block: { ... } | test.rs:224:13:224:13 | 1 | true | +| test.rs:222:13:222:30 | [boolean(false)] break ''block ... | test.rs:221:13:223:9 | [boolean(false)] 'block: { ... } | break | +| test.rs:222:13:222:30 | [boolean(true)] break ''block ... | test.rs:221:13:223:9 | [boolean(true)] 'block: { ... } | break | | test.rs:222:13:222:31 | ExprStmt | test.rs:222:26:222:26 | a | | | test.rs:222:26:222:26 | a | test.rs:222:30:222:30 | 0 | | -| test.rs:222:26:222:30 | ... > ... | test.rs:222:13:222:30 | [boolean(false)] BreakExpr | false | -| test.rs:222:26:222:30 | ... > ... | test.rs:222:13:222:30 | [boolean(true)] BreakExpr | true | +| test.rs:222:26:222:30 | ... > ... | test.rs:222:13:222:30 | [boolean(false)] break ''block ... | false | +| test.rs:222:26:222:30 | ... > ... | test.rs:222:13:222:30 | [boolean(true)] break ''block ... | true | | test.rs:222:30:222:30 | 0 | test.rs:222:26:222:30 | ... > ... | | -| test.rs:223:12:225:9 | BlockExpr | test.rs:221:9:227:9 | IfExpr | | -| test.rs:224:13:224:13 | 1 | test.rs:223:12:225:9 | BlockExpr | | -| test.rs:225:16:227:9 | BlockExpr | test.rs:221:9:227:9 | IfExpr | | -| test.rs:226:13:226:13 | 0 | test.rs:225:16:227:9 | BlockExpr | | -| test.rs:233:5:236:5 | enter test_and_operator | test.rs:233:30:233:30 | a | | -| test.rs:233:5:236:5 | exit test_and_operator (normal) | test.rs:233:5:236:5 | exit test_and_operator | | -| test.rs:233:30:233:30 | a | test.rs:233:30:233:36 | Param | match | -| test.rs:233:30:233:36 | Param | test.rs:233:39:233:39 | b | | -| test.rs:233:39:233:39 | b | test.rs:233:39:233:45 | Param | match | -| test.rs:233:39:233:45 | Param | test.rs:233:48:233:48 | c | | -| test.rs:233:48:233:48 | c | test.rs:233:48:233:54 | Param | match | -| test.rs:233:48:233:54 | Param | test.rs:234:9:234:28 | LetStmt | | -| test.rs:233:65:236:5 | BlockExpr | test.rs:233:5:236:5 | exit test_and_operator (normal) | | -| test.rs:234:9:234:28 | LetStmt | test.rs:234:17:234:17 | a | | +| test.rs:223:12:225:9 | { ... } | test.rs:221:9:227:9 | if ... {...} else {...} | | +| test.rs:224:13:224:13 | 1 | test.rs:223:12:225:9 | { ... } | | +| test.rs:225:16:227:9 | { ... } | test.rs:221:9:227:9 | if ... {...} else {...} | | +| test.rs:226:13:226:13 | 0 | test.rs:225:16:227:9 | { ... } | | +| test.rs:233:5:236:5 | enter fn test_and_operator | test.rs:233:30:233:30 | a | | +| test.rs:233:5:236:5 | exit fn test_and_operator (normal) | test.rs:233:5:236:5 | exit fn test_and_operator | | +| test.rs:233:30:233:30 | a | test.rs:233:30:233:36 | ...: bool | match | +| test.rs:233:30:233:36 | ...: bool | test.rs:233:39:233:39 | b | | +| test.rs:233:39:233:39 | b | test.rs:233:39:233:45 | ...: bool | match | +| test.rs:233:39:233:45 | ...: bool | test.rs:233:48:233:48 | c | | +| test.rs:233:48:233:48 | c | test.rs:233:48:233:54 | ...: bool | match | +| test.rs:233:48:233:54 | ...: bool | test.rs:234:9:234:28 | let ... = ... | | +| test.rs:233:65:236:5 | { ... } | test.rs:233:5:236:5 | exit fn test_and_operator (normal) | | +| test.rs:234:9:234:28 | let ... = ... | test.rs:234:17:234:17 | a | | | test.rs:234:13:234:13 | d | test.rs:235:9:235:9 | d | match | | test.rs:234:17:234:17 | a | test.rs:234:17:234:22 | [boolean(false)] ... && ... | false | | test.rs:234:17:234:17 | a | test.rs:234:22:234:22 | b | true | @@ -483,17 +483,17 @@ edges | test.rs:234:22:234:22 | b | test.rs:234:17:234:22 | [boolean(false)] ... && ... | false | | test.rs:234:22:234:22 | b | test.rs:234:17:234:22 | [boolean(true)] ... && ... | true | | test.rs:234:27:234:27 | c | test.rs:234:17:234:27 | ... && ... | | -| test.rs:235:9:235:9 | d | test.rs:233:65:236:5 | BlockExpr | | -| test.rs:238:5:241:5 | enter test_or_operator | test.rs:238:25:238:25 | a | | -| test.rs:238:5:241:5 | exit test_or_operator (normal) | test.rs:238:5:241:5 | exit test_or_operator | | -| test.rs:238:25:238:25 | a | test.rs:238:25:238:31 | Param | match | -| test.rs:238:25:238:31 | Param | test.rs:238:34:238:34 | b | | -| test.rs:238:34:238:34 | b | test.rs:238:34:238:40 | Param | match | -| test.rs:238:34:238:40 | Param | test.rs:238:43:238:43 | c | | -| test.rs:238:43:238:43 | c | test.rs:238:43:238:49 | Param | match | -| test.rs:238:43:238:49 | Param | test.rs:239:9:239:28 | LetStmt | | -| test.rs:238:60:241:5 | BlockExpr | test.rs:238:5:241:5 | exit test_or_operator (normal) | | -| test.rs:239:9:239:28 | LetStmt | test.rs:239:17:239:17 | a | | +| test.rs:235:9:235:9 | d | test.rs:233:65:236:5 | { ... } | | +| test.rs:238:5:241:5 | enter fn test_or_operator | test.rs:238:25:238:25 | a | | +| test.rs:238:5:241:5 | exit fn test_or_operator (normal) | test.rs:238:5:241:5 | exit fn test_or_operator | | +| test.rs:238:25:238:25 | a | test.rs:238:25:238:31 | ...: bool | match | +| test.rs:238:25:238:31 | ...: bool | test.rs:238:34:238:34 | b | | +| test.rs:238:34:238:34 | b | test.rs:238:34:238:40 | ...: bool | match | +| test.rs:238:34:238:40 | ...: bool | test.rs:238:43:238:43 | c | | +| test.rs:238:43:238:43 | c | test.rs:238:43:238:49 | ...: bool | match | +| test.rs:238:43:238:49 | ...: bool | test.rs:239:9:239:28 | let ... = ... | | +| test.rs:238:60:241:5 | { ... } | test.rs:238:5:241:5 | exit fn test_or_operator (normal) | | +| test.rs:239:9:239:28 | let ... = ... | test.rs:239:17:239:17 | a | | | test.rs:239:13:239:13 | d | test.rs:240:9:240:9 | d | match | | test.rs:239:17:239:17 | a | test.rs:239:17:239:22 | [boolean(true)] ... \|\| ... | true | | test.rs:239:17:239:17 | a | test.rs:239:22:239:22 | b | false | @@ -503,17 +503,17 @@ edges | test.rs:239:22:239:22 | b | test.rs:239:17:239:22 | [boolean(false)] ... \|\| ... | false | | test.rs:239:22:239:22 | b | test.rs:239:17:239:22 | [boolean(true)] ... \|\| ... | true | | test.rs:239:27:239:27 | c | test.rs:239:17:239:27 | ... \|\| ... | | -| test.rs:240:9:240:9 | d | test.rs:238:60:241:5 | BlockExpr | | -| test.rs:243:5:246:5 | enter test_or_operator_2 | test.rs:243:27:243:27 | a | | -| test.rs:243:5:246:5 | exit test_or_operator_2 (normal) | test.rs:243:5:246:5 | exit test_or_operator_2 | | -| test.rs:243:27:243:27 | a | test.rs:243:27:243:33 | Param | match | -| test.rs:243:27:243:33 | Param | test.rs:243:36:243:36 | b | | -| test.rs:243:36:243:36 | b | test.rs:243:36:243:41 | Param | match | -| test.rs:243:36:243:41 | Param | test.rs:243:44:243:44 | c | | -| test.rs:243:44:243:44 | c | test.rs:243:44:243:50 | Param | match | -| test.rs:243:44:243:50 | Param | test.rs:244:9:244:36 | LetStmt | | -| test.rs:243:61:246:5 | BlockExpr | test.rs:243:5:246:5 | exit test_or_operator_2 (normal) | | -| test.rs:244:9:244:36 | LetStmt | test.rs:244:17:244:17 | a | | +| test.rs:240:9:240:9 | d | test.rs:238:60:241:5 | { ... } | | +| test.rs:243:5:246:5 | enter fn test_or_operator_2 | test.rs:243:27:243:27 | a | | +| test.rs:243:5:246:5 | exit fn test_or_operator_2 (normal) | test.rs:243:5:246:5 | exit fn test_or_operator_2 | | +| test.rs:243:27:243:27 | a | test.rs:243:27:243:33 | ...: bool | match | +| test.rs:243:27:243:33 | ...: bool | test.rs:243:36:243:36 | b | | +| test.rs:243:36:243:36 | b | test.rs:243:36:243:41 | ...: i64 | match | +| test.rs:243:36:243:41 | ...: i64 | test.rs:243:44:243:44 | c | | +| test.rs:243:44:243:44 | c | test.rs:243:44:243:50 | ...: bool | match | +| test.rs:243:44:243:50 | ...: bool | test.rs:244:9:244:36 | let ... = ... | | +| test.rs:243:61:246:5 | { ... } | test.rs:243:5:246:5 | exit fn test_or_operator_2 (normal) | | +| test.rs:244:9:244:36 | let ... = ... | test.rs:244:17:244:17 | a | | | test.rs:244:13:244:13 | d | test.rs:245:9:245:9 | d | match | | test.rs:244:17:244:17 | a | test.rs:244:17:244:30 | [boolean(true)] ... \|\| ... | true | | test.rs:244:17:244:17 | a | test.rs:244:23:244:23 | b | false | @@ -525,27 +525,27 @@ edges | test.rs:244:23:244:29 | ... == ... | test.rs:244:17:244:30 | [boolean(true)] ... \|\| ... | true | | test.rs:244:28:244:29 | 28 | test.rs:244:23:244:29 | ... == ... | | | test.rs:244:35:244:35 | c | test.rs:244:17:244:35 | ... \|\| ... | | -| test.rs:245:9:245:9 | d | test.rs:243:61:246:5 | BlockExpr | | -| test.rs:248:5:251:5 | enter test_not_operator | test.rs:248:26:248:26 | a | | -| test.rs:248:5:251:5 | exit test_not_operator (normal) | test.rs:248:5:251:5 | exit test_not_operator | | -| test.rs:248:26:248:26 | a | test.rs:248:26:248:32 | Param | match | -| test.rs:248:26:248:32 | Param | test.rs:249:9:249:19 | LetStmt | | -| test.rs:248:43:251:5 | BlockExpr | test.rs:248:5:251:5 | exit test_not_operator (normal) | | -| test.rs:249:9:249:19 | LetStmt | test.rs:249:18:249:18 | a | | +| test.rs:245:9:245:9 | d | test.rs:243:61:246:5 | { ... } | | +| test.rs:248:5:251:5 | enter fn test_not_operator | test.rs:248:26:248:26 | a | | +| test.rs:248:5:251:5 | exit fn test_not_operator (normal) | test.rs:248:5:251:5 | exit fn test_not_operator | | +| test.rs:248:26:248:26 | a | test.rs:248:26:248:32 | ...: bool | match | +| test.rs:248:26:248:32 | ...: bool | test.rs:249:9:249:19 | let ... = ... | | +| test.rs:248:43:251:5 | { ... } | test.rs:248:5:251:5 | exit fn test_not_operator (normal) | | +| test.rs:249:9:249:19 | let ... = ... | test.rs:249:18:249:18 | a | | | test.rs:249:13:249:13 | d | test.rs:250:9:250:9 | d | match | | test.rs:249:17:249:18 | ! ... | test.rs:249:13:249:13 | d | | | test.rs:249:18:249:18 | a | test.rs:249:17:249:18 | ! ... | | -| test.rs:250:9:250:9 | d | test.rs:248:43:251:5 | BlockExpr | | -| test.rs:253:5:259:5 | enter test_if_and_operator | test.rs:253:29:253:29 | a | | -| test.rs:253:5:259:5 | exit test_if_and_operator (normal) | test.rs:253:5:259:5 | exit test_if_and_operator | | -| test.rs:253:29:253:29 | a | test.rs:253:29:253:35 | Param | match | -| test.rs:253:29:253:35 | Param | test.rs:253:38:253:38 | b | | -| test.rs:253:38:253:38 | b | test.rs:253:38:253:44 | Param | match | -| test.rs:253:38:253:44 | Param | test.rs:253:47:253:47 | c | | -| test.rs:253:47:253:47 | c | test.rs:253:47:253:53 | Param | match | -| test.rs:253:47:253:53 | Param | test.rs:254:12:254:12 | a | | -| test.rs:253:64:259:5 | BlockExpr | test.rs:253:5:259:5 | exit test_if_and_operator (normal) | | -| test.rs:254:9:258:9 | IfExpr | test.rs:253:64:259:5 | BlockExpr | | +| test.rs:250:9:250:9 | d | test.rs:248:43:251:5 | { ... } | | +| test.rs:253:5:259:5 | enter fn test_if_and_operator | test.rs:253:29:253:29 | a | | +| test.rs:253:5:259:5 | exit fn test_if_and_operator (normal) | test.rs:253:5:259:5 | exit fn test_if_and_operator | | +| test.rs:253:29:253:29 | a | test.rs:253:29:253:35 | ...: bool | match | +| test.rs:253:29:253:35 | ...: bool | test.rs:253:38:253:38 | b | | +| test.rs:253:38:253:38 | b | test.rs:253:38:253:44 | ...: bool | match | +| test.rs:253:38:253:44 | ...: bool | test.rs:253:47:253:47 | c | | +| test.rs:253:47:253:47 | c | test.rs:253:47:253:53 | ...: bool | match | +| test.rs:253:47:253:53 | ...: bool | test.rs:254:12:254:12 | a | | +| test.rs:253:64:259:5 | { ... } | test.rs:253:5:259:5 | exit fn test_if_and_operator (normal) | | +| test.rs:254:9:258:9 | if ... {...} else {...} | test.rs:253:64:259:5 | { ... } | | | test.rs:254:12:254:12 | a | test.rs:254:12:254:17 | [boolean(false)] ... && ... | false | | test.rs:254:12:254:12 | a | test.rs:254:17:254:17 | b | true | | test.rs:254:12:254:17 | [boolean(false)] ... && ... | test.rs:254:12:254:22 | [boolean(false)] ... && ... | false | @@ -556,20 +556,20 @@ edges | test.rs:254:17:254:17 | b | test.rs:254:12:254:17 | [boolean(true)] ... && ... | true | | test.rs:254:22:254:22 | c | test.rs:254:12:254:22 | [boolean(false)] ... && ... | false | | test.rs:254:22:254:22 | c | test.rs:254:12:254:22 | [boolean(true)] ... && ... | true | -| test.rs:254:24:256:9 | BlockExpr | test.rs:254:9:258:9 | IfExpr | | -| test.rs:255:13:255:16 | true | test.rs:254:24:256:9 | BlockExpr | | -| test.rs:256:16:258:9 | BlockExpr | test.rs:254:9:258:9 | IfExpr | | -| test.rs:257:13:257:17 | false | test.rs:256:16:258:9 | BlockExpr | | -| test.rs:261:5:267:5 | enter test_if_or_operator | test.rs:261:28:261:28 | a | | -| test.rs:261:5:267:5 | exit test_if_or_operator (normal) | test.rs:261:5:267:5 | exit test_if_or_operator | | -| test.rs:261:28:261:28 | a | test.rs:261:28:261:34 | Param | match | -| test.rs:261:28:261:34 | Param | test.rs:261:37:261:37 | b | | -| test.rs:261:37:261:37 | b | test.rs:261:37:261:43 | Param | match | -| test.rs:261:37:261:43 | Param | test.rs:261:46:261:46 | c | | -| test.rs:261:46:261:46 | c | test.rs:261:46:261:52 | Param | match | -| test.rs:261:46:261:52 | Param | test.rs:262:12:262:12 | a | | -| test.rs:261:63:267:5 | BlockExpr | test.rs:261:5:267:5 | exit test_if_or_operator (normal) | | -| test.rs:262:9:266:9 | IfExpr | test.rs:261:63:267:5 | BlockExpr | | +| test.rs:254:24:256:9 | { ... } | test.rs:254:9:258:9 | if ... {...} else {...} | | +| test.rs:255:13:255:16 | true | test.rs:254:24:256:9 | { ... } | | +| test.rs:256:16:258:9 | { ... } | test.rs:254:9:258:9 | if ... {...} else {...} | | +| test.rs:257:13:257:17 | false | test.rs:256:16:258:9 | { ... } | | +| test.rs:261:5:267:5 | enter fn test_if_or_operator | test.rs:261:28:261:28 | a | | +| test.rs:261:5:267:5 | exit fn test_if_or_operator (normal) | test.rs:261:5:267:5 | exit fn test_if_or_operator | | +| test.rs:261:28:261:28 | a | test.rs:261:28:261:34 | ...: bool | match | +| test.rs:261:28:261:34 | ...: bool | test.rs:261:37:261:37 | b | | +| test.rs:261:37:261:37 | b | test.rs:261:37:261:43 | ...: bool | match | +| test.rs:261:37:261:43 | ...: bool | test.rs:261:46:261:46 | c | | +| test.rs:261:46:261:46 | c | test.rs:261:46:261:52 | ...: bool | match | +| test.rs:261:46:261:52 | ...: bool | test.rs:262:12:262:12 | a | | +| test.rs:261:63:267:5 | { ... } | test.rs:261:5:267:5 | exit fn test_if_or_operator (normal) | | +| test.rs:262:9:266:9 | if ... {...} else {...} | test.rs:261:63:267:5 | { ... } | | | test.rs:262:12:262:12 | a | test.rs:262:12:262:17 | [boolean(true)] ... \|\| ... | true | | test.rs:262:12:262:12 | a | test.rs:262:17:262:17 | b | false | | test.rs:262:12:262:17 | [boolean(false)] ... \|\| ... | test.rs:262:22:262:22 | c | false | @@ -580,490 +580,540 @@ edges | test.rs:262:17:262:17 | b | test.rs:262:12:262:17 | [boolean(true)] ... \|\| ... | true | | test.rs:262:22:262:22 | c | test.rs:262:12:262:22 | [boolean(false)] ... \|\| ... | false | | test.rs:262:22:262:22 | c | test.rs:262:12:262:22 | [boolean(true)] ... \|\| ... | true | -| test.rs:262:24:264:9 | BlockExpr | test.rs:262:9:266:9 | IfExpr | | -| test.rs:263:13:263:16 | true | test.rs:262:24:264:9 | BlockExpr | | -| test.rs:264:16:266:9 | BlockExpr | test.rs:262:9:266:9 | IfExpr | | -| test.rs:265:13:265:17 | false | test.rs:264:16:266:9 | BlockExpr | | -| test.rs:269:5:275:5 | enter test_if_not_operator | test.rs:269:29:269:29 | a | | -| test.rs:269:5:275:5 | exit test_if_not_operator (normal) | test.rs:269:5:275:5 | exit test_if_not_operator | | -| test.rs:269:29:269:29 | a | test.rs:269:29:269:35 | Param | match | -| test.rs:269:29:269:35 | Param | test.rs:270:13:270:13 | a | | -| test.rs:269:46:275:5 | BlockExpr | test.rs:269:5:275:5 | exit test_if_not_operator (normal) | | -| test.rs:270:9:274:9 | IfExpr | test.rs:269:46:275:5 | BlockExpr | | +| test.rs:262:24:264:9 | { ... } | test.rs:262:9:266:9 | if ... {...} else {...} | | +| test.rs:263:13:263:16 | true | test.rs:262:24:264:9 | { ... } | | +| test.rs:264:16:266:9 | { ... } | test.rs:262:9:266:9 | if ... {...} else {...} | | +| test.rs:265:13:265:17 | false | test.rs:264:16:266:9 | { ... } | | +| test.rs:269:5:275:5 | enter fn test_if_not_operator | test.rs:269:29:269:29 | a | | +| test.rs:269:5:275:5 | exit fn test_if_not_operator (normal) | test.rs:269:5:275:5 | exit fn test_if_not_operator | | +| test.rs:269:29:269:29 | a | test.rs:269:29:269:35 | ...: bool | match | +| test.rs:269:29:269:35 | ...: bool | test.rs:270:13:270:13 | a | | +| test.rs:269:46:275:5 | { ... } | test.rs:269:5:275:5 | exit fn test_if_not_operator (normal) | | +| test.rs:270:9:274:9 | if ... {...} else {...} | test.rs:269:46:275:5 | { ... } | | | test.rs:270:12:270:13 | [boolean(false)] ! ... | test.rs:273:13:273:17 | false | false | | test.rs:270:12:270:13 | [boolean(true)] ! ... | test.rs:271:13:271:16 | true | true | | test.rs:270:13:270:13 | a | test.rs:270:12:270:13 | [boolean(false)] ! ... | true | | test.rs:270:13:270:13 | a | test.rs:270:12:270:13 | [boolean(true)] ! ... | false | -| test.rs:270:15:272:9 | BlockExpr | test.rs:270:9:274:9 | IfExpr | | -| test.rs:271:13:271:16 | true | test.rs:270:15:272:9 | BlockExpr | | -| test.rs:272:16:274:9 | BlockExpr | test.rs:270:9:274:9 | IfExpr | | -| test.rs:273:13:273:17 | false | test.rs:272:16:274:9 | BlockExpr | | -| test.rs:277:5:279:5 | enter test_and_return | test.rs:277:24:277:24 | a | | -| test.rs:277:5:279:5 | exit test_and_return (normal) | test.rs:277:5:279:5 | exit test_and_return | | -| test.rs:277:24:277:24 | a | test.rs:277:24:277:30 | Param | match | -| test.rs:277:24:277:30 | Param | test.rs:278:9:278:20 | ExprStmt | | -| test.rs:277:33:279:5 | BlockExpr | test.rs:277:5:279:5 | exit test_and_return (normal) | | +| test.rs:270:15:272:9 | { ... } | test.rs:270:9:274:9 | if ... {...} else {...} | | +| test.rs:271:13:271:16 | true | test.rs:270:15:272:9 | { ... } | | +| test.rs:272:16:274:9 | { ... } | test.rs:270:9:274:9 | if ... {...} else {...} | | +| test.rs:273:13:273:17 | false | test.rs:272:16:274:9 | { ... } | | +| test.rs:277:5:279:5 | enter fn test_and_return | test.rs:277:24:277:24 | a | | +| test.rs:277:5:279:5 | exit fn test_and_return (normal) | test.rs:277:5:279:5 | exit fn test_and_return | | +| test.rs:277:24:277:24 | a | test.rs:277:24:277:30 | ...: bool | match | +| test.rs:277:24:277:30 | ...: bool | test.rs:278:9:278:20 | ExprStmt | | +| test.rs:277:33:279:5 | { ... } | test.rs:277:5:279:5 | exit fn test_and_return (normal) | | | test.rs:278:9:278:9 | a | test.rs:278:9:278:19 | ... && ... | false | -| test.rs:278:9:278:9 | a | test.rs:278:14:278:19 | ReturnExpr | true | -| test.rs:278:9:278:19 | ... && ... | test.rs:277:33:279:5 | BlockExpr | | +| test.rs:278:9:278:9 | a | test.rs:278:14:278:19 | return | true | +| test.rs:278:9:278:19 | ... && ... | test.rs:277:33:279:5 | { ... } | | | test.rs:278:9:278:20 | ExprStmt | test.rs:278:9:278:9 | a | | -| test.rs:278:14:278:19 | ReturnExpr | test.rs:277:5:279:5 | exit test_and_return (normal) | return | -| test.rs:285:5:287:5 | enter test_question_mark_operator_1 | test.rs:285:38:285:38 | s | | -| test.rs:285:5:287:5 | exit test_question_mark_operator_1 (normal) | test.rs:285:5:287:5 | exit test_question_mark_operator_1 | | -| test.rs:285:38:285:38 | s | test.rs:285:38:285:44 | Param | match | -| test.rs:285:38:285:44 | Param | test.rs:286:9:286:10 | Ok | | -| test.rs:285:87:287:5 | BlockExpr | test.rs:285:5:287:5 | exit test_question_mark_operator_1 (normal) | | -| test.rs:286:9:286:10 | Ok | test.rs:286:12:286:12 | s | | -| test.rs:286:9:286:33 | CallExpr | test.rs:285:87:287:5 | BlockExpr | | -| test.rs:286:12:286:12 | s | test.rs:286:12:286:27 | ... .parse(...) | | -| test.rs:286:12:286:27 | ... .parse(...) | test.rs:286:12:286:28 | TryExpr | | -| test.rs:286:12:286:28 | TryExpr | test.rs:285:5:287:5 | exit test_question_mark_operator_1 (normal) | return | -| test.rs:286:12:286:28 | TryExpr | test.rs:286:32:286:32 | 4 | match | -| test.rs:286:12:286:32 | ... + ... | test.rs:286:9:286:33 | CallExpr | | -| test.rs:286:32:286:32 | 4 | test.rs:286:12:286:32 | ... + ... | | -| test.rs:289:5:294:5 | enter test_question_mark_operator_2 | test.rs:289:38:289:38 | b | | -| test.rs:289:5:294:5 | exit test_question_mark_operator_2 (normal) | test.rs:289:5:294:5 | exit test_question_mark_operator_2 | | -| test.rs:289:38:289:38 | b | test.rs:289:38:289:52 | Param | match | -| test.rs:289:38:289:52 | Param | test.rs:290:15:290:15 | b | | -| test.rs:289:71:294:5 | BlockExpr | test.rs:289:5:294:5 | exit test_question_mark_operator_2 (normal) | | -| test.rs:290:9:293:9 | MatchExpr | test.rs:289:71:294:5 | BlockExpr | | -| test.rs:290:15:290:15 | b | test.rs:290:15:290:16 | TryExpr | | -| test.rs:290:15:290:16 | TryExpr | test.rs:289:5:294:5 | exit test_question_mark_operator_2 (normal) | return | -| test.rs:290:15:290:16 | TryExpr | test.rs:291:13:291:16 | true | match | -| test.rs:291:13:291:16 | LiteralPat | test.rs:291:21:291:24 | Some | match | -| test.rs:291:13:291:16 | LiteralPat | test.rs:292:13:292:17 | false | no-match | -| test.rs:291:13:291:16 | true | test.rs:291:13:291:16 | LiteralPat | | -| test.rs:291:21:291:24 | Some | test.rs:291:26:291:30 | false | | -| test.rs:291:21:291:31 | CallExpr | test.rs:290:9:293:9 | MatchExpr | | -| test.rs:291:26:291:30 | false | test.rs:291:21:291:31 | CallExpr | | -| test.rs:292:13:292:17 | LiteralPat | test.rs:292:22:292:25 | Some | match | -| test.rs:292:13:292:17 | false | test.rs:292:13:292:17 | LiteralPat | | -| test.rs:292:22:292:25 | Some | test.rs:292:27:292:30 | true | | -| test.rs:292:22:292:31 | CallExpr | test.rs:290:9:293:9 | MatchExpr | | -| test.rs:292:27:292:30 | true | test.rs:292:22:292:31 | CallExpr | | -| test.rs:300:5:306:5 | enter test_match | test.rs:300:19:300:29 | maybe_digit | | -| test.rs:300:5:306:5 | exit test_match (normal) | test.rs:300:5:306:5 | exit test_match | | -| test.rs:300:19:300:29 | maybe_digit | test.rs:300:19:300:42 | Param | match | -| test.rs:300:19:300:42 | Param | test.rs:301:15:301:25 | maybe_digit | | -| test.rs:300:52:306:5 | BlockExpr | test.rs:300:5:306:5 | exit test_match (normal) | | -| test.rs:301:9:305:9 | MatchExpr | test.rs:300:52:306:5 | BlockExpr | | -| test.rs:301:15:301:25 | maybe_digit | test.rs:302:13:302:27 | TupleStructPat | | -| test.rs:302:13:302:27 | TupleStructPat | test.rs:302:26:302:26 | x | match | -| test.rs:302:13:302:27 | TupleStructPat | test.rs:303:13:303:27 | TupleStructPat | no-match | -| test.rs:302:26:302:26 | x | test.rs:302:32:302:32 | x | match | -| test.rs:302:32:302:32 | x | test.rs:302:36:302:37 | 10 | | -| test.rs:302:32:302:37 | ... < ... | test.rs:302:42:302:42 | x | true | -| test.rs:302:32:302:37 | ... < ... | test.rs:303:13:303:27 | TupleStructPat | false | -| test.rs:302:36:302:37 | 10 | test.rs:302:32:302:37 | ... < ... | | -| test.rs:302:42:302:42 | x | test.rs:302:46:302:46 | 5 | | -| test.rs:302:42:302:46 | ... + ... | test.rs:301:9:305:9 | MatchExpr | | -| test.rs:302:46:302:46 | 5 | test.rs:302:42:302:46 | ... + ... | | -| test.rs:303:13:303:27 | TupleStructPat | test.rs:303:26:303:26 | x | match | -| test.rs:303:13:303:27 | TupleStructPat | test.rs:304:13:304:24 | PathPat | no-match | -| test.rs:303:26:303:26 | x | test.rs:303:32:303:32 | x | match | -| test.rs:303:32:303:32 | x | test.rs:301:9:305:9 | MatchExpr | | -| test.rs:304:13:304:24 | PathPat | test.rs:304:29:304:29 | 5 | match | -| test.rs:304:29:304:29 | 5 | test.rs:301:9:305:9 | MatchExpr | | -| test.rs:308:5:317:5 | enter test_match_with_return_in_scrutinee | test.rs:308:44:308:54 | maybe_digit | | -| test.rs:308:5:317:5 | exit test_match_with_return_in_scrutinee (normal) | test.rs:308:5:317:5 | exit test_match_with_return_in_scrutinee | | -| test.rs:308:44:308:54 | maybe_digit | test.rs:308:44:308:67 | Param | match | -| test.rs:308:44:308:67 | Param | test.rs:309:19:309:29 | maybe_digit | | -| test.rs:308:77:317:5 | BlockExpr | test.rs:308:5:317:5 | exit test_match_with_return_in_scrutinee (normal) | | -| test.rs:309:9:316:9 | MatchExpr | test.rs:308:77:317:5 | BlockExpr | | -| test.rs:309:16:313:9 | IfExpr | test.rs:314:13:314:27 | TupleStructPat | | -| test.rs:309:19:309:29 | maybe_digit | test.rs:309:34:309:37 | Some | | -| test.rs:309:19:309:40 | ... == ... | test.rs:310:13:310:21 | ExprStmt | true | -| test.rs:309:19:309:40 | ... == ... | test.rs:312:13:312:23 | maybe_digit | false | -| test.rs:309:34:309:37 | Some | test.rs:309:39:309:39 | 3 | | -| test.rs:309:34:309:40 | CallExpr | test.rs:309:19:309:40 | ... == ... | | -| test.rs:309:39:309:39 | 3 | test.rs:309:34:309:40 | CallExpr | | -| test.rs:310:13:310:20 | ReturnExpr | test.rs:308:5:317:5 | exit test_match_with_return_in_scrutinee (normal) | return | -| test.rs:310:13:310:21 | ExprStmt | test.rs:310:20:310:20 | 3 | | -| test.rs:310:20:310:20 | 3 | test.rs:310:13:310:20 | ReturnExpr | | -| test.rs:311:16:313:9 | BlockExpr | test.rs:309:16:313:9 | IfExpr | | -| test.rs:312:13:312:23 | maybe_digit | test.rs:311:16:313:9 | BlockExpr | | -| test.rs:314:13:314:27 | TupleStructPat | test.rs:314:26:314:26 | x | match | -| test.rs:314:13:314:27 | TupleStructPat | test.rs:315:13:315:24 | PathPat | no-match | -| test.rs:314:26:314:26 | x | test.rs:314:32:314:32 | x | match | -| test.rs:314:32:314:32 | x | test.rs:314:36:314:36 | 5 | | -| test.rs:314:32:314:36 | ... + ... | test.rs:309:9:316:9 | MatchExpr | | -| test.rs:314:36:314:36 | 5 | test.rs:314:32:314:36 | ... + ... | | -| test.rs:315:13:315:24 | PathPat | test.rs:315:29:315:29 | 5 | match | -| test.rs:315:29:315:29 | 5 | test.rs:309:9:316:9 | MatchExpr | | -| test.rs:319:5:324:5 | enter test_match_and | test.rs:319:23:319:26 | cond | | -| test.rs:319:5:324:5 | exit test_match_and (normal) | test.rs:319:5:324:5 | exit test_match_and | | -| test.rs:319:23:319:26 | cond | test.rs:319:23:319:32 | Param | match | -| test.rs:319:23:319:32 | Param | test.rs:319:35:319:35 | r | | -| test.rs:319:35:319:35 | r | test.rs:319:35:319:49 | Param | match | -| test.rs:319:35:319:49 | Param | test.rs:320:16:320:16 | r | | -| test.rs:319:60:324:5 | BlockExpr | test.rs:319:5:324:5 | exit test_match_and (normal) | | -| test.rs:320:9:323:18 | ... && ... | test.rs:319:60:324:5 | BlockExpr | | -| test.rs:320:10:323:9 | [boolean(false)] MatchExpr | test.rs:320:9:323:18 | ... && ... | false | -| test.rs:320:10:323:9 | [boolean(true)] MatchExpr | test.rs:323:15:323:18 | cond | true | -| test.rs:320:16:320:16 | r | test.rs:321:13:321:19 | TupleStructPat | | -| test.rs:321:13:321:19 | TupleStructPat | test.rs:321:18:321:18 | a | match | -| test.rs:321:13:321:19 | TupleStructPat | test.rs:322:13:322:13 | WildcardPat | no-match | -| test.rs:321:18:321:18 | a | test.rs:321:24:321:24 | a | match | -| test.rs:321:24:321:24 | a | test.rs:320:10:323:9 | [boolean(false)] MatchExpr | false | -| test.rs:321:24:321:24 | a | test.rs:320:10:323:9 | [boolean(true)] MatchExpr | true | -| test.rs:322:13:322:13 | WildcardPat | test.rs:322:18:322:22 | false | match | -| test.rs:322:18:322:22 | false | test.rs:320:10:323:9 | [boolean(false)] MatchExpr | false | -| test.rs:323:15:323:18 | cond | test.rs:320:9:323:18 | ... && ... | | -| test.rs:326:5:331:5 | enter test_match_with_no_arms | test.rs:326:35:326:35 | r | | -| test.rs:326:5:331:5 | exit test_match_with_no_arms (normal) | test.rs:326:5:331:5 | exit test_match_with_no_arms | | -| test.rs:326:35:326:35 | r | test.rs:326:35:326:58 | Param | match | -| test.rs:326:35:326:58 | Param | test.rs:327:15:327:15 | r | | -| test.rs:326:66:331:5 | BlockExpr | test.rs:326:5:331:5 | exit test_match_with_no_arms (normal) | | -| test.rs:327:9:330:9 | MatchExpr | test.rs:326:66:331:5 | BlockExpr | | -| test.rs:327:15:327:15 | r | test.rs:328:13:328:21 | TupleStructPat | | -| test.rs:328:13:328:21 | TupleStructPat | test.rs:328:16:328:20 | value | match | -| test.rs:328:13:328:21 | TupleStructPat | test.rs:329:13:329:22 | TupleStructPat | no-match | -| test.rs:328:16:328:20 | value | test.rs:328:26:328:30 | value | match | -| test.rs:328:26:328:30 | value | test.rs:327:9:330:9 | MatchExpr | | -| test.rs:329:13:329:22 | TupleStructPat | test.rs:329:17:329:21 | never | match | -| test.rs:329:17:329:21 | never | test.rs:329:33:329:37 | never | match | -| test.rs:329:27:329:40 | MatchExpr | test.rs:327:9:330:9 | MatchExpr | | -| test.rs:329:33:329:37 | never | test.rs:329:27:329:40 | MatchExpr | | -| test.rs:336:5:339:5 | enter test_let_match | test.rs:336:23:336:23 | a | | -| test.rs:336:5:339:5 | exit test_let_match (normal) | test.rs:336:5:339:5 | exit test_let_match | | -| test.rs:336:23:336:23 | a | test.rs:336:23:336:36 | Param | match | -| test.rs:336:23:336:36 | Param | test.rs:337:9:337:57 | LetStmt | | -| test.rs:336:46:339:5 | BlockExpr | test.rs:336:5:339:5 | exit test_let_match (normal) | | -| test.rs:337:9:337:57 | LetStmt | test.rs:337:23:337:23 | a | | -| test.rs:337:13:337:19 | TupleStructPat | test.rs:337:18:337:18 | n | match | -| test.rs:337:13:337:19 | TupleStructPat | test.rs:337:39:337:53 | MacroStmts | no-match | -| test.rs:337:18:337:18 | n | test.rs:338:9:338:9 | n | match | -| test.rs:337:23:337:23 | a | test.rs:337:13:337:19 | TupleStructPat | | -| test.rs:337:32:337:54 | $crate::panicking::panic_fmt | test.rs:337:39:337:53 | "Expected some" | | -| test.rs:337:32:337:54 | MacroExpr | test.rs:337:30:337:56 | BlockExpr | | -| test.rs:337:39:337:53 | "Expected some" | test.rs:337:39:337:53 | FormatArgsExpr | | -| test.rs:337:39:337:53 | BlockExpr | test.rs:337:39:337:53 | MacroExpr | | -| test.rs:337:39:337:53 | CallExpr | test.rs:337:39:337:53 | BlockExpr | | -| test.rs:337:39:337:53 | ExprStmt | test.rs:337:32:337:54 | $crate::panicking::panic_fmt | | -| test.rs:337:39:337:53 | FormatArgsExpr | test.rs:337:39:337:53 | MacroExpr | | -| test.rs:337:39:337:53 | MacroExpr | test.rs:337:32:337:54 | MacroExpr | | -| test.rs:337:39:337:53 | MacroExpr | test.rs:337:39:337:53 | CallExpr | | -| test.rs:337:39:337:53 | MacroStmts | test.rs:337:39:337:53 | ExprStmt | | -| test.rs:337:39:337:53 | MacroStmts | test.rs:337:39:337:53 | MacroStmts | | -| test.rs:338:9:338:9 | n | test.rs:336:46:339:5 | BlockExpr | | -| test.rs:341:5:347:5 | enter test_let_with_return | test.rs:341:29:341:29 | m | | -| test.rs:341:5:347:5 | exit test_let_with_return (normal) | test.rs:341:5:347:5 | exit test_let_with_return | | -| test.rs:341:29:341:29 | m | test.rs:341:29:341:42 | Param | match | -| test.rs:341:29:341:42 | Param | test.rs:342:9:345:10 | LetStmt | | -| test.rs:341:53:347:5 | BlockExpr | test.rs:341:5:347:5 | exit test_let_with_return (normal) | | -| test.rs:342:9:345:10 | LetStmt | test.rs:342:25:342:25 | m | | -| test.rs:342:13:342:15 | ret | test.rs:346:9:346:12 | true | match | -| test.rs:342:19:345:9 | MatchExpr | test.rs:342:13:342:15 | ret | | -| test.rs:342:25:342:25 | m | test.rs:343:13:343:21 | TupleStructPat | | -| test.rs:343:13:343:21 | TupleStructPat | test.rs:343:18:343:20 | ret | match | -| test.rs:343:13:343:21 | TupleStructPat | test.rs:344:13:344:16 | None | no-match | -| test.rs:343:18:343:20 | ret | test.rs:343:26:343:28 | ret | match | -| test.rs:343:26:343:28 | ret | test.rs:342:19:345:9 | MatchExpr | | -| test.rs:344:13:344:16 | None | test.rs:344:28:344:32 | false | match | -| test.rs:344:21:344:32 | ReturnExpr | test.rs:341:5:347:5 | exit test_let_with_return (normal) | return | -| test.rs:344:28:344:32 | false | test.rs:344:21:344:32 | ReturnExpr | | -| test.rs:346:9:346:12 | true | test.rs:341:53:347:5 | BlockExpr | | -| test.rs:352:5:355:5 | enter empty_tuple_pattern | test.rs:352:28:352:31 | unit | | -| test.rs:352:5:355:5 | exit empty_tuple_pattern (normal) | test.rs:352:5:355:5 | exit empty_tuple_pattern | | -| test.rs:352:28:352:31 | unit | test.rs:352:28:352:35 | Param | match | -| test.rs:352:28:352:35 | Param | test.rs:353:9:353:22 | LetStmt | | -| test.rs:353:9:353:22 | LetStmt | test.rs:353:18:353:21 | unit | | -| test.rs:353:13:353:14 | TuplePat | test.rs:354:9:354:15 | ExprStmt | match | -| test.rs:353:18:353:21 | unit | test.rs:353:13:353:14 | TuplePat | | -| test.rs:354:9:354:14 | ReturnExpr | test.rs:352:5:355:5 | exit empty_tuple_pattern (normal) | return | -| test.rs:354:9:354:15 | ExprStmt | test.rs:354:9:354:14 | ReturnExpr | | -| test.rs:359:5:363:5 | enter empty_struct_pattern | test.rs:359:29:359:30 | st | | -| test.rs:359:5:363:5 | exit empty_struct_pattern (normal) | test.rs:359:5:363:5 | exit empty_struct_pattern | | -| test.rs:359:29:359:30 | st | test.rs:359:29:359:40 | Param | match | -| test.rs:359:29:359:40 | Param | test.rs:360:15:360:16 | st | | -| test.rs:359:50:363:5 | BlockExpr | test.rs:359:5:363:5 | exit empty_struct_pattern (normal) | | -| test.rs:360:9:362:9 | MatchExpr | test.rs:359:50:363:5 | BlockExpr | | -| test.rs:360:15:360:16 | st | test.rs:361:13:361:27 | RecordPat | | -| test.rs:361:13:361:27 | RecordPat | test.rs:361:24:361:25 | RestPat | match | -| test.rs:361:24:361:25 | RestPat | test.rs:361:32:361:32 | 1 | match | -| test.rs:361:32:361:32 | 1 | test.rs:360:9:362:9 | MatchExpr | | -| test.rs:365:5:372:5 | enter range_pattern | test.rs:366:15:366:16 | 42 | | -| test.rs:365:5:372:5 | exit range_pattern (normal) | test.rs:365:5:372:5 | exit range_pattern | | -| test.rs:365:31:372:5 | BlockExpr | test.rs:365:5:372:5 | exit range_pattern (normal) | | -| test.rs:366:9:371:9 | MatchExpr | test.rs:365:31:372:5 | BlockExpr | | -| test.rs:366:15:366:16 | 42 | test.rs:367:13:367:15 | RangePat | | -| test.rs:367:13:367:15 | RangePat | test.rs:367:15:367:15 | 0 | match | -| test.rs:367:13:367:15 | RangePat | test.rs:368:13:368:16 | RangePat | no-match | -| test.rs:367:15:367:15 | 0 | test.rs:367:15:367:15 | LiteralPat | | -| test.rs:367:15:367:15 | LiteralPat | test.rs:367:20:367:20 | 1 | match | -| test.rs:367:15:367:15 | LiteralPat | test.rs:368:13:368:16 | RangePat | no-match | -| test.rs:367:20:367:20 | 1 | test.rs:366:9:371:9 | MatchExpr | | -| test.rs:368:13:368:13 | 1 | test.rs:368:13:368:13 | LiteralPat | | -| test.rs:368:13:368:13 | LiteralPat | test.rs:368:16:368:16 | 2 | match | -| test.rs:368:13:368:13 | LiteralPat | test.rs:369:13:369:15 | RangePat | no-match | -| test.rs:368:13:368:16 | RangePat | test.rs:368:13:368:13 | 1 | match | -| test.rs:368:13:368:16 | RangePat | test.rs:369:13:369:15 | RangePat | no-match | -| test.rs:368:16:368:16 | 2 | test.rs:368:16:368:16 | LiteralPat | | -| test.rs:368:16:368:16 | LiteralPat | test.rs:368:21:368:21 | 2 | match | -| test.rs:368:16:368:16 | LiteralPat | test.rs:369:13:369:15 | RangePat | no-match | -| test.rs:368:21:368:21 | 2 | test.rs:366:9:371:9 | MatchExpr | | -| test.rs:369:13:369:13 | 5 | test.rs:369:13:369:13 | LiteralPat | | -| test.rs:369:13:369:13 | LiteralPat | test.rs:369:20:369:20 | 3 | match | -| test.rs:369:13:369:13 | LiteralPat | test.rs:370:13:370:13 | WildcardPat | no-match | -| test.rs:369:13:369:15 | RangePat | test.rs:369:13:369:13 | 5 | match | -| test.rs:369:13:369:15 | RangePat | test.rs:370:13:370:13 | WildcardPat | no-match | -| test.rs:369:20:369:20 | 3 | test.rs:366:9:371:9 | MatchExpr | | -| test.rs:370:13:370:13 | WildcardPat | test.rs:370:18:370:18 | 4 | match | -| test.rs:370:18:370:18 | 4 | test.rs:366:9:371:9 | MatchExpr | | -| test.rs:376:5:381:5 | enter test_infinite_loop | test.rs:377:9:379:9 | ExprStmt | | -| test.rs:377:9:379:9 | ExprStmt | test.rs:378:13:378:14 | TupleExpr | | -| test.rs:377:14:379:9 | BlockExpr | test.rs:378:13:378:14 | TupleExpr | | -| test.rs:378:13:378:14 | TupleExpr | test.rs:377:14:379:9 | BlockExpr | | -| test.rs:385:5:387:5 | enter say_hello | test.rs:386:9:386:34 | ExprStmt | | -| test.rs:385:5:387:5 | exit say_hello (normal) | test.rs:385:5:387:5 | exit say_hello | | -| test.rs:385:26:387:5 | BlockExpr | test.rs:385:5:387:5 | exit say_hello (normal) | | -| test.rs:386:9:386:33 | $crate::io::_print | test.rs:386:18:386:32 | "hello, world!\\n" | | -| test.rs:386:9:386:33 | MacroExpr | test.rs:385:26:387:5 | BlockExpr | | -| test.rs:386:9:386:34 | ExprStmt | test.rs:386:18:386:32 | MacroStmts | | -| test.rs:386:18:386:32 | "hello, world!\\n" | test.rs:386:18:386:32 | FormatArgsExpr | | -| test.rs:386:18:386:32 | BlockExpr | test.rs:386:9:386:33 | MacroExpr | | -| test.rs:386:18:386:32 | CallExpr | test.rs:386:18:386:32 | BlockExpr | | -| test.rs:386:18:386:32 | ExprStmt | test.rs:386:9:386:33 | $crate::io::_print | | -| test.rs:386:18:386:32 | FormatArgsExpr | test.rs:386:18:386:32 | MacroExpr | | -| test.rs:386:18:386:32 | MacroExpr | test.rs:386:18:386:32 | CallExpr | | -| test.rs:386:18:386:32 | MacroStmts | test.rs:386:18:386:32 | ExprStmt | | -| test.rs:389:5:408:5 | enter async_block | test.rs:389:26:389:26 | b | | -| test.rs:389:5:408:5 | exit async_block (normal) | test.rs:389:5:408:5 | exit async_block | | -| test.rs:389:26:389:26 | b | test.rs:389:26:389:32 | Param | match | -| test.rs:389:26:389:32 | Param | test.rs:390:9:392:10 | LetStmt | | -| test.rs:389:35:408:5 | BlockExpr | test.rs:389:5:408:5 | exit async_block (normal) | | -| test.rs:390:9:392:10 | LetStmt | test.rs:390:26:392:9 | BlockExpr | | -| test.rs:390:13:390:22 | say_godbye | test.rs:393:9:395:10 | LetStmt | match | -| test.rs:390:26:392:9 | BlockExpr | test.rs:390:13:390:22 | say_godbye | | -| test.rs:390:26:392:9 | enter BlockExpr | test.rs:391:13:391:42 | ExprStmt | | -| test.rs:390:26:392:9 | exit BlockExpr (normal) | test.rs:390:26:392:9 | exit BlockExpr | | -| test.rs:391:13:391:41 | $crate::io::_print | test.rs:391:22:391:40 | "godbye, everyone!\\n" | | -| test.rs:391:13:391:41 | MacroExpr | test.rs:390:26:392:9 | exit BlockExpr (normal) | | -| test.rs:391:13:391:42 | ExprStmt | test.rs:391:22:391:40 | MacroStmts | | -| test.rs:391:22:391:40 | "godbye, everyone!\\n" | test.rs:391:22:391:40 | FormatArgsExpr | | -| test.rs:391:22:391:40 | BlockExpr | test.rs:391:13:391:41 | MacroExpr | | -| test.rs:391:22:391:40 | CallExpr | test.rs:391:22:391:40 | BlockExpr | | -| test.rs:391:22:391:40 | ExprStmt | test.rs:391:13:391:41 | $crate::io::_print | | -| test.rs:391:22:391:40 | FormatArgsExpr | test.rs:391:22:391:40 | MacroExpr | | -| test.rs:391:22:391:40 | MacroExpr | test.rs:391:22:391:40 | CallExpr | | -| test.rs:391:22:391:40 | MacroStmts | test.rs:391:22:391:40 | ExprStmt | | -| test.rs:393:9:395:10 | LetStmt | test.rs:393:31:395:9 | BlockExpr | | -| test.rs:393:13:393:27 | say_how_are_you | test.rs:396:9:396:28 | LetStmt | match | -| test.rs:393:31:395:9 | BlockExpr | test.rs:393:13:393:27 | say_how_are_you | | -| test.rs:393:31:395:9 | enter BlockExpr | test.rs:394:13:394:37 | ExprStmt | | -| test.rs:393:31:395:9 | exit BlockExpr (normal) | test.rs:393:31:395:9 | exit BlockExpr | | -| test.rs:394:13:394:36 | $crate::io::_print | test.rs:394:22:394:35 | "how are you?\\n" | | -| test.rs:394:13:394:36 | MacroExpr | test.rs:393:31:395:9 | exit BlockExpr (normal) | | -| test.rs:394:13:394:37 | ExprStmt | test.rs:394:22:394:35 | MacroStmts | | -| test.rs:394:22:394:35 | "how are you?\\n" | test.rs:394:22:394:35 | FormatArgsExpr | | -| test.rs:394:22:394:35 | BlockExpr | test.rs:394:13:394:36 | MacroExpr | | -| test.rs:394:22:394:35 | CallExpr | test.rs:394:22:394:35 | BlockExpr | | -| test.rs:394:22:394:35 | ExprStmt | test.rs:394:13:394:36 | $crate::io::_print | | -| test.rs:394:22:394:35 | FormatArgsExpr | test.rs:394:22:394:35 | MacroExpr | | -| test.rs:394:22:394:35 | MacroExpr | test.rs:394:22:394:35 | CallExpr | | -| test.rs:394:22:394:35 | MacroStmts | test.rs:394:22:394:35 | ExprStmt | | -| test.rs:396:9:396:28 | LetStmt | test.rs:396:20:396:27 | BlockExpr | | -| test.rs:396:13:396:16 | noop | test.rs:397:9:397:26 | ExprStmt | match | -| test.rs:396:20:396:27 | BlockExpr | test.rs:396:13:396:16 | noop | | -| test.rs:397:9:397:17 | say_hello | test.rs:397:9:397:19 | CallExpr | | -| test.rs:397:9:397:19 | CallExpr | test.rs:397:9:397:25 | AwaitExpr | | -| test.rs:397:9:397:25 | AwaitExpr | test.rs:398:9:398:30 | ExprStmt | | -| test.rs:397:9:397:26 | ExprStmt | test.rs:397:9:397:17 | say_hello | | -| test.rs:398:9:398:23 | say_how_are_you | test.rs:398:9:398:29 | AwaitExpr | | -| test.rs:398:9:398:29 | AwaitExpr | test.rs:399:9:399:25 | ExprStmt | | -| test.rs:398:9:398:30 | ExprStmt | test.rs:398:9:398:23 | say_how_are_you | | -| test.rs:399:9:399:18 | say_godbye | test.rs:399:9:399:24 | AwaitExpr | | -| test.rs:399:9:399:24 | AwaitExpr | test.rs:400:9:400:19 | ExprStmt | | -| test.rs:399:9:399:25 | ExprStmt | test.rs:399:9:399:18 | say_godbye | | -| test.rs:400:9:400:12 | noop | test.rs:400:9:400:18 | AwaitExpr | | -| test.rs:400:9:400:18 | AwaitExpr | test.rs:402:9:407:10 | LetStmt | | -| test.rs:400:9:400:19 | ExprStmt | test.rs:400:9:400:12 | noop | | -| test.rs:402:9:407:10 | LetStmt | test.rs:402:22:407:9 | ClosureExpr | | -| test.rs:402:13:402:18 | lambda | test.rs:389:35:408:5 | BlockExpr | match | -| test.rs:402:22:407:9 | ClosureExpr | test.rs:402:13:402:18 | lambda | | -| test.rs:402:22:407:9 | enter ClosureExpr | test.rs:402:23:402:25 | foo | | -| test.rs:402:22:407:9 | exit ClosureExpr (normal) | test.rs:402:22:407:9 | exit ClosureExpr | | -| test.rs:402:23:402:25 | Param | test.rs:402:28:407:9 | BlockExpr | | -| test.rs:402:23:402:25 | foo | test.rs:402:23:402:25 | Param | match | -| test.rs:402:28:407:9 | BlockExpr | test.rs:402:22:407:9 | exit ClosureExpr (normal) | | -| test.rs:402:28:407:9 | enter BlockExpr | test.rs:403:13:405:14 | ExprStmt | | -| test.rs:402:28:407:9 | exit BlockExpr (normal) | test.rs:402:28:407:9 | exit BlockExpr | | -| test.rs:403:13:405:13 | IfExpr | test.rs:406:13:406:15 | foo | | -| test.rs:403:13:405:14 | ExprStmt | test.rs:403:16:403:16 | b | | -| test.rs:403:16:403:16 | b | test.rs:403:13:405:13 | IfExpr | false | -| test.rs:403:16:403:16 | b | test.rs:404:17:404:41 | ExprStmt | true | -| test.rs:404:17:404:40 | ReturnExpr | test.rs:402:28:407:9 | exit BlockExpr (normal) | return | -| test.rs:404:17:404:41 | ExprStmt | test.rs:404:24:404:34 | async_block | | -| test.rs:404:24:404:34 | async_block | test.rs:404:36:404:39 | true | | -| test.rs:404:24:404:40 | CallExpr | test.rs:404:17:404:40 | ReturnExpr | | -| test.rs:404:36:404:39 | true | test.rs:404:24:404:40 | CallExpr | | -| test.rs:406:13:406:15 | foo | test.rs:402:28:407:9 | exit BlockExpr (normal) | | -| test.rs:414:5:416:5 | enter add_two | test.rs:414:22:414:22 | n | | -| test.rs:414:5:416:5 | exit add_two (normal) | test.rs:414:5:416:5 | exit add_two | | -| test.rs:414:22:414:22 | n | test.rs:414:22:414:27 | Param | match | -| test.rs:414:22:414:27 | Param | test.rs:415:9:415:9 | n | | -| test.rs:414:37:416:5 | BlockExpr | test.rs:414:5:416:5 | exit add_two (normal) | | -| test.rs:415:9:415:9 | n | test.rs:415:13:415:13 | 2 | | -| test.rs:415:9:415:13 | ... + ... | test.rs:414:37:416:5 | BlockExpr | | -| test.rs:415:13:415:13 | 2 | test.rs:415:9:415:13 | ... + ... | | -| test.rs:420:5:428:5 | enter const_block_assert | test.rs:423:9:425:9 | ExprStmt | | -| test.rs:420:5:428:5 | exit const_block_assert (normal) | test.rs:420:5:428:5 | exit const_block_assert | | -| test.rs:420:41:428:5 | BlockExpr | test.rs:420:5:428:5 | exit const_block_assert (normal) | | -| test.rs:423:9:425:9 | BlockExpr | test.rs:427:9:427:10 | 42 | | -| test.rs:423:9:425:9 | ExprStmt | test.rs:424:13:424:50 | ExprStmt | | -| test.rs:424:13:424:49 | $crate::panicking::panic_explicit | test.rs:424:13:424:49 | CallExpr | | -| test.rs:424:13:424:49 | BlockExpr | test.rs:424:13:424:49 | MacroExpr | | -| test.rs:424:13:424:49 | BlockExpr | test.rs:424:13:424:49 | exit panic_cold_explicit (normal) | | -| test.rs:424:13:424:49 | BlockExpr | test.rs:424:21:424:48 | IfExpr | | -| test.rs:424:13:424:49 | CallExpr | test.rs:424:13:424:49 | BlockExpr | | -| test.rs:424:13:424:49 | CallExpr | test.rs:424:13:424:49 | BlockExpr | | -| test.rs:424:13:424:49 | ExprStmt | test.rs:424:13:424:49 | MacroStmts | | -| test.rs:424:13:424:49 | ExprStmt | test.rs:424:13:424:49 | panic_cold_explicit | | -| test.rs:424:13:424:49 | MacroExpr | test.rs:423:9:425:9 | BlockExpr | | -| test.rs:424:13:424:49 | MacroExpr | test.rs:424:13:424:49 | BlockExpr | | -| test.rs:424:13:424:49 | MacroStmts | test.rs:424:13:424:49 | panic_cold_explicit | | -| test.rs:424:13:424:49 | enter panic_cold_explicit | test.rs:424:13:424:49 | $crate::panicking::panic_explicit | | -| test.rs:424:13:424:49 | exit panic_cold_explicit (normal) | test.rs:424:13:424:49 | exit panic_cold_explicit | | -| test.rs:424:13:424:49 | panic_cold_explicit | test.rs:424:13:424:49 | CallExpr | | -| test.rs:424:13:424:49 | panic_cold_explicit | test.rs:424:13:424:49 | ExprStmt | | -| test.rs:424:13:424:50 | ExprStmt | test.rs:424:21:424:48 | MacroStmts | | -| test.rs:424:21:424:42 | std::mem::size_of::<...> | test.rs:424:21:424:44 | CallExpr | | -| test.rs:424:21:424:44 | CallExpr | test.rs:424:48:424:48 | 0 | | -| test.rs:424:21:424:48 | ... > ... | test.rs:424:21:424:48 | [boolean(false)] ! ... | true | -| test.rs:424:21:424:48 | ... > ... | test.rs:424:21:424:48 | [boolean(true)] ! ... | false | -| test.rs:424:21:424:48 | BlockExpr | test.rs:424:13:424:49 | MacroExpr | | -| test.rs:424:21:424:48 | IfExpr | test.rs:424:21:424:48 | BlockExpr | | -| test.rs:424:21:424:48 | MacroStmts | test.rs:424:21:424:42 | std::mem::size_of::<...> | | -| test.rs:424:21:424:48 | [boolean(false)] ! ... | test.rs:424:21:424:48 | IfExpr | false | -| test.rs:424:21:424:48 | [boolean(true)] ! ... | test.rs:424:13:424:49 | ExprStmt | true | -| test.rs:424:48:424:48 | 0 | test.rs:424:21:424:48 | ... > ... | | -| test.rs:427:9:427:10 | 42 | test.rs:420:41:428:5 | BlockExpr | | -| test.rs:430:5:439:5 | enter const_block_panic | test.rs:431:9:431:30 | Const | | -| test.rs:430:5:439:5 | exit const_block_panic (normal) | test.rs:430:5:439:5 | exit const_block_panic | | -| test.rs:430:35:439:5 | BlockExpr | test.rs:430:5:439:5 | exit const_block_panic (normal) | | -| test.rs:431:9:431:30 | Const | test.rs:432:9:437:9 | ExprStmt | | -| test.rs:432:9:437:9 | ExprStmt | test.rs:432:12:432:16 | false | | -| test.rs:432:9:437:9 | IfExpr | test.rs:438:9:438:9 | N | | -| test.rs:432:12:432:16 | false | test.rs:432:9:437:9 | IfExpr | false | -| test.rs:435:17:435:24 | $crate::panicking::panic_explicit | test.rs:435:17:435:24 | CallExpr | | -| test.rs:435:17:435:24 | BlockExpr | test.rs:435:17:435:24 | exit panic_cold_explicit (normal) | | -| test.rs:435:17:435:24 | CallExpr | test.rs:435:17:435:24 | BlockExpr | | -| test.rs:435:17:435:24 | enter panic_cold_explicit | test.rs:435:17:435:24 | $crate::panicking::panic_explicit | | -| test.rs:435:17:435:24 | exit panic_cold_explicit (normal) | test.rs:435:17:435:24 | exit panic_cold_explicit | | -| test.rs:438:9:438:9 | N | test.rs:430:35:439:5 | BlockExpr | | -| test.rs:442:1:447:1 | enter dead_code | test.rs:443:5:445:5 | ExprStmt | | -| test.rs:442:1:447:1 | exit dead_code (normal) | test.rs:442:1:447:1 | exit dead_code | | -| test.rs:443:5:445:5 | ExprStmt | test.rs:443:9:443:12 | true | | -| test.rs:443:9:443:12 | true | test.rs:444:9:444:17 | ExprStmt | true | -| test.rs:444:9:444:16 | ReturnExpr | test.rs:442:1:447:1 | exit dead_code (normal) | return | -| test.rs:444:9:444:17 | ExprStmt | test.rs:444:16:444:16 | 0 | | -| test.rs:444:16:444:16 | 0 | test.rs:444:9:444:16 | ReturnExpr | | -| test.rs:449:1:449:16 | enter do_thing | test.rs:449:15:449:16 | BlockExpr | | -| test.rs:449:1:449:16 | exit do_thing (normal) | test.rs:449:1:449:16 | exit do_thing | | -| test.rs:449:15:449:16 | BlockExpr | test.rs:449:1:449:16 | exit do_thing (normal) | | -| test.rs:451:1:453:1 | enter condition_not_met | test.rs:452:5:452:9 | false | | -| test.rs:451:1:453:1 | exit condition_not_met (normal) | test.rs:451:1:453:1 | exit condition_not_met | | -| test.rs:451:32:453:1 | BlockExpr | test.rs:451:1:453:1 | exit condition_not_met (normal) | | -| test.rs:452:5:452:9 | false | test.rs:451:32:453:1 | BlockExpr | | -| test.rs:455:1:455:21 | enter do_next_thing | test.rs:455:20:455:21 | BlockExpr | | -| test.rs:455:1:455:21 | exit do_next_thing (normal) | test.rs:455:1:455:21 | exit do_next_thing | | -| test.rs:455:20:455:21 | BlockExpr | test.rs:455:1:455:21 | exit do_next_thing (normal) | | -| test.rs:457:1:457:21 | enter do_last_thing | test.rs:457:20:457:21 | BlockExpr | | -| test.rs:457:1:457:21 | exit do_last_thing (normal) | test.rs:457:1:457:21 | exit do_last_thing | | -| test.rs:457:20:457:21 | BlockExpr | test.rs:457:1:457:21 | exit do_last_thing (normal) | | -| test.rs:459:1:473:1 | enter labelled_block1 | test.rs:460:5:471:6 | LetStmt | | -| test.rs:459:1:473:1 | exit labelled_block1 (normal) | test.rs:459:1:473:1 | exit labelled_block1 | | -| test.rs:459:29:473:1 | BlockExpr | test.rs:459:1:473:1 | exit labelled_block1 (normal) | | -| test.rs:460:5:471:6 | LetStmt | test.rs:461:9:461:19 | ExprStmt | | -| test.rs:460:9:460:14 | result | test.rs:472:5:472:10 | result | match | -| test.rs:460:18:471:5 | BlockExpr | test.rs:460:9:460:14 | result | | -| test.rs:461:9:461:16 | do_thing | test.rs:461:9:461:18 | CallExpr | | -| test.rs:461:9:461:18 | CallExpr | test.rs:462:9:464:9 | ExprStmt | | -| test.rs:461:9:461:19 | ExprStmt | test.rs:461:9:461:16 | do_thing | | -| test.rs:462:9:464:9 | ExprStmt | test.rs:462:12:462:28 | condition_not_met | | -| test.rs:462:9:464:9 | IfExpr | test.rs:465:9:465:24 | ExprStmt | | -| test.rs:462:12:462:28 | condition_not_met | test.rs:462:12:462:30 | CallExpr | | -| test.rs:462:12:462:30 | CallExpr | test.rs:462:9:464:9 | IfExpr | false | -| test.rs:462:12:462:30 | CallExpr | test.rs:463:13:463:27 | ExprStmt | true | -| test.rs:463:13:463:26 | BreakExpr | test.rs:460:18:471:5 | BlockExpr | break | -| test.rs:463:13:463:27 | ExprStmt | test.rs:463:26:463:26 | 1 | | -| test.rs:463:26:463:26 | 1 | test.rs:463:13:463:26 | BreakExpr | | -| test.rs:465:9:465:21 | do_next_thing | test.rs:465:9:465:23 | CallExpr | | -| test.rs:465:9:465:23 | CallExpr | test.rs:466:9:468:9 | ExprStmt | | -| test.rs:465:9:465:24 | ExprStmt | test.rs:465:9:465:21 | do_next_thing | | -| test.rs:466:9:468:9 | ExprStmt | test.rs:466:12:466:28 | condition_not_met | | -| test.rs:466:9:468:9 | IfExpr | test.rs:469:9:469:24 | ExprStmt | | -| test.rs:466:12:466:28 | condition_not_met | test.rs:466:12:466:30 | CallExpr | | -| test.rs:466:12:466:30 | CallExpr | test.rs:466:9:468:9 | IfExpr | false | -| test.rs:466:12:466:30 | CallExpr | test.rs:467:13:467:27 | ExprStmt | true | -| test.rs:467:13:467:26 | BreakExpr | test.rs:460:18:471:5 | BlockExpr | break | -| test.rs:467:13:467:27 | ExprStmt | test.rs:467:26:467:26 | 2 | | -| test.rs:467:26:467:26 | 2 | test.rs:467:13:467:26 | BreakExpr | | -| test.rs:469:9:469:21 | do_last_thing | test.rs:469:9:469:23 | CallExpr | | -| test.rs:469:9:469:23 | CallExpr | test.rs:470:9:470:9 | 3 | | -| test.rs:469:9:469:24 | ExprStmt | test.rs:469:9:469:21 | do_last_thing | | -| test.rs:470:9:470:9 | 3 | test.rs:460:18:471:5 | BlockExpr | | -| test.rs:472:5:472:10 | result | test.rs:459:29:473:1 | BlockExpr | | -| test.rs:475:1:483:1 | enter labelled_block2 | test.rs:476:5:482:6 | LetStmt | | -| test.rs:475:1:483:1 | exit labelled_block2 (normal) | test.rs:475:1:483:1 | exit labelled_block2 | | -| test.rs:475:22:483:1 | BlockExpr | test.rs:475:1:483:1 | exit labelled_block2 (normal) | | -| test.rs:476:5:482:6 | LetStmt | test.rs:477:9:477:34 | LetStmt | | -| test.rs:476:9:476:14 | result | test.rs:475:22:483:1 | BlockExpr | match | -| test.rs:476:18:482:5 | BlockExpr | test.rs:476:9:476:14 | result | | -| test.rs:477:9:477:34 | LetStmt | test.rs:477:30:477:33 | None | | -| test.rs:477:13:477:13 | x | test.rs:478:9:480:10 | LetStmt | match | -| test.rs:477:30:477:33 | None | test.rs:477:13:477:13 | x | | -| test.rs:478:9:480:10 | LetStmt | test.rs:478:23:478:23 | x | | -| test.rs:478:13:478:19 | TupleStructPat | test.rs:478:18:478:18 | y | match | -| test.rs:478:13:478:19 | TupleStructPat | test.rs:479:13:479:27 | ExprStmt | no-match | -| test.rs:478:18:478:18 | y | test.rs:481:9:481:9 | 0 | match | -| test.rs:478:23:478:23 | x | test.rs:478:13:478:19 | TupleStructPat | | -| test.rs:479:13:479:26 | BreakExpr | test.rs:476:18:482:5 | BlockExpr | break | -| test.rs:479:13:479:27 | ExprStmt | test.rs:479:26:479:26 | 1 | | -| test.rs:479:26:479:26 | 1 | test.rs:479:13:479:26 | BreakExpr | | -| test.rs:481:9:481:9 | 0 | test.rs:476:18:482:5 | BlockExpr | | -| test.rs:485:1:491:1 | enter test_nested_function2 | test.rs:486:5:486:18 | LetStmt | | -| test.rs:485:1:491:1 | exit test_nested_function2 (normal) | test.rs:485:1:491:1 | exit test_nested_function2 | | -| test.rs:485:28:491:1 | BlockExpr | test.rs:485:1:491:1 | exit test_nested_function2 (normal) | | -| test.rs:486:5:486:18 | LetStmt | test.rs:486:17:486:17 | 0 | | -| test.rs:486:9:486:13 | x | test.rs:487:5:489:5 | nested | match | -| test.rs:486:17:486:17 | 0 | test.rs:486:9:486:13 | x | | -| test.rs:487:5:489:5 | enter nested | test.rs:487:15:487:15 | x | | -| test.rs:487:5:489:5 | exit nested (normal) | test.rs:487:5:489:5 | exit nested | | -| test.rs:487:5:489:5 | nested | test.rs:490:5:490:19 | ExprStmt | | -| test.rs:487:15:487:15 | x | test.rs:487:15:487:25 | Param | match | -| test.rs:487:15:487:25 | Param | test.rs:488:9:488:16 | ExprStmt | | -| test.rs:487:28:489:5 | BlockExpr | test.rs:487:5:489:5 | exit nested (normal) | | -| test.rs:488:9:488:10 | * ... | test.rs:488:15:488:15 | 1 | | -| test.rs:488:9:488:15 | ... += ... | test.rs:487:28:489:5 | BlockExpr | | -| test.rs:488:9:488:16 | ExprStmt | test.rs:488:10:488:10 | x | | -| test.rs:488:10:488:10 | x | test.rs:488:9:488:10 | * ... | | -| test.rs:488:15:488:15 | 1 | test.rs:488:9:488:15 | ... += ... | | -| test.rs:490:5:490:10 | nested | test.rs:490:17:490:17 | x | | -| test.rs:490:5:490:18 | CallExpr | test.rs:485:28:491:1 | BlockExpr | | -| test.rs:490:5:490:19 | ExprStmt | test.rs:490:5:490:10 | nested | | -| test.rs:490:12:490:17 | RefExpr | test.rs:490:5:490:18 | CallExpr | | -| test.rs:490:17:490:17 | x | test.rs:490:12:490:17 | RefExpr | | +| test.rs:278:14:278:19 | return | test.rs:277:5:279:5 | exit fn test_and_return (normal) | return | +| test.rs:281:5:286:5 | enter fn test_and_true | test.rs:281:22:281:22 | a | | +| test.rs:281:5:286:5 | exit fn test_and_true (normal) | test.rs:281:5:286:5 | exit fn test_and_true | | +| test.rs:281:22:281:22 | a | test.rs:281:22:281:28 | ...: bool | match | +| test.rs:281:22:281:28 | ...: bool | test.rs:282:9:284:9 | ExprStmt | | +| test.rs:281:38:286:5 | { ... } | test.rs:281:5:286:5 | exit fn test_and_true (normal) | | +| test.rs:282:9:284:9 | ExprStmt | test.rs:282:13:282:13 | a | | +| test.rs:282:9:284:9 | if ... {...} | test.rs:285:9:285:9 | 0 | | +| test.rs:282:13:282:13 | a | test.rs:282:13:282:21 | [boolean(false)] ... && ... | false | +| test.rs:282:13:282:13 | a | test.rs:282:18:282:21 | true | true | +| test.rs:282:13:282:21 | [boolean(false)] ... && ... | test.rs:282:9:284:9 | if ... {...} | false | +| test.rs:282:13:282:21 | [boolean(true)] ... && ... | test.rs:283:13:283:21 | ExprStmt | true | +| test.rs:282:18:282:21 | true | test.rs:282:13:282:21 | [boolean(true)] ... && ... | true | +| test.rs:283:13:283:20 | return 1 | test.rs:281:5:286:5 | exit fn test_and_true (normal) | return | +| test.rs:283:13:283:21 | ExprStmt | test.rs:283:20:283:20 | 1 | | +| test.rs:283:20:283:20 | 1 | test.rs:283:13:283:20 | return 1 | | +| test.rs:285:9:285:9 | 0 | test.rs:281:38:286:5 | { ... } | | +| test.rs:292:5:294:5 | enter fn test_question_mark_operator_1 | test.rs:292:38:292:38 | s | | +| test.rs:292:5:294:5 | exit fn test_question_mark_operator_1 (normal) | test.rs:292:5:294:5 | exit fn test_question_mark_operator_1 | | +| test.rs:292:38:292:38 | s | test.rs:292:38:292:44 | ...: ... | match | +| test.rs:292:38:292:44 | ...: ... | test.rs:293:9:293:10 | Ok | | +| test.rs:292:87:294:5 | { ... } | test.rs:292:5:294:5 | exit fn test_question_mark_operator_1 (normal) | | +| test.rs:293:9:293:10 | Ok | test.rs:293:12:293:12 | s | | +| test.rs:293:9:293:33 | Ok(...) | test.rs:292:87:294:5 | { ... } | | +| test.rs:293:12:293:12 | s | test.rs:293:12:293:27 | ... .parse(...) | | +| test.rs:293:12:293:27 | ... .parse(...) | test.rs:293:12:293:28 | TryExpr | | +| test.rs:293:12:293:28 | TryExpr | test.rs:292:5:294:5 | exit fn test_question_mark_operator_1 (normal) | return | +| test.rs:293:12:293:28 | TryExpr | test.rs:293:32:293:32 | 4 | match | +| test.rs:293:12:293:32 | ... + ... | test.rs:293:9:293:33 | Ok(...) | | +| test.rs:293:32:293:32 | 4 | test.rs:293:12:293:32 | ... + ... | | +| test.rs:296:5:301:5 | enter fn test_question_mark_operator_2 | test.rs:296:38:296:38 | b | | +| test.rs:296:5:301:5 | exit fn test_question_mark_operator_2 (normal) | test.rs:296:5:301:5 | exit fn test_question_mark_operator_2 | | +| test.rs:296:38:296:38 | b | test.rs:296:38:296:52 | ...: Option::<...> | match | +| test.rs:296:38:296:52 | ...: Option::<...> | test.rs:297:15:297:15 | b | | +| test.rs:296:71:301:5 | { ... } | test.rs:296:5:301:5 | exit fn test_question_mark_operator_2 (normal) | | +| test.rs:297:9:300:9 | match ... { ... } | test.rs:296:71:301:5 | { ... } | | +| test.rs:297:15:297:15 | b | test.rs:297:15:297:16 | TryExpr | | +| test.rs:297:15:297:16 | TryExpr | test.rs:296:5:301:5 | exit fn test_question_mark_operator_2 (normal) | return | +| test.rs:297:15:297:16 | TryExpr | test.rs:298:13:298:16 | true | match | +| test.rs:298:13:298:16 | true | test.rs:298:13:298:16 | true | | +| test.rs:298:13:298:16 | true | test.rs:298:21:298:24 | Some | match | +| test.rs:298:13:298:16 | true | test.rs:299:13:299:17 | false | no-match | +| test.rs:298:21:298:24 | Some | test.rs:298:26:298:30 | false | | +| test.rs:298:21:298:31 | Some(...) | test.rs:297:9:300:9 | match ... { ... } | | +| test.rs:298:26:298:30 | false | test.rs:298:21:298:31 | Some(...) | | +| test.rs:299:13:299:17 | false | test.rs:299:13:299:17 | false | | +| test.rs:299:13:299:17 | false | test.rs:299:22:299:25 | Some | match | +| test.rs:299:22:299:25 | Some | test.rs:299:27:299:30 | true | | +| test.rs:299:22:299:31 | Some(...) | test.rs:297:9:300:9 | match ... { ... } | | +| test.rs:299:27:299:30 | true | test.rs:299:22:299:31 | Some(...) | | +| test.rs:307:5:313:5 | enter fn test_match | test.rs:307:19:307:29 | maybe_digit | | +| test.rs:307:5:313:5 | exit fn test_match (normal) | test.rs:307:5:313:5 | exit fn test_match | | +| test.rs:307:19:307:29 | maybe_digit | test.rs:307:19:307:42 | ...: Option::<...> | match | +| test.rs:307:19:307:42 | ...: Option::<...> | test.rs:308:15:308:25 | maybe_digit | | +| test.rs:307:52:313:5 | { ... } | test.rs:307:5:313:5 | exit fn test_match (normal) | | +| test.rs:308:9:312:9 | match maybe_digit { ... } | test.rs:307:52:313:5 | { ... } | | +| test.rs:308:15:308:25 | maybe_digit | test.rs:309:13:309:27 | TupleStructPat | | +| test.rs:309:13:309:27 | TupleStructPat | test.rs:309:26:309:26 | x | match | +| test.rs:309:13:309:27 | TupleStructPat | test.rs:310:13:310:27 | TupleStructPat | no-match | +| test.rs:309:26:309:26 | x | test.rs:309:32:309:32 | x | match | +| test.rs:309:32:309:32 | x | test.rs:309:36:309:37 | 10 | | +| test.rs:309:32:309:37 | ... < ... | test.rs:309:42:309:42 | x | true | +| test.rs:309:32:309:37 | ... < ... | test.rs:310:13:310:27 | TupleStructPat | false | +| test.rs:309:36:309:37 | 10 | test.rs:309:32:309:37 | ... < ... | | +| test.rs:309:42:309:42 | x | test.rs:309:46:309:46 | 5 | | +| test.rs:309:42:309:46 | ... + ... | test.rs:308:9:312:9 | match maybe_digit { ... } | | +| test.rs:309:46:309:46 | 5 | test.rs:309:42:309:46 | ... + ... | | +| test.rs:310:13:310:27 | TupleStructPat | test.rs:310:26:310:26 | x | match | +| test.rs:310:13:310:27 | TupleStructPat | test.rs:311:13:311:24 | ...::None | no-match | +| test.rs:310:26:310:26 | x | test.rs:310:32:310:32 | x | match | +| test.rs:310:32:310:32 | x | test.rs:308:9:312:9 | match maybe_digit { ... } | | +| test.rs:311:13:311:24 | ...::None | test.rs:311:29:311:29 | 5 | match | +| test.rs:311:29:311:29 | 5 | test.rs:308:9:312:9 | match maybe_digit { ... } | | +| test.rs:315:5:324:5 | enter fn test_match_with_return_in_scrutinee | test.rs:315:44:315:54 | maybe_digit | | +| test.rs:315:5:324:5 | exit fn test_match_with_return_in_scrutinee (normal) | test.rs:315:5:324:5 | exit fn test_match_with_return_in_scrutinee | | +| test.rs:315:44:315:54 | maybe_digit | test.rs:315:44:315:67 | ...: Option::<...> | match | +| test.rs:315:44:315:67 | ...: Option::<...> | test.rs:316:19:316:29 | maybe_digit | | +| test.rs:315:77:324:5 | { ... } | test.rs:315:5:324:5 | exit fn test_match_with_return_in_scrutinee (normal) | | +| test.rs:316:9:323:9 | match ... { ... } | test.rs:315:77:324:5 | { ... } | | +| test.rs:316:16:320:9 | if ... {...} else {...} | test.rs:321:13:321:27 | TupleStructPat | | +| test.rs:316:19:316:29 | maybe_digit | test.rs:316:34:316:37 | Some | | +| test.rs:316:19:316:40 | ... == ... | test.rs:317:13:317:21 | ExprStmt | true | +| test.rs:316:19:316:40 | ... == ... | test.rs:319:13:319:23 | maybe_digit | false | +| test.rs:316:34:316:37 | Some | test.rs:316:39:316:39 | 3 | | +| test.rs:316:34:316:40 | Some(...) | test.rs:316:19:316:40 | ... == ... | | +| test.rs:316:39:316:39 | 3 | test.rs:316:34:316:40 | Some(...) | | +| test.rs:317:13:317:20 | return 3 | test.rs:315:5:324:5 | exit fn test_match_with_return_in_scrutinee (normal) | return | +| test.rs:317:13:317:21 | ExprStmt | test.rs:317:20:317:20 | 3 | | +| test.rs:317:20:317:20 | 3 | test.rs:317:13:317:20 | return 3 | | +| test.rs:318:16:320:9 | { ... } | test.rs:316:16:320:9 | if ... {...} else {...} | | +| test.rs:319:13:319:23 | maybe_digit | test.rs:318:16:320:9 | { ... } | | +| test.rs:321:13:321:27 | TupleStructPat | test.rs:321:26:321:26 | x | match | +| test.rs:321:13:321:27 | TupleStructPat | test.rs:322:13:322:24 | ...::None | no-match | +| test.rs:321:26:321:26 | x | test.rs:321:32:321:32 | x | match | +| test.rs:321:32:321:32 | x | test.rs:321:36:321:36 | 5 | | +| test.rs:321:32:321:36 | ... + ... | test.rs:316:9:323:9 | match ... { ... } | | +| test.rs:321:36:321:36 | 5 | test.rs:321:32:321:36 | ... + ... | | +| test.rs:322:13:322:24 | ...::None | test.rs:322:29:322:29 | 5 | match | +| test.rs:322:29:322:29 | 5 | test.rs:316:9:323:9 | match ... { ... } | | +| test.rs:326:5:331:5 | enter fn test_match_and | test.rs:326:23:326:26 | cond | | +| test.rs:326:5:331:5 | exit fn test_match_and (normal) | test.rs:326:5:331:5 | exit fn test_match_and | | +| test.rs:326:23:326:26 | cond | test.rs:326:23:326:32 | ...: bool | match | +| test.rs:326:23:326:32 | ...: bool | test.rs:326:35:326:35 | r | | +| test.rs:326:35:326:35 | r | test.rs:326:35:326:49 | ...: Option::<...> | match | +| test.rs:326:35:326:49 | ...: Option::<...> | test.rs:327:16:327:16 | r | | +| test.rs:326:60:331:5 | { ... } | test.rs:326:5:331:5 | exit fn test_match_and (normal) | | +| test.rs:327:9:330:18 | ... && ... | test.rs:326:60:331:5 | { ... } | | +| test.rs:327:10:330:9 | [boolean(false)] match r { ... } | test.rs:327:9:330:18 | ... && ... | false | +| test.rs:327:10:330:9 | [boolean(true)] match r { ... } | test.rs:330:15:330:18 | cond | true | +| test.rs:327:16:327:16 | r | test.rs:328:13:328:19 | TupleStructPat | | +| test.rs:328:13:328:19 | TupleStructPat | test.rs:328:18:328:18 | a | match | +| test.rs:328:13:328:19 | TupleStructPat | test.rs:329:13:329:13 | _ | no-match | +| test.rs:328:18:328:18 | a | test.rs:328:24:328:24 | a | match | +| test.rs:328:24:328:24 | a | test.rs:327:10:330:9 | [boolean(false)] match r { ... } | false | +| test.rs:328:24:328:24 | a | test.rs:327:10:330:9 | [boolean(true)] match r { ... } | true | +| test.rs:329:13:329:13 | _ | test.rs:329:18:329:22 | false | match | +| test.rs:329:18:329:22 | false | test.rs:327:10:330:9 | [boolean(false)] match r { ... } | false | +| test.rs:330:15:330:18 | cond | test.rs:327:9:330:18 | ... && ... | | +| test.rs:333:5:338:5 | enter fn test_match_with_no_arms | test.rs:333:35:333:35 | r | | +| test.rs:333:5:338:5 | exit fn test_match_with_no_arms (normal) | test.rs:333:5:338:5 | exit fn test_match_with_no_arms | | +| test.rs:333:35:333:35 | r | test.rs:333:35:333:58 | ...: Result::<...> | match | +| test.rs:333:35:333:58 | ...: Result::<...> | test.rs:334:15:334:15 | r | | +| test.rs:333:66:338:5 | { ... } | test.rs:333:5:338:5 | exit fn test_match_with_no_arms (normal) | | +| test.rs:334:9:337:9 | match r { ... } | test.rs:333:66:338:5 | { ... } | | +| test.rs:334:15:334:15 | r | test.rs:335:13:335:21 | TupleStructPat | | +| test.rs:335:13:335:21 | TupleStructPat | test.rs:335:16:335:20 | value | match | +| test.rs:335:13:335:21 | TupleStructPat | test.rs:336:13:336:22 | TupleStructPat | no-match | +| test.rs:335:16:335:20 | value | test.rs:335:26:335:30 | value | match | +| test.rs:335:26:335:30 | value | test.rs:334:9:337:9 | match r { ... } | | +| test.rs:336:13:336:22 | TupleStructPat | test.rs:336:17:336:21 | never | match | +| test.rs:336:17:336:21 | never | test.rs:336:33:336:37 | never | match | +| test.rs:336:27:336:40 | match never { ... } | test.rs:334:9:337:9 | match r { ... } | | +| test.rs:336:33:336:37 | never | test.rs:336:27:336:40 | match never { ... } | | +| test.rs:343:5:346:5 | enter fn test_let_match | test.rs:343:23:343:23 | a | | +| test.rs:343:5:346:5 | exit fn test_let_match (normal) | test.rs:343:5:346:5 | exit fn test_let_match | | +| test.rs:343:23:343:23 | a | test.rs:343:23:343:36 | ...: Option::<...> | match | +| test.rs:343:23:343:36 | ...: Option::<...> | test.rs:344:9:344:57 | let ... = a else {...} | | +| test.rs:343:46:346:5 | { ... } | test.rs:343:5:346:5 | exit fn test_let_match (normal) | | +| test.rs:344:9:344:57 | let ... = a else {...} | test.rs:344:23:344:23 | a | | +| test.rs:344:13:344:19 | TupleStructPat | test.rs:344:18:344:18 | n | match | +| test.rs:344:13:344:19 | TupleStructPat | test.rs:344:39:344:53 | MacroStmts | no-match | +| test.rs:344:18:344:18 | n | test.rs:345:9:345:9 | n | match | +| test.rs:344:23:344:23 | a | test.rs:344:13:344:19 | TupleStructPat | | +| test.rs:344:32:344:54 | ...::panic_fmt | test.rs:344:39:344:53 | "Expected some" | | +| test.rs:344:32:344:54 | MacroExpr | test.rs:344:30:344:56 | { ... } | | +| test.rs:344:39:344:53 | "Expected some" | test.rs:344:39:344:53 | FormatArgsExpr | | +| test.rs:344:39:344:53 | ...::panic_fmt(...) | test.rs:344:39:344:53 | { ... } | | +| test.rs:344:39:344:53 | ExprStmt | test.rs:344:32:344:54 | ...::panic_fmt | | +| test.rs:344:39:344:53 | FormatArgsExpr | test.rs:344:39:344:53 | MacroExpr | | +| test.rs:344:39:344:53 | MacroExpr | test.rs:344:32:344:54 | MacroExpr | | +| test.rs:344:39:344:53 | MacroExpr | test.rs:344:39:344:53 | ...::panic_fmt(...) | | +| test.rs:344:39:344:53 | MacroStmts | test.rs:344:39:344:53 | ExprStmt | | +| test.rs:344:39:344:53 | MacroStmts | test.rs:344:39:344:53 | MacroStmts | | +| test.rs:344:39:344:53 | { ... } | test.rs:344:39:344:53 | MacroExpr | | +| test.rs:345:9:345:9 | n | test.rs:343:46:346:5 | { ... } | | +| test.rs:348:5:354:5 | enter fn test_let_with_return | test.rs:348:29:348:29 | m | | +| test.rs:348:5:354:5 | exit fn test_let_with_return (normal) | test.rs:348:5:354:5 | exit fn test_let_with_return | | +| test.rs:348:29:348:29 | m | test.rs:348:29:348:42 | ...: Option::<...> | match | +| test.rs:348:29:348:42 | ...: Option::<...> | test.rs:349:9:352:10 | let ... = ... | | +| test.rs:348:53:354:5 | { ... } | test.rs:348:5:354:5 | exit fn test_let_with_return (normal) | | +| test.rs:349:9:352:10 | let ... = ... | test.rs:349:25:349:25 | m | | +| test.rs:349:13:349:15 | ret | test.rs:353:9:353:12 | true | match | +| test.rs:349:19:352:9 | match m { ... } | test.rs:349:13:349:15 | ret | | +| test.rs:349:25:349:25 | m | test.rs:350:13:350:21 | TupleStructPat | | +| test.rs:350:13:350:21 | TupleStructPat | test.rs:350:18:350:20 | ret | match | +| test.rs:350:13:350:21 | TupleStructPat | test.rs:351:13:351:16 | None | no-match | +| test.rs:350:18:350:20 | ret | test.rs:350:26:350:28 | ret | match | +| test.rs:350:26:350:28 | ret | test.rs:349:19:352:9 | match m { ... } | | +| test.rs:351:13:351:16 | None | test.rs:351:28:351:32 | false | match | +| test.rs:351:21:351:32 | return false | test.rs:348:5:354:5 | exit fn test_let_with_return (normal) | return | +| test.rs:351:28:351:32 | false | test.rs:351:21:351:32 | return false | | +| test.rs:353:9:353:12 | true | test.rs:348:53:354:5 | { ... } | | +| test.rs:359:5:362:5 | enter fn empty_tuple_pattern | test.rs:359:28:359:31 | unit | | +| test.rs:359:5:362:5 | exit fn empty_tuple_pattern (normal) | test.rs:359:5:362:5 | exit fn empty_tuple_pattern | | +| test.rs:359:28:359:31 | unit | test.rs:359:28:359:35 | ...: ... | match | +| test.rs:359:28:359:35 | ...: ... | test.rs:360:9:360:22 | let ... = unit | | +| test.rs:360:9:360:22 | let ... = unit | test.rs:360:18:360:21 | unit | | +| test.rs:360:13:360:14 | TuplePat | test.rs:361:9:361:15 | ExprStmt | match | +| test.rs:360:18:360:21 | unit | test.rs:360:13:360:14 | TuplePat | | +| test.rs:361:9:361:14 | return | test.rs:359:5:362:5 | exit fn empty_tuple_pattern (normal) | return | +| test.rs:361:9:361:15 | ExprStmt | test.rs:361:9:361:14 | return | | +| test.rs:366:5:370:5 | enter fn empty_struct_pattern | test.rs:366:29:366:30 | st | | +| test.rs:366:5:370:5 | exit fn empty_struct_pattern (normal) | test.rs:366:5:370:5 | exit fn empty_struct_pattern | | +| test.rs:366:29:366:30 | st | test.rs:366:29:366:40 | ...: MyStruct | match | +| test.rs:366:29:366:40 | ...: MyStruct | test.rs:367:15:367:16 | st | | +| test.rs:366:50:370:5 | { ... } | test.rs:366:5:370:5 | exit fn empty_struct_pattern (normal) | | +| test.rs:367:9:369:9 | match st { ... } | test.rs:366:50:370:5 | { ... } | | +| test.rs:367:15:367:16 | st | test.rs:368:13:368:27 | MyStruct {...} | | +| test.rs:368:13:368:27 | MyStruct {...} | test.rs:368:24:368:25 | .. | match | +| test.rs:368:24:368:25 | .. | test.rs:368:32:368:32 | 1 | match | +| test.rs:368:32:368:32 | 1 | test.rs:367:9:369:9 | match st { ... } | | +| test.rs:372:5:379:5 | enter fn range_pattern | test.rs:373:15:373:16 | 42 | | +| test.rs:372:5:379:5 | exit fn range_pattern (normal) | test.rs:372:5:379:5 | exit fn range_pattern | | +| test.rs:372:31:379:5 | { ... } | test.rs:372:5:379:5 | exit fn range_pattern (normal) | | +| test.rs:373:9:378:9 | match 42 { ... } | test.rs:372:31:379:5 | { ... } | | +| test.rs:373:15:373:16 | 42 | test.rs:374:13:374:15 | RangePat | | +| test.rs:374:13:374:15 | RangePat | test.rs:374:15:374:15 | 0 | match | +| test.rs:374:13:374:15 | RangePat | test.rs:375:13:375:16 | RangePat | no-match | +| test.rs:374:15:374:15 | 0 | test.rs:374:15:374:15 | 0 | | +| test.rs:374:15:374:15 | 0 | test.rs:374:20:374:20 | 1 | match | +| test.rs:374:15:374:15 | 0 | test.rs:375:13:375:16 | RangePat | no-match | +| test.rs:374:20:374:20 | 1 | test.rs:373:9:378:9 | match 42 { ... } | | +| test.rs:375:13:375:13 | 1 | test.rs:375:13:375:13 | 1 | | +| test.rs:375:13:375:13 | 1 | test.rs:375:16:375:16 | 2 | match | +| test.rs:375:13:375:13 | 1 | test.rs:376:13:376:15 | RangePat | no-match | +| test.rs:375:13:375:16 | RangePat | test.rs:375:13:375:13 | 1 | match | +| test.rs:375:13:375:16 | RangePat | test.rs:376:13:376:15 | RangePat | no-match | +| test.rs:375:16:375:16 | 2 | test.rs:375:16:375:16 | 2 | | +| test.rs:375:16:375:16 | 2 | test.rs:375:21:375:21 | 2 | match | +| test.rs:375:16:375:16 | 2 | test.rs:376:13:376:15 | RangePat | no-match | +| test.rs:375:21:375:21 | 2 | test.rs:373:9:378:9 | match 42 { ... } | | +| test.rs:376:13:376:13 | 5 | test.rs:376:13:376:13 | 5 | | +| test.rs:376:13:376:13 | 5 | test.rs:376:20:376:20 | 3 | match | +| test.rs:376:13:376:13 | 5 | test.rs:377:13:377:13 | _ | no-match | +| test.rs:376:13:376:15 | RangePat | test.rs:376:13:376:13 | 5 | match | +| test.rs:376:13:376:15 | RangePat | test.rs:377:13:377:13 | _ | no-match | +| test.rs:376:20:376:20 | 3 | test.rs:373:9:378:9 | match 42 { ... } | | +| test.rs:377:13:377:13 | _ | test.rs:377:18:377:18 | 4 | match | +| test.rs:377:18:377:18 | 4 | test.rs:373:9:378:9 | match 42 { ... } | | +| test.rs:383:5:388:5 | enter fn test_infinite_loop | test.rs:384:9:386:9 | ExprStmt | | +| test.rs:384:9:386:9 | ExprStmt | test.rs:385:13:385:14 | TupleExpr | | +| test.rs:384:14:386:9 | { ... } | test.rs:385:13:385:14 | TupleExpr | | +| test.rs:385:13:385:14 | TupleExpr | test.rs:384:14:386:9 | { ... } | | +| test.rs:392:5:394:5 | enter fn say_hello | test.rs:393:9:393:34 | ExprStmt | | +| test.rs:392:5:394:5 | exit fn say_hello (normal) | test.rs:392:5:394:5 | exit fn say_hello | | +| test.rs:392:26:394:5 | { ... } | test.rs:392:5:394:5 | exit fn say_hello (normal) | | +| test.rs:393:9:393:33 | ...::_print | test.rs:393:18:393:32 | "hello, world!\\n" | | +| test.rs:393:9:393:33 | MacroExpr | test.rs:392:26:394:5 | { ... } | | +| test.rs:393:9:393:34 | ExprStmt | test.rs:393:18:393:32 | MacroStmts | | +| test.rs:393:18:393:32 | "hello, world!\\n" | test.rs:393:18:393:32 | FormatArgsExpr | | +| test.rs:393:18:393:32 | ...::_print(...) | test.rs:393:18:393:32 | { ... } | | +| test.rs:393:18:393:32 | ExprStmt | test.rs:393:9:393:33 | ...::_print | | +| test.rs:393:18:393:32 | FormatArgsExpr | test.rs:393:18:393:32 | MacroExpr | | +| test.rs:393:18:393:32 | MacroExpr | test.rs:393:18:393:32 | ...::_print(...) | | +| test.rs:393:18:393:32 | MacroStmts | test.rs:393:18:393:32 | ExprStmt | | +| test.rs:393:18:393:32 | { ... } | test.rs:393:9:393:33 | MacroExpr | | +| test.rs:396:5:415:5 | enter fn async_block | test.rs:396:26:396:26 | b | | +| test.rs:396:5:415:5 | exit fn async_block (normal) | test.rs:396:5:415:5 | exit fn async_block | | +| test.rs:396:26:396:26 | b | test.rs:396:26:396:32 | ...: bool | match | +| test.rs:396:26:396:32 | ...: bool | test.rs:397:9:399:10 | let ... = ... | | +| test.rs:396:35:415:5 | { ... } | test.rs:396:5:415:5 | exit fn async_block (normal) | | +| test.rs:397:9:399:10 | let ... = ... | test.rs:397:26:399:9 | { ... } | | +| test.rs:397:13:397:22 | say_godbye | test.rs:400:9:402:10 | let ... = ... | match | +| test.rs:397:26:399:9 | enter { ... } | test.rs:398:13:398:42 | ExprStmt | | +| test.rs:397:26:399:9 | exit { ... } (normal) | test.rs:397:26:399:9 | exit { ... } | | +| test.rs:397:26:399:9 | { ... } | test.rs:397:13:397:22 | say_godbye | | +| test.rs:398:13:398:41 | ...::_print | test.rs:398:22:398:40 | "godbye, everyone!\\n" | | +| test.rs:398:13:398:41 | MacroExpr | test.rs:397:26:399:9 | exit { ... } (normal) | | +| test.rs:398:13:398:42 | ExprStmt | test.rs:398:22:398:40 | MacroStmts | | +| test.rs:398:22:398:40 | "godbye, everyone!\\n" | test.rs:398:22:398:40 | FormatArgsExpr | | +| test.rs:398:22:398:40 | ...::_print(...) | test.rs:398:22:398:40 | { ... } | | +| test.rs:398:22:398:40 | ExprStmt | test.rs:398:13:398:41 | ...::_print | | +| test.rs:398:22:398:40 | FormatArgsExpr | test.rs:398:22:398:40 | MacroExpr | | +| test.rs:398:22:398:40 | MacroExpr | test.rs:398:22:398:40 | ...::_print(...) | | +| test.rs:398:22:398:40 | MacroStmts | test.rs:398:22:398:40 | ExprStmt | | +| test.rs:398:22:398:40 | { ... } | test.rs:398:13:398:41 | MacroExpr | | +| test.rs:400:9:402:10 | let ... = ... | test.rs:400:31:402:9 | { ... } | | +| test.rs:400:13:400:27 | say_how_are_you | test.rs:403:9:403:28 | let ... = ... | match | +| test.rs:400:31:402:9 | enter { ... } | test.rs:401:13:401:37 | ExprStmt | | +| test.rs:400:31:402:9 | exit { ... } (normal) | test.rs:400:31:402:9 | exit { ... } | | +| test.rs:400:31:402:9 | { ... } | test.rs:400:13:400:27 | say_how_are_you | | +| test.rs:401:13:401:36 | ...::_print | test.rs:401:22:401:35 | "how are you?\\n" | | +| test.rs:401:13:401:36 | MacroExpr | test.rs:400:31:402:9 | exit { ... } (normal) | | +| test.rs:401:13:401:37 | ExprStmt | test.rs:401:22:401:35 | MacroStmts | | +| test.rs:401:22:401:35 | "how are you?\\n" | test.rs:401:22:401:35 | FormatArgsExpr | | +| test.rs:401:22:401:35 | ...::_print(...) | test.rs:401:22:401:35 | { ... } | | +| test.rs:401:22:401:35 | ExprStmt | test.rs:401:13:401:36 | ...::_print | | +| test.rs:401:22:401:35 | FormatArgsExpr | test.rs:401:22:401:35 | MacroExpr | | +| test.rs:401:22:401:35 | MacroExpr | test.rs:401:22:401:35 | ...::_print(...) | | +| test.rs:401:22:401:35 | MacroStmts | test.rs:401:22:401:35 | ExprStmt | | +| test.rs:401:22:401:35 | { ... } | test.rs:401:13:401:36 | MacroExpr | | +| test.rs:403:9:403:28 | let ... = ... | test.rs:403:20:403:27 | { ... } | | +| test.rs:403:13:403:16 | noop | test.rs:404:9:404:26 | ExprStmt | match | +| test.rs:403:20:403:27 | { ... } | test.rs:403:13:403:16 | noop | | +| test.rs:404:9:404:17 | say_hello | test.rs:404:9:404:19 | say_hello(...) | | +| test.rs:404:9:404:19 | say_hello(...) | test.rs:404:9:404:25 | await ... | | +| test.rs:404:9:404:25 | await ... | test.rs:405:9:405:30 | ExprStmt | | +| test.rs:404:9:404:26 | ExprStmt | test.rs:404:9:404:17 | say_hello | | +| test.rs:405:9:405:23 | say_how_are_you | test.rs:405:9:405:29 | await say_how_are_you | | +| test.rs:405:9:405:29 | await say_how_are_you | test.rs:406:9:406:25 | ExprStmt | | +| test.rs:405:9:405:30 | ExprStmt | test.rs:405:9:405:23 | say_how_are_you | | +| test.rs:406:9:406:18 | say_godbye | test.rs:406:9:406:24 | await say_godbye | | +| test.rs:406:9:406:24 | await say_godbye | test.rs:407:9:407:19 | ExprStmt | | +| test.rs:406:9:406:25 | ExprStmt | test.rs:406:9:406:18 | say_godbye | | +| test.rs:407:9:407:12 | noop | test.rs:407:9:407:18 | await noop | | +| test.rs:407:9:407:18 | await noop | test.rs:409:9:414:10 | let ... = ... | | +| test.rs:407:9:407:19 | ExprStmt | test.rs:407:9:407:12 | noop | | +| test.rs:409:9:414:10 | let ... = ... | test.rs:409:22:414:9 | \|...\| ... | | +| test.rs:409:13:409:18 | lambda | test.rs:396:35:415:5 | { ... } | match | +| test.rs:409:22:414:9 | \|...\| ... | test.rs:409:13:409:18 | lambda | | +| test.rs:409:22:414:9 | enter \|...\| ... | test.rs:409:23:409:25 | foo | | +| test.rs:409:22:414:9 | exit \|...\| ... (normal) | test.rs:409:22:414:9 | exit \|...\| ... | | +| test.rs:409:23:409:25 | ... | test.rs:409:28:414:9 | { ... } | | +| test.rs:409:23:409:25 | foo | test.rs:409:23:409:25 | ... | match | +| test.rs:409:28:414:9 | enter { ... } | test.rs:410:13:412:14 | ExprStmt | | +| test.rs:409:28:414:9 | exit { ... } (normal) | test.rs:409:28:414:9 | exit { ... } | | +| test.rs:409:28:414:9 | { ... } | test.rs:409:22:414:9 | exit \|...\| ... (normal) | | +| test.rs:410:13:412:13 | if b {...} | test.rs:413:13:413:15 | foo | | +| test.rs:410:13:412:14 | ExprStmt | test.rs:410:16:410:16 | b | | +| test.rs:410:16:410:16 | b | test.rs:410:13:412:13 | if b {...} | false | +| test.rs:410:16:410:16 | b | test.rs:411:17:411:41 | ExprStmt | true | +| test.rs:411:17:411:40 | return ... | test.rs:409:28:414:9 | exit { ... } (normal) | return | +| test.rs:411:17:411:41 | ExprStmt | test.rs:411:24:411:34 | async_block | | +| test.rs:411:24:411:34 | async_block | test.rs:411:36:411:39 | true | | +| test.rs:411:24:411:40 | async_block(...) | test.rs:411:17:411:40 | return ... | | +| test.rs:411:36:411:39 | true | test.rs:411:24:411:40 | async_block(...) | | +| test.rs:413:13:413:15 | foo | test.rs:409:28:414:9 | exit { ... } (normal) | | +| test.rs:421:5:423:5 | enter fn add_two | test.rs:421:22:421:22 | n | | +| test.rs:421:5:423:5 | exit fn add_two (normal) | test.rs:421:5:423:5 | exit fn add_two | | +| test.rs:421:22:421:22 | n | test.rs:421:22:421:27 | ...: i64 | match | +| test.rs:421:22:421:27 | ...: i64 | test.rs:422:9:422:9 | n | | +| test.rs:421:37:423:5 | { ... } | test.rs:421:5:423:5 | exit fn add_two (normal) | | +| test.rs:422:9:422:9 | n | test.rs:422:13:422:13 | 2 | | +| test.rs:422:9:422:13 | ... + ... | test.rs:421:37:423:5 | { ... } | | +| test.rs:422:13:422:13 | 2 | test.rs:422:9:422:13 | ... + ... | | +| test.rs:427:5:435:5 | enter fn const_block_assert | test.rs:430:9:432:9 | ExprStmt | | +| test.rs:427:5:435:5 | exit fn const_block_assert (normal) | test.rs:427:5:435:5 | exit fn const_block_assert | | +| test.rs:427:41:435:5 | { ... } | test.rs:427:5:435:5 | exit fn const_block_assert (normal) | | +| test.rs:430:9:432:9 | ExprStmt | test.rs:431:13:431:50 | ExprStmt | | +| test.rs:430:9:432:9 | { ... } | test.rs:434:9:434:10 | 42 | | +| test.rs:431:13:431:49 | ...::panic_explicit | test.rs:431:13:431:49 | ...::panic_explicit(...) | | +| test.rs:431:13:431:49 | ...::panic_explicit(...) | test.rs:431:13:431:49 | { ... } | | +| test.rs:431:13:431:49 | ExprStmt | test.rs:431:13:431:49 | MacroStmts | | +| test.rs:431:13:431:49 | ExprStmt | test.rs:431:13:431:49 | panic_cold_explicit | | +| test.rs:431:13:431:49 | MacroExpr | test.rs:430:9:432:9 | { ... } | | +| test.rs:431:13:431:49 | MacroExpr | test.rs:431:13:431:49 | { ... } | | +| test.rs:431:13:431:49 | MacroStmts | test.rs:431:13:431:49 | fn panic_cold_explicit | | +| test.rs:431:13:431:49 | enter fn panic_cold_explicit | test.rs:431:13:431:49 | ...::panic_explicit | | +| test.rs:431:13:431:49 | exit fn panic_cold_explicit (normal) | test.rs:431:13:431:49 | exit fn panic_cold_explicit | | +| test.rs:431:13:431:49 | fn panic_cold_explicit | test.rs:431:13:431:49 | ExprStmt | | +| test.rs:431:13:431:49 | panic_cold_explicit | test.rs:431:13:431:49 | panic_cold_explicit(...) | | +| test.rs:431:13:431:49 | panic_cold_explicit(...) | test.rs:431:13:431:49 | { ... } | | +| test.rs:431:13:431:49 | { ... } | test.rs:431:13:431:49 | MacroExpr | | +| test.rs:431:13:431:49 | { ... } | test.rs:431:13:431:49 | exit fn panic_cold_explicit (normal) | | +| test.rs:431:13:431:49 | { ... } | test.rs:431:21:431:48 | if ... {...} | | +| test.rs:431:13:431:50 | ExprStmt | test.rs:431:21:431:48 | MacroStmts | | +| test.rs:431:21:431:42 | ...::size_of::<...> | test.rs:431:21:431:44 | ...::size_of::<...>(...) | | +| test.rs:431:21:431:44 | ...::size_of::<...>(...) | test.rs:431:48:431:48 | 0 | | +| test.rs:431:21:431:48 | ... > ... | test.rs:431:21:431:48 | [boolean(false)] ! ... | true | +| test.rs:431:21:431:48 | ... > ... | test.rs:431:21:431:48 | [boolean(true)] ! ... | false | +| test.rs:431:21:431:48 | MacroStmts | test.rs:431:21:431:42 | ...::size_of::<...> | | +| test.rs:431:21:431:48 | [boolean(false)] ! ... | test.rs:431:21:431:48 | if ... {...} | false | +| test.rs:431:21:431:48 | [boolean(true)] ! ... | test.rs:431:13:431:49 | ExprStmt | true | +| test.rs:431:21:431:48 | if ... {...} | test.rs:431:21:431:48 | { ... } | | +| test.rs:431:21:431:48 | { ... } | test.rs:431:13:431:49 | MacroExpr | | +| test.rs:431:48:431:48 | 0 | test.rs:431:21:431:48 | ... > ... | | +| test.rs:434:9:434:10 | 42 | test.rs:427:41:435:5 | { ... } | | +| test.rs:437:5:446:5 | enter fn const_block_panic | test.rs:438:9:438:30 | Const | | +| test.rs:437:5:446:5 | exit fn const_block_panic (normal) | test.rs:437:5:446:5 | exit fn const_block_panic | | +| test.rs:437:35:446:5 | { ... } | test.rs:437:5:446:5 | exit fn const_block_panic (normal) | | +| test.rs:438:9:438:30 | Const | test.rs:439:9:444:9 | ExprStmt | | +| test.rs:439:9:444:9 | ExprStmt | test.rs:439:12:439:16 | false | | +| test.rs:439:9:444:9 | if false {...} | test.rs:445:9:445:9 | N | | +| test.rs:439:12:439:16 | false | test.rs:439:9:444:9 | if false {...} | false | +| test.rs:442:17:442:24 | ...::panic_explicit | test.rs:442:17:442:24 | ...::panic_explicit(...) | | +| test.rs:442:17:442:24 | ...::panic_explicit(...) | test.rs:442:17:442:24 | { ... } | | +| test.rs:442:17:442:24 | enter fn panic_cold_explicit | test.rs:442:17:442:24 | ...::panic_explicit | | +| test.rs:442:17:442:24 | exit fn panic_cold_explicit (normal) | test.rs:442:17:442:24 | exit fn panic_cold_explicit | | +| test.rs:442:17:442:24 | { ... } | test.rs:442:17:442:24 | exit fn panic_cold_explicit (normal) | | +| test.rs:445:9:445:9 | N | test.rs:437:35:446:5 | { ... } | | +| test.rs:449:1:454:1 | enter fn dead_code | test.rs:450:5:452:5 | ExprStmt | | +| test.rs:449:1:454:1 | exit fn dead_code (normal) | test.rs:449:1:454:1 | exit fn dead_code | | +| test.rs:450:5:452:5 | ExprStmt | test.rs:450:9:450:12 | true | | +| test.rs:450:9:450:12 | true | test.rs:451:9:451:17 | ExprStmt | true | +| test.rs:451:9:451:16 | return 0 | test.rs:449:1:454:1 | exit fn dead_code (normal) | return | +| test.rs:451:9:451:17 | ExprStmt | test.rs:451:16:451:16 | 0 | | +| test.rs:451:16:451:16 | 0 | test.rs:451:9:451:16 | return 0 | | +| test.rs:456:1:456:16 | enter fn do_thing | test.rs:456:15:456:16 | { ... } | | +| test.rs:456:1:456:16 | exit fn do_thing (normal) | test.rs:456:1:456:16 | exit fn do_thing | | +| test.rs:456:15:456:16 | { ... } | test.rs:456:1:456:16 | exit fn do_thing (normal) | | +| test.rs:458:1:460:1 | enter fn condition_not_met | test.rs:459:5:459:9 | false | | +| test.rs:458:1:460:1 | exit fn condition_not_met (normal) | test.rs:458:1:460:1 | exit fn condition_not_met | | +| test.rs:458:32:460:1 | { ... } | test.rs:458:1:460:1 | exit fn condition_not_met (normal) | | +| test.rs:459:5:459:9 | false | test.rs:458:32:460:1 | { ... } | | +| test.rs:462:1:462:21 | enter fn do_next_thing | test.rs:462:20:462:21 | { ... } | | +| test.rs:462:1:462:21 | exit fn do_next_thing (normal) | test.rs:462:1:462:21 | exit fn do_next_thing | | +| test.rs:462:20:462:21 | { ... } | test.rs:462:1:462:21 | exit fn do_next_thing (normal) | | +| test.rs:464:1:464:21 | enter fn do_last_thing | test.rs:464:20:464:21 | { ... } | | +| test.rs:464:1:464:21 | exit fn do_last_thing (normal) | test.rs:464:1:464:21 | exit fn do_last_thing | | +| test.rs:464:20:464:21 | { ... } | test.rs:464:1:464:21 | exit fn do_last_thing (normal) | | +| test.rs:466:1:480:1 | enter fn labelled_block1 | test.rs:467:5:478:6 | let ... = ... | | +| test.rs:466:1:480:1 | exit fn labelled_block1 (normal) | test.rs:466:1:480:1 | exit fn labelled_block1 | | +| test.rs:466:29:480:1 | { ... } | test.rs:466:1:480:1 | exit fn labelled_block1 (normal) | | +| test.rs:467:5:478:6 | let ... = ... | test.rs:468:9:468:19 | ExprStmt | | +| test.rs:467:9:467:14 | result | test.rs:479:5:479:10 | result | match | +| test.rs:467:18:478:5 | 'block: { ... } | test.rs:467:9:467:14 | result | | +| test.rs:468:9:468:16 | do_thing | test.rs:468:9:468:18 | do_thing(...) | | +| test.rs:468:9:468:18 | do_thing(...) | test.rs:469:9:471:9 | ExprStmt | | +| test.rs:468:9:468:19 | ExprStmt | test.rs:468:9:468:16 | do_thing | | +| test.rs:469:9:471:9 | ExprStmt | test.rs:469:12:469:28 | condition_not_met | | +| test.rs:469:9:471:9 | if ... {...} | test.rs:472:9:472:24 | ExprStmt | | +| test.rs:469:12:469:28 | condition_not_met | test.rs:469:12:469:30 | condition_not_met(...) | | +| test.rs:469:12:469:30 | condition_not_met(...) | test.rs:469:9:471:9 | if ... {...} | false | +| test.rs:469:12:469:30 | condition_not_met(...) | test.rs:470:13:470:27 | ExprStmt | true | +| test.rs:470:13:470:26 | break ''block 1 | test.rs:467:18:478:5 | 'block: { ... } | break | +| test.rs:470:13:470:27 | ExprStmt | test.rs:470:26:470:26 | 1 | | +| test.rs:470:26:470:26 | 1 | test.rs:470:13:470:26 | break ''block 1 | | +| test.rs:472:9:472:21 | do_next_thing | test.rs:472:9:472:23 | do_next_thing(...) | | +| test.rs:472:9:472:23 | do_next_thing(...) | test.rs:473:9:475:9 | ExprStmt | | +| test.rs:472:9:472:24 | ExprStmt | test.rs:472:9:472:21 | do_next_thing | | +| test.rs:473:9:475:9 | ExprStmt | test.rs:473:12:473:28 | condition_not_met | | +| test.rs:473:9:475:9 | if ... {...} | test.rs:476:9:476:24 | ExprStmt | | +| test.rs:473:12:473:28 | condition_not_met | test.rs:473:12:473:30 | condition_not_met(...) | | +| test.rs:473:12:473:30 | condition_not_met(...) | test.rs:473:9:475:9 | if ... {...} | false | +| test.rs:473:12:473:30 | condition_not_met(...) | test.rs:474:13:474:27 | ExprStmt | true | +| test.rs:474:13:474:26 | break ''block 2 | test.rs:467:18:478:5 | 'block: { ... } | break | +| test.rs:474:13:474:27 | ExprStmt | test.rs:474:26:474:26 | 2 | | +| test.rs:474:26:474:26 | 2 | test.rs:474:13:474:26 | break ''block 2 | | +| test.rs:476:9:476:21 | do_last_thing | test.rs:476:9:476:23 | do_last_thing(...) | | +| test.rs:476:9:476:23 | do_last_thing(...) | test.rs:477:9:477:9 | 3 | | +| test.rs:476:9:476:24 | ExprStmt | test.rs:476:9:476:21 | do_last_thing | | +| test.rs:477:9:477:9 | 3 | test.rs:467:18:478:5 | 'block: { ... } | | +| test.rs:479:5:479:10 | result | test.rs:466:29:480:1 | { ... } | | +| test.rs:482:1:490:1 | enter fn labelled_block2 | test.rs:483:5:489:6 | let ... = ... | | +| test.rs:482:1:490:1 | exit fn labelled_block2 (normal) | test.rs:482:1:490:1 | exit fn labelled_block2 | | +| test.rs:482:22:490:1 | { ... } | test.rs:482:1:490:1 | exit fn labelled_block2 (normal) | | +| test.rs:483:5:489:6 | let ... = ... | test.rs:484:9:484:34 | let ... = None | | +| test.rs:483:9:483:14 | result | test.rs:482:22:490:1 | { ... } | match | +| test.rs:483:18:489:5 | 'block: { ... } | test.rs:483:9:483:14 | result | | +| test.rs:484:9:484:34 | let ... = None | test.rs:484:30:484:33 | None | | +| test.rs:484:13:484:13 | x | test.rs:485:9:487:10 | let ... = x else {...} | match | +| test.rs:484:30:484:33 | None | test.rs:484:13:484:13 | x | | +| test.rs:485:9:487:10 | let ... = x else {...} | test.rs:485:23:485:23 | x | | +| test.rs:485:13:485:19 | TupleStructPat | test.rs:485:18:485:18 | y | match | +| test.rs:485:13:485:19 | TupleStructPat | test.rs:486:13:486:27 | ExprStmt | no-match | +| test.rs:485:18:485:18 | y | test.rs:488:9:488:9 | 0 | match | +| test.rs:485:23:485:23 | x | test.rs:485:13:485:19 | TupleStructPat | | +| test.rs:486:13:486:26 | break ''block 1 | test.rs:483:18:489:5 | 'block: { ... } | break | +| test.rs:486:13:486:27 | ExprStmt | test.rs:486:26:486:26 | 1 | | +| test.rs:486:26:486:26 | 1 | test.rs:486:13:486:26 | break ''block 1 | | +| test.rs:488:9:488:9 | 0 | test.rs:483:18:489:5 | 'block: { ... } | | +| test.rs:492:1:498:1 | enter fn test_nested_function2 | test.rs:493:5:493:18 | let ... = 0 | | +| test.rs:492:1:498:1 | exit fn test_nested_function2 (normal) | test.rs:492:1:498:1 | exit fn test_nested_function2 | | +| test.rs:492:28:498:1 | { ... } | test.rs:492:1:498:1 | exit fn test_nested_function2 (normal) | | +| test.rs:493:5:493:18 | let ... = 0 | test.rs:493:17:493:17 | 0 | | +| test.rs:493:9:493:13 | x | test.rs:494:5:496:5 | fn nested | match | +| test.rs:493:17:493:17 | 0 | test.rs:493:9:493:13 | x | | +| test.rs:494:5:496:5 | enter fn nested | test.rs:494:15:494:15 | x | | +| test.rs:494:5:496:5 | exit fn nested (normal) | test.rs:494:5:496:5 | exit fn nested | | +| test.rs:494:5:496:5 | fn nested | test.rs:497:5:497:19 | ExprStmt | | +| test.rs:494:15:494:15 | x | test.rs:494:15:494:25 | ...: ... | match | +| test.rs:494:15:494:25 | ...: ... | test.rs:495:9:495:16 | ExprStmt | | +| test.rs:494:28:496:5 | { ... } | test.rs:494:5:496:5 | exit fn nested (normal) | | +| test.rs:495:9:495:10 | * ... | test.rs:495:15:495:15 | 1 | | +| test.rs:495:9:495:15 | ... += ... | test.rs:494:28:496:5 | { ... } | | +| test.rs:495:9:495:16 | ExprStmt | test.rs:495:10:495:10 | x | | +| test.rs:495:10:495:10 | x | test.rs:495:9:495:10 | * ... | | +| test.rs:495:15:495:15 | 1 | test.rs:495:9:495:15 | ... += ... | | +| test.rs:497:5:497:10 | nested | test.rs:497:17:497:17 | x | | +| test.rs:497:5:497:18 | nested(...) | test.rs:492:28:498:1 | { ... } | | +| test.rs:497:5:497:19 | ExprStmt | test.rs:497:5:497:10 | nested | | +| test.rs:497:12:497:17 | &mut x | test.rs:497:5:497:18 | nested(...) | | +| test.rs:497:17:497:17 | x | test.rs:497:12:497:17 | &mut x | | +| test.rs:509:5:511:5 | enter fn new | test.rs:509:12:509:12 | a | | +| test.rs:509:5:511:5 | exit fn new (normal) | test.rs:509:5:511:5 | exit fn new | | +| test.rs:509:12:509:12 | a | test.rs:509:12:509:17 | ...: i64 | match | +| test.rs:509:12:509:17 | ...: i64 | test.rs:510:23:510:23 | a | | +| test.rs:509:28:511:5 | { ... } | test.rs:509:5:511:5 | exit fn new (normal) | | +| test.rs:510:9:510:25 | MyNumber {...} | test.rs:509:28:511:5 | { ... } | | +| test.rs:510:23:510:23 | a | test.rs:510:9:510:25 | MyNumber {...} | | +| test.rs:513:5:515:5 | enter fn negated | test.rs:513:16:513:19 | self | | +| test.rs:513:5:515:5 | exit fn negated (normal) | test.rs:513:5:515:5 | exit fn negated | | +| test.rs:513:16:513:19 | SelfParam | test.rs:514:23:514:26 | self | | +| test.rs:513:16:513:19 | self | test.rs:513:16:513:19 | SelfParam | | +| test.rs:513:30:515:5 | { ... } | test.rs:513:5:515:5 | exit fn negated (normal) | | +| test.rs:514:9:514:30 | MyNumber {...} | test.rs:513:30:515:5 | { ... } | | +| test.rs:514:23:514:26 | self | test.rs:514:23:514:28 | self.n | | +| test.rs:514:23:514:28 | self.n | test.rs:514:9:514:30 | MyNumber {...} | | +| test.rs:517:5:519:5 | enter fn multifly_add | test.rs:517:26:517:29 | self | | +| test.rs:517:5:519:5 | exit fn multifly_add (normal) | test.rs:517:5:519:5 | exit fn multifly_add | | +| test.rs:517:21:517:29 | SelfParam | test.rs:517:32:517:32 | a | | +| test.rs:517:26:517:29 | self | test.rs:517:21:517:29 | SelfParam | | +| test.rs:517:32:517:32 | a | test.rs:517:32:517:37 | ...: i64 | match | +| test.rs:517:32:517:37 | ...: i64 | test.rs:517:40:517:40 | b | | +| test.rs:517:40:517:40 | b | test.rs:517:40:517:45 | ...: i64 | match | +| test.rs:517:40:517:45 | ...: i64 | test.rs:518:9:518:34 | ExprStmt | | +| test.rs:517:48:519:5 | { ... } | test.rs:517:5:519:5 | exit fn multifly_add (normal) | | +| test.rs:518:9:518:12 | self | test.rs:518:9:518:14 | self.n | | +| test.rs:518:9:518:14 | self.n | test.rs:518:19:518:22 | self | | +| test.rs:518:9:518:33 | ... = ... | test.rs:517:48:519:5 | { ... } | | +| test.rs:518:9:518:34 | ExprStmt | test.rs:518:9:518:12 | self | | +| test.rs:518:18:518:33 | ... + ... | test.rs:518:9:518:33 | ... = ... | | +| test.rs:518:19:518:22 | self | test.rs:518:19:518:24 | self.n | | +| test.rs:518:19:518:24 | self.n | test.rs:518:28:518:28 | a | | +| test.rs:518:19:518:28 | ... * ... | test.rs:518:33:518:33 | b | | +| test.rs:518:28:518:28 | a | test.rs:518:19:518:28 | ... * ... | | +| test.rs:518:33:518:33 | b | test.rs:518:18:518:33 | ... + ... | | breakTarget -| test.rs:34:17:34:21 | BreakExpr | test.rs:28:9:40:9 | LoopExpr | -| test.rs:48:21:48:25 | BreakExpr | test.rs:46:13:53:13 | LoopExpr | -| test.rs:50:21:50:32 | BreakExpr | test.rs:45:9:54:9 | LoopExpr | -| test.rs:52:17:52:28 | BreakExpr | test.rs:46:13:53:13 | LoopExpr | -| test.rs:91:17:91:21 | BreakExpr | test.rs:88:9:94:9 | WhileExpr | -| test.rs:101:17:101:21 | BreakExpr | test.rs:99:9:103:9 | WhileExpr | -| test.rs:109:17:109:21 | BreakExpr | test.rs:107:9:112:9 | ForExpr | -| test.rs:117:13:117:26 | BreakExpr | test.rs:116:9:118:9 | LoopExpr | -| test.rs:197:17:197:28 | BreakExpr | test.rs:195:13:200:9 | LoopExpr | -| test.rs:210:17:210:35 | BreakExpr | test.rs:208:13:213:9 | LoopExpr | -| test.rs:222:13:222:30 | BreakExpr | test.rs:221:13:223:9 | BlockExpr | -| test.rs:463:13:463:26 | BreakExpr | test.rs:460:18:471:5 | BlockExpr | -| test.rs:467:13:467:26 | BreakExpr | test.rs:460:18:471:5 | BlockExpr | -| test.rs:479:13:479:26 | BreakExpr | test.rs:476:18:482:5 | BlockExpr | +| test.rs:34:17:34:21 | break | test.rs:28:9:40:9 | loop { ... } | +| test.rs:48:21:48:25 | break | test.rs:46:13:53:13 | 'inner: loop { ... } | +| test.rs:50:21:50:32 | break ''outer | test.rs:45:9:54:9 | 'outer: loop { ... } | +| test.rs:52:17:52:28 | break ''inner | test.rs:46:13:53:13 | 'inner: loop { ... } | +| test.rs:91:17:91:21 | break | test.rs:88:9:94:9 | while b { ... } | +| test.rs:101:17:101:21 | break | test.rs:99:9:103:9 | while ... { ... } | +| test.rs:109:17:109:21 | break | test.rs:107:9:112:9 | for ... in ... { ... } | +| test.rs:117:13:117:26 | break ... | test.rs:116:9:118:9 | loop { ... } | +| test.rs:197:17:197:28 | break ... | test.rs:195:13:200:9 | loop { ... } | +| test.rs:210:17:210:35 | break ''label ... | test.rs:208:13:213:9 | 'label: loop { ... } | +| test.rs:222:13:222:30 | break ''block ... | test.rs:221:13:223:9 | 'block: { ... } | +| test.rs:470:13:470:26 | break ''block 1 | test.rs:467:18:478:5 | 'block: { ... } | +| test.rs:474:13:474:26 | break ''block 2 | test.rs:467:18:478:5 | 'block: { ... } | +| test.rs:486:13:486:26 | break ''block 1 | test.rs:483:18:489:5 | 'block: { ... } | continueTarget -| test.rs:37:17:37:24 | ContinueExpr | test.rs:28:9:40:9 | LoopExpr | -| test.rs:63:21:63:28 | ContinueExpr | test.rs:61:13:68:13 | LoopExpr | -| test.rs:65:21:65:35 | ContinueExpr | test.rs:59:9:69:9 | LoopExpr | -| test.rs:67:17:67:31 | ContinueExpr | test.rs:61:13:68:13 | LoopExpr | -| test.rs:77:21:77:28 | ContinueExpr | test.rs:75:13:82:13 | LoopExpr | -| test.rs:79:21:79:35 | ContinueExpr | test.rs:75:13:82:13 | LoopExpr | -| test.rs:81:17:81:31 | ContinueExpr | test.rs:75:13:82:13 | LoopExpr | +| test.rs:37:17:37:24 | continue | test.rs:28:9:40:9 | loop { ... } | +| test.rs:63:21:63:28 | continue | test.rs:61:13:68:13 | 'inner: loop { ... } | +| test.rs:65:21:65:35 | continue 'outer | test.rs:59:9:69:9 | 'outer: loop { ... } | +| test.rs:67:17:67:31 | continue 'inner | test.rs:61:13:68:13 | 'inner: loop { ... } | +| test.rs:77:21:77:28 | continue | test.rs:75:13:82:13 | 'label: loop { ... } | +| test.rs:79:21:79:35 | continue 'label | test.rs:75:13:82:13 | 'label: loop { ... } | +| test.rs:81:17:81:31 | continue 'label | test.rs:75:13:82:13 | 'label: loop { ... } | diff --git a/rust/ql/test/library-tests/controlflow/test.rs b/rust/ql/test/library-tests/controlflow/test.rs index e1d596188061..42285f42b719 100644 --- a/rust/ql/test/library-tests/controlflow/test.rs +++ b/rust/ql/test/library-tests/controlflow/test.rs @@ -277,6 +277,13 @@ mod logical_operators { fn test_and_return(a: bool) { a && return; } + + fn test_and_true(a: bool) -> i64 { + if (a && true) { + return 1; + } + 0 + } } mod question_mark_operator { @@ -493,3 +500,21 @@ fn test_nested_function2() { trait MyFrom { fn my_from(x: T) -> Self; } + +struct MyNumber { + n: i64, +} + +impl MyNumber { + fn new(a: i64) -> Self { + MyNumber { n: a } + } + + fn negated(self) -> Self { + MyNumber { n: self.n } + } + + fn multifly_add(&mut self, a: i64, b: i64) { + self.n = (self.n * a) + b; + } +} diff --git a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected index a54c75d0c17f..7df553b65a06 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/barrier/inline-flow.expected @@ -1,16 +1,29 @@ models edges -| main.rs:21:13:21:21 | CallExpr : unit | main.rs:22:10:22:10 | s | provenance | | -| main.rs:32:13:32:21 | CallExpr : unit | main.rs:33:10:33:10 | s | provenance | | +| main.rs:9:13:9:19 | ...: ... | main.rs:9:30:14:1 | { ... } | provenance | | +| main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | provenance | | +| main.rs:26:13:26:21 | source(...) | main.rs:27:22:27:22 | s | provenance | | +| main.rs:27:13:27:23 | sanitize(...) | main.rs:28:10:28:10 | s | provenance | | +| main.rs:27:22:27:22 | s | main.rs:9:13:9:19 | ...: ... | provenance | | +| main.rs:27:22:27:22 | s | main.rs:27:13:27:23 | sanitize(...) | provenance | | +| main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | provenance | | nodes -| main.rs:17:10:17:18 | CallExpr | semmle.label | CallExpr | -| main.rs:21:13:21:21 | CallExpr : unit | semmle.label | CallExpr : unit | +| main.rs:9:13:9:19 | ...: ... | semmle.label | ...: ... | +| main.rs:9:30:14:1 | { ... } | semmle.label | { ... } | +| main.rs:17:10:17:18 | source(...) | semmle.label | source(...) | +| main.rs:21:13:21:21 | source(...) | semmle.label | source(...) | | main.rs:22:10:22:10 | s | semmle.label | s | -| main.rs:32:13:32:21 | CallExpr : unit | semmle.label | CallExpr : unit | +| main.rs:26:13:26:21 | source(...) | semmle.label | source(...) | +| main.rs:27:13:27:23 | sanitize(...) | semmle.label | sanitize(...) | +| main.rs:27:22:27:22 | s | semmle.label | s | +| main.rs:28:10:28:10 | s | semmle.label | s | +| main.rs:32:13:32:21 | source(...) | semmle.label | source(...) | | main.rs:33:10:33:10 | s | semmle.label | s | subpaths +| main.rs:27:22:27:22 | s | main.rs:9:13:9:19 | ...: ... | main.rs:9:30:14:1 | { ... } | main.rs:27:13:27:23 | sanitize(...) | testFailures #select -| main.rs:17:10:17:18 | CallExpr | main.rs:17:10:17:18 | CallExpr | main.rs:17:10:17:18 | CallExpr | $@ | main.rs:17:10:17:18 | CallExpr | CallExpr | -| main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | CallExpr : unit | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | CallExpr : unit | CallExpr : unit | -| main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | CallExpr : unit | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | CallExpr : unit | CallExpr : unit | +| main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | $@ | main.rs:17:10:17:18 | source(...) | source(...) | +| main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) | source(...) | +| main.rs:28:10:28:10 | s | main.rs:26:13:26:21 | source(...) | main.rs:28:10:28:10 | s | $@ | main.rs:26:13:26:21 | source(...) | source(...) | +| main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/barrier/main.rs b/rust/ql/test/library-tests/dataflow/barrier/main.rs index 8a0a7bc2be62..14935f0f3286 100644 --- a/rust/ql/test/library-tests/dataflow/barrier/main.rs +++ b/rust/ql/test/library-tests/dataflow/barrier/main.rs @@ -9,7 +9,7 @@ fn sink(s: &str) { fn sanitize(s: &str) -> &str { match s { "dangerous" => "", - s => s + s => s, } } @@ -25,7 +25,7 @@ fn through_variable() { fn with_barrier() { let s = source(1); let s = sanitize(s); - sink(s); + sink(s); // $ SPURIOUS: hasValueFlow=1 } fn main() { diff --git a/rust/ql/test/library-tests/dataflow/global/inline-flow.expected b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected new file mode 100644 index 000000000000..89fa0442293a --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/global/inline-flow.expected @@ -0,0 +1,74 @@ +models +edges +| main.rs:12:28:14:1 | { ... } | main.rs:17:13:17:23 | get_data(...) | provenance | | +| main.rs:13:5:13:13 | source(...) | main.rs:12:28:14:1 | { ... } | provenance | | +| main.rs:17:13:17:23 | get_data(...) | main.rs:18:10:18:10 | a | provenance | | +| main.rs:21:12:21:17 | ...: i64 | main.rs:22:10:22:10 | n | provenance | | +| main.rs:26:13:26:21 | source(...) | main.rs:27:13:27:13 | a | provenance | | +| main.rs:27:13:27:13 | a | main.rs:21:12:21:17 | ...: i64 | provenance | | +| main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | provenance | | +| main.rs:35:13:35:21 | source(...) | main.rs:36:26:36:26 | a | provenance | | +| main.rs:36:13:36:27 | pass_through(...) | main.rs:37:10:37:10 | b | provenance | | +| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | provenance | | +| main.rs:36:26:36:26 | a | main.rs:36:13:36:27 | pass_through(...) | provenance | | +| main.rs:41:13:44:6 | pass_through(...) | main.rs:45:10:45:10 | a | provenance | | +| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | provenance | | +| main.rs:41:26:44:5 | { ... } | main.rs:41:13:44:6 | pass_through(...) | provenance | | +| main.rs:43:9:43:18 | source(...) | main.rs:41:26:44:5 | { ... } | provenance | | +| main.rs:56:23:56:28 | ...: i64 | main.rs:57:14:57:14 | n | provenance | | +| main.rs:59:31:65:5 | { ... } | main.rs:77:13:77:25 | ... .get_data(...) | provenance | | +| main.rs:63:13:63:21 | source(...) | main.rs:59:31:65:5 | { ... } | provenance | | +| main.rs:66:28:66:33 | ...: i64 | main.rs:66:43:72:5 | { ... } | provenance | | +| main.rs:77:13:77:25 | ... .get_data(...) | main.rs:78:10:78:10 | a | provenance | | +| main.rs:83:13:83:21 | source(...) | main.rs:84:16:84:16 | a | provenance | | +| main.rs:84:16:84:16 | a | main.rs:56:23:56:28 | ...: i64 | provenance | | +| main.rs:89:13:89:21 | source(...) | main.rs:90:29:90:29 | a | provenance | | +| main.rs:90:13:90:30 | ... .data_through(...) | main.rs:91:10:91:10 | b | provenance | | +| main.rs:90:29:90:29 | a | main.rs:66:28:66:33 | ...: i64 | provenance | | +| main.rs:90:29:90:29 | a | main.rs:90:13:90:30 | ... .data_through(...) | provenance | | +nodes +| main.rs:12:28:14:1 | { ... } | semmle.label | { ... } | +| main.rs:13:5:13:13 | source(...) | semmle.label | source(...) | +| main.rs:17:13:17:23 | get_data(...) | semmle.label | get_data(...) | +| main.rs:18:10:18:10 | a | semmle.label | a | +| main.rs:21:12:21:17 | ...: i64 | semmle.label | ...: i64 | +| main.rs:22:10:22:10 | n | semmle.label | n | +| main.rs:26:13:26:21 | source(...) | semmle.label | source(...) | +| main.rs:27:13:27:13 | a | semmle.label | a | +| main.rs:30:17:30:22 | ...: i64 | semmle.label | ...: i64 | +| main.rs:30:32:32:1 | { ... } | semmle.label | { ... } | +| main.rs:35:13:35:21 | source(...) | semmle.label | source(...) | +| main.rs:36:13:36:27 | pass_through(...) | semmle.label | pass_through(...) | +| main.rs:36:26:36:26 | a | semmle.label | a | +| main.rs:37:10:37:10 | b | semmle.label | b | +| main.rs:41:13:44:6 | pass_through(...) | semmle.label | pass_through(...) | +| main.rs:41:26:44:5 | { ... } | semmle.label | { ... } | +| main.rs:43:9:43:18 | source(...) | semmle.label | source(...) | +| main.rs:45:10:45:10 | a | semmle.label | a | +| main.rs:56:23:56:28 | ...: i64 | semmle.label | ...: i64 | +| main.rs:57:14:57:14 | n | semmle.label | n | +| main.rs:59:31:65:5 | { ... } | semmle.label | { ... } | +| main.rs:63:13:63:21 | source(...) | semmle.label | source(...) | +| main.rs:66:28:66:33 | ...: i64 | semmle.label | ...: i64 | +| main.rs:66:43:72:5 | { ... } | semmle.label | { ... } | +| main.rs:77:13:77:25 | ... .get_data(...) | semmle.label | ... .get_data(...) | +| main.rs:78:10:78:10 | a | semmle.label | a | +| main.rs:83:13:83:21 | source(...) | semmle.label | source(...) | +| main.rs:84:16:84:16 | a | semmle.label | a | +| main.rs:89:13:89:21 | source(...) | semmle.label | source(...) | +| main.rs:90:13:90:30 | ... .data_through(...) | semmle.label | ... .data_through(...) | +| main.rs:90:29:90:29 | a | semmle.label | a | +| main.rs:91:10:91:10 | b | semmle.label | b | +subpaths +| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:36:13:36:27 | pass_through(...) | +| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:41:13:44:6 | pass_through(...) | +| main.rs:90:29:90:29 | a | main.rs:66:28:66:33 | ...: i64 | main.rs:66:43:72:5 | { ... } | main.rs:90:13:90:30 | ... .data_through(...) | +testFailures +#select +| main.rs:18:10:18:10 | a | main.rs:13:5:13:13 | source(...) | main.rs:18:10:18:10 | a | $@ | main.rs:13:5:13:13 | source(...) | source(...) | +| main.rs:22:10:22:10 | n | main.rs:26:13:26:21 | source(...) | main.rs:22:10:22:10 | n | $@ | main.rs:26:13:26:21 | source(...) | source(...) | +| main.rs:37:10:37:10 | b | main.rs:35:13:35:21 | source(...) | main.rs:37:10:37:10 | b | $@ | main.rs:35:13:35:21 | source(...) | source(...) | +| main.rs:45:10:45:10 | a | main.rs:43:9:43:18 | source(...) | main.rs:45:10:45:10 | a | $@ | main.rs:43:9:43:18 | source(...) | source(...) | +| main.rs:57:14:57:14 | n | main.rs:83:13:83:21 | source(...) | main.rs:57:14:57:14 | n | $@ | main.rs:83:13:83:21 | source(...) | source(...) | +| main.rs:78:10:78:10 | a | main.rs:63:13:63:21 | source(...) | main.rs:78:10:78:10 | a | $@ | main.rs:63:13:63:21 | source(...) | source(...) | +| main.rs:91:10:91:10 | b | main.rs:89:13:89:21 | source(...) | main.rs:91:10:91:10 | b | $@ | main.rs:89:13:89:21 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/global/inline-flow.ql b/rust/ql/test/library-tests/dataflow/global/inline-flow.ql new file mode 100644 index 000000000000..ad553fe548dc --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/global/inline-flow.ql @@ -0,0 +1,12 @@ +/** + * @kind path-problem + */ + +import rust +import utils.InlineFlowTest +import DefaultFlowTest +import ValueFlow::PathGraph + +from ValueFlow::PathNode source, ValueFlow::PathNode sink +where ValueFlow::flowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() diff --git a/rust/ql/test/library-tests/dataflow/global/main.rs b/rust/ql/test/library-tests/dataflow/global/main.rs index eb3a59856922..77c37a945b8f 100644 --- a/rust/ql/test/library-tests/dataflow/global/main.rs +++ b/rust/ql/test/library-tests/dataflow/global/main.rs @@ -19,7 +19,7 @@ fn data_out_of_call() { } fn data_in(n: i64) { - sink(n + 7); // $ hasValueFlow + sink(n); // $ hasValueFlow=3 } fn data_in_to_call() { @@ -37,6 +37,14 @@ fn data_through_call() { sink(b); // $ hasValueFlow=1 } +fn block_expression_as_argument() { + let a = pass_through({ + println!("Hello"); + source(14) + }); + sink(a); // $ hasValueFlow=14 +} + // ----------------------------------------------------------------------------- // Data flow in, out, and through method. @@ -67,7 +75,7 @@ impl MyFlag { fn data_out_of_method() { let mn = MyFlag { flag: true }; let a = mn.get_data(); - sink(a); + sink(a); // $ hasValueFlow=2 } fn data_in_to_method_call() { @@ -79,8 +87,8 @@ fn data_in_to_method_call() { fn data_through_method() { let mn = MyFlag { flag: true }; let a = source(4); - mn.data_through(a); - sink(a); // $ hasValueFlow=4 + let b = mn.data_through(a); + sink(b); // $ hasValueFlow=4 } fn main() { diff --git a/rust/ql/test/library-tests/dataflow/global/viableCallable.expected b/rust/ql/test/library-tests/dataflow/global/viableCallable.expected index 6a15bb25249a..eaf4a7b14d91 100644 --- a/rust/ql/test/library-tests/dataflow/global/viableCallable.expected +++ b/rust/ql/test/library-tests/dataflow/global/viableCallable.expected @@ -1,24 +1,27 @@ -| main.rs:13:5:13:13 | CallExpr | main.rs:1:1:3:1 | source | -| main.rs:17:13:17:23 | CallExpr | main.rs:12:1:14:1 | get_data | -| main.rs:18:5:18:11 | CallExpr | main.rs:5:1:7:1 | sink | -| main.rs:22:5:22:15 | CallExpr | main.rs:5:1:7:1 | sink | -| main.rs:26:13:26:21 | CallExpr | main.rs:1:1:3:1 | source | -| main.rs:27:5:27:14 | CallExpr | main.rs:21:1:23:1 | data_in | -| main.rs:35:13:35:21 | CallExpr | main.rs:1:1:3:1 | source | -| main.rs:36:13:36:27 | CallExpr | main.rs:30:1:32:1 | pass_through | -| main.rs:37:5:37:11 | CallExpr | main.rs:5:1:7:1 | sink | -| main.rs:49:9:49:15 | CallExpr | main.rs:5:1:7:1 | sink | -| main.rs:55:13:55:21 | CallExpr | main.rs:1:1:3:1 | source | -| main.rs:69:13:69:25 | ... .get_data(...) | main.rs:51:5:57:5 | get_data | -| main.rs:70:5:70:11 | CallExpr | main.rs:5:1:7:1 | sink | -| main.rs:75:13:75:21 | CallExpr | main.rs:1:1:3:1 | source | -| main.rs:76:5:76:17 | ... .data_in(...) | main.rs:48:5:50:5 | data_in | -| main.rs:81:13:81:21 | CallExpr | main.rs:1:1:3:1 | source | -| main.rs:82:5:82:22 | ... .data_through(...) | main.rs:58:5:64:5 | data_through | -| main.rs:83:5:83:11 | CallExpr | main.rs:5:1:7:1 | sink | -| main.rs:87:5:87:22 | CallExpr | main.rs:16:1:19:1 | data_out_of_call | -| main.rs:88:5:88:21 | CallExpr | main.rs:25:1:28:1 | data_in_to_call | -| main.rs:89:5:89:23 | CallExpr | main.rs:34:1:38:1 | data_through_call | -| main.rs:91:5:91:24 | CallExpr | main.rs:67:1:71:1 | data_out_of_method | -| main.rs:92:5:92:28 | CallExpr | main.rs:73:1:77:1 | data_in_to_method_call | -| main.rs:93:5:93:25 | CallExpr | main.rs:79:1:84:1 | data_through_method | +| main.rs:13:5:13:13 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:17:13:17:23 | get_data(...) | main.rs:12:1:14:1 | fn get_data | +| main.rs:18:5:18:11 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:22:5:22:11 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:26:13:26:21 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:27:5:27:14 | data_in(...) | main.rs:21:1:23:1 | fn data_in | +| main.rs:35:13:35:21 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:36:13:36:27 | pass_through(...) | main.rs:30:1:32:1 | fn pass_through | +| main.rs:37:5:37:11 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:41:13:44:6 | pass_through(...) | main.rs:30:1:32:1 | fn pass_through | +| main.rs:43:9:43:18 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:45:5:45:11 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:57:9:57:15 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:63:13:63:21 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:77:13:77:25 | ... .get_data(...) | main.rs:59:5:65:5 | fn get_data | +| main.rs:78:5:78:11 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:83:13:83:21 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:84:5:84:17 | ... .data_in(...) | main.rs:56:5:58:5 | fn data_in | +| main.rs:89:13:89:21 | source(...) | main.rs:1:1:3:1 | fn source | +| main.rs:90:13:90:30 | ... .data_through(...) | main.rs:66:5:72:5 | fn data_through | +| main.rs:91:5:91:11 | sink(...) | main.rs:5:1:7:1 | fn sink | +| main.rs:95:5:95:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call | +| main.rs:96:5:96:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call | +| main.rs:97:5:97:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call | +| main.rs:99:5:99:24 | data_out_of_method(...) | main.rs:75:1:79:1 | fn data_out_of_method | +| main.rs:100:5:100:28 | data_in_to_method_call(...) | main.rs:81:1:85:1 | fn data_in_to_method_call | +| main.rs:101:5:101:25 | data_through_method(...) | main.rs:87:1:92:1 | fn data_through_method | diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 8cc12598f62b..a49da7516790 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -1,85 +1,306 @@ +localStep | main.rs:3:11:3:11 | [SSA] i | main.rs:4:12:4:12 | i | | main.rs:3:11:3:11 | i | main.rs:3:11:3:11 | [SSA] i | -| main.rs:4:5:4:12 | ... + ... | main.rs:3:26:5:1 | BlockExpr | +| main.rs:3:11:3:16 | ...: i64 | main.rs:3:11:3:11 | i | +| main.rs:4:5:4:12 | ... + ... | main.rs:3:26:5:1 | { ... } | | main.rs:7:9:7:9 | [SSA] s | main.rs:8:20:8:20 | s | | main.rs:7:9:7:9 | s | main.rs:7:9:7:9 | [SSA] s | +| main.rs:7:9:7:14 | ...: i64 | main.rs:7:9:7:9 | s | | main.rs:19:9:19:9 | [SSA] s | main.rs:20:10:20:10 | s | | main.rs:19:9:19:9 | s | main.rs:19:9:19:9 | [SSA] s | -| main.rs:19:13:19:21 | CallExpr | main.rs:19:9:19:9 | s | +| main.rs:19:13:19:21 | source(...) | main.rs:19:9:19:9 | s | | main.rs:23:18:23:21 | [SSA] cond | main.rs:26:16:26:19 | cond | | main.rs:23:18:23:21 | cond | main.rs:23:18:23:21 | [SSA] cond | +| main.rs:23:18:23:27 | ...: bool | main.rs:23:18:23:21 | cond | | main.rs:24:9:24:9 | [SSA] a | main.rs:26:23:26:23 | a | | main.rs:24:9:24:9 | a | main.rs:24:9:24:9 | [SSA] a | -| main.rs:24:13:24:21 | CallExpr | main.rs:24:9:24:9 | a | +| main.rs:24:13:24:21 | source(...) | main.rs:24:9:24:9 | a | | main.rs:25:9:25:9 | [SSA] b | main.rs:26:34:26:34 | b | | main.rs:25:9:25:9 | b | main.rs:25:9:25:9 | [SSA] b | | main.rs:25:13:25:13 | 2 | main.rs:25:9:25:9 | b | | main.rs:26:9:26:9 | [SSA] c | main.rs:27:10:27:10 | c | | main.rs:26:9:26:9 | c | main.rs:26:9:26:9 | [SSA] c | -| main.rs:26:13:26:36 | IfExpr | main.rs:26:9:26:9 | c | -| main.rs:26:21:26:25 | BlockExpr | main.rs:26:13:26:36 | IfExpr | -| main.rs:26:23:26:23 | a | main.rs:26:21:26:25 | BlockExpr | -| main.rs:26:32:26:36 | BlockExpr | main.rs:26:13:26:36 | IfExpr | -| main.rs:26:34:26:34 | b | main.rs:26:32:26:36 | BlockExpr | +| main.rs:26:13:26:36 | if cond {...} else {...} | main.rs:26:9:26:9 | c | +| main.rs:26:21:26:25 | { ... } | main.rs:26:13:26:36 | if cond {...} else {...} | +| main.rs:26:23:26:23 | a | main.rs:26:21:26:25 | { ... } | +| main.rs:26:32:26:36 | { ... } | main.rs:26:13:26:36 | if cond {...} else {...} | +| main.rs:26:34:26:34 | b | main.rs:26:32:26:36 | { ... } | | main.rs:30:21:30:21 | [SSA] m | main.rs:32:19:32:19 | m | | main.rs:30:21:30:21 | m | main.rs:30:21:30:21 | [SSA] m | +| main.rs:30:21:30:34 | ...: Option::<...> | main.rs:30:21:30:21 | m | | main.rs:31:9:31:9 | [SSA] a | main.rs:33:20:33:20 | a | | main.rs:31:9:31:9 | a | main.rs:31:9:31:9 | [SSA] a | -| main.rs:31:13:31:21 | CallExpr | main.rs:31:9:31:9 | a | +| main.rs:31:13:31:21 | source(...) | main.rs:31:9:31:9 | a | | main.rs:32:9:32:9 | [SSA] b | main.rs:36:10:36:10 | b | | main.rs:32:9:32:9 | b | main.rs:32:9:32:9 | [SSA] b | -| main.rs:32:13:35:5 | MatchExpr | main.rs:32:9:32:9 | b | -| main.rs:33:20:33:20 | a | main.rs:32:13:35:5 | MatchExpr | -| main.rs:34:17:34:17 | 0 | main.rs:32:13:35:5 | MatchExpr | +| main.rs:32:13:35:5 | match m { ... } | main.rs:32:9:32:9 | b | +| main.rs:32:19:32:19 | m | main.rs:33:9:33:15 | TupleStructPat | +| main.rs:32:19:32:19 | m | main.rs:34:9:34:12 | None | +| main.rs:33:20:33:20 | a | main.rs:32:13:35:5 | match m { ... } | +| main.rs:34:17:34:17 | 0 | main.rs:32:13:35:5 | match m { ... } | | main.rs:40:9:40:9 | [SSA] a | main.rs:43:10:43:10 | a | | main.rs:40:9:40:9 | a | main.rs:40:9:40:9 | [SSA] a | -| main.rs:40:13:42:5 | LoopExpr | main.rs:40:9:40:9 | a | -| main.rs:41:9:41:15 | BreakExpr | main.rs:40:13:42:5 | LoopExpr | -| main.rs:41:15:41:15 | 1 | main.rs:41:9:41:15 | BreakExpr | +| main.rs:40:13:42:5 | loop { ... } | main.rs:40:9:40:9 | a | +| main.rs:41:9:41:15 | break 1 | main.rs:40:13:42:5 | loop { ... } | +| main.rs:41:15:41:15 | 1 | main.rs:41:9:41:15 | break 1 | | main.rs:44:9:44:9 | [SSA] b | main.rs:47:10:47:10 | b | | main.rs:44:9:44:9 | b | main.rs:44:9:44:9 | [SSA] b | -| main.rs:44:13:46:5 | LoopExpr | main.rs:44:9:44:9 | b | -| main.rs:45:9:45:23 | BreakExpr | main.rs:44:13:46:5 | LoopExpr | -| main.rs:45:15:45:23 | CallExpr | main.rs:45:9:45:23 | BreakExpr | +| main.rs:44:13:46:5 | loop { ... } | main.rs:44:9:44:9 | b | +| main.rs:45:9:45:23 | break ... | main.rs:44:13:46:5 | loop { ... } | +| main.rs:45:15:45:23 | source(...) | main.rs:45:9:45:23 | break ... | | main.rs:51:9:51:13 | [SSA] i | main.rs:52:10:52:10 | i | | main.rs:51:9:51:13 | i | main.rs:51:9:51:13 | [SSA] i | | main.rs:51:17:51:17 | 1 | main.rs:51:9:51:13 | i | | main.rs:53:5:53:5 | [SSA] i | main.rs:54:10:54:10 | i | | main.rs:53:5:53:5 | i | main.rs:53:5:53:5 | [SSA] i | +| main.rs:53:9:53:17 | source(...) | main.rs:53:5:53:5 | i | | main.rs:61:9:61:9 | [SSA] i | main.rs:62:11:62:11 | i | | main.rs:61:9:61:9 | i | main.rs:61:9:61:9 | [SSA] i | -| main.rs:61:13:61:31 | CallExpr | main.rs:61:9:61:9 | i | +| main.rs:61:13:61:31 | ...::new(...) | main.rs:61:9:61:9 | i | | main.rs:66:9:66:9 | [SSA] a | main.rs:67:10:67:10 | a | | main.rs:66:9:66:9 | a | main.rs:66:9:66:9 | [SSA] a | | main.rs:66:13:66:26 | TupleExpr | main.rs:66:9:66:9 | a | | main.rs:67:10:67:10 | a | main.rs:68:10:68:10 | a | | main.rs:78:9:78:9 | [SSA] p | main.rs:83:10:83:10 | p | | main.rs:78:9:78:9 | p | main.rs:78:9:78:9 | [SSA] p | -| main.rs:78:13:82:5 | RecordExpr | main.rs:78:9:78:9 | p | +| main.rs:78:13:82:5 | Point {...} | main.rs:78:9:78:9 | p | | main.rs:83:10:83:10 | p | main.rs:84:10:84:10 | p | | main.rs:84:10:84:10 | p | main.rs:85:10:85:10 | p | | main.rs:92:9:92:9 | [SSA] p | main.rs:97:38:97:38 | p | | main.rs:92:9:92:9 | p | main.rs:92:9:92:9 | [SSA] p | -| main.rs:92:13:96:5 | RecordExpr | main.rs:92:9:92:9 | p | +| main.rs:92:13:96:5 | Point {...} | main.rs:92:9:92:9 | p | | main.rs:97:20:97:20 | [SSA] a | main.rs:98:10:98:10 | a | | main.rs:97:20:97:20 | a | main.rs:97:20:97:20 | [SSA] a | | main.rs:97:26:97:26 | [SSA] b | main.rs:99:10:99:10 | b | | main.rs:97:26:97:26 | b | main.rs:97:26:97:26 | [SSA] b | | main.rs:97:32:97:32 | [SSA] c | main.rs:100:10:100:10 | c | | main.rs:97:32:97:32 | c | main.rs:97:32:97:32 | [SSA] c | -| main.rs:97:38:97:38 | p | main.rs:97:9:97:34 | RecordPat | +| main.rs:97:38:97:38 | p | main.rs:97:9:97:34 | Point {...} | | main.rs:104:9:104:10 | [SSA] s1 | main.rs:106:11:106:12 | s1 | | main.rs:104:9:104:10 | s1 | main.rs:104:9:104:10 | [SSA] s1 | -| main.rs:104:14:104:28 | CallExpr | main.rs:104:9:104:10 | s1 | +| main.rs:104:14:104:37 | ...::Some(...) | main.rs:104:9:104:10 | s1 | | main.rs:105:9:105:10 | [SSA] s2 | main.rs:110:11:110:12 | s2 | | main.rs:105:9:105:10 | s2 | main.rs:105:9:105:10 | [SSA] s2 | -| main.rs:105:14:105:20 | CallExpr | main.rs:105:9:105:10 | s2 | -| main.rs:107:14:107:14 | [SSA] n | main.rs:107:25:107:25 | n | -| main.rs:107:14:107:14 | n | main.rs:107:14:107:14 | [SSA] n | -| main.rs:107:20:107:26 | CallExpr | main.rs:106:5:109:5 | MatchExpr | -| main.rs:108:17:108:23 | CallExpr | main.rs:106:5:109:5 | MatchExpr | -| main.rs:110:5:113:5 | MatchExpr | main.rs:103:27:114:1 | BlockExpr | -| main.rs:111:14:111:14 | [SSA] n | main.rs:111:25:111:25 | n | -| main.rs:111:14:111:14 | n | main.rs:111:14:111:14 | [SSA] n | -| main.rs:111:20:111:26 | CallExpr | main.rs:110:5:113:5 | MatchExpr | -| main.rs:112:17:112:23 | CallExpr | main.rs:110:5:113:5 | MatchExpr | +| main.rs:105:14:105:28 | ...::Some(...) | main.rs:105:9:105:10 | s2 | +| main.rs:106:11:106:12 | s1 | main.rs:107:9:107:23 | TupleStructPat | +| main.rs:106:11:106:12 | s1 | main.rs:108:9:108:20 | ...::None | +| main.rs:107:22:107:22 | [SSA] n | main.rs:107:33:107:33 | n | +| main.rs:107:22:107:22 | n | main.rs:107:22:107:22 | [SSA] n | +| main.rs:107:28:107:34 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } | +| main.rs:108:25:108:31 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } | +| main.rs:110:5:113:5 | match s2 { ... } | main.rs:103:37:114:1 | { ... } | +| main.rs:110:11:110:12 | s2 | main.rs:111:9:111:23 | TupleStructPat | +| main.rs:110:11:110:12 | s2 | main.rs:112:9:112:20 | ...::None | +| main.rs:111:22:111:22 | [SSA] n | main.rs:111:33:111:33 | n | +| main.rs:111:22:111:22 | n | main.rs:111:22:111:22 | [SSA] n | +| main.rs:111:28:111:34 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } | +| main.rs:112:25:112:31 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } | +| main.rs:117:9:117:10 | [SSA] s1 | main.rs:119:11:119:12 | s1 | +| main.rs:117:9:117:10 | s1 | main.rs:117:9:117:10 | [SSA] s1 | +| main.rs:117:14:117:29 | Some(...) | main.rs:117:9:117:10 | s1 | +| main.rs:118:9:118:10 | [SSA] s2 | main.rs:123:11:123:12 | s2 | +| main.rs:118:9:118:10 | s2 | main.rs:118:9:118:10 | [SSA] s2 | +| main.rs:118:14:118:20 | Some(...) | main.rs:118:9:118:10 | s2 | +| main.rs:119:11:119:12 | s1 | main.rs:120:9:120:15 | TupleStructPat | +| main.rs:119:11:119:12 | s1 | main.rs:121:9:121:12 | None | +| main.rs:120:14:120:14 | [SSA] n | main.rs:120:25:120:25 | n | +| main.rs:120:14:120:14 | n | main.rs:120:14:120:14 | [SSA] n | +| main.rs:120:20:120:26 | sink(...) | main.rs:119:5:122:5 | match s1 { ... } | +| main.rs:121:17:121:23 | sink(...) | main.rs:119:5:122:5 | match s1 { ... } | +| main.rs:123:5:126:5 | match s2 { ... } | main.rs:116:39:127:1 | { ... } | +| main.rs:123:11:123:12 | s2 | main.rs:124:9:124:15 | TupleStructPat | +| main.rs:123:11:123:12 | s2 | main.rs:125:9:125:12 | None | +| main.rs:124:14:124:14 | [SSA] n | main.rs:124:25:124:25 | n | +| main.rs:124:14:124:14 | n | main.rs:124:14:124:14 | [SSA] n | +| main.rs:124:20:124:26 | sink(...) | main.rs:123:5:126:5 | match s2 { ... } | +| main.rs:125:17:125:23 | sink(...) | main.rs:123:5:126:5 | match s2 { ... } | +| main.rs:135:9:135:10 | [SSA] s1 | main.rs:137:11:137:12 | s1 | +| main.rs:135:9:135:10 | s1 | main.rs:135:9:135:10 | [SSA] s1 | +| main.rs:135:14:135:39 | ...::A(...) | main.rs:135:9:135:10 | s1 | +| main.rs:136:9:136:10 | [SSA] s2 | main.rs:144:11:144:12 | s2 | +| main.rs:136:9:136:10 | s2 | main.rs:136:9:136:10 | [SSA] s2 | +| main.rs:136:14:136:30 | ...::B(...) | main.rs:136:9:136:10 | s2 | +| main.rs:137:11:137:12 | s1 | main.rs:138:9:138:25 | TupleStructPat | +| main.rs:137:11:137:12 | s1 | main.rs:139:9:139:25 | TupleStructPat | +| main.rs:137:11:137:12 | s1 | main.rs:141:11:141:12 | s1 | +| main.rs:138:24:138:24 | [SSA] n | main.rs:138:35:138:35 | n | +| main.rs:138:24:138:24 | n | main.rs:138:24:138:24 | [SSA] n | +| main.rs:138:30:138:36 | sink(...) | main.rs:137:5:140:5 | match s1 { ... } | +| main.rs:139:24:139:24 | [SSA] n | main.rs:139:35:139:35 | n | +| main.rs:139:24:139:24 | n | main.rs:139:24:139:24 | [SSA] n | +| main.rs:139:30:139:36 | sink(...) | main.rs:137:5:140:5 | match s1 { ... } | +| main.rs:141:11:141:12 | s1 | main.rs:142:10:142:46 | ... \| ... | +| main.rs:142:10:142:46 | ... \| ... | main.rs:142:10:142:26 | TupleStructPat | +| main.rs:142:10:142:46 | ... \| ... | main.rs:142:30:142:46 | TupleStructPat | +| main.rs:142:10:142:46 | [SSA] [match(true)] phi | main.rs:142:57:142:57 | n | +| main.rs:142:25:142:25 | [SSA] [input] [match(true)] phi | main.rs:142:10:142:46 | [SSA] [match(true)] phi | +| main.rs:142:25:142:25 | [SSA] n | main.rs:142:25:142:25 | [SSA] [input] [match(true)] phi | +| main.rs:142:25:142:25 | n | main.rs:142:25:142:25 | [SSA] n | +| main.rs:142:45:142:45 | [SSA] [input] [match(true)] phi | main.rs:142:10:142:46 | [SSA] [match(true)] phi | +| main.rs:142:45:142:45 | [SSA] n | main.rs:142:45:142:45 | [SSA] [input] [match(true)] phi | +| main.rs:142:45:142:45 | n | main.rs:142:45:142:45 | [SSA] n | +| main.rs:142:52:142:58 | sink(...) | main.rs:141:5:143:5 | match s1 { ... } | +| main.rs:144:5:147:5 | match s2 { ... } | main.rs:134:48:148:1 | { ... } | +| main.rs:144:11:144:12 | s2 | main.rs:145:9:145:25 | TupleStructPat | +| main.rs:144:11:144:12 | s2 | main.rs:146:9:146:25 | TupleStructPat | +| main.rs:145:24:145:24 | [SSA] n | main.rs:145:35:145:35 | n | +| main.rs:145:24:145:24 | n | main.rs:145:24:145:24 | [SSA] n | +| main.rs:145:30:145:36 | sink(...) | main.rs:144:5:147:5 | match s2 { ... } | +| main.rs:146:24:146:24 | [SSA] n | main.rs:146:35:146:35 | n | +| main.rs:146:24:146:24 | n | main.rs:146:24:146:24 | [SSA] n | +| main.rs:146:30:146:36 | sink(...) | main.rs:144:5:147:5 | match s2 { ... } | +| main.rs:153:9:153:10 | [SSA] s1 | main.rs:155:11:155:12 | s1 | +| main.rs:153:9:153:10 | s1 | main.rs:153:9:153:10 | [SSA] s1 | +| main.rs:153:14:153:26 | A(...) | main.rs:153:9:153:10 | s1 | +| main.rs:154:9:154:10 | [SSA] s2 | main.rs:162:11:162:12 | s2 | +| main.rs:154:9:154:10 | s2 | main.rs:154:9:154:10 | [SSA] s2 | +| main.rs:154:14:154:17 | B(...) | main.rs:154:9:154:10 | s2 | +| main.rs:155:11:155:12 | s1 | main.rs:156:9:156:12 | TupleStructPat | +| main.rs:155:11:155:12 | s1 | main.rs:157:9:157:12 | TupleStructPat | +| main.rs:155:11:155:12 | s1 | main.rs:159:11:159:12 | s1 | +| main.rs:156:11:156:11 | [SSA] n | main.rs:156:22:156:22 | n | +| main.rs:156:11:156:11 | n | main.rs:156:11:156:11 | [SSA] n | +| main.rs:156:17:156:23 | sink(...) | main.rs:155:5:158:5 | match s1 { ... } | +| main.rs:157:11:157:11 | [SSA] n | main.rs:157:22:157:22 | n | +| main.rs:157:11:157:11 | n | main.rs:157:11:157:11 | [SSA] n | +| main.rs:157:17:157:23 | sink(...) | main.rs:155:5:158:5 | match s1 { ... } | +| main.rs:159:11:159:12 | s1 | main.rs:160:10:160:20 | ... \| ... | +| main.rs:160:10:160:20 | ... \| ... | main.rs:160:10:160:13 | TupleStructPat | +| main.rs:160:10:160:20 | ... \| ... | main.rs:160:17:160:20 | TupleStructPat | +| main.rs:160:10:160:20 | [SSA] [match(true)] phi | main.rs:160:31:160:31 | n | +| main.rs:160:12:160:12 | [SSA] [input] [match(true)] phi | main.rs:160:10:160:20 | [SSA] [match(true)] phi | +| main.rs:160:12:160:12 | [SSA] n | main.rs:160:12:160:12 | [SSA] [input] [match(true)] phi | +| main.rs:160:12:160:12 | n | main.rs:160:12:160:12 | [SSA] n | +| main.rs:160:19:160:19 | [SSA] [input] [match(true)] phi | main.rs:160:10:160:20 | [SSA] [match(true)] phi | +| main.rs:160:19:160:19 | [SSA] n | main.rs:160:19:160:19 | [SSA] [input] [match(true)] phi | +| main.rs:160:19:160:19 | n | main.rs:160:19:160:19 | [SSA] n | +| main.rs:160:26:160:32 | sink(...) | main.rs:159:5:161:5 | match s1 { ... } | +| main.rs:162:5:165:5 | match s2 { ... } | main.rs:152:50:166:1 | { ... } | +| main.rs:162:11:162:12 | s2 | main.rs:163:9:163:12 | TupleStructPat | +| main.rs:162:11:162:12 | s2 | main.rs:164:9:164:12 | TupleStructPat | +| main.rs:163:11:163:11 | [SSA] n | main.rs:163:22:163:22 | n | +| main.rs:163:11:163:11 | n | main.rs:163:11:163:11 | [SSA] n | +| main.rs:163:17:163:23 | sink(...) | main.rs:162:5:165:5 | match s2 { ... } | +| main.rs:164:11:164:11 | [SSA] n | main.rs:164:22:164:22 | n | +| main.rs:164:11:164:11 | n | main.rs:164:11:164:11 | [SSA] n | +| main.rs:164:17:164:23 | sink(...) | main.rs:162:5:165:5 | match s2 { ... } | +| main.rs:174:9:174:10 | [SSA] s1 | main.rs:178:11:178:12 | s1 | +| main.rs:174:9:174:10 | s1 | main.rs:174:9:174:10 | [SSA] s1 | +| main.rs:174:14:176:5 | ...::C {...} | main.rs:174:9:174:10 | s1 | +| main.rs:177:9:177:10 | [SSA] s2 | main.rs:185:11:185:12 | s2 | +| main.rs:177:9:177:10 | s2 | main.rs:177:9:177:10 | [SSA] s2 | +| main.rs:177:14:177:43 | ...::D {...} | main.rs:177:9:177:10 | s2 | +| main.rs:178:11:178:12 | s1 | main.rs:179:9:179:38 | ...::C {...} | +| main.rs:178:11:178:12 | s1 | main.rs:180:9:180:38 | ...::D {...} | +| main.rs:178:11:178:12 | s1 | main.rs:182:11:182:12 | s1 | +| main.rs:179:36:179:36 | [SSA] n | main.rs:179:48:179:48 | n | +| main.rs:179:36:179:36 | n | main.rs:179:36:179:36 | [SSA] n | +| main.rs:179:43:179:49 | sink(...) | main.rs:178:5:181:5 | match s1 { ... } | +| main.rs:180:36:180:36 | [SSA] n | main.rs:180:48:180:48 | n | +| main.rs:180:36:180:36 | n | main.rs:180:36:180:36 | [SSA] n | +| main.rs:180:43:180:49 | sink(...) | main.rs:178:5:181:5 | match s1 { ... } | +| main.rs:182:11:182:12 | s1 | main.rs:183:10:183:72 | ... \| ... | +| main.rs:183:10:183:72 | ... \| ... | main.rs:183:10:183:39 | ...::C {...} | +| main.rs:183:10:183:72 | ... \| ... | main.rs:183:43:183:72 | ...::D {...} | +| main.rs:183:10:183:72 | [SSA] [match(true)] phi | main.rs:183:83:183:83 | n | +| main.rs:183:37:183:37 | [SSA] [input] [match(true)] phi | main.rs:183:10:183:72 | [SSA] [match(true)] phi | +| main.rs:183:37:183:37 | [SSA] n | main.rs:183:37:183:37 | [SSA] [input] [match(true)] phi | +| main.rs:183:37:183:37 | n | main.rs:183:37:183:37 | [SSA] n | +| main.rs:183:70:183:70 | [SSA] [input] [match(true)] phi | main.rs:183:10:183:72 | [SSA] [match(true)] phi | +| main.rs:183:70:183:70 | [SSA] n | main.rs:183:70:183:70 | [SSA] [input] [match(true)] phi | +| main.rs:183:70:183:70 | n | main.rs:183:70:183:70 | [SSA] n | +| main.rs:183:78:183:84 | sink(...) | main.rs:182:5:184:5 | match s1 { ... } | +| main.rs:185:5:188:5 | match s2 { ... } | main.rs:173:49:189:1 | { ... } | +| main.rs:185:11:185:12 | s2 | main.rs:186:9:186:38 | ...::C {...} | +| main.rs:185:11:185:12 | s2 | main.rs:187:9:187:38 | ...::D {...} | +| main.rs:186:36:186:36 | [SSA] n | main.rs:186:48:186:48 | n | +| main.rs:186:36:186:36 | n | main.rs:186:36:186:36 | [SSA] n | +| main.rs:186:43:186:49 | sink(...) | main.rs:185:5:188:5 | match s2 { ... } | +| main.rs:187:36:187:36 | [SSA] n | main.rs:187:48:187:48 | n | +| main.rs:187:36:187:36 | n | main.rs:187:36:187:36 | [SSA] n | +| main.rs:187:43:187:49 | sink(...) | main.rs:185:5:188:5 | match s2 { ... } | +| main.rs:194:9:194:10 | [SSA] s1 | main.rs:198:11:198:12 | s1 | +| main.rs:194:9:194:10 | s1 | main.rs:194:9:194:10 | [SSA] s1 | +| main.rs:194:14:196:5 | C {...} | main.rs:194:9:194:10 | s1 | +| main.rs:197:9:197:10 | [SSA] s2 | main.rs:205:11:205:12 | s2 | +| main.rs:197:9:197:10 | s2 | main.rs:197:9:197:10 | [SSA] s2 | +| main.rs:197:14:197:29 | D {...} | main.rs:197:9:197:10 | s2 | +| main.rs:198:11:198:12 | s1 | main.rs:199:9:199:24 | C {...} | +| main.rs:198:11:198:12 | s1 | main.rs:200:9:200:24 | D {...} | +| main.rs:198:11:198:12 | s1 | main.rs:202:11:202:12 | s1 | +| main.rs:199:22:199:22 | [SSA] n | main.rs:199:34:199:34 | n | +| main.rs:199:22:199:22 | n | main.rs:199:22:199:22 | [SSA] n | +| main.rs:199:29:199:35 | sink(...) | main.rs:198:5:201:5 | match s1 { ... } | +| main.rs:200:22:200:22 | [SSA] n | main.rs:200:34:200:34 | n | +| main.rs:200:22:200:22 | n | main.rs:200:22:200:22 | [SSA] n | +| main.rs:200:29:200:35 | sink(...) | main.rs:198:5:201:5 | match s1 { ... } | +| main.rs:202:11:202:12 | s1 | main.rs:203:10:203:44 | ... \| ... | +| main.rs:203:10:203:44 | ... \| ... | main.rs:203:10:203:25 | C {...} | +| main.rs:203:10:203:44 | ... \| ... | main.rs:203:29:203:44 | D {...} | +| main.rs:203:10:203:44 | [SSA] [match(true)] phi | main.rs:203:55:203:55 | n | +| main.rs:203:23:203:23 | [SSA] [input] [match(true)] phi | main.rs:203:10:203:44 | [SSA] [match(true)] phi | +| main.rs:203:23:203:23 | [SSA] n | main.rs:203:23:203:23 | [SSA] [input] [match(true)] phi | +| main.rs:203:23:203:23 | n | main.rs:203:23:203:23 | [SSA] n | +| main.rs:203:42:203:42 | [SSA] [input] [match(true)] phi | main.rs:203:10:203:44 | [SSA] [match(true)] phi | +| main.rs:203:42:203:42 | [SSA] n | main.rs:203:42:203:42 | [SSA] [input] [match(true)] phi | +| main.rs:203:42:203:42 | n | main.rs:203:42:203:42 | [SSA] n | +| main.rs:203:50:203:56 | sink(...) | main.rs:202:5:204:5 | match s1 { ... } | +| main.rs:205:5:208:5 | match s2 { ... } | main.rs:193:51:209:1 | { ... } | +| main.rs:205:11:205:12 | s2 | main.rs:206:9:206:24 | C {...} | +| main.rs:205:11:205:12 | s2 | main.rs:207:9:207:24 | D {...} | +| main.rs:206:22:206:22 | [SSA] n | main.rs:206:34:206:34 | n | +| main.rs:206:22:206:22 | n | main.rs:206:22:206:22 | [SSA] n | +| main.rs:206:29:206:35 | sink(...) | main.rs:205:5:208:5 | match s2 { ... } | +| main.rs:207:22:207:22 | [SSA] n | main.rs:207:34:207:34 | n | +| main.rs:207:22:207:22 | n | main.rs:207:22:207:22 | [SSA] n | +| main.rs:207:29:207:35 | sink(...) | main.rs:205:5:208:5 | match s2 { ... } | +| main.rs:212:9:212:9 | [SSA] a | main.rs:213:5:213:5 | a | +| main.rs:212:9:212:9 | a | main.rs:212:9:212:9 | [SSA] a | +| main.rs:212:13:212:17 | { ... } | main.rs:212:9:212:9 | a | +| main.rs:212:15:212:15 | 0 | main.rs:212:13:212:17 | { ... } | +| main.rs:213:5:213:5 | a | main.rs:211:31:214:1 | { ... } | +| main.rs:216:22:216:22 | [SSA] b | main.rs:218:12:218:12 | b | +| main.rs:216:22:216:22 | b | main.rs:216:22:216:22 | [SSA] b | +| main.rs:216:22:216:28 | ...: bool | main.rs:216:22:216:22 | b | +| main.rs:217:9:217:9 | [SSA] a | main.rs:223:5:223:5 | a | +| main.rs:217:9:217:9 | a | main.rs:217:9:217:9 | [SSA] a | +| main.rs:217:13:222:5 | 'block: { ... } | main.rs:217:9:217:9 | a | +| main.rs:219:13:219:26 | break ''block 1 | main.rs:217:13:222:5 | 'block: { ... } | +| main.rs:219:26:219:26 | 1 | main.rs:219:13:219:26 | break ''block 1 | +| main.rs:221:9:221:9 | 2 | main.rs:217:13:222:5 | 'block: { ... } | +| main.rs:223:5:223:5 | a | main.rs:216:38:224:1 | { ... } | +| main.rs:226:22:226:22 | [SSA] b | main.rs:228:12:228:12 | b | +| main.rs:226:22:226:22 | b | main.rs:226:22:226:22 | [SSA] b | +| main.rs:226:22:226:28 | ...: bool | main.rs:226:22:226:22 | b | +| main.rs:227:9:227:9 | [SSA] a | main.rs:233:5:233:5 | a | +| main.rs:227:9:227:9 | a | main.rs:227:9:227:9 | [SSA] a | +| main.rs:227:13:232:5 | 'block: { ... } | main.rs:227:9:227:9 | a | +| main.rs:229:13:229:26 | break ''block 1 | main.rs:227:13:232:5 | 'block: { ... } | +| main.rs:229:26:229:26 | 1 | main.rs:229:13:229:26 | break ''block 1 | +| main.rs:231:9:231:22 | break ''block 2 | main.rs:227:13:232:5 | 'block: { ... } | +| main.rs:231:22:231:22 | 2 | main.rs:231:9:231:22 | break ''block 2 | +| main.rs:233:5:233:5 | a | main.rs:226:38:234:1 | { ... } | +storeStep +| main.rs:117:19:117:28 | source(...) | Some | main.rs:117:14:117:29 | Some(...) | +| main.rs:118:19:118:19 | 2 | Some | main.rs:118:14:118:20 | Some(...) | +| main.rs:135:29:135:38 | source(...) | A | main.rs:135:14:135:39 | ...::A(...) | +| main.rs:136:29:136:29 | 2 | B | main.rs:136:14:136:30 | ...::B(...) | +| main.rs:175:18:175:27 | source(...) | C | main.rs:174:14:176:5 | ...::C {...} | +| main.rs:177:41:177:41 | 2 | D | main.rs:177:14:177:43 | ...::D {...} | +| main.rs:240:27:240:27 | 0 | Some | main.rs:240:22:240:28 | Some(...) | +readStep +| main.rs:33:9:33:15 | TupleStructPat | Some | main.rs:33:14:33:14 | _ | +| main.rs:120:9:120:15 | TupleStructPat | Some | main.rs:120:14:120:14 | n | +| main.rs:124:9:124:15 | TupleStructPat | Some | main.rs:124:14:124:14 | n | +| main.rs:138:9:138:25 | TupleStructPat | A | main.rs:138:24:138:24 | n | +| main.rs:139:9:139:25 | TupleStructPat | B | main.rs:139:24:139:24 | n | +| main.rs:142:10:142:26 | TupleStructPat | A | main.rs:142:25:142:25 | n | +| main.rs:142:30:142:46 | TupleStructPat | B | main.rs:142:45:142:45 | n | +| main.rs:145:9:145:25 | TupleStructPat | A | main.rs:145:24:145:24 | n | +| main.rs:146:9:146:25 | TupleStructPat | B | main.rs:146:24:146:24 | n | +| main.rs:179:9:179:38 | ...::C {...} | C | main.rs:179:36:179:36 | n | +| main.rs:180:9:180:38 | ...::D {...} | D | main.rs:180:36:180:36 | n | +| main.rs:183:10:183:39 | ...::C {...} | C | main.rs:183:37:183:37 | n | +| main.rs:183:43:183:72 | ...::D {...} | D | main.rs:183:70:183:70 | n | +| main.rs:186:9:186:38 | ...::C {...} | C | main.rs:186:36:186:36 | n | +| main.rs:187:9:187:38 | ...::D {...} | D | main.rs:187:36:187:36 | n | diff --git a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql index 77147a50573a..8bbde28564ac 100644 --- a/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql +++ b/rust/ql/test/library-tests/dataflow/local/DataFlowStep.ql @@ -1,5 +1,8 @@ import codeql.rust.dataflow.DataFlow +import codeql.rust.dataflow.internal.DataFlowImpl -from DataFlow::Node pred, DataFlow::Node succ -where DataFlow::localFlowStep(pred, succ) -select pred, succ +query predicate localStep = DataFlow::localFlowStep/2; + +query predicate storeStep = RustDataFlow::storeStep/3; + +query predicate readStep = RustDataFlow::readStep/3; diff --git a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected index 72273334c6f5..bfafa38c3ff3 100644 --- a/rust/ql/test/library-tests/dataflow/local/inline-flow.expected +++ b/rust/ql/test/library-tests/dataflow/local/inline-flow.expected @@ -1,24 +1,72 @@ models edges -| main.rs:19:13:19:21 | CallExpr : unit | main.rs:20:10:20:10 | s | provenance | | -| main.rs:24:13:24:21 | CallExpr : unit | main.rs:27:10:27:10 | c | provenance | | -| main.rs:31:13:31:21 | CallExpr : unit | main.rs:36:10:36:10 | b | provenance | | -| main.rs:45:15:45:23 | CallExpr : unit | main.rs:47:10:47:10 | b | provenance | | +| main.rs:19:13:19:21 | source(...) | main.rs:20:10:20:10 | s | provenance | | +| main.rs:24:13:24:21 | source(...) | main.rs:27:10:27:10 | c | provenance | | +| main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | provenance | | +| main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | provenance | | +| main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | provenance | | +| main.rs:117:14:117:29 | Some(...) [Some] | main.rs:120:9:120:15 | TupleStructPat [Some] | provenance | | +| main.rs:117:19:117:28 | source(...) | main.rs:117:14:117:29 | Some(...) [Some] | provenance | | +| main.rs:120:9:120:15 | TupleStructPat [Some] | main.rs:120:14:120:14 | n | provenance | | +| main.rs:120:14:120:14 | n | main.rs:120:25:120:25 | n | provenance | | +| main.rs:135:14:135:39 | ...::A(...) [A] | main.rs:138:9:138:25 | TupleStructPat [A] | provenance | | +| main.rs:135:14:135:39 | ...::A(...) [A] | main.rs:142:10:142:26 | TupleStructPat [A] | provenance | | +| main.rs:135:29:135:38 | source(...) | main.rs:135:14:135:39 | ...::A(...) [A] | provenance | | +| main.rs:138:9:138:25 | TupleStructPat [A] | main.rs:138:24:138:24 | n | provenance | | +| main.rs:138:24:138:24 | n | main.rs:138:35:138:35 | n | provenance | | +| main.rs:142:10:142:26 | TupleStructPat [A] | main.rs:142:25:142:25 | n | provenance | | +| main.rs:142:25:142:25 | n | main.rs:142:57:142:57 | n | provenance | | +| main.rs:174:14:176:5 | ...::C {...} [C] | main.rs:179:9:179:38 | ...::C {...} [C] | provenance | | +| main.rs:174:14:176:5 | ...::C {...} [C] | main.rs:183:10:183:39 | ...::C {...} [C] | provenance | | +| main.rs:175:18:175:27 | source(...) | main.rs:174:14:176:5 | ...::C {...} [C] | provenance | | +| main.rs:179:9:179:38 | ...::C {...} [C] | main.rs:179:36:179:36 | n | provenance | | +| main.rs:179:36:179:36 | n | main.rs:179:48:179:48 | n | provenance | | +| main.rs:183:10:183:39 | ...::C {...} [C] | main.rs:183:37:183:37 | n | provenance | | +| main.rs:183:37:183:37 | n | main.rs:183:83:183:83 | n | provenance | | nodes -| main.rs:15:10:15:18 | CallExpr | semmle.label | CallExpr | -| main.rs:19:13:19:21 | CallExpr : unit | semmle.label | CallExpr : unit | +| main.rs:15:10:15:18 | source(...) | semmle.label | source(...) | +| main.rs:19:13:19:21 | source(...) | semmle.label | source(...) | | main.rs:20:10:20:10 | s | semmle.label | s | -| main.rs:24:13:24:21 | CallExpr : unit | semmle.label | CallExpr : unit | +| main.rs:24:13:24:21 | source(...) | semmle.label | source(...) | | main.rs:27:10:27:10 | c | semmle.label | c | -| main.rs:31:13:31:21 | CallExpr : unit | semmle.label | CallExpr : unit | +| main.rs:31:13:31:21 | source(...) | semmle.label | source(...) | | main.rs:36:10:36:10 | b | semmle.label | b | -| main.rs:45:15:45:23 | CallExpr : unit | semmle.label | CallExpr : unit | +| main.rs:45:15:45:23 | source(...) | semmle.label | source(...) | | main.rs:47:10:47:10 | b | semmle.label | b | +| main.rs:53:9:53:17 | source(...) | semmle.label | source(...) | +| main.rs:54:10:54:10 | i | semmle.label | i | +| main.rs:117:14:117:29 | Some(...) [Some] | semmle.label | Some(...) [Some] | +| main.rs:117:19:117:28 | source(...) | semmle.label | source(...) | +| main.rs:120:9:120:15 | TupleStructPat [Some] | semmle.label | TupleStructPat [Some] | +| main.rs:120:14:120:14 | n | semmle.label | n | +| main.rs:120:25:120:25 | n | semmle.label | n | +| main.rs:135:14:135:39 | ...::A(...) [A] | semmle.label | ...::A(...) [A] | +| main.rs:135:29:135:38 | source(...) | semmle.label | source(...) | +| main.rs:138:9:138:25 | TupleStructPat [A] | semmle.label | TupleStructPat [A] | +| main.rs:138:24:138:24 | n | semmle.label | n | +| main.rs:138:35:138:35 | n | semmle.label | n | +| main.rs:142:10:142:26 | TupleStructPat [A] | semmle.label | TupleStructPat [A] | +| main.rs:142:25:142:25 | n | semmle.label | n | +| main.rs:142:57:142:57 | n | semmle.label | n | +| main.rs:174:14:176:5 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:175:18:175:27 | source(...) | semmle.label | source(...) | +| main.rs:179:9:179:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:179:36:179:36 | n | semmle.label | n | +| main.rs:179:48:179:48 | n | semmle.label | n | +| main.rs:183:10:183:39 | ...::C {...} [C] | semmle.label | ...::C {...} [C] | +| main.rs:183:37:183:37 | n | semmle.label | n | +| main.rs:183:83:183:83 | n | semmle.label | n | subpaths testFailures #select -| main.rs:15:10:15:18 | CallExpr | main.rs:15:10:15:18 | CallExpr | main.rs:15:10:15:18 | CallExpr | $@ | main.rs:15:10:15:18 | CallExpr | CallExpr | -| main.rs:20:10:20:10 | s | main.rs:19:13:19:21 | CallExpr : unit | main.rs:20:10:20:10 | s | $@ | main.rs:19:13:19:21 | CallExpr : unit | CallExpr : unit | -| main.rs:27:10:27:10 | c | main.rs:24:13:24:21 | CallExpr : unit | main.rs:27:10:27:10 | c | $@ | main.rs:24:13:24:21 | CallExpr : unit | CallExpr : unit | -| main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | CallExpr : unit | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | CallExpr : unit | CallExpr : unit | -| main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | CallExpr : unit | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | CallExpr : unit | CallExpr : unit | +| main.rs:15:10:15:18 | source(...) | main.rs:15:10:15:18 | source(...) | main.rs:15:10:15:18 | source(...) | $@ | main.rs:15:10:15:18 | source(...) | source(...) | +| main.rs:20:10:20:10 | s | main.rs:19:13:19:21 | source(...) | main.rs:20:10:20:10 | s | $@ | main.rs:19:13:19:21 | source(...) | source(...) | +| main.rs:27:10:27:10 | c | main.rs:24:13:24:21 | source(...) | main.rs:27:10:27:10 | c | $@ | main.rs:24:13:24:21 | source(...) | source(...) | +| main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | source(...) | source(...) | +| main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | source(...) | source(...) | +| main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | source(...) | source(...) | +| main.rs:120:25:120:25 | n | main.rs:117:19:117:28 | source(...) | main.rs:120:25:120:25 | n | $@ | main.rs:117:19:117:28 | source(...) | source(...) | +| main.rs:138:35:138:35 | n | main.rs:135:29:135:38 | source(...) | main.rs:138:35:138:35 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) | +| main.rs:142:57:142:57 | n | main.rs:135:29:135:38 | source(...) | main.rs:142:57:142:57 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) | +| main.rs:179:48:179:48 | n | main.rs:175:18:175:27 | source(...) | main.rs:179:48:179:48 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) | +| main.rs:183:83:183:83 | n | main.rs:175:18:175:27 | source(...) | main.rs:183:83:183:83 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) | diff --git a/rust/ql/test/library-tests/dataflow/local/main.rs b/rust/ql/test/library-tests/dataflow/local/main.rs index fb79baa70bdb..9a9e6b467e0e 100644 --- a/rust/ql/test/library-tests/dataflow/local/main.rs +++ b/rust/ql/test/library-tests/dataflow/local/main.rs @@ -16,24 +16,24 @@ fn direct() { } fn variable_usage() { - let s = source(1); - sink(s); // $ hasValueFlow=1 + let s = source(2); + sink(s); // $ hasValueFlow=2 } fn if_expression(cond: bool) { - let a = source(1); + let a = source(3); let b = 2; let c = if cond { a } else { b }; - sink(c); // $ hasValueFlow=1 + sink(c); // $ hasValueFlow=3 } fn match_expression(m: Option) { - let a = source(1); + let a = source(4); let b = match m { Some(_) => a, None => 0, }; - sink(b); // $ hasValueFlow=1 + sink(b); // $ hasValueFlow=4 } fn loop_with_break() { @@ -42,29 +42,29 @@ fn loop_with_break() { }; sink(a); let b = loop { - break source(1); + break source(5); }; - sink(b); // $ hasValueFlow=1 + sink(b); // $ hasValueFlow=5 } fn assignment() { let mut i = 1; sink(i); - i = source(2); - sink(i); // $ MISSING: hasValueFlow=2 + i = source(6); + sink(i); // $ hasValueFlow=6 } // ----------------------------------------------------------------------------- // Data flow through data structures by writing and reading fn box_deref() { - let i = Box::new(source(1)); - sink(*i); // $ MISSING: hasValueFlow=1 + let i = Box::new(source(7)); + sink(*i); // $ MISSING: hasValueFlow=7 } fn tuple() { - let a = (source(1), 2); - sink(a.0); // $ MISSING: hasValueFlow=1 + let a = (source(8), 2); + sink(a.0); // $ MISSING: hasValueFlow=8 sink(a.1); } @@ -76,13 +76,13 @@ struct Point { fn struct_field() { let p = Point { - x: source(1), + x: source(9), y: 2, - z: source(3), + z: source(10), }; - sink(p.x); // MISSING: hasValueFlow=1 + sink(p.x); // $ MISSING: hasValueFlow=9 sink(p.y); - sink(p.z); // MISSING: hasValueFlow=3 + sink(p.z); // $ MISSING: hasValueFlow=10 } // ----------------------------------------------------------------------------- @@ -90,21 +90,34 @@ fn struct_field() { fn struct_pattern_match() { let p = Point { - x: source(1), + x: source(11), y: 2, - z: source(3), + z: source(12), }; let Point { x: a, y: b, z: c } = p; - sink(a); // MISSING: hasValueFlow=1 + sink(a); // $ MISSING: hasValueFlow=11 sink(b); - sink(c); // MISSING: hasValueFlow=3 + sink(c); // $ MISSING: hasValueFlow=12 } -fn option_pattern_match() { - let s1 = Some(source(1)); +fn option_pattern_match_qualified() { + let s1 = Option::Some(source(13)); + let s2 = Option::Some(2); + match s1 { + Option::Some(n) => sink(n), // $ MISSING: hasValueFlow=13 + Option::None => sink(0), + } + match s2 { + Option::Some(n) => sink(n), + Option::None => sink(0), + } +} + +fn option_pattern_match_unqualified() { + let s1 = Some(source(14)); let s2 = Some(2); match s1 { - Some(n) => sink(n), // MISSING: hasValueFlow=3 + Some(n) => sink(n), // $ hasValueFlow=14 None => sink(0), } match s2 { @@ -113,6 +126,113 @@ fn option_pattern_match() { } } +enum MyTupleEnum { + A(i64), + B(i64), +} + +fn custom_tuple_enum_pattern_match_qualified() { + let s1 = MyTupleEnum::A(source(15)); + let s2 = MyTupleEnum::B(2); + match s1 { + MyTupleEnum::A(n) => sink(n), // $ hasValueFlow=15 + MyTupleEnum::B(n) => sink(n), + } + match s1 { + (MyTupleEnum::A(n) | MyTupleEnum::B(n)) => sink(n), // $ hasValueFlow=15 + } + match s2 { + MyTupleEnum::A(n) => sink(n), + MyTupleEnum::B(n) => sink(n), + } +} + +use crate::MyTupleEnum::*; + +fn custom_tuple_enum_pattern_match_unqualified() { + let s1 = A(source(16)); + let s2 = B(2); + match s1 { + A(n) => sink(n), // $ MISSING: hasValueFlow=16 + B(n) => sink(n), + } + match s1 { + (A(n) | B(n)) => sink(n), // $ MISSING: hasValueFlow=16 + } + match s2 { + A(n) => sink(n), + B(n) => sink(n), + } +} + +enum MyRecordEnum { + C { field_c: i64 }, + D { field_d: i64 }, +} + +fn custom_record_enum_pattern_match_qualified() { + let s1 = MyRecordEnum::C { + field_c: source(17), + }; + let s2 = MyRecordEnum::D { field_d: 2 }; + match s1 { + MyRecordEnum::C { field_c: n } => sink(n), // $ hasValueFlow=17 + MyRecordEnum::D { field_d: n } => sink(n), + } + match s1 { + (MyRecordEnum::C { field_c: n } | MyRecordEnum::D { field_d: n }) => sink(n), // $ hasValueFlow=17 + } + match s2 { + MyRecordEnum::C { field_c: n } => sink(n), + MyRecordEnum::D { field_d: n } => sink(n), + } +} + +use crate::MyRecordEnum::*; + +fn custom_record_enum_pattern_match_unqualified() { + let s1 = C { + field_c: source(18), + }; + let s2 = D { field_d: 2 }; + match s1 { + C { field_c: n } => sink(n), // $ MISSING: hasValueFlow=18 + D { field_d: n } => sink(n), + } + match s1 { + (C { field_c: n } | D { field_d: n }) => sink(n), // $ MISSING: hasValueFlow=18 + } + match s2 { + C { field_c: n } => sink(n), + D { field_d: n } => sink(n), + } +} + +fn block_expression1() -> i64 { + let a = { 0 }; + a +} + +fn block_expression2(b: bool) -> i64 { + let a = 'block: { + if b { + break 'block 1; + }; + 2 + }; + a +} + +fn block_expression3(b: bool) -> i64 { + let a = 'block: { + if b { + break 'block 1; + } + break 'block 2; + }; + a +} + fn main() { direct(); variable_usage(); @@ -124,5 +244,13 @@ fn main() { tuple(); struct_field(); struct_pattern_match(); - option_pattern_match(); + option_pattern_match_qualified(); + option_pattern_match_unqualified(); + custom_tuple_enum_pattern_match_qualified(); + custom_tuple_enum_pattern_match_unqualified(); + custom_record_enum_pattern_match_qualified(); + custom_record_enum_pattern_match_unqualified(); + block_expression1(); + block_expression2(true); + block_expression3(true); } diff --git a/rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getGenericArgList.expected b/rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected similarity index 100% rename from rust/ql/test/extractor-tests/generated/PathSegment/PathSegment_getGenericArgList.expected rename to rust/ql/test/library-tests/dataflow/sources/InlineFlow.expected diff --git a/rust/ql/test/library-tests/dataflow/sources/InlineFlow.ql b/rust/ql/test/library-tests/dataflow/sources/InlineFlow.ql new file mode 100644 index 000000000000..2b08aeea63f5 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/InlineFlow.ql @@ -0,0 +1,21 @@ +import rust +import codeql.rust.dataflow.DataFlow +import codeql.rust.Concepts +import utils.InlineFlowTest + +/** + * Configuration for flow from any threat model source to an argument of the function `sink`. + */ +module MyFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof ThreatModelSource } + + predicate isSink(DataFlow::Node sink) { + any(CallExpr call | + call.getFunction().(PathExpr).getPath().getResolvedPath() = "crate::test::sink" + ).getArgList().getAnArg() = sink.asExpr().getExpr() + } +} + +module MyFlowTest = TaintFlowTest; + +import MyFlowTest diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected new file mode 100644 index 000000000000..cebbc00f3a5e --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.expected @@ -0,0 +1,17 @@ +| test.rs:8:10:8:30 | ...::var(...) | Flow source 'EnvironmentSource' of type environment. | +| test.rs:9:10:9:33 | ...::var_os(...) | Flow source 'EnvironmentSource' of type environment. | +| test.rs:11:16:11:36 | ...::var(...) | Flow source 'EnvironmentSource' of type environment. | +| test.rs:12:16:12:39 | ...::var_os(...) | Flow source 'EnvironmentSource' of type environment. | +| test.rs:17:25:17:40 | ...::vars(...) | Flow source 'EnvironmentSource' of type environment. | +| test.rs:22:25:22:43 | ...::vars_os(...) | Flow source 'EnvironmentSource' of type environment. | +| test.rs:29:29:29:44 | ...::args(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:32:16:32:31 | ...::args(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:33:16:33:34 | ...::args_os(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:40:16:40:31 | ...::args(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:44:16:44:34 | ...::args_os(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:50:15:50:37 | ...::current_dir(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:51:15:51:37 | ...::current_exe(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:52:16:52:35 | ...::home_dir(...) | Flow source 'CommandLineArgs' of type commandargs. | +| test.rs:60:26:60:70 | ...::get(...) | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:63:26:63:70 | ...::get(...) | Flow source 'RemoteSource' of type remote (DEFAULT). | +| test.rs:66:26:66:60 | ...::get(...) | Flow source 'RemoteSource' of type remote (DEFAULT). | diff --git a/rust/ql/test/library-tests/dataflow/sources/TaintSources.qlref b/rust/ql/test/library-tests/dataflow/sources/TaintSources.qlref new file mode 100644 index 000000000000..3f6de4d0e4e3 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/TaintSources.qlref @@ -0,0 +1,2 @@ +query: queries/summary/TaintSources.ql +postprocess: utils/InlineExpectationsTestQuery.ql diff --git a/rust/ql/test/library-tests/dataflow/sources/options.yml b/rust/ql/test/library-tests/dataflow/sources/options.yml new file mode 100644 index 000000000000..3885768c7fa9 --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/options.yml @@ -0,0 +1,3 @@ +qltest_cargo_check: true +qltest_dependencies: + - reqwest = { version = "0.12.9", features = ["blocking"] } diff --git a/rust/ql/test/library-tests/dataflow/sources/reqwest.rs b/rust/ql/test/library-tests/dataflow/sources/reqwest.rs new file mode 100644 index 000000000000..3e8f5ef8510a --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/reqwest.rs @@ -0,0 +1,36 @@ + +// --- stubs for the "reqwest" library --- + +/* + --- we don't seem to have a way to use this, hence we currently test against the real reqwest library +#[derive(Debug)] +pub struct Error { } + +pub mod blocking { + pub struct Response { } + impl Response { + pub fn text(self) -> Result { + Ok("".to_string()) + } + } + + pub fn get(url: T) -> Result { + let _url = url; + + Ok(Response {}) + } +} + +pub struct Response { } +impl Response { + pub async fn text(self) -> Result { + Ok("".to_string()) + } +} + +pub async fn get(url: T) -> Result { + let _url = url; + + Ok(Response {}) +} +*/ diff --git a/rust/ql/test/library-tests/dataflow/sources/test.rs b/rust/ql/test/library-tests/dataflow/sources/test.rs new file mode 100644 index 000000000000..e4701865a7ea --- /dev/null +++ b/rust/ql/test/library-tests/dataflow/sources/test.rs @@ -0,0 +1,70 @@ +#![allow(deprecated)] + +fn sink(_: T) { } + +// --- tests --- + +fn test_env_vars() { + sink(std::env::var("HOME")); // $ Alert[rust/summary/taint-sources] hasTaintFlow + sink(std::env::var_os("PATH")); // $ Alert[rust/summary/taint-sources] hasTaintFlow + + let var1 = std::env::var("HOME").expect("HOME not set"); // $ Alert[rust/summary/taint-sources] + let var2 = std::env::var_os("PATH").unwrap(); // $ Alert[rust/summary/taint-sources] + + sink(var1); // $ MISSING: hasTaintFlow + sink(var2); // $ MISSING: hasTaintFlow + + for (key, value) in std::env::vars() { // $ Alert[rust/summary/taint-sources] + sink(key); // $ MISSING: hasTaintFlow + sink(value); // $ MISSING: hasTaintFlow + } + + for (key, value) in std::env::vars_os() { // $ Alert[rust/summary/taint-sources] + sink(key); // $ MISSING: hasTaintFlow + sink(value); // $ MISSING: hasTaintFlow + } +} + +fn test_env_args() { + let args: Vec = std::env::args().collect(); // $ Alert[rust/summary/taint-sources] + let my_path = &args[0]; + let arg1 = &args[1]; + let arg2 = std::env::args().nth(2).unwrap(); // $ Alert[rust/summary/taint-sources] + let arg3 = std::env::args_os().nth(3).unwrap(); // $ Alert[rust/summary/taint-sources] + + sink(my_path); // $ MISSING: hasTaintFlow + sink(arg1); // $ MISSING: hasTaintFlow + sink(arg2); // $ MISSING: hasTaintFlow + sink(arg3); // $ MISSING: hasTaintFlow + + for arg in std::env::args() { // $ Alert[rust/summary/taint-sources] + sink(arg); // $ MISSING: hasTaintFlow + } + + for arg in std::env::args_os() { // $ Alert[rust/summary/taint-sources] + sink(arg); // $ MISSING: hasTaintFlow + } +} + +fn test_env_dirs() { + let dir = std::env::current_dir().expect("FAILED"); // $ Alert[rust/summary/taint-sources] + let exe = std::env::current_exe().expect("FAILED"); // $ Alert[rust/summary/taint-sources] + let home = std::env::home_dir().expect("FAILED"); // $ Alert[rust/summary/taint-sources] + + sink(dir); // $ MISSING: hasTaintFlow + sink(exe); // $ MISSING: hasTaintFlow + sink(home); // $ MISSING: hasTaintFlow +} + +async fn test_reqwest() -> Result<(), reqwest::Error> { + let remote_string1 = reqwest::blocking::get("http://example.com/")?.text()?; // $ Alert[rust/summary/taint-sources] + sink(remote_string1); // $ MISSING: hasTaintFlow + + let remote_string2 = reqwest::blocking::get("http://example.com/").unwrap().text().unwrap(); // $ Alert[rust/summary/taint-sources] + sink(remote_string2); // $ MISSING: hasTaintFlow + + let remote_string3 = reqwest::get("http://example.com/").await?.text().await?; // $ Alert[rust/summary/taint-sources] + sink(remote_string3); // $ MISSING: hasTaintFlow + + Ok(()) +} diff --git a/rust/ql/test/library-tests/definitions/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/library-tests/definitions/CONSISTENCY/DataFlowConsistency.expected deleted file mode 100644 index 8d729bb5fd93..000000000000 --- a/rust/ql/test/library-tests/definitions/CONSISTENCY/DataFlowConsistency.expected +++ /dev/null @@ -1,4 +0,0 @@ -uniqueEnclosingCallable -| main.rs:5:29:5:33 | width | Node should have one enclosing callable but has 0. | -| main.rs:5:36:5:44 | precision | Node should have one enclosing callable but has 0. | -| main.rs:9:22:9:27 | people | Node should have one enclosing callable but has 0. | diff --git a/rust/ql/test/library-tests/formatstrings/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/library-tests/formatstrings/CONSISTENCY/DataFlowConsistency.expected deleted file mode 100644 index 5bd870a72056..000000000000 --- a/rust/ql/test/library-tests/formatstrings/CONSISTENCY/DataFlowConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -uniqueEnclosingCallable -| main.rs:5:29:5:33 | width | Node should have one enclosing callable but has 0. | -| main.rs:5:36:5:44 | precision | Node should have one enclosing callable but has 0. | -| main.rs:16:22:16:27 | people | Node should have one enclosing callable but has 0. | -| main.rs:27:23:27:27 | width | Node should have one enclosing callable but has 0. | diff --git a/rust/ql/test/library-tests/variables/Cfg.expected b/rust/ql/test/library-tests/variables/Cfg.expected index 3ff46aa9f7ec..6b979eac0da2 100644 --- a/rust/ql/test/library-tests/variables/Cfg.expected +++ b/rust/ql/test/library-tests/variables/Cfg.expected @@ -1,292 +1,292 @@ edges -| variables.rs:3:1:5:1 | enter print_str | variables.rs:3:14:3:14 | s | | -| variables.rs:3:1:5:1 | exit print_str (normal) | variables.rs:3:1:5:1 | exit print_str | | -| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:20 | Param | match | -| variables.rs:3:14:3:20 | Param | variables.rs:4:5:4:22 | ExprStmt | | -| variables.rs:3:23:5:1 | BlockExpr | variables.rs:3:1:5:1 | exit print_str (normal) | | -| variables.rs:4:5:4:21 | $crate::io::_print | variables.rs:4:14:4:17 | "{}\\n" | | -| variables.rs:4:5:4:21 | MacroExpr | variables.rs:3:23:5:1 | BlockExpr | | +| variables.rs:3:1:5:1 | enter fn print_str | variables.rs:3:14:3:14 | s | | +| variables.rs:3:1:5:1 | exit fn print_str (normal) | variables.rs:3:1:5:1 | exit fn print_str | | +| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:20 | ...: ... | match | +| variables.rs:3:14:3:20 | ...: ... | variables.rs:4:5:4:22 | ExprStmt | | +| variables.rs:3:23:5:1 | { ... } | variables.rs:3:1:5:1 | exit fn print_str (normal) | | +| variables.rs:4:5:4:21 | ...::_print | variables.rs:4:14:4:17 | "{}\\n" | | +| variables.rs:4:5:4:21 | MacroExpr | variables.rs:3:23:5:1 | { ... } | | | variables.rs:4:5:4:22 | ExprStmt | variables.rs:4:14:4:20 | MacroStmts | | | variables.rs:4:14:4:17 | "{}\\n" | variables.rs:4:20:4:20 | s | | -| variables.rs:4:14:4:20 | BlockExpr | variables.rs:4:5:4:21 | MacroExpr | | -| variables.rs:4:14:4:20 | CallExpr | variables.rs:4:14:4:20 | BlockExpr | | -| variables.rs:4:14:4:20 | ExprStmt | variables.rs:4:5:4:21 | $crate::io::_print | | +| variables.rs:4:14:4:20 | ...::_print(...) | variables.rs:4:14:4:20 | { ... } | | +| variables.rs:4:14:4:20 | ExprStmt | variables.rs:4:5:4:21 | ...::_print | | | variables.rs:4:14:4:20 | FormatArgsExpr | variables.rs:4:14:4:20 | MacroExpr | | -| variables.rs:4:14:4:20 | MacroExpr | variables.rs:4:14:4:20 | CallExpr | | +| variables.rs:4:14:4:20 | MacroExpr | variables.rs:4:14:4:20 | ...::_print(...) | | | variables.rs:4:14:4:20 | MacroStmts | variables.rs:4:14:4:20 | ExprStmt | | +| variables.rs:4:14:4:20 | { ... } | variables.rs:4:5:4:21 | MacroExpr | | | variables.rs:4:20:4:20 | s | variables.rs:4:14:4:20 | FormatArgsExpr | | -| variables.rs:7:1:9:1 | enter print_i64 | variables.rs:7:14:7:14 | i | | -| variables.rs:7:1:9:1 | exit print_i64 (normal) | variables.rs:7:1:9:1 | exit print_i64 | | -| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:19 | Param | match | -| variables.rs:7:14:7:19 | Param | variables.rs:8:5:8:22 | ExprStmt | | -| variables.rs:7:22:9:1 | BlockExpr | variables.rs:7:1:9:1 | exit print_i64 (normal) | | -| variables.rs:8:5:8:21 | $crate::io::_print | variables.rs:8:14:8:17 | "{}\\n" | | -| variables.rs:8:5:8:21 | MacroExpr | variables.rs:7:22:9:1 | BlockExpr | | +| variables.rs:7:1:9:1 | enter fn print_i64 | variables.rs:7:14:7:14 | i | | +| variables.rs:7:1:9:1 | exit fn print_i64 (normal) | variables.rs:7:1:9:1 | exit fn print_i64 | | +| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:19 | ...: i64 | match | +| variables.rs:7:14:7:19 | ...: i64 | variables.rs:8:5:8:22 | ExprStmt | | +| variables.rs:7:22:9:1 | { ... } | variables.rs:7:1:9:1 | exit fn print_i64 (normal) | | +| variables.rs:8:5:8:21 | ...::_print | variables.rs:8:14:8:17 | "{}\\n" | | +| variables.rs:8:5:8:21 | MacroExpr | variables.rs:7:22:9:1 | { ... } | | | variables.rs:8:5:8:22 | ExprStmt | variables.rs:8:14:8:20 | MacroStmts | | | variables.rs:8:14:8:17 | "{}\\n" | variables.rs:8:20:8:20 | i | | -| variables.rs:8:14:8:20 | BlockExpr | variables.rs:8:5:8:21 | MacroExpr | | -| variables.rs:8:14:8:20 | CallExpr | variables.rs:8:14:8:20 | BlockExpr | | -| variables.rs:8:14:8:20 | ExprStmt | variables.rs:8:5:8:21 | $crate::io::_print | | +| variables.rs:8:14:8:20 | ...::_print(...) | variables.rs:8:14:8:20 | { ... } | | +| variables.rs:8:14:8:20 | ExprStmt | variables.rs:8:5:8:21 | ...::_print | | | variables.rs:8:14:8:20 | FormatArgsExpr | variables.rs:8:14:8:20 | MacroExpr | | -| variables.rs:8:14:8:20 | MacroExpr | variables.rs:8:14:8:20 | CallExpr | | +| variables.rs:8:14:8:20 | MacroExpr | variables.rs:8:14:8:20 | ...::_print(...) | | | variables.rs:8:14:8:20 | MacroStmts | variables.rs:8:14:8:20 | ExprStmt | | +| variables.rs:8:14:8:20 | { ... } | variables.rs:8:5:8:21 | MacroExpr | | | variables.rs:8:20:8:20 | i | variables.rs:8:14:8:20 | FormatArgsExpr | | -| variables.rs:11:1:13:1 | enter print_i64_ref | variables.rs:11:18:11:18 | i | | -| variables.rs:11:1:13:1 | exit print_i64_ref (normal) | variables.rs:11:1:13:1 | exit print_i64_ref | | -| variables.rs:11:18:11:18 | i | variables.rs:11:18:11:24 | Param | match | -| variables.rs:11:18:11:24 | Param | variables.rs:12:5:12:13 | print_i64 | | -| variables.rs:11:27:13:1 | BlockExpr | variables.rs:11:1:13:1 | exit print_i64_ref (normal) | | +| variables.rs:11:1:13:1 | enter fn print_i64_ref | variables.rs:11:18:11:18 | i | | +| variables.rs:11:1:13:1 | exit fn print_i64_ref (normal) | variables.rs:11:1:13:1 | exit fn print_i64_ref | | +| variables.rs:11:18:11:18 | i | variables.rs:11:18:11:24 | ...: ... | match | +| variables.rs:11:18:11:24 | ...: ... | variables.rs:12:5:12:13 | print_i64 | | +| variables.rs:11:27:13:1 | { ... } | variables.rs:11:1:13:1 | exit fn print_i64_ref (normal) | | | variables.rs:12:5:12:13 | print_i64 | variables.rs:12:16:12:16 | i | | -| variables.rs:12:5:12:17 | CallExpr | variables.rs:11:27:13:1 | BlockExpr | | -| variables.rs:12:15:12:16 | * ... | variables.rs:12:5:12:17 | CallExpr | | +| variables.rs:12:5:12:17 | print_i64(...) | variables.rs:11:27:13:1 | { ... } | | +| variables.rs:12:15:12:16 | * ... | variables.rs:12:5:12:17 | print_i64(...) | | | variables.rs:12:16:12:16 | i | variables.rs:12:15:12:16 | * ... | | -| variables.rs:15:1:18:1 | enter immutable_variable | variables.rs:16:5:16:17 | LetStmt | | -| variables.rs:15:1:18:1 | exit immutable_variable (normal) | variables.rs:15:1:18:1 | exit immutable_variable | | -| variables.rs:15:25:18:1 | BlockExpr | variables.rs:15:1:18:1 | exit immutable_variable (normal) | | -| variables.rs:16:5:16:17 | LetStmt | variables.rs:16:14:16:16 | "a" | | +| variables.rs:15:1:18:1 | enter fn immutable_variable | variables.rs:16:5:16:17 | let ... = "a" | | +| variables.rs:15:1:18:1 | exit fn immutable_variable (normal) | variables.rs:15:1:18:1 | exit fn immutable_variable | | +| variables.rs:15:25:18:1 | { ... } | variables.rs:15:1:18:1 | exit fn immutable_variable (normal) | | +| variables.rs:16:5:16:17 | let ... = "a" | variables.rs:16:14:16:16 | "a" | | | variables.rs:16:9:16:10 | x1 | variables.rs:17:5:17:18 | ExprStmt | match | | variables.rs:16:14:16:16 | "a" | variables.rs:16:9:16:10 | x1 | | | variables.rs:17:5:17:13 | print_str | variables.rs:17:15:17:16 | x1 | | -| variables.rs:17:5:17:17 | CallExpr | variables.rs:15:25:18:1 | BlockExpr | | +| variables.rs:17:5:17:17 | print_str(...) | variables.rs:15:25:18:1 | { ... } | | | variables.rs:17:5:17:18 | ExprStmt | variables.rs:17:5:17:13 | print_str | | -| variables.rs:17:15:17:16 | x1 | variables.rs:17:5:17:17 | CallExpr | | -| variables.rs:20:1:25:1 | enter mutable_variable | variables.rs:21:5:21:19 | LetStmt | | -| variables.rs:20:1:25:1 | exit mutable_variable (normal) | variables.rs:20:1:25:1 | exit mutable_variable | | -| variables.rs:20:23:25:1 | BlockExpr | variables.rs:20:1:25:1 | exit mutable_variable (normal) | | -| variables.rs:21:5:21:19 | LetStmt | variables.rs:21:18:21:18 | 4 | | +| variables.rs:17:15:17:16 | x1 | variables.rs:17:5:17:17 | print_str(...) | | +| variables.rs:20:1:25:1 | enter fn mutable_variable | variables.rs:21:5:21:19 | let ... = 4 | | +| variables.rs:20:1:25:1 | exit fn mutable_variable (normal) | variables.rs:20:1:25:1 | exit fn mutable_variable | | +| variables.rs:20:23:25:1 | { ... } | variables.rs:20:1:25:1 | exit fn mutable_variable (normal) | | +| variables.rs:21:5:21:19 | let ... = 4 | variables.rs:21:18:21:18 | 4 | | | variables.rs:21:9:21:14 | x2 | variables.rs:22:5:22:18 | ExprStmt | match | | variables.rs:21:18:21:18 | 4 | variables.rs:21:9:21:14 | x2 | | | variables.rs:22:5:22:13 | print_i64 | variables.rs:22:15:22:16 | x2 | | -| variables.rs:22:5:22:17 | CallExpr | variables.rs:23:5:23:11 | ExprStmt | | +| variables.rs:22:5:22:17 | print_i64(...) | variables.rs:23:5:23:11 | ExprStmt | | | variables.rs:22:5:22:18 | ExprStmt | variables.rs:22:5:22:13 | print_i64 | | -| variables.rs:22:15:22:16 | x2 | variables.rs:22:5:22:17 | CallExpr | | +| variables.rs:22:15:22:16 | x2 | variables.rs:22:5:22:17 | print_i64(...) | | | variables.rs:23:5:23:6 | x2 | variables.rs:23:10:23:10 | 5 | | | variables.rs:23:5:23:10 | ... = ... | variables.rs:24:5:24:18 | ExprStmt | | | variables.rs:23:5:23:11 | ExprStmt | variables.rs:23:5:23:6 | x2 | | | variables.rs:23:10:23:10 | 5 | variables.rs:23:5:23:10 | ... = ... | | | variables.rs:24:5:24:13 | print_i64 | variables.rs:24:15:24:16 | x2 | | -| variables.rs:24:5:24:17 | CallExpr | variables.rs:20:23:25:1 | BlockExpr | | +| variables.rs:24:5:24:17 | print_i64(...) | variables.rs:20:23:25:1 | { ... } | | | variables.rs:24:5:24:18 | ExprStmt | variables.rs:24:5:24:13 | print_i64 | | -| variables.rs:24:15:24:16 | x2 | variables.rs:24:5:24:17 | CallExpr | | -| variables.rs:27:1:32:1 | enter mutable_variable_immutable_borrow | variables.rs:28:5:28:18 | LetStmt | | -| variables.rs:27:1:32:1 | exit mutable_variable_immutable_borrow (normal) | variables.rs:27:1:32:1 | exit mutable_variable_immutable_borrow | | -| variables.rs:27:40:32:1 | BlockExpr | variables.rs:27:1:32:1 | exit mutable_variable_immutable_borrow (normal) | | -| variables.rs:28:5:28:18 | LetStmt | variables.rs:28:17:28:17 | 1 | | +| variables.rs:24:15:24:16 | x2 | variables.rs:24:5:24:17 | print_i64(...) | | +| variables.rs:27:1:32:1 | enter fn mutable_variable_immutable_borrow | variables.rs:28:5:28:18 | let ... = 1 | | +| variables.rs:27:1:32:1 | exit fn mutable_variable_immutable_borrow (normal) | variables.rs:27:1:32:1 | exit fn mutable_variable_immutable_borrow | | +| variables.rs:27:40:32:1 | { ... } | variables.rs:27:1:32:1 | exit fn mutable_variable_immutable_borrow (normal) | | +| variables.rs:28:5:28:18 | let ... = 1 | variables.rs:28:17:28:17 | 1 | | | variables.rs:28:9:28:13 | x | variables.rs:29:5:29:22 | ExprStmt | match | | variables.rs:28:17:28:17 | 1 | variables.rs:28:9:28:13 | x | | | variables.rs:29:5:29:17 | print_i64_ref | variables.rs:29:20:29:20 | x | | -| variables.rs:29:5:29:21 | CallExpr | variables.rs:30:5:30:10 | ExprStmt | | +| variables.rs:29:5:29:21 | print_i64_ref(...) | variables.rs:30:5:30:10 | ExprStmt | | | variables.rs:29:5:29:22 | ExprStmt | variables.rs:29:5:29:17 | print_i64_ref | | -| variables.rs:29:19:29:20 | RefExpr | variables.rs:29:5:29:21 | CallExpr | | -| variables.rs:29:20:29:20 | x | variables.rs:29:19:29:20 | RefExpr | | +| variables.rs:29:19:29:20 | &x | variables.rs:29:5:29:21 | print_i64_ref(...) | | +| variables.rs:29:20:29:20 | x | variables.rs:29:19:29:20 | &x | | | variables.rs:30:5:30:5 | x | variables.rs:30:9:30:9 | 2 | | | variables.rs:30:5:30:9 | ... = ... | variables.rs:31:5:31:22 | ExprStmt | | | variables.rs:30:5:30:10 | ExprStmt | variables.rs:30:5:30:5 | x | | | variables.rs:30:9:30:9 | 2 | variables.rs:30:5:30:9 | ... = ... | | | variables.rs:31:5:31:17 | print_i64_ref | variables.rs:31:20:31:20 | x | | -| variables.rs:31:5:31:21 | CallExpr | variables.rs:27:40:32:1 | BlockExpr | | +| variables.rs:31:5:31:21 | print_i64_ref(...) | variables.rs:27:40:32:1 | { ... } | | | variables.rs:31:5:31:22 | ExprStmt | variables.rs:31:5:31:17 | print_i64_ref | | -| variables.rs:31:19:31:20 | RefExpr | variables.rs:31:5:31:21 | CallExpr | | -| variables.rs:31:20:31:20 | x | variables.rs:31:19:31:20 | RefExpr | | -| variables.rs:34:1:40:1 | enter variable_shadow1 | variables.rs:35:5:35:15 | LetStmt | | -| variables.rs:34:1:40:1 | exit variable_shadow1 (normal) | variables.rs:34:1:40:1 | exit variable_shadow1 | | -| variables.rs:34:23:40:1 | BlockExpr | variables.rs:34:1:40:1 | exit variable_shadow1 (normal) | | -| variables.rs:35:5:35:15 | LetStmt | variables.rs:35:14:35:14 | 1 | | +| variables.rs:31:19:31:20 | &x | variables.rs:31:5:31:21 | print_i64_ref(...) | | +| variables.rs:31:20:31:20 | x | variables.rs:31:19:31:20 | &x | | +| variables.rs:34:1:40:1 | enter fn variable_shadow1 | variables.rs:35:5:35:15 | let ... = 1 | | +| variables.rs:34:1:40:1 | exit fn variable_shadow1 (normal) | variables.rs:34:1:40:1 | exit fn variable_shadow1 | | +| variables.rs:34:23:40:1 | { ... } | variables.rs:34:1:40:1 | exit fn variable_shadow1 (normal) | | +| variables.rs:35:5:35:15 | let ... = 1 | variables.rs:35:14:35:14 | 1 | | | variables.rs:35:9:35:10 | x3 | variables.rs:36:5:36:18 | ExprStmt | match | | variables.rs:35:14:35:14 | 1 | variables.rs:35:9:35:10 | x3 | | | variables.rs:36:5:36:13 | print_i64 | variables.rs:36:15:36:16 | x3 | | -| variables.rs:36:5:36:17 | CallExpr | variables.rs:37:5:38:15 | LetStmt | | +| variables.rs:36:5:36:17 | print_i64(...) | variables.rs:37:5:38:15 | let ... = ... | | | variables.rs:36:5:36:18 | ExprStmt | variables.rs:36:5:36:13 | print_i64 | | -| variables.rs:36:15:36:16 | x3 | variables.rs:36:5:36:17 | CallExpr | | -| variables.rs:37:5:38:15 | LetStmt | variables.rs:38:9:38:10 | x3 | | +| variables.rs:36:15:36:16 | x3 | variables.rs:36:5:36:17 | print_i64(...) | | +| variables.rs:37:5:38:15 | let ... = ... | variables.rs:38:9:38:10 | x3 | | | variables.rs:37:9:37:10 | x3 | variables.rs:39:5:39:18 | ExprStmt | match | | variables.rs:38:9:38:10 | x3 | variables.rs:38:14:38:14 | 1 | | | variables.rs:38:9:38:14 | ... + ... | variables.rs:37:9:37:10 | x3 | | | variables.rs:38:14:38:14 | 1 | variables.rs:38:9:38:14 | ... + ... | | | variables.rs:39:5:39:13 | print_i64 | variables.rs:39:15:39:16 | x3 | | -| variables.rs:39:5:39:17 | CallExpr | variables.rs:34:23:40:1 | BlockExpr | | +| variables.rs:39:5:39:17 | print_i64(...) | variables.rs:34:23:40:1 | { ... } | | | variables.rs:39:5:39:18 | ExprStmt | variables.rs:39:5:39:13 | print_i64 | | -| variables.rs:39:15:39:16 | x3 | variables.rs:39:5:39:17 | CallExpr | | -| variables.rs:42:1:50:1 | enter variable_shadow2 | variables.rs:43:5:43:17 | LetStmt | | -| variables.rs:42:1:50:1 | exit variable_shadow2 (normal) | variables.rs:42:1:50:1 | exit variable_shadow2 | | -| variables.rs:42:23:50:1 | BlockExpr | variables.rs:42:1:50:1 | exit variable_shadow2 (normal) | | -| variables.rs:43:5:43:17 | LetStmt | variables.rs:43:14:43:16 | "a" | | +| variables.rs:39:15:39:16 | x3 | variables.rs:39:5:39:17 | print_i64(...) | | +| variables.rs:42:1:50:1 | enter fn variable_shadow2 | variables.rs:43:5:43:17 | let ... = "a" | | +| variables.rs:42:1:50:1 | exit fn variable_shadow2 (normal) | variables.rs:42:1:50:1 | exit fn variable_shadow2 | | +| variables.rs:42:23:50:1 | { ... } | variables.rs:42:1:50:1 | exit fn variable_shadow2 (normal) | | +| variables.rs:43:5:43:17 | let ... = "a" | variables.rs:43:14:43:16 | "a" | | | variables.rs:43:9:43:10 | x4 | variables.rs:44:5:44:18 | ExprStmt | match | | variables.rs:43:14:43:16 | "a" | variables.rs:43:9:43:10 | x4 | | | variables.rs:44:5:44:13 | print_str | variables.rs:44:15:44:16 | x4 | | -| variables.rs:44:5:44:17 | CallExpr | variables.rs:45:5:48:5 | ExprStmt | | +| variables.rs:44:5:44:17 | print_str(...) | variables.rs:45:5:48:5 | ExprStmt | | | variables.rs:44:5:44:18 | ExprStmt | variables.rs:44:5:44:13 | print_str | | -| variables.rs:44:15:44:16 | x4 | variables.rs:44:5:44:17 | CallExpr | | -| variables.rs:45:5:48:5 | BlockExpr | variables.rs:49:5:49:18 | ExprStmt | | -| variables.rs:45:5:48:5 | ExprStmt | variables.rs:46:9:46:21 | LetStmt | | -| variables.rs:46:9:46:21 | LetStmt | variables.rs:46:18:46:20 | "b" | | +| variables.rs:44:15:44:16 | x4 | variables.rs:44:5:44:17 | print_str(...) | | +| variables.rs:45:5:48:5 | ExprStmt | variables.rs:46:9:46:21 | let ... = "b" | | +| variables.rs:45:5:48:5 | { ... } | variables.rs:49:5:49:18 | ExprStmt | | +| variables.rs:46:9:46:21 | let ... = "b" | variables.rs:46:18:46:20 | "b" | | | variables.rs:46:13:46:14 | x4 | variables.rs:47:9:47:22 | ExprStmt | match | | variables.rs:46:18:46:20 | "b" | variables.rs:46:13:46:14 | x4 | | | variables.rs:47:9:47:17 | print_str | variables.rs:47:19:47:20 | x4 | | -| variables.rs:47:9:47:21 | CallExpr | variables.rs:45:5:48:5 | BlockExpr | | +| variables.rs:47:9:47:21 | print_str(...) | variables.rs:45:5:48:5 | { ... } | | | variables.rs:47:9:47:22 | ExprStmt | variables.rs:47:9:47:17 | print_str | | -| variables.rs:47:19:47:20 | x4 | variables.rs:47:9:47:21 | CallExpr | | +| variables.rs:47:19:47:20 | x4 | variables.rs:47:9:47:21 | print_str(...) | | | variables.rs:49:5:49:13 | print_str | variables.rs:49:15:49:16 | x4 | | -| variables.rs:49:5:49:17 | CallExpr | variables.rs:42:23:50:1 | BlockExpr | | +| variables.rs:49:5:49:17 | print_str(...) | variables.rs:42:23:50:1 | { ... } | | | variables.rs:49:5:49:18 | ExprStmt | variables.rs:49:5:49:13 | print_str | | -| variables.rs:49:15:49:16 | x4 | variables.rs:49:5:49:17 | CallExpr | | -| variables.rs:57:1:72:1 | enter let_pattern1 | variables.rs:58:5:67:47 | LetStmt | | -| variables.rs:57:1:72:1 | exit let_pattern1 (normal) | variables.rs:57:1:72:1 | exit let_pattern1 | | -| variables.rs:57:19:72:1 | BlockExpr | variables.rs:57:1:72:1 | exit let_pattern1 (normal) | | -| variables.rs:58:5:67:47 | LetStmt | variables.rs:67:11:67:13 | "a" | | +| variables.rs:49:15:49:16 | x4 | variables.rs:49:5:49:17 | print_str(...) | | +| variables.rs:57:1:72:1 | enter fn let_pattern1 | variables.rs:58:5:67:47 | let ... = ... | | +| variables.rs:57:1:72:1 | exit fn let_pattern1 (normal) | variables.rs:57:1:72:1 | exit fn let_pattern1 | | +| variables.rs:57:19:72:1 | { ... } | variables.rs:57:1:72:1 | exit fn let_pattern1 (normal) | | +| variables.rs:58:5:67:47 | let ... = ... | variables.rs:67:11:67:13 | "a" | | | variables.rs:58:9:67:5 | TuplePat | variables.rs:59:9:62:9 | TuplePat | match | | variables.rs:59:9:62:9 | TuplePat | variables.rs:60:13:60:14 | a1 | match | | variables.rs:60:13:60:14 | a1 | variables.rs:61:13:61:14 | b1 | match | -| variables.rs:61:13:61:14 | b1 | variables.rs:63:9:66:9 | RecordPat | match | -| variables.rs:63:9:66:9 | RecordPat | variables.rs:64:13:64:13 | x | match | +| variables.rs:61:13:61:14 | b1 | variables.rs:63:9:66:9 | Point {...} | match | +| variables.rs:63:9:66:9 | Point {...} | variables.rs:64:13:64:13 | x | match | | variables.rs:64:13:64:13 | x | variables.rs:65:13:65:13 | y | match | | variables.rs:65:13:65:13 | y | variables.rs:68:5:68:18 | ExprStmt | match | | variables.rs:67:9:67:46 | TupleExpr | variables.rs:58:9:67:5 | TuplePat | | | variables.rs:67:10:67:19 | TupleExpr | variables.rs:67:33:67:35 | "x" | | | variables.rs:67:11:67:13 | "a" | variables.rs:67:16:67:18 | "b" | | | variables.rs:67:16:67:18 | "b" | variables.rs:67:10:67:19 | TupleExpr | | -| variables.rs:67:22:67:45 | RecordExpr | variables.rs:67:9:67:46 | TupleExpr | | +| variables.rs:67:22:67:45 | Point {...} | variables.rs:67:9:67:46 | TupleExpr | | | variables.rs:67:33:67:35 | "x" | variables.rs:67:41:67:43 | "y" | | -| variables.rs:67:41:67:43 | "y" | variables.rs:67:22:67:45 | RecordExpr | | +| variables.rs:67:41:67:43 | "y" | variables.rs:67:22:67:45 | Point {...} | | | variables.rs:68:5:68:13 | print_str | variables.rs:68:15:68:16 | a1 | | -| variables.rs:68:5:68:17 | CallExpr | variables.rs:69:5:69:18 | ExprStmt | | +| variables.rs:68:5:68:17 | print_str(...) | variables.rs:69:5:69:18 | ExprStmt | | | variables.rs:68:5:68:18 | ExprStmt | variables.rs:68:5:68:13 | print_str | | -| variables.rs:68:15:68:16 | a1 | variables.rs:68:5:68:17 | CallExpr | | +| variables.rs:68:15:68:16 | a1 | variables.rs:68:5:68:17 | print_str(...) | | | variables.rs:69:5:69:13 | print_str | variables.rs:69:15:69:16 | b1 | | -| variables.rs:69:5:69:17 | CallExpr | variables.rs:70:5:70:17 | ExprStmt | | +| variables.rs:69:5:69:17 | print_str(...) | variables.rs:70:5:70:17 | ExprStmt | | | variables.rs:69:5:69:18 | ExprStmt | variables.rs:69:5:69:13 | print_str | | -| variables.rs:69:15:69:16 | b1 | variables.rs:69:5:69:17 | CallExpr | | +| variables.rs:69:15:69:16 | b1 | variables.rs:69:5:69:17 | print_str(...) | | | variables.rs:70:5:70:13 | print_str | variables.rs:70:15:70:15 | x | | -| variables.rs:70:5:70:16 | CallExpr | variables.rs:71:5:71:17 | ExprStmt | | +| variables.rs:70:5:70:16 | print_str(...) | variables.rs:71:5:71:17 | ExprStmt | | | variables.rs:70:5:70:17 | ExprStmt | variables.rs:70:5:70:13 | print_str | | -| variables.rs:70:15:70:15 | x | variables.rs:70:5:70:16 | CallExpr | | +| variables.rs:70:15:70:15 | x | variables.rs:70:5:70:16 | print_str(...) | | | variables.rs:71:5:71:13 | print_str | variables.rs:71:15:71:15 | y | | -| variables.rs:71:5:71:16 | CallExpr | variables.rs:57:19:72:1 | BlockExpr | | +| variables.rs:71:5:71:16 | print_str(...) | variables.rs:57:19:72:1 | { ... } | | | variables.rs:71:5:71:17 | ExprStmt | variables.rs:71:5:71:13 | print_str | | -| variables.rs:71:15:71:15 | y | variables.rs:71:5:71:16 | CallExpr | | -| variables.rs:74:1:82:1 | enter let_pattern2 | variables.rs:75:5:75:38 | LetStmt | | -| variables.rs:74:1:82:1 | exit let_pattern2 (normal) | variables.rs:74:1:82:1 | exit let_pattern2 | | -| variables.rs:74:19:82:1 | BlockExpr | variables.rs:74:1:82:1 | exit let_pattern2 (normal) | | -| variables.rs:75:5:75:38 | LetStmt | variables.rs:75:25:75:27 | "a" | | -| variables.rs:75:9:75:10 | p1 | variables.rs:76:5:79:11 | LetStmt | match | -| variables.rs:75:14:75:37 | RecordExpr | variables.rs:75:9:75:10 | p1 | | +| variables.rs:71:15:71:15 | y | variables.rs:71:5:71:16 | print_str(...) | | +| variables.rs:74:1:82:1 | enter fn let_pattern2 | variables.rs:75:5:75:38 | let ... = ... | | +| variables.rs:74:1:82:1 | exit fn let_pattern2 (normal) | variables.rs:74:1:82:1 | exit fn let_pattern2 | | +| variables.rs:74:19:82:1 | { ... } | variables.rs:74:1:82:1 | exit fn let_pattern2 (normal) | | +| variables.rs:75:5:75:38 | let ... = ... | variables.rs:75:25:75:27 | "a" | | +| variables.rs:75:9:75:10 | p1 | variables.rs:76:5:79:11 | let ... = p1 | match | +| variables.rs:75:14:75:37 | Point {...} | variables.rs:75:9:75:10 | p1 | | | variables.rs:75:25:75:27 | "a" | variables.rs:75:33:75:35 | "b" | | -| variables.rs:75:33:75:35 | "b" | variables.rs:75:14:75:37 | RecordExpr | | -| variables.rs:76:5:79:11 | LetStmt | variables.rs:79:9:79:10 | p1 | | -| variables.rs:76:9:79:5 | RecordPat | variables.rs:77:12:77:13 | a2 | match | +| variables.rs:75:33:75:35 | "b" | variables.rs:75:14:75:37 | Point {...} | | +| variables.rs:76:5:79:11 | let ... = p1 | variables.rs:79:9:79:10 | p1 | | +| variables.rs:76:9:79:5 | Point {...} | variables.rs:77:12:77:13 | a2 | match | | variables.rs:77:12:77:13 | a2 | variables.rs:78:12:78:13 | b2 | match | | variables.rs:78:12:78:13 | b2 | variables.rs:80:5:80:18 | ExprStmt | match | -| variables.rs:79:9:79:10 | p1 | variables.rs:76:9:79:5 | RecordPat | | +| variables.rs:79:9:79:10 | p1 | variables.rs:76:9:79:5 | Point {...} | | | variables.rs:80:5:80:13 | print_str | variables.rs:80:15:80:16 | a2 | | -| variables.rs:80:5:80:17 | CallExpr | variables.rs:81:5:81:18 | ExprStmt | | +| variables.rs:80:5:80:17 | print_str(...) | variables.rs:81:5:81:18 | ExprStmt | | | variables.rs:80:5:80:18 | ExprStmt | variables.rs:80:5:80:13 | print_str | | -| variables.rs:80:15:80:16 | a2 | variables.rs:80:5:80:17 | CallExpr | | +| variables.rs:80:15:80:16 | a2 | variables.rs:80:5:80:17 | print_str(...) | | | variables.rs:81:5:81:13 | print_str | variables.rs:81:15:81:16 | b2 | | -| variables.rs:81:5:81:17 | CallExpr | variables.rs:74:19:82:1 | BlockExpr | | +| variables.rs:81:5:81:17 | print_str(...) | variables.rs:74:19:82:1 | { ... } | | | variables.rs:81:5:81:18 | ExprStmt | variables.rs:81:5:81:13 | print_str | | -| variables.rs:81:15:81:16 | b2 | variables.rs:81:5:81:17 | CallExpr | | -| variables.rs:84:1:91:1 | enter let_pattern3 | variables.rs:85:5:85:42 | LetStmt | | -| variables.rs:84:1:91:1 | exit let_pattern3 (normal) | variables.rs:84:1:91:1 | exit let_pattern3 | | -| variables.rs:84:19:91:1 | BlockExpr | variables.rs:84:1:91:1 | exit let_pattern3 (normal) | | -| variables.rs:85:5:85:42 | LetStmt | variables.rs:85:14:85:17 | Some | | -| variables.rs:85:9:85:10 | s1 | variables.rs:87:8:88:12 | LetExpr | match | -| variables.rs:85:14:85:17 | Some | variables.rs:85:19:85:30 | String::from | | -| variables.rs:85:14:85:41 | CallExpr | variables.rs:85:9:85:10 | s1 | | -| variables.rs:85:19:85:30 | String::from | variables.rs:85:32:85:39 | "Hello!" | | -| variables.rs:85:19:85:40 | CallExpr | variables.rs:85:14:85:41 | CallExpr | | -| variables.rs:85:32:85:39 | "Hello!" | variables.rs:85:19:85:40 | CallExpr | | -| variables.rs:87:5:90:5 | IfExpr | variables.rs:84:19:91:1 | BlockExpr | | -| variables.rs:87:8:88:12 | LetExpr | variables.rs:88:11:88:12 | s1 | | -| variables.rs:87:12:87:23 | TupleStructPat | variables.rs:87:5:90:5 | IfExpr | no-match | +| variables.rs:81:15:81:16 | b2 | variables.rs:81:5:81:17 | print_str(...) | | +| variables.rs:84:1:91:1 | enter fn let_pattern3 | variables.rs:85:5:85:42 | let ... = ... | | +| variables.rs:84:1:91:1 | exit fn let_pattern3 (normal) | variables.rs:84:1:91:1 | exit fn let_pattern3 | | +| variables.rs:84:19:91:1 | { ... } | variables.rs:84:1:91:1 | exit fn let_pattern3 (normal) | | +| variables.rs:85:5:85:42 | let ... = ... | variables.rs:85:14:85:17 | Some | | +| variables.rs:85:9:85:10 | s1 | variables.rs:87:8:88:12 | let ... = s1 | match | +| variables.rs:85:14:85:17 | Some | variables.rs:85:19:85:30 | ...::from | | +| variables.rs:85:14:85:41 | Some(...) | variables.rs:85:9:85:10 | s1 | | +| variables.rs:85:19:85:30 | ...::from | variables.rs:85:32:85:39 | "Hello!" | | +| variables.rs:85:19:85:40 | ...::from(...) | variables.rs:85:14:85:41 | Some(...) | | +| variables.rs:85:32:85:39 | "Hello!" | variables.rs:85:19:85:40 | ...::from(...) | | +| variables.rs:87:5:90:5 | if ... {...} | variables.rs:84:19:91:1 | { ... } | | +| variables.rs:87:8:88:12 | let ... = s1 | variables.rs:88:11:88:12 | s1 | | +| variables.rs:87:12:87:23 | TupleStructPat | variables.rs:87:5:90:5 | if ... {...} | no-match | | variables.rs:87:12:87:23 | TupleStructPat | variables.rs:87:17:87:22 | s2 | match | | variables.rs:87:17:87:22 | s2 | variables.rs:89:9:89:22 | ExprStmt | match | | variables.rs:88:11:88:12 | s1 | variables.rs:87:12:87:23 | TupleStructPat | | -| variables.rs:88:14:90:5 | BlockExpr | variables.rs:87:5:90:5 | IfExpr | | +| variables.rs:88:14:90:5 | { ... } | variables.rs:87:5:90:5 | if ... {...} | | | variables.rs:89:9:89:17 | print_str | variables.rs:89:19:89:20 | s2 | | -| variables.rs:89:9:89:21 | CallExpr | variables.rs:88:14:90:5 | BlockExpr | | +| variables.rs:89:9:89:21 | print_str(...) | variables.rs:88:14:90:5 | { ... } | | | variables.rs:89:9:89:22 | ExprStmt | variables.rs:89:9:89:17 | print_str | | -| variables.rs:89:19:89:20 | s2 | variables.rs:89:9:89:21 | CallExpr | | -| variables.rs:93:1:99:1 | enter let_pattern4 | variables.rs:94:5:97:10 | LetStmt | | -| variables.rs:93:1:99:1 | exit let_pattern4 (normal) | variables.rs:93:1:99:1 | exit let_pattern4 | | -| variables.rs:93:19:99:1 | BlockExpr | variables.rs:93:1:99:1 | exit let_pattern4 (normal) | | -| variables.rs:94:5:97:10 | LetStmt | variables.rs:94:34:94:37 | Some | | +| variables.rs:89:19:89:20 | s2 | variables.rs:89:9:89:21 | print_str(...) | | +| variables.rs:93:1:99:1 | enter fn let_pattern4 | variables.rs:94:5:97:10 | let ... = ... else {...} | | +| variables.rs:93:1:99:1 | exit fn let_pattern4 (normal) | variables.rs:93:1:99:1 | exit fn let_pattern4 | | +| variables.rs:93:19:99:1 | { ... } | variables.rs:93:1:99:1 | exit fn let_pattern4 (normal) | | +| variables.rs:94:5:97:10 | let ... = ... else {...} | variables.rs:94:34:94:37 | Some | | | variables.rs:94:9:94:16 | TupleStructPat | variables.rs:94:14:94:15 | x5 | match | | variables.rs:94:9:94:16 | TupleStructPat | variables.rs:96:13:96:19 | MacroStmts | no-match | | variables.rs:94:14:94:15 | x5 | variables.rs:98:5:98:18 | ExprStmt | match | | variables.rs:94:34:94:37 | Some | variables.rs:94:39:94:42 | "x5" | | -| variables.rs:94:34:94:43 | CallExpr | variables.rs:94:9:94:16 | TupleStructPat | | -| variables.rs:94:39:94:42 | "x5" | variables.rs:94:34:94:43 | CallExpr | | -| variables.rs:96:13:96:19 | "not yet implemented" | variables.rs:96:13:96:19 | CallExpr | | -| variables.rs:96:13:96:19 | $crate::panicking::panic | variables.rs:96:13:96:19 | "not yet implemented" | | -| variables.rs:96:13:96:19 | CallExpr | variables.rs:96:13:96:19 | MacroExpr | | -| variables.rs:96:13:96:19 | MacroExpr | variables.rs:95:14:97:9 | BlockExpr | | -| variables.rs:96:13:96:19 | MacroStmts | variables.rs:96:13:96:19 | $crate::panicking::panic | | +| variables.rs:94:34:94:43 | Some(...) | variables.rs:94:9:94:16 | TupleStructPat | | +| variables.rs:94:39:94:42 | "x5" | variables.rs:94:34:94:43 | Some(...) | | +| variables.rs:96:13:96:19 | "not yet implemented" | variables.rs:96:13:96:19 | ...::panic(...) | | +| variables.rs:96:13:96:19 | ...::panic | variables.rs:96:13:96:19 | "not yet implemented" | | +| variables.rs:96:13:96:19 | ...::panic(...) | variables.rs:96:13:96:19 | MacroExpr | | +| variables.rs:96:13:96:19 | MacroExpr | variables.rs:95:14:97:9 | { ... } | | +| variables.rs:96:13:96:19 | MacroStmts | variables.rs:96:13:96:19 | ...::panic | | | variables.rs:98:5:98:13 | print_str | variables.rs:98:15:98:16 | x5 | | -| variables.rs:98:5:98:17 | CallExpr | variables.rs:93:19:99:1 | BlockExpr | | +| variables.rs:98:5:98:17 | print_str(...) | variables.rs:93:19:99:1 | { ... } | | | variables.rs:98:5:98:18 | ExprStmt | variables.rs:98:5:98:13 | print_str | | -| variables.rs:98:15:98:16 | x5 | variables.rs:98:5:98:17 | CallExpr | | -| variables.rs:101:1:108:1 | enter let_pattern5 | variables.rs:102:5:102:42 | LetStmt | | -| variables.rs:101:1:108:1 | exit let_pattern5 (normal) | variables.rs:101:1:108:1 | exit let_pattern5 | | -| variables.rs:101:19:108:1 | BlockExpr | variables.rs:101:1:108:1 | exit let_pattern5 (normal) | | -| variables.rs:102:5:102:42 | LetStmt | variables.rs:102:14:102:17 | Some | | -| variables.rs:102:9:102:10 | s1 | variables.rs:104:11:105:12 | LetExpr | match | -| variables.rs:102:14:102:17 | Some | variables.rs:102:19:102:30 | String::from | | -| variables.rs:102:14:102:41 | CallExpr | variables.rs:102:9:102:10 | s1 | | -| variables.rs:102:19:102:30 | String::from | variables.rs:102:32:102:39 | "Hello!" | | -| variables.rs:102:19:102:40 | CallExpr | variables.rs:102:14:102:41 | CallExpr | | -| variables.rs:102:32:102:39 | "Hello!" | variables.rs:102:19:102:40 | CallExpr | | -| variables.rs:104:5:107:5 | WhileExpr | variables.rs:101:19:108:1 | BlockExpr | | -| variables.rs:104:11:105:12 | LetExpr | variables.rs:105:11:105:12 | s1 | | -| variables.rs:104:15:104:26 | TupleStructPat | variables.rs:104:5:107:5 | WhileExpr | no-match | +| variables.rs:98:15:98:16 | x5 | variables.rs:98:5:98:17 | print_str(...) | | +| variables.rs:101:1:108:1 | enter fn let_pattern5 | variables.rs:102:5:102:42 | let ... = ... | | +| variables.rs:101:1:108:1 | exit fn let_pattern5 (normal) | variables.rs:101:1:108:1 | exit fn let_pattern5 | | +| variables.rs:101:19:108:1 | { ... } | variables.rs:101:1:108:1 | exit fn let_pattern5 (normal) | | +| variables.rs:102:5:102:42 | let ... = ... | variables.rs:102:14:102:17 | Some | | +| variables.rs:102:9:102:10 | s1 | variables.rs:104:11:105:12 | let ... = s1 | match | +| variables.rs:102:14:102:17 | Some | variables.rs:102:19:102:30 | ...::from | | +| variables.rs:102:14:102:41 | Some(...) | variables.rs:102:9:102:10 | s1 | | +| variables.rs:102:19:102:30 | ...::from | variables.rs:102:32:102:39 | "Hello!" | | +| variables.rs:102:19:102:40 | ...::from(...) | variables.rs:102:14:102:41 | Some(...) | | +| variables.rs:102:32:102:39 | "Hello!" | variables.rs:102:19:102:40 | ...::from(...) | | +| variables.rs:104:5:107:5 | while ... { ... } | variables.rs:101:19:108:1 | { ... } | | +| variables.rs:104:11:105:12 | let ... = s1 | variables.rs:105:11:105:12 | s1 | | +| variables.rs:104:15:104:26 | TupleStructPat | variables.rs:104:5:107:5 | while ... { ... } | no-match | | variables.rs:104:15:104:26 | TupleStructPat | variables.rs:104:20:104:25 | s2 | match | | variables.rs:104:20:104:25 | s2 | variables.rs:106:9:106:22 | ExprStmt | match | | variables.rs:105:11:105:12 | s1 | variables.rs:104:15:104:26 | TupleStructPat | | -| variables.rs:105:14:107:5 | BlockExpr | variables.rs:104:11:105:12 | LetExpr | | +| variables.rs:105:14:107:5 | { ... } | variables.rs:104:11:105:12 | let ... = s1 | | | variables.rs:106:9:106:17 | print_str | variables.rs:106:19:106:20 | s2 | | -| variables.rs:106:9:106:21 | CallExpr | variables.rs:105:14:107:5 | BlockExpr | | +| variables.rs:106:9:106:21 | print_str(...) | variables.rs:105:14:107:5 | { ... } | | | variables.rs:106:9:106:22 | ExprStmt | variables.rs:106:9:106:17 | print_str | | -| variables.rs:106:19:106:20 | s2 | variables.rs:106:9:106:21 | CallExpr | | -| variables.rs:110:1:125:1 | enter match_pattern1 | variables.rs:111:5:111:21 | LetStmt | | -| variables.rs:110:1:125:1 | exit match_pattern1 (normal) | variables.rs:110:1:125:1 | exit match_pattern1 | | -| variables.rs:110:21:125:1 | BlockExpr | variables.rs:110:1:125:1 | exit match_pattern1 (normal) | | -| variables.rs:111:5:111:21 | LetStmt | variables.rs:111:14:111:17 | Some | | -| variables.rs:111:9:111:10 | x6 | variables.rs:112:5:112:16 | LetStmt | match | +| variables.rs:106:19:106:20 | s2 | variables.rs:106:9:106:21 | print_str(...) | | +| variables.rs:110:1:125:1 | enter fn match_pattern1 | variables.rs:111:5:111:21 | let ... = ... | | +| variables.rs:110:1:125:1 | exit fn match_pattern1 (normal) | variables.rs:110:1:125:1 | exit fn match_pattern1 | | +| variables.rs:110:21:125:1 | { ... } | variables.rs:110:1:125:1 | exit fn match_pattern1 (normal) | | +| variables.rs:111:5:111:21 | let ... = ... | variables.rs:111:14:111:17 | Some | | +| variables.rs:111:9:111:10 | x6 | variables.rs:112:5:112:16 | let ... = 10 | match | | variables.rs:111:14:111:17 | Some | variables.rs:111:19:111:19 | 5 | | -| variables.rs:111:14:111:20 | CallExpr | variables.rs:111:9:111:10 | x6 | | -| variables.rs:111:19:111:19 | 5 | variables.rs:111:14:111:20 | CallExpr | | -| variables.rs:112:5:112:16 | LetStmt | variables.rs:112:14:112:15 | 10 | | +| variables.rs:111:14:111:20 | Some(...) | variables.rs:111:9:111:10 | x6 | | +| variables.rs:111:19:111:19 | 5 | variables.rs:111:14:111:20 | Some(...) | | +| variables.rs:112:5:112:16 | let ... = 10 | variables.rs:112:14:112:15 | 10 | | | variables.rs:112:9:112:10 | y1 | variables.rs:114:5:122:5 | ExprStmt | match | | variables.rs:112:14:112:15 | 10 | variables.rs:112:9:112:10 | y1 | | | variables.rs:114:5:122:5 | ExprStmt | variables.rs:114:11:114:12 | x6 | | -| variables.rs:114:5:122:5 | MatchExpr | variables.rs:124:5:124:18 | ExprStmt | | +| variables.rs:114:5:122:5 | match x6 { ... } | variables.rs:124:5:124:18 | ExprStmt | | | variables.rs:114:11:114:12 | x6 | variables.rs:115:9:115:16 | TupleStructPat | | | variables.rs:115:9:115:16 | TupleStructPat | variables.rs:115:14:115:15 | 50 | match | | variables.rs:115:9:115:16 | TupleStructPat | variables.rs:116:9:116:16 | TupleStructPat | no-match | -| variables.rs:115:14:115:15 | 50 | variables.rs:115:14:115:15 | LiteralPat | | -| variables.rs:115:14:115:15 | LiteralPat | variables.rs:115:21:115:29 | print_str | match | -| variables.rs:115:14:115:15 | LiteralPat | variables.rs:116:9:116:16 | TupleStructPat | no-match | +| variables.rs:115:14:115:15 | 50 | variables.rs:115:14:115:15 | 50 | | +| variables.rs:115:14:115:15 | 50 | variables.rs:115:21:115:29 | print_str | match | +| variables.rs:115:14:115:15 | 50 | variables.rs:116:9:116:16 | TupleStructPat | no-match | | variables.rs:115:21:115:29 | print_str | variables.rs:115:31:115:38 | "Got 50" | | -| variables.rs:115:21:115:39 | CallExpr | variables.rs:114:5:122:5 | MatchExpr | | -| variables.rs:115:31:115:38 | "Got 50" | variables.rs:115:21:115:39 | CallExpr | | +| variables.rs:115:21:115:39 | print_str(...) | variables.rs:114:5:122:5 | match x6 { ... } | | +| variables.rs:115:31:115:38 | "Got 50" | variables.rs:115:21:115:39 | print_str(...) | | | variables.rs:116:9:116:16 | TupleStructPat | variables.rs:116:14:116:15 | y1 | match | | variables.rs:116:9:116:16 | TupleStructPat | variables.rs:121:9:121:12 | None | no-match | | variables.rs:116:14:116:15 | y1 | variables.rs:119:13:119:21 | print_i64 | match | -| variables.rs:118:9:120:9 | BlockExpr | variables.rs:114:5:122:5 | MatchExpr | | +| variables.rs:118:9:120:9 | { ... } | variables.rs:114:5:122:5 | match x6 { ... } | | | variables.rs:119:13:119:21 | print_i64 | variables.rs:119:23:119:24 | y1 | | -| variables.rs:119:13:119:25 | CallExpr | variables.rs:118:9:120:9 | BlockExpr | | -| variables.rs:119:23:119:24 | y1 | variables.rs:119:13:119:25 | CallExpr | | +| variables.rs:119:13:119:25 | print_i64(...) | variables.rs:118:9:120:9 | { ... } | | +| variables.rs:119:23:119:24 | y1 | variables.rs:119:13:119:25 | print_i64(...) | | | variables.rs:121:9:121:12 | None | variables.rs:121:17:121:25 | print_str | match | | variables.rs:121:17:121:25 | print_str | variables.rs:121:27:121:32 | "NONE" | | -| variables.rs:121:17:121:33 | CallExpr | variables.rs:114:5:122:5 | MatchExpr | | -| variables.rs:121:27:121:32 | "NONE" | variables.rs:121:17:121:33 | CallExpr | | +| variables.rs:121:17:121:33 | print_str(...) | variables.rs:114:5:122:5 | match x6 { ... } | | +| variables.rs:121:27:121:32 | "NONE" | variables.rs:121:17:121:33 | print_str(...) | | | variables.rs:124:5:124:13 | print_i64 | variables.rs:124:15:124:16 | y1 | | -| variables.rs:124:5:124:17 | CallExpr | variables.rs:110:21:125:1 | BlockExpr | | +| variables.rs:124:5:124:17 | print_i64(...) | variables.rs:110:21:125:1 | { ... } | | | variables.rs:124:5:124:18 | ExprStmt | variables.rs:124:5:124:13 | print_i64 | | -| variables.rs:124:15:124:16 | y1 | variables.rs:124:5:124:17 | CallExpr | | -| variables.rs:127:1:152:1 | enter match_pattern2 | variables.rs:128:5:128:36 | LetStmt | | -| variables.rs:127:1:152:1 | exit match_pattern2 (normal) | variables.rs:127:1:152:1 | exit match_pattern2 | | -| variables.rs:127:21:152:1 | BlockExpr | variables.rs:127:1:152:1 | exit match_pattern2 (normal) | | -| variables.rs:128:5:128:36 | LetStmt | variables.rs:128:20:128:20 | 2 | | +| variables.rs:124:15:124:16 | y1 | variables.rs:124:5:124:17 | print_i64(...) | | +| variables.rs:127:1:152:1 | enter fn match_pattern2 | variables.rs:128:5:128:36 | let ... = ... | | +| variables.rs:127:1:152:1 | exit fn match_pattern2 (normal) | variables.rs:127:1:152:1 | exit fn match_pattern2 | | +| variables.rs:127:21:152:1 | { ... } | variables.rs:127:1:152:1 | exit fn match_pattern2 (normal) | | +| variables.rs:128:5:128:36 | let ... = ... | variables.rs:128:20:128:20 | 2 | | | variables.rs:128:9:128:15 | numbers | variables.rs:130:5:140:5 | ExprStmt | match | | variables.rs:128:19:128:35 | TupleExpr | variables.rs:128:9:128:15 | numbers | | | variables.rs:128:20:128:20 | 2 | variables.rs:128:23:128:23 | 4 | | @@ -295,311 +295,311 @@ edges | variables.rs:128:29:128:30 | 16 | variables.rs:128:33:128:34 | 32 | | | variables.rs:128:33:128:34 | 32 | variables.rs:128:19:128:35 | TupleExpr | | | variables.rs:130:5:140:5 | ExprStmt | variables.rs:130:11:130:17 | numbers | | -| variables.rs:130:5:140:5 | MatchExpr | variables.rs:142:11:142:17 | numbers | | +| variables.rs:130:5:140:5 | match numbers { ... } | variables.rs:142:11:142:17 | numbers | | | variables.rs:130:11:130:17 | numbers | variables.rs:131:9:135:9 | TuplePat | | | variables.rs:131:9:135:9 | TuplePat | variables.rs:132:13:132:17 | first | match | -| variables.rs:132:13:132:17 | first | variables.rs:132:20:132:20 | WildcardPat | match | -| variables.rs:132:20:132:20 | WildcardPat | variables.rs:133:13:133:17 | third | match | -| variables.rs:133:13:133:17 | third | variables.rs:133:20:133:20 | WildcardPat | match | -| variables.rs:133:20:133:20 | WildcardPat | variables.rs:134:13:134:17 | fifth | match | +| variables.rs:132:13:132:17 | first | variables.rs:132:20:132:20 | _ | match | +| variables.rs:132:20:132:20 | _ | variables.rs:133:13:133:17 | third | match | +| variables.rs:133:13:133:17 | third | variables.rs:133:20:133:20 | _ | match | +| variables.rs:133:20:133:20 | _ | variables.rs:134:13:134:17 | fifth | match | | variables.rs:134:13:134:17 | fifth | variables.rs:136:13:136:29 | ExprStmt | match | -| variables.rs:135:14:139:9 | BlockExpr | variables.rs:130:5:140:5 | MatchExpr | | +| variables.rs:135:14:139:9 | { ... } | variables.rs:130:5:140:5 | match numbers { ... } | | | variables.rs:136:13:136:21 | print_i64 | variables.rs:136:23:136:27 | first | | -| variables.rs:136:13:136:28 | CallExpr | variables.rs:137:13:137:29 | ExprStmt | | +| variables.rs:136:13:136:28 | print_i64(...) | variables.rs:137:13:137:29 | ExprStmt | | | variables.rs:136:13:136:29 | ExprStmt | variables.rs:136:13:136:21 | print_i64 | | -| variables.rs:136:23:136:27 | first | variables.rs:136:13:136:28 | CallExpr | | +| variables.rs:136:23:136:27 | first | variables.rs:136:13:136:28 | print_i64(...) | | | variables.rs:137:13:137:21 | print_i64 | variables.rs:137:23:137:27 | third | | -| variables.rs:137:13:137:28 | CallExpr | variables.rs:138:13:138:29 | ExprStmt | | +| variables.rs:137:13:137:28 | print_i64(...) | variables.rs:138:13:138:29 | ExprStmt | | | variables.rs:137:13:137:29 | ExprStmt | variables.rs:137:13:137:21 | print_i64 | | -| variables.rs:137:23:137:27 | third | variables.rs:137:13:137:28 | CallExpr | | +| variables.rs:137:23:137:27 | third | variables.rs:137:13:137:28 | print_i64(...) | | | variables.rs:138:13:138:21 | print_i64 | variables.rs:138:23:138:27 | fifth | | -| variables.rs:138:13:138:28 | CallExpr | variables.rs:135:14:139:9 | BlockExpr | | +| variables.rs:138:13:138:28 | print_i64(...) | variables.rs:135:14:139:9 | { ... } | | | variables.rs:138:13:138:29 | ExprStmt | variables.rs:138:13:138:21 | print_i64 | | -| variables.rs:138:23:138:27 | fifth | variables.rs:138:13:138:28 | CallExpr | | -| variables.rs:142:5:151:5 | MatchExpr | variables.rs:127:21:152:1 | BlockExpr | | +| variables.rs:138:23:138:27 | fifth | variables.rs:138:13:138:28 | print_i64(...) | | +| variables.rs:142:5:151:5 | match numbers { ... } | variables.rs:127:21:152:1 | { ... } | | | variables.rs:142:11:142:17 | numbers | variables.rs:143:9:147:9 | TuplePat | | | variables.rs:143:9:147:9 | TuplePat | variables.rs:144:13:144:17 | first | match | -| variables.rs:144:13:144:17 | first | variables.rs:145:13:145:14 | RestPat | match | -| variables.rs:145:13:145:14 | RestPat | variables.rs:146:13:146:16 | last | match | +| variables.rs:144:13:144:17 | first | variables.rs:145:13:145:14 | .. | match | +| variables.rs:145:13:145:14 | .. | variables.rs:146:13:146:16 | last | match | | variables.rs:146:13:146:16 | last | variables.rs:148:13:148:29 | ExprStmt | match | -| variables.rs:147:14:150:9 | BlockExpr | variables.rs:142:5:151:5 | MatchExpr | | +| variables.rs:147:14:150:9 | { ... } | variables.rs:142:5:151:5 | match numbers { ... } | | | variables.rs:148:13:148:21 | print_i64 | variables.rs:148:23:148:27 | first | | -| variables.rs:148:13:148:28 | CallExpr | variables.rs:149:13:149:28 | ExprStmt | | +| variables.rs:148:13:148:28 | print_i64(...) | variables.rs:149:13:149:28 | ExprStmt | | | variables.rs:148:13:148:29 | ExprStmt | variables.rs:148:13:148:21 | print_i64 | | -| variables.rs:148:23:148:27 | first | variables.rs:148:13:148:28 | CallExpr | | +| variables.rs:148:23:148:27 | first | variables.rs:148:13:148:28 | print_i64(...) | | | variables.rs:149:13:149:21 | print_i64 | variables.rs:149:23:149:26 | last | | -| variables.rs:149:13:149:27 | CallExpr | variables.rs:147:14:150:9 | BlockExpr | | +| variables.rs:149:13:149:27 | print_i64(...) | variables.rs:147:14:150:9 | { ... } | | | variables.rs:149:13:149:28 | ExprStmt | variables.rs:149:13:149:21 | print_i64 | | -| variables.rs:149:23:149:26 | last | variables.rs:149:13:149:27 | CallExpr | | -| variables.rs:154:1:162:1 | enter match_pattern3 | variables.rs:155:5:155:38 | LetStmt | | -| variables.rs:154:1:162:1 | exit match_pattern3 (normal) | variables.rs:154:1:162:1 | exit match_pattern3 | | -| variables.rs:154:21:162:1 | BlockExpr | variables.rs:154:1:162:1 | exit match_pattern3 (normal) | | -| variables.rs:155:5:155:38 | LetStmt | variables.rs:155:25:155:27 | "x" | | +| variables.rs:149:23:149:26 | last | variables.rs:149:13:149:27 | print_i64(...) | | +| variables.rs:154:1:162:1 | enter fn match_pattern3 | variables.rs:155:5:155:38 | let ... = ... | | +| variables.rs:154:1:162:1 | exit fn match_pattern3 (normal) | variables.rs:154:1:162:1 | exit fn match_pattern3 | | +| variables.rs:154:21:162:1 | { ... } | variables.rs:154:1:162:1 | exit fn match_pattern3 (normal) | | +| variables.rs:155:5:155:38 | let ... = ... | variables.rs:155:25:155:27 | "x" | | | variables.rs:155:9:155:10 | p2 | variables.rs:157:11:157:12 | p2 | match | -| variables.rs:155:14:155:37 | RecordExpr | variables.rs:155:9:155:10 | p2 | | +| variables.rs:155:14:155:37 | Point {...} | variables.rs:155:9:155:10 | p2 | | | variables.rs:155:25:155:27 | "x" | variables.rs:155:33:155:35 | "y" | | -| variables.rs:155:33:155:35 | "y" | variables.rs:155:14:155:37 | RecordExpr | | -| variables.rs:157:5:161:5 | MatchExpr | variables.rs:154:21:162:1 | BlockExpr | | -| variables.rs:157:11:157:12 | p2 | variables.rs:158:9:160:9 | RecordPat | | -| variables.rs:158:9:160:9 | RecordPat | variables.rs:159:16:159:17 | x7 | match | -| variables.rs:159:16:159:17 | x7 | variables.rs:159:20:159:21 | RestPat | match | -| variables.rs:159:20:159:21 | RestPat | variables.rs:160:14:160:22 | print_str | match | +| variables.rs:155:33:155:35 | "y" | variables.rs:155:14:155:37 | Point {...} | | +| variables.rs:157:5:161:5 | match p2 { ... } | variables.rs:154:21:162:1 | { ... } | | +| variables.rs:157:11:157:12 | p2 | variables.rs:158:9:160:9 | Point {...} | | +| variables.rs:158:9:160:9 | Point {...} | variables.rs:159:16:159:17 | x7 | match | +| variables.rs:159:16:159:17 | x7 | variables.rs:159:20:159:21 | .. | match | +| variables.rs:159:20:159:21 | .. | variables.rs:160:14:160:22 | print_str | match | | variables.rs:160:14:160:22 | print_str | variables.rs:160:24:160:25 | x7 | | -| variables.rs:160:14:160:26 | CallExpr | variables.rs:157:5:161:5 | MatchExpr | | -| variables.rs:160:24:160:25 | x7 | variables.rs:160:14:160:26 | CallExpr | | -| variables.rs:168:1:181:1 | enter match_pattern4 | variables.rs:169:5:169:39 | LetStmt | | -| variables.rs:168:1:181:1 | exit match_pattern4 (normal) | variables.rs:168:1:181:1 | exit match_pattern4 | | -| variables.rs:168:21:181:1 | BlockExpr | variables.rs:168:1:181:1 | exit match_pattern4 (normal) | | -| variables.rs:169:5:169:39 | LetStmt | variables.rs:169:36:169:36 | 0 | | +| variables.rs:160:14:160:26 | print_str(...) | variables.rs:157:5:161:5 | match p2 { ... } | | +| variables.rs:160:24:160:25 | x7 | variables.rs:160:14:160:26 | print_str(...) | | +| variables.rs:168:1:181:1 | enter fn match_pattern4 | variables.rs:169:5:169:39 | let ... = ... | | +| variables.rs:168:1:181:1 | exit fn match_pattern4 (normal) | variables.rs:168:1:181:1 | exit fn match_pattern4 | | +| variables.rs:168:21:181:1 | { ... } | variables.rs:168:1:181:1 | exit fn match_pattern4 (normal) | | +| variables.rs:169:5:169:39 | let ... = ... | variables.rs:169:36:169:36 | 0 | | | variables.rs:169:9:169:11 | msg | variables.rs:171:11:171:13 | msg | match | -| variables.rs:169:15:169:38 | RecordExpr | variables.rs:169:9:169:11 | msg | | -| variables.rs:169:36:169:36 | 0 | variables.rs:169:15:169:38 | RecordExpr | | -| variables.rs:171:5:180:5 | MatchExpr | variables.rs:168:21:181:1 | BlockExpr | | -| variables.rs:171:11:171:13 | msg | variables.rs:172:9:174:9 | RecordPat | | -| variables.rs:172:9:174:9 | RecordPat | variables.rs:173:31:173:35 | RangePat | match | -| variables.rs:172:9:174:9 | RecordPat | variables.rs:175:9:175:38 | RecordPat | no-match | +| variables.rs:169:15:169:38 | ...::Hello {...} | variables.rs:169:9:169:11 | msg | | +| variables.rs:169:36:169:36 | 0 | variables.rs:169:15:169:38 | ...::Hello {...} | | +| variables.rs:171:5:180:5 | match msg { ... } | variables.rs:168:21:181:1 | { ... } | | +| variables.rs:171:11:171:13 | msg | variables.rs:172:9:174:9 | ...::Hello {...} | | +| variables.rs:172:9:174:9 | ...::Hello {...} | variables.rs:173:31:173:35 | RangePat | match | +| variables.rs:172:9:174:9 | ...::Hello {...} | variables.rs:175:9:175:38 | ...::Hello {...} | no-match | | variables.rs:173:17:173:35 | [match(true)] id_variable | variables.rs:174:14:174:22 | print_i64 | match | -| variables.rs:173:31:173:31 | 3 | variables.rs:173:31:173:31 | LiteralPat | | -| variables.rs:173:31:173:31 | LiteralPat | variables.rs:173:35:173:35 | 7 | match | -| variables.rs:173:31:173:31 | LiteralPat | variables.rs:175:9:175:38 | RecordPat | no-match | +| variables.rs:173:31:173:31 | 3 | variables.rs:173:31:173:31 | 3 | | +| variables.rs:173:31:173:31 | 3 | variables.rs:173:35:173:35 | 7 | match | +| variables.rs:173:31:173:31 | 3 | variables.rs:175:9:175:38 | ...::Hello {...} | no-match | | variables.rs:173:31:173:35 | RangePat | variables.rs:173:31:173:31 | 3 | match | -| variables.rs:173:31:173:35 | RangePat | variables.rs:175:9:175:38 | RecordPat | no-match | -| variables.rs:173:35:173:35 | 7 | variables.rs:173:35:173:35 | LiteralPat | | -| variables.rs:173:35:173:35 | LiteralPat | variables.rs:173:17:173:35 | [match(true)] id_variable | match | -| variables.rs:173:35:173:35 | LiteralPat | variables.rs:175:9:175:38 | RecordPat | no-match | +| variables.rs:173:31:173:35 | RangePat | variables.rs:175:9:175:38 | ...::Hello {...} | no-match | +| variables.rs:173:35:173:35 | 7 | variables.rs:173:17:173:35 | [match(true)] id_variable | match | +| variables.rs:173:35:173:35 | 7 | variables.rs:173:35:173:35 | 7 | | +| variables.rs:173:35:173:35 | 7 | variables.rs:175:9:175:38 | ...::Hello {...} | no-match | | variables.rs:174:14:174:22 | print_i64 | variables.rs:174:24:174:34 | id_variable | | -| variables.rs:174:14:174:35 | CallExpr | variables.rs:171:5:180:5 | MatchExpr | | -| variables.rs:174:24:174:34 | id_variable | variables.rs:174:14:174:35 | CallExpr | | -| variables.rs:175:9:175:38 | RecordPat | variables.rs:175:30:175:36 | RangePat | match | -| variables.rs:175:9:175:38 | RecordPat | variables.rs:178:9:178:29 | RecordPat | no-match | -| variables.rs:175:30:175:31 | 10 | variables.rs:175:30:175:31 | LiteralPat | | -| variables.rs:175:30:175:31 | LiteralPat | variables.rs:175:35:175:36 | 12 | match | -| variables.rs:175:30:175:31 | LiteralPat | variables.rs:178:9:178:29 | RecordPat | no-match | +| variables.rs:174:14:174:35 | print_i64(...) | variables.rs:171:5:180:5 | match msg { ... } | | +| variables.rs:174:24:174:34 | id_variable | variables.rs:174:14:174:35 | print_i64(...) | | +| variables.rs:175:9:175:38 | ...::Hello {...} | variables.rs:175:30:175:36 | RangePat | match | +| variables.rs:175:9:175:38 | ...::Hello {...} | variables.rs:178:9:178:29 | ...::Hello {...} | no-match | +| variables.rs:175:30:175:31 | 10 | variables.rs:175:30:175:31 | 10 | | +| variables.rs:175:30:175:31 | 10 | variables.rs:175:35:175:36 | 12 | match | +| variables.rs:175:30:175:31 | 10 | variables.rs:178:9:178:29 | ...::Hello {...} | no-match | | variables.rs:175:30:175:36 | RangePat | variables.rs:175:30:175:31 | 10 | match | -| variables.rs:175:30:175:36 | RangePat | variables.rs:178:9:178:29 | RecordPat | no-match | -| variables.rs:175:35:175:36 | 12 | variables.rs:175:35:175:36 | LiteralPat | | -| variables.rs:175:35:175:36 | LiteralPat | variables.rs:176:22:176:51 | MacroStmts | match | -| variables.rs:175:35:175:36 | LiteralPat | variables.rs:178:9:178:29 | RecordPat | no-match | -| variables.rs:175:43:177:9 | BlockExpr | variables.rs:171:5:180:5 | MatchExpr | | -| variables.rs:176:13:176:52 | $crate::io::_print | variables.rs:176:22:176:51 | "Found an id in another range\\n" | | -| variables.rs:176:13:176:52 | MacroExpr | variables.rs:175:43:177:9 | BlockExpr | | -| variables.rs:176:22:176:51 | "Found an id in another range\\n" | variables.rs:176:22:176:51 | FormatArgsExpr | | -| variables.rs:176:22:176:51 | BlockExpr | variables.rs:176:13:176:52 | MacroExpr | | -| variables.rs:176:22:176:51 | CallExpr | variables.rs:176:22:176:51 | BlockExpr | | -| variables.rs:176:22:176:51 | ExprStmt | variables.rs:176:13:176:52 | $crate::io::_print | | +| variables.rs:175:30:175:36 | RangePat | variables.rs:178:9:178:29 | ...::Hello {...} | no-match | +| variables.rs:175:35:175:36 | 12 | variables.rs:175:35:175:36 | 12 | | +| variables.rs:175:35:175:36 | 12 | variables.rs:176:22:176:51 | MacroStmts | match | +| variables.rs:175:35:175:36 | 12 | variables.rs:178:9:178:29 | ...::Hello {...} | no-match | +| variables.rs:175:43:177:9 | { ... } | variables.rs:171:5:180:5 | match msg { ... } | | +| variables.rs:176:13:176:52 | ...::_print | variables.rs:176:22:176:51 | "Found an id in another range\\... | | +| variables.rs:176:13:176:52 | MacroExpr | variables.rs:175:43:177:9 | { ... } | | +| variables.rs:176:22:176:51 | "Found an id in another range\\... | variables.rs:176:22:176:51 | FormatArgsExpr | | +| variables.rs:176:22:176:51 | ...::_print(...) | variables.rs:176:22:176:51 | { ... } | | +| variables.rs:176:22:176:51 | ExprStmt | variables.rs:176:13:176:52 | ...::_print | | | variables.rs:176:22:176:51 | FormatArgsExpr | variables.rs:176:22:176:51 | MacroExpr | | -| variables.rs:176:22:176:51 | MacroExpr | variables.rs:176:22:176:51 | CallExpr | | +| variables.rs:176:22:176:51 | MacroExpr | variables.rs:176:22:176:51 | ...::_print(...) | | | variables.rs:176:22:176:51 | MacroStmts | variables.rs:176:22:176:51 | ExprStmt | | -| variables.rs:178:9:178:29 | RecordPat | variables.rs:178:26:178:27 | id | match | +| variables.rs:176:22:176:51 | { ... } | variables.rs:176:13:176:52 | MacroExpr | | +| variables.rs:178:9:178:29 | ...::Hello {...} | variables.rs:178:26:178:27 | id | match | | variables.rs:178:26:178:27 | id | variables.rs:179:13:179:21 | print_i64 | match | | variables.rs:179:13:179:21 | print_i64 | variables.rs:179:23:179:24 | id | | -| variables.rs:179:13:179:25 | CallExpr | variables.rs:171:5:180:5 | MatchExpr | | -| variables.rs:179:23:179:24 | id | variables.rs:179:13:179:25 | CallExpr | | -| variables.rs:188:1:194:1 | enter match_pattern5 | variables.rs:189:5:189:34 | LetStmt | | -| variables.rs:188:1:194:1 | exit match_pattern5 (normal) | variables.rs:188:1:194:1 | exit match_pattern5 | | -| variables.rs:188:21:194:1 | BlockExpr | variables.rs:188:1:194:1 | exit match_pattern5 (normal) | | -| variables.rs:189:5:189:34 | LetStmt | variables.rs:189:18:189:29 | Either::Left | | +| variables.rs:179:13:179:25 | print_i64(...) | variables.rs:171:5:180:5 | match msg { ... } | | +| variables.rs:179:23:179:24 | id | variables.rs:179:13:179:25 | print_i64(...) | | +| variables.rs:188:1:194:1 | enter fn match_pattern5 | variables.rs:189:5:189:34 | let ... = ... | | +| variables.rs:188:1:194:1 | exit fn match_pattern5 (normal) | variables.rs:188:1:194:1 | exit fn match_pattern5 | | +| variables.rs:188:21:194:1 | { ... } | variables.rs:188:1:194:1 | exit fn match_pattern5 (normal) | | +| variables.rs:189:5:189:34 | let ... = ... | variables.rs:189:18:189:29 | ...::Left | | | variables.rs:189:9:189:14 | either | variables.rs:190:11:190:16 | either | match | -| variables.rs:189:18:189:29 | Either::Left | variables.rs:189:31:189:32 | 32 | | -| variables.rs:189:18:189:33 | CallExpr | variables.rs:189:9:189:14 | either | | -| variables.rs:189:31:189:32 | 32 | variables.rs:189:18:189:33 | CallExpr | | -| variables.rs:190:5:193:5 | MatchExpr | variables.rs:188:21:194:1 | BlockExpr | | +| variables.rs:189:18:189:29 | ...::Left | variables.rs:189:31:189:32 | 32 | | +| variables.rs:189:18:189:33 | ...::Left(...) | variables.rs:189:9:189:14 | either | | +| variables.rs:189:31:189:32 | 32 | variables.rs:189:18:189:33 | ...::Left(...) | | +| variables.rs:190:5:193:5 | match either { ... } | variables.rs:188:21:194:1 | { ... } | | | variables.rs:190:11:190:16 | either | variables.rs:191:9:191:24 | TupleStructPat | | | variables.rs:191:9:191:24 | TupleStructPat | variables.rs:191:22:191:23 | a3 | match | | variables.rs:191:9:191:24 | TupleStructPat | variables.rs:191:28:191:44 | TupleStructPat | no-match | -| variables.rs:191:9:191:44 | [match(true)] OrPat | variables.rs:192:16:192:24 | print_i64 | match | -| variables.rs:191:22:191:23 | a3 | variables.rs:191:9:191:44 | [match(true)] OrPat | match | +| variables.rs:191:9:191:44 | [match(true)] ... \| ... | variables.rs:192:16:192:24 | print_i64 | match | +| variables.rs:191:22:191:23 | a3 | variables.rs:191:9:191:44 | [match(true)] ... \| ... | match | | variables.rs:191:28:191:44 | TupleStructPat | variables.rs:191:42:191:43 | a3 | match | -| variables.rs:191:42:191:43 | a3 | variables.rs:191:9:191:44 | [match(true)] OrPat | match | +| variables.rs:191:42:191:43 | a3 | variables.rs:191:9:191:44 | [match(true)] ... \| ... | match | | variables.rs:192:16:192:24 | print_i64 | variables.rs:192:26:192:27 | a3 | | -| variables.rs:192:16:192:28 | CallExpr | variables.rs:190:5:193:5 | MatchExpr | | -| variables.rs:192:26:192:27 | a3 | variables.rs:192:16:192:28 | CallExpr | | -| variables.rs:202:1:216:1 | enter match_pattern6 | variables.rs:203:5:203:37 | LetStmt | | -| variables.rs:202:1:216:1 | exit match_pattern6 (normal) | variables.rs:202:1:216:1 | exit match_pattern6 | | -| variables.rs:202:21:216:1 | BlockExpr | variables.rs:202:1:216:1 | exit match_pattern6 (normal) | | -| variables.rs:203:5:203:37 | LetStmt | variables.rs:203:14:203:32 | ThreeValued::Second | | +| variables.rs:192:16:192:28 | print_i64(...) | variables.rs:190:5:193:5 | match either { ... } | | +| variables.rs:192:26:192:27 | a3 | variables.rs:192:16:192:28 | print_i64(...) | | +| variables.rs:202:1:216:1 | enter fn match_pattern6 | variables.rs:203:5:203:37 | let ... = ... | | +| variables.rs:202:1:216:1 | exit fn match_pattern6 (normal) | variables.rs:202:1:216:1 | exit fn match_pattern6 | | +| variables.rs:202:21:216:1 | { ... } | variables.rs:202:1:216:1 | exit fn match_pattern6 (normal) | | +| variables.rs:203:5:203:37 | let ... = ... | variables.rs:203:14:203:32 | ...::Second | | | variables.rs:203:9:203:10 | tv | variables.rs:204:5:207:5 | ExprStmt | match | -| variables.rs:203:14:203:32 | ThreeValued::Second | variables.rs:203:34:203:35 | 62 | | -| variables.rs:203:14:203:36 | CallExpr | variables.rs:203:9:203:10 | tv | | -| variables.rs:203:34:203:35 | 62 | variables.rs:203:14:203:36 | CallExpr | | +| variables.rs:203:14:203:32 | ...::Second | variables.rs:203:34:203:35 | 62 | | +| variables.rs:203:14:203:36 | ...::Second(...) | variables.rs:203:9:203:10 | tv | | +| variables.rs:203:34:203:35 | 62 | variables.rs:203:14:203:36 | ...::Second(...) | | | variables.rs:204:5:207:5 | ExprStmt | variables.rs:204:11:204:12 | tv | | -| variables.rs:204:5:207:5 | MatchExpr | variables.rs:208:5:211:5 | ExprStmt | | +| variables.rs:204:5:207:5 | match tv { ... } | variables.rs:208:5:211:5 | ExprStmt | | | variables.rs:204:11:204:12 | tv | variables.rs:205:9:205:30 | TupleStructPat | | | variables.rs:205:9:205:30 | TupleStructPat | variables.rs:205:28:205:29 | a4 | match | | variables.rs:205:9:205:30 | TupleStructPat | variables.rs:205:34:205:56 | TupleStructPat | no-match | -| variables.rs:205:9:205:81 | [match(true)] OrPat | variables.rs:206:16:206:24 | print_i64 | match | -| variables.rs:205:28:205:29 | a4 | variables.rs:205:9:205:81 | [match(true)] OrPat | match | +| variables.rs:205:9:205:81 | [match(true)] ... \| ... \| ... | variables.rs:206:16:206:24 | print_i64 | match | +| variables.rs:205:28:205:29 | a4 | variables.rs:205:9:205:81 | [match(true)] ... \| ... \| ... | match | | variables.rs:205:34:205:56 | TupleStructPat | variables.rs:205:54:205:55 | a4 | match | | variables.rs:205:34:205:56 | TupleStructPat | variables.rs:205:60:205:81 | TupleStructPat | no-match | -| variables.rs:205:54:205:55 | a4 | variables.rs:205:9:205:81 | [match(true)] OrPat | match | +| variables.rs:205:54:205:55 | a4 | variables.rs:205:9:205:81 | [match(true)] ... \| ... \| ... | match | | variables.rs:205:60:205:81 | TupleStructPat | variables.rs:205:79:205:80 | a4 | match | -| variables.rs:205:79:205:80 | a4 | variables.rs:205:9:205:81 | [match(true)] OrPat | match | +| variables.rs:205:79:205:80 | a4 | variables.rs:205:9:205:81 | [match(true)] ... \| ... \| ... | match | | variables.rs:206:16:206:24 | print_i64 | variables.rs:206:26:206:27 | a4 | | -| variables.rs:206:16:206:28 | CallExpr | variables.rs:204:5:207:5 | MatchExpr | | -| variables.rs:206:26:206:27 | a4 | variables.rs:206:16:206:28 | CallExpr | | +| variables.rs:206:16:206:28 | print_i64(...) | variables.rs:204:5:207:5 | match tv { ... } | | +| variables.rs:206:26:206:27 | a4 | variables.rs:206:16:206:28 | print_i64(...) | | | variables.rs:208:5:211:5 | ExprStmt | variables.rs:208:11:208:12 | tv | | -| variables.rs:208:5:211:5 | MatchExpr | variables.rs:212:11:212:12 | tv | | +| variables.rs:208:5:211:5 | match tv { ... } | variables.rs:212:11:212:12 | tv | | | variables.rs:208:11:208:12 | tv | variables.rs:209:10:209:31 | TupleStructPat | | -| variables.rs:209:9:209:83 | [match(true)] OrPat | variables.rs:210:16:210:24 | print_i64 | match | +| variables.rs:209:9:209:83 | [match(true)] ... \| ... | variables.rs:210:16:210:24 | print_i64 | match | | variables.rs:209:10:209:31 | TupleStructPat | variables.rs:209:29:209:30 | a5 | match | | variables.rs:209:10:209:31 | TupleStructPat | variables.rs:209:35:209:57 | TupleStructPat | no-match | -| variables.rs:209:10:209:57 | [match(false)] OrPat | variables.rs:209:62:209:83 | TupleStructPat | no-match | -| variables.rs:209:10:209:57 | [match(true)] OrPat | variables.rs:209:9:209:83 | [match(true)] OrPat | match | -| variables.rs:209:29:209:30 | a5 | variables.rs:209:10:209:57 | [match(true)] OrPat | match | -| variables.rs:209:35:209:57 | TupleStructPat | variables.rs:209:10:209:57 | [match(false)] OrPat | no-match | +| variables.rs:209:10:209:57 | [match(false)] ... \| ... | variables.rs:209:62:209:83 | TupleStructPat | no-match | +| variables.rs:209:10:209:57 | [match(true)] ... \| ... | variables.rs:209:9:209:83 | [match(true)] ... \| ... | match | +| variables.rs:209:29:209:30 | a5 | variables.rs:209:10:209:57 | [match(true)] ... \| ... | match | +| variables.rs:209:35:209:57 | TupleStructPat | variables.rs:209:10:209:57 | [match(false)] ... \| ... | no-match | | variables.rs:209:35:209:57 | TupleStructPat | variables.rs:209:55:209:56 | a5 | match | -| variables.rs:209:55:209:56 | a5 | variables.rs:209:10:209:57 | [match(true)] OrPat | match | +| variables.rs:209:55:209:56 | a5 | variables.rs:209:10:209:57 | [match(true)] ... \| ... | match | | variables.rs:209:62:209:83 | TupleStructPat | variables.rs:209:81:209:82 | a5 | match | -| variables.rs:209:81:209:82 | a5 | variables.rs:209:9:209:83 | [match(true)] OrPat | match | +| variables.rs:209:81:209:82 | a5 | variables.rs:209:9:209:83 | [match(true)] ... \| ... | match | | variables.rs:210:16:210:24 | print_i64 | variables.rs:210:26:210:27 | a5 | | -| variables.rs:210:16:210:28 | CallExpr | variables.rs:208:5:211:5 | MatchExpr | | -| variables.rs:210:26:210:27 | a5 | variables.rs:210:16:210:28 | CallExpr | | -| variables.rs:212:5:215:5 | MatchExpr | variables.rs:202:21:216:1 | BlockExpr | | +| variables.rs:210:16:210:28 | print_i64(...) | variables.rs:208:5:211:5 | match tv { ... } | | +| variables.rs:210:26:210:27 | a5 | variables.rs:210:16:210:28 | print_i64(...) | | +| variables.rs:212:5:215:5 | match tv { ... } | variables.rs:202:21:216:1 | { ... } | | | variables.rs:212:11:212:12 | tv | variables.rs:213:9:213:30 | TupleStructPat | | | variables.rs:213:9:213:30 | TupleStructPat | variables.rs:213:28:213:29 | a6 | match | | variables.rs:213:9:213:30 | TupleStructPat | variables.rs:213:35:213:57 | TupleStructPat | no-match | -| variables.rs:213:9:213:83 | [match(true)] OrPat | variables.rs:214:16:214:24 | print_i64 | match | -| variables.rs:213:28:213:29 | a6 | variables.rs:213:9:213:83 | [match(true)] OrPat | match | +| variables.rs:213:9:213:83 | [match(true)] ... \| ... | variables.rs:214:16:214:24 | print_i64 | match | +| variables.rs:213:28:213:29 | a6 | variables.rs:213:9:213:83 | [match(true)] ... \| ... | match | | variables.rs:213:35:213:57 | TupleStructPat | variables.rs:213:55:213:56 | a6 | match | | variables.rs:213:35:213:57 | TupleStructPat | variables.rs:213:61:213:82 | TupleStructPat | no-match | -| variables.rs:213:35:213:82 | [match(true)] OrPat | variables.rs:213:9:213:83 | [match(true)] OrPat | match | -| variables.rs:213:55:213:56 | a6 | variables.rs:213:35:213:82 | [match(true)] OrPat | match | +| variables.rs:213:35:213:82 | [match(true)] ... \| ... | variables.rs:213:9:213:83 | [match(true)] ... \| ... | match | +| variables.rs:213:55:213:56 | a6 | variables.rs:213:35:213:82 | [match(true)] ... \| ... | match | | variables.rs:213:61:213:82 | TupleStructPat | variables.rs:213:80:213:81 | a6 | match | -| variables.rs:213:80:213:81 | a6 | variables.rs:213:35:213:82 | [match(true)] OrPat | match | +| variables.rs:213:80:213:81 | a6 | variables.rs:213:35:213:82 | [match(true)] ... \| ... | match | | variables.rs:214:16:214:24 | print_i64 | variables.rs:214:26:214:27 | a6 | | -| variables.rs:214:16:214:28 | CallExpr | variables.rs:212:5:215:5 | MatchExpr | | -| variables.rs:214:26:214:27 | a6 | variables.rs:214:16:214:28 | CallExpr | | -| variables.rs:218:1:226:1 | enter match_pattern7 | variables.rs:219:5:219:34 | LetStmt | | -| variables.rs:218:1:226:1 | exit match_pattern7 (normal) | variables.rs:218:1:226:1 | exit match_pattern7 | | -| variables.rs:218:21:226:1 | BlockExpr | variables.rs:218:1:226:1 | exit match_pattern7 (normal) | | -| variables.rs:219:5:219:34 | LetStmt | variables.rs:219:18:219:29 | Either::Left | | +| variables.rs:214:16:214:28 | print_i64(...) | variables.rs:212:5:215:5 | match tv { ... } | | +| variables.rs:214:26:214:27 | a6 | variables.rs:214:16:214:28 | print_i64(...) | | +| variables.rs:218:1:226:1 | enter fn match_pattern7 | variables.rs:219:5:219:34 | let ... = ... | | +| variables.rs:218:1:226:1 | exit fn match_pattern7 (normal) | variables.rs:218:1:226:1 | exit fn match_pattern7 | | +| variables.rs:218:21:226:1 | { ... } | variables.rs:218:1:226:1 | exit fn match_pattern7 (normal) | | +| variables.rs:219:5:219:34 | let ... = ... | variables.rs:219:18:219:29 | ...::Left | | | variables.rs:219:9:219:14 | either | variables.rs:220:11:220:16 | either | match | -| variables.rs:219:18:219:29 | Either::Left | variables.rs:219:31:219:32 | 32 | | -| variables.rs:219:18:219:33 | CallExpr | variables.rs:219:9:219:14 | either | | -| variables.rs:219:31:219:32 | 32 | variables.rs:219:18:219:33 | CallExpr | | -| variables.rs:220:5:225:5 | MatchExpr | variables.rs:218:21:226:1 | BlockExpr | | +| variables.rs:219:18:219:29 | ...::Left | variables.rs:219:31:219:32 | 32 | | +| variables.rs:219:18:219:33 | ...::Left(...) | variables.rs:219:9:219:14 | either | | +| variables.rs:219:31:219:32 | 32 | variables.rs:219:18:219:33 | ...::Left(...) | | +| variables.rs:220:5:225:5 | match either { ... } | variables.rs:218:21:226:1 | { ... } | | | variables.rs:220:11:220:16 | either | variables.rs:221:9:221:24 | TupleStructPat | | | variables.rs:221:9:221:24 | TupleStructPat | variables.rs:221:22:221:23 | a7 | match | | variables.rs:221:9:221:24 | TupleStructPat | variables.rs:221:28:221:44 | TupleStructPat | no-match | -| variables.rs:221:9:221:44 | [match(false)] OrPat | variables.rs:224:9:224:9 | WildcardPat | no-match | -| variables.rs:221:9:221:44 | [match(true)] OrPat | variables.rs:222:16:222:17 | a7 | match | -| variables.rs:221:22:221:23 | a7 | variables.rs:221:9:221:44 | [match(true)] OrPat | match | -| variables.rs:221:28:221:44 | TupleStructPat | variables.rs:221:9:221:44 | [match(false)] OrPat | no-match | +| variables.rs:221:9:221:44 | [match(false)] ... \| ... | variables.rs:224:9:224:9 | _ | no-match | +| variables.rs:221:9:221:44 | [match(true)] ... \| ... | variables.rs:222:16:222:17 | a7 | match | +| variables.rs:221:22:221:23 | a7 | variables.rs:221:9:221:44 | [match(true)] ... \| ... | match | +| variables.rs:221:28:221:44 | TupleStructPat | variables.rs:221:9:221:44 | [match(false)] ... \| ... | no-match | | variables.rs:221:28:221:44 | TupleStructPat | variables.rs:221:42:221:43 | a7 | match | -| variables.rs:221:42:221:43 | a7 | variables.rs:221:9:221:44 | [match(true)] OrPat | match | +| variables.rs:221:42:221:43 | a7 | variables.rs:221:9:221:44 | [match(true)] ... \| ... | match | | variables.rs:222:16:222:17 | a7 | variables.rs:222:21:222:21 | 0 | | | variables.rs:222:16:222:21 | ... > ... | variables.rs:223:16:223:24 | print_i64 | true | -| variables.rs:222:16:222:21 | ... > ... | variables.rs:224:9:224:9 | WildcardPat | false | +| variables.rs:222:16:222:21 | ... > ... | variables.rs:224:9:224:9 | _ | false | | variables.rs:222:21:222:21 | 0 | variables.rs:222:16:222:21 | ... > ... | | | variables.rs:223:16:223:24 | print_i64 | variables.rs:223:26:223:27 | a7 | | -| variables.rs:223:16:223:28 | CallExpr | variables.rs:220:5:225:5 | MatchExpr | | -| variables.rs:223:26:223:27 | a7 | variables.rs:223:16:223:28 | CallExpr | | -| variables.rs:224:9:224:9 | WildcardPat | variables.rs:224:14:224:15 | TupleExpr | match | -| variables.rs:224:14:224:15 | TupleExpr | variables.rs:220:5:225:5 | MatchExpr | | -| variables.rs:228:1:243:1 | enter match_pattern8 | variables.rs:229:5:229:34 | LetStmt | | -| variables.rs:228:1:243:1 | exit match_pattern8 (normal) | variables.rs:228:1:243:1 | exit match_pattern8 | | -| variables.rs:228:21:243:1 | BlockExpr | variables.rs:228:1:243:1 | exit match_pattern8 (normal) | | -| variables.rs:229:5:229:34 | LetStmt | variables.rs:229:18:229:29 | Either::Left | | +| variables.rs:223:16:223:28 | print_i64(...) | variables.rs:220:5:225:5 | match either { ... } | | +| variables.rs:223:26:223:27 | a7 | variables.rs:223:16:223:28 | print_i64(...) | | +| variables.rs:224:9:224:9 | _ | variables.rs:224:14:224:15 | TupleExpr | match | +| variables.rs:224:14:224:15 | TupleExpr | variables.rs:220:5:225:5 | match either { ... } | | +| variables.rs:228:1:243:1 | enter fn match_pattern8 | variables.rs:229:5:229:34 | let ... = ... | | +| variables.rs:228:1:243:1 | exit fn match_pattern8 (normal) | variables.rs:228:1:243:1 | exit fn match_pattern8 | | +| variables.rs:228:21:243:1 | { ... } | variables.rs:228:1:243:1 | exit fn match_pattern8 (normal) | | +| variables.rs:229:5:229:34 | let ... = ... | variables.rs:229:18:229:29 | ...::Left | | | variables.rs:229:9:229:14 | either | variables.rs:231:11:231:16 | either | match | -| variables.rs:229:18:229:29 | Either::Left | variables.rs:229:31:229:32 | 32 | | -| variables.rs:229:18:229:33 | CallExpr | variables.rs:229:9:229:14 | either | | -| variables.rs:229:31:229:32 | 32 | variables.rs:229:18:229:33 | CallExpr | | -| variables.rs:231:5:242:5 | MatchExpr | variables.rs:228:21:243:1 | BlockExpr | | +| variables.rs:229:18:229:29 | ...::Left | variables.rs:229:31:229:32 | 32 | | +| variables.rs:229:18:229:33 | ...::Left(...) | variables.rs:229:9:229:14 | either | | +| variables.rs:229:31:229:32 | 32 | variables.rs:229:18:229:33 | ...::Left(...) | | +| variables.rs:231:5:242:5 | match either { ... } | variables.rs:228:21:243:1 | { ... } | | | variables.rs:231:11:231:16 | either | variables.rs:233:14:233:30 | TupleStructPat | | | variables.rs:232:9:233:52 | [match(true)] e | variables.rs:235:13:235:27 | ExprStmt | match | | variables.rs:233:14:233:30 | TupleStructPat | variables.rs:233:27:233:29 | a11 | match | | variables.rs:233:14:233:30 | TupleStructPat | variables.rs:233:34:233:51 | TupleStructPat | no-match | -| variables.rs:233:14:233:51 | [match(false)] OrPat | variables.rs:241:9:241:9 | WildcardPat | no-match | -| variables.rs:233:14:233:51 | [match(true)] OrPat | variables.rs:232:9:233:52 | [match(true)] e | match | -| variables.rs:233:27:233:29 | a11 | variables.rs:233:14:233:51 | [match(true)] OrPat | match | -| variables.rs:233:34:233:51 | TupleStructPat | variables.rs:233:14:233:51 | [match(false)] OrPat | no-match | +| variables.rs:233:14:233:51 | [match(false)] ... \| ... | variables.rs:241:9:241:9 | _ | no-match | +| variables.rs:233:14:233:51 | [match(true)] ... \| ... | variables.rs:232:9:233:52 | [match(true)] e | match | +| variables.rs:233:27:233:29 | a11 | variables.rs:233:14:233:51 | [match(true)] ... \| ... | match | +| variables.rs:233:34:233:51 | TupleStructPat | variables.rs:233:14:233:51 | [match(false)] ... \| ... | no-match | | variables.rs:233:34:233:51 | TupleStructPat | variables.rs:233:48:233:50 | a11 | match | -| variables.rs:233:48:233:50 | a11 | variables.rs:233:14:233:51 | [match(true)] OrPat | match | -| variables.rs:234:12:240:9 | BlockExpr | variables.rs:231:5:242:5 | MatchExpr | | +| variables.rs:233:48:233:50 | a11 | variables.rs:233:14:233:51 | [match(true)] ... \| ... | match | +| variables.rs:234:12:240:9 | { ... } | variables.rs:231:5:242:5 | match either { ... } | | | variables.rs:235:13:235:21 | print_i64 | variables.rs:235:23:235:25 | a11 | | -| variables.rs:235:13:235:26 | CallExpr | variables.rs:236:16:237:15 | LetExpr | | +| variables.rs:235:13:235:26 | print_i64(...) | variables.rs:236:16:237:15 | let ... = e | | | variables.rs:235:13:235:27 | ExprStmt | variables.rs:235:13:235:21 | print_i64 | | -| variables.rs:235:23:235:25 | a11 | variables.rs:235:13:235:26 | CallExpr | | -| variables.rs:236:13:239:13 | IfExpr | variables.rs:234:12:240:9 | BlockExpr | | -| variables.rs:236:16:237:15 | LetExpr | variables.rs:237:15:237:15 | e | | -| variables.rs:236:20:236:36 | TupleStructPat | variables.rs:236:13:239:13 | IfExpr | no-match | +| variables.rs:235:23:235:25 | a11 | variables.rs:235:13:235:26 | print_i64(...) | | +| variables.rs:236:13:239:13 | if ... {...} | variables.rs:234:12:240:9 | { ... } | | +| variables.rs:236:16:237:15 | let ... = e | variables.rs:237:15:237:15 | e | | +| variables.rs:236:20:236:36 | TupleStructPat | variables.rs:236:13:239:13 | if ... {...} | no-match | | variables.rs:236:20:236:36 | TupleStructPat | variables.rs:236:33:236:35 | a12 | match | | variables.rs:236:33:236:35 | a12 | variables.rs:238:17:238:32 | ExprStmt | match | | variables.rs:237:15:237:15 | e | variables.rs:236:20:236:36 | TupleStructPat | | -| variables.rs:237:17:239:13 | BlockExpr | variables.rs:236:13:239:13 | IfExpr | | +| variables.rs:237:17:239:13 | { ... } | variables.rs:236:13:239:13 | if ... {...} | | | variables.rs:238:17:238:25 | print_i64 | variables.rs:238:28:238:30 | a12 | | -| variables.rs:238:17:238:31 | CallExpr | variables.rs:237:17:239:13 | BlockExpr | | +| variables.rs:238:17:238:31 | print_i64(...) | variables.rs:237:17:239:13 | { ... } | | | variables.rs:238:17:238:32 | ExprStmt | variables.rs:238:17:238:25 | print_i64 | | -| variables.rs:238:27:238:30 | * ... | variables.rs:238:17:238:31 | CallExpr | | +| variables.rs:238:27:238:30 | * ... | variables.rs:238:17:238:31 | print_i64(...) | | | variables.rs:238:28:238:30 | a12 | variables.rs:238:27:238:30 | * ... | | -| variables.rs:241:9:241:9 | WildcardPat | variables.rs:241:14:241:15 | TupleExpr | match | -| variables.rs:241:14:241:15 | TupleExpr | variables.rs:231:5:242:5 | MatchExpr | | -| variables.rs:252:1:258:1 | enter match_pattern9 | variables.rs:253:5:253:36 | LetStmt | | -| variables.rs:252:1:258:1 | exit match_pattern9 (normal) | variables.rs:252:1:258:1 | exit match_pattern9 | | -| variables.rs:252:21:258:1 | BlockExpr | variables.rs:252:1:258:1 | exit match_pattern9 (normal) | | -| variables.rs:253:5:253:36 | LetStmt | variables.rs:253:14:253:31 | FourValued::Second | | +| variables.rs:241:9:241:9 | _ | variables.rs:241:14:241:15 | TupleExpr | match | +| variables.rs:241:14:241:15 | TupleExpr | variables.rs:231:5:242:5 | match either { ... } | | +| variables.rs:252:1:258:1 | enter fn match_pattern9 | variables.rs:253:5:253:36 | let ... = ... | | +| variables.rs:252:1:258:1 | exit fn match_pattern9 (normal) | variables.rs:252:1:258:1 | exit fn match_pattern9 | | +| variables.rs:252:21:258:1 | { ... } | variables.rs:252:1:258:1 | exit fn match_pattern9 (normal) | | +| variables.rs:253:5:253:36 | let ... = ... | variables.rs:253:14:253:31 | ...::Second | | | variables.rs:253:9:253:10 | fv | variables.rs:254:11:254:12 | fv | match | -| variables.rs:253:14:253:31 | FourValued::Second | variables.rs:253:33:253:34 | 62 | | -| variables.rs:253:14:253:35 | CallExpr | variables.rs:253:9:253:10 | fv | | -| variables.rs:253:33:253:34 | 62 | variables.rs:253:14:253:35 | CallExpr | | -| variables.rs:254:5:257:5 | MatchExpr | variables.rs:252:21:258:1 | BlockExpr | | +| variables.rs:253:14:253:31 | ...::Second | variables.rs:253:33:253:34 | 62 | | +| variables.rs:253:14:253:35 | ...::Second(...) | variables.rs:253:9:253:10 | fv | | +| variables.rs:253:33:253:34 | 62 | variables.rs:253:14:253:35 | ...::Second(...) | | +| variables.rs:254:5:257:5 | match fv { ... } | variables.rs:252:21:258:1 | { ... } | | | variables.rs:254:11:254:12 | fv | variables.rs:255:9:255:30 | TupleStructPat | | | variables.rs:255:9:255:30 | TupleStructPat | variables.rs:255:27:255:29 | a13 | match | | variables.rs:255:9:255:30 | TupleStructPat | variables.rs:255:35:255:57 | TupleStructPat | no-match | -| variables.rs:255:9:255:109 | [match(true)] OrPat | variables.rs:256:16:256:24 | print_i64 | match | -| variables.rs:255:27:255:29 | a13 | variables.rs:255:9:255:109 | [match(true)] OrPat | match | +| variables.rs:255:9:255:109 | [match(true)] ... \| ... \| ... | variables.rs:256:16:256:24 | print_i64 | match | +| variables.rs:255:27:255:29 | a13 | variables.rs:255:9:255:109 | [match(true)] ... \| ... \| ... | match | | variables.rs:255:35:255:57 | TupleStructPat | variables.rs:255:54:255:56 | a13 | match | | variables.rs:255:35:255:57 | TupleStructPat | variables.rs:255:61:255:82 | TupleStructPat | no-match | -| variables.rs:255:35:255:82 | [match(false)] OrPat | variables.rs:255:87:255:109 | TupleStructPat | no-match | -| variables.rs:255:35:255:82 | [match(true)] OrPat | variables.rs:255:9:255:109 | [match(true)] OrPat | match | -| variables.rs:255:54:255:56 | a13 | variables.rs:255:35:255:82 | [match(true)] OrPat | match | -| variables.rs:255:61:255:82 | TupleStructPat | variables.rs:255:35:255:82 | [match(false)] OrPat | no-match | +| variables.rs:255:35:255:82 | [match(false)] ... \| ... | variables.rs:255:87:255:109 | TupleStructPat | no-match | +| variables.rs:255:35:255:82 | [match(true)] ... \| ... | variables.rs:255:9:255:109 | [match(true)] ... \| ... \| ... | match | +| variables.rs:255:54:255:56 | a13 | variables.rs:255:35:255:82 | [match(true)] ... \| ... | match | +| variables.rs:255:61:255:82 | TupleStructPat | variables.rs:255:35:255:82 | [match(false)] ... \| ... | no-match | | variables.rs:255:61:255:82 | TupleStructPat | variables.rs:255:79:255:81 | a13 | match | -| variables.rs:255:79:255:81 | a13 | variables.rs:255:35:255:82 | [match(true)] OrPat | match | +| variables.rs:255:79:255:81 | a13 | variables.rs:255:35:255:82 | [match(true)] ... \| ... | match | | variables.rs:255:87:255:109 | TupleStructPat | variables.rs:255:106:255:108 | a13 | match | -| variables.rs:255:106:255:108 | a13 | variables.rs:255:9:255:109 | [match(true)] OrPat | match | +| variables.rs:255:106:255:108 | a13 | variables.rs:255:9:255:109 | [match(true)] ... \| ... \| ... | match | | variables.rs:256:16:256:24 | print_i64 | variables.rs:256:26:256:28 | a13 | | -| variables.rs:256:16:256:29 | CallExpr | variables.rs:254:5:257:5 | MatchExpr | | -| variables.rs:256:26:256:28 | a13 | variables.rs:256:16:256:29 | CallExpr | | -| variables.rs:260:1:269:1 | enter param_pattern1 | variables.rs:261:5:261:6 | a8 | | -| variables.rs:260:1:269:1 | exit param_pattern1 (normal) | variables.rs:260:1:269:1 | exit param_pattern1 | | -| variables.rs:261:5:261:6 | a8 | variables.rs:261:5:261:12 | Param | match | -| variables.rs:261:5:261:12 | Param | variables.rs:262:5:265:5 | TuplePat | | +| variables.rs:256:16:256:29 | print_i64(...) | variables.rs:254:5:257:5 | match fv { ... } | | +| variables.rs:256:26:256:28 | a13 | variables.rs:256:16:256:29 | print_i64(...) | | +| variables.rs:260:1:269:1 | enter fn param_pattern1 | variables.rs:261:5:261:6 | a8 | | +| variables.rs:260:1:269:1 | exit fn param_pattern1 (normal) | variables.rs:260:1:269:1 | exit fn param_pattern1 | | +| variables.rs:261:5:261:6 | a8 | variables.rs:261:5:261:12 | ...: ... | match | +| variables.rs:261:5:261:12 | ...: ... | variables.rs:262:5:265:5 | TuplePat | | | variables.rs:262:5:265:5 | TuplePat | variables.rs:263:9:263:10 | b3 | match | -| variables.rs:262:5:265:19 | Param | variables.rs:266:5:266:18 | ExprStmt | | +| variables.rs:262:5:265:19 | ...: ... | variables.rs:266:5:266:18 | ExprStmt | | | variables.rs:263:9:263:10 | b3 | variables.rs:264:9:264:10 | c1 | match | -| variables.rs:264:9:264:10 | c1 | variables.rs:262:5:265:19 | Param | match | -| variables.rs:265:28:269:1 | BlockExpr | variables.rs:260:1:269:1 | exit param_pattern1 (normal) | | +| variables.rs:264:9:264:10 | c1 | variables.rs:262:5:265:19 | ...: ... | match | +| variables.rs:265:28:269:1 | { ... } | variables.rs:260:1:269:1 | exit fn param_pattern1 (normal) | | | variables.rs:266:5:266:13 | print_str | variables.rs:266:15:266:16 | a8 | | -| variables.rs:266:5:266:17 | CallExpr | variables.rs:267:5:267:18 | ExprStmt | | +| variables.rs:266:5:266:17 | print_str(...) | variables.rs:267:5:267:18 | ExprStmt | | | variables.rs:266:5:266:18 | ExprStmt | variables.rs:266:5:266:13 | print_str | | -| variables.rs:266:15:266:16 | a8 | variables.rs:266:5:266:17 | CallExpr | | +| variables.rs:266:15:266:16 | a8 | variables.rs:266:5:266:17 | print_str(...) | | | variables.rs:267:5:267:13 | print_str | variables.rs:267:15:267:16 | b3 | | -| variables.rs:267:5:267:17 | CallExpr | variables.rs:268:5:268:18 | ExprStmt | | +| variables.rs:267:5:267:17 | print_str(...) | variables.rs:268:5:268:18 | ExprStmt | | | variables.rs:267:5:267:18 | ExprStmt | variables.rs:267:5:267:13 | print_str | | -| variables.rs:267:15:267:16 | b3 | variables.rs:267:5:267:17 | CallExpr | | +| variables.rs:267:15:267:16 | b3 | variables.rs:267:5:267:17 | print_str(...) | | | variables.rs:268:5:268:13 | print_str | variables.rs:268:15:268:16 | c1 | | -| variables.rs:268:5:268:17 | CallExpr | variables.rs:265:28:269:1 | BlockExpr | | +| variables.rs:268:5:268:17 | print_str(...) | variables.rs:265:28:269:1 | { ... } | | | variables.rs:268:5:268:18 | ExprStmt | variables.rs:268:5:268:13 | print_str | | -| variables.rs:268:15:268:16 | c1 | variables.rs:268:5:268:17 | CallExpr | | -| variables.rs:271:1:275:1 | enter param_pattern2 | variables.rs:272:6:272:21 | TupleStructPat | | -| variables.rs:271:1:275:1 | exit param_pattern2 (normal) | variables.rs:271:1:275:1 | exit param_pattern2 | | -| variables.rs:272:5:272:50 | Param | variables.rs:274:5:274:18 | ExprStmt | | +| variables.rs:268:15:268:16 | c1 | variables.rs:268:5:268:17 | print_str(...) | | +| variables.rs:271:1:275:1 | enter fn param_pattern2 | variables.rs:272:6:272:21 | TupleStructPat | | +| variables.rs:271:1:275:1 | exit fn param_pattern2 (normal) | variables.rs:271:1:275:1 | exit fn param_pattern2 | | +| variables.rs:272:5:272:50 | ...: Either | variables.rs:274:5:274:18 | ExprStmt | | | variables.rs:272:6:272:21 | TupleStructPat | variables.rs:272:19:272:20 | a9 | match | | variables.rs:272:6:272:21 | TupleStructPat | variables.rs:272:25:272:41 | TupleStructPat | no-match | -| variables.rs:272:6:272:41 | [match(true)] OrPat | variables.rs:272:5:272:50 | Param | match | -| variables.rs:272:19:272:20 | a9 | variables.rs:272:6:272:41 | [match(true)] OrPat | match | +| variables.rs:272:6:272:41 | [match(true)] ... \| ... | variables.rs:272:5:272:50 | ...: Either | match | +| variables.rs:272:19:272:20 | a9 | variables.rs:272:6:272:41 | [match(true)] ... \| ... | match | | variables.rs:272:25:272:41 | TupleStructPat | variables.rs:272:39:272:40 | a9 | match | -| variables.rs:272:39:272:40 | a9 | variables.rs:272:6:272:41 | [match(true)] OrPat | match | -| variables.rs:273:9:275:1 | BlockExpr | variables.rs:271:1:275:1 | exit param_pattern2 (normal) | | +| variables.rs:272:39:272:40 | a9 | variables.rs:272:6:272:41 | [match(true)] ... \| ... | match | +| variables.rs:273:9:275:1 | { ... } | variables.rs:271:1:275:1 | exit fn param_pattern2 (normal) | | | variables.rs:274:5:274:13 | print_i64 | variables.rs:274:15:274:16 | a9 | | -| variables.rs:274:5:274:17 | CallExpr | variables.rs:273:9:275:1 | BlockExpr | | +| variables.rs:274:5:274:17 | print_i64(...) | variables.rs:273:9:275:1 | { ... } | | | variables.rs:274:5:274:18 | ExprStmt | variables.rs:274:5:274:13 | print_i64 | | -| variables.rs:274:15:274:16 | a9 | variables.rs:274:5:274:17 | CallExpr | | -| variables.rs:277:1:312:1 | enter destruct_assignment | variables.rs:278:5:282:18 | LetStmt | | -| variables.rs:277:1:312:1 | exit destruct_assignment (normal) | variables.rs:277:1:312:1 | exit destruct_assignment | | -| variables.rs:277:26:312:1 | BlockExpr | variables.rs:277:1:312:1 | exit destruct_assignment (normal) | | -| variables.rs:278:5:282:18 | LetStmt | variables.rs:282:10:282:10 | 1 | | +| variables.rs:274:15:274:16 | a9 | variables.rs:274:5:274:17 | print_i64(...) | | +| variables.rs:277:1:312:1 | enter fn destruct_assignment | variables.rs:278:5:282:18 | let ... = ... | | +| variables.rs:277:1:312:1 | exit fn destruct_assignment (normal) | variables.rs:277:1:312:1 | exit fn destruct_assignment | | +| variables.rs:277:26:312:1 | { ... } | variables.rs:277:1:312:1 | exit fn destruct_assignment (normal) | | +| variables.rs:278:5:282:18 | let ... = ... | variables.rs:282:10:282:10 | 1 | | | variables.rs:278:9:282:5 | TuplePat | variables.rs:279:9:279:15 | a10 | match | | variables.rs:279:9:279:15 | a10 | variables.rs:280:9:280:14 | b4 | match | | variables.rs:280:9:280:14 | b4 | variables.rs:281:9:281:14 | c2 | match | @@ -609,17 +609,17 @@ edges | variables.rs:282:13:282:13 | 2 | variables.rs:282:16:282:16 | 3 | | | variables.rs:282:16:282:16 | 3 | variables.rs:282:9:282:17 | TupleExpr | | | variables.rs:283:5:283:13 | print_i64 | variables.rs:283:15:283:17 | a10 | | -| variables.rs:283:5:283:18 | CallExpr | variables.rs:284:5:284:18 | ExprStmt | | +| variables.rs:283:5:283:18 | print_i64(...) | variables.rs:284:5:284:18 | ExprStmt | | | variables.rs:283:5:283:19 | ExprStmt | variables.rs:283:5:283:13 | print_i64 | | -| variables.rs:283:15:283:17 | a10 | variables.rs:283:5:283:18 | CallExpr | | +| variables.rs:283:15:283:17 | a10 | variables.rs:283:5:283:18 | print_i64(...) | | | variables.rs:284:5:284:13 | print_i64 | variables.rs:284:15:284:16 | b4 | | -| variables.rs:284:5:284:17 | CallExpr | variables.rs:285:5:285:18 | ExprStmt | | +| variables.rs:284:5:284:17 | print_i64(...) | variables.rs:285:5:285:18 | ExprStmt | | | variables.rs:284:5:284:18 | ExprStmt | variables.rs:284:5:284:13 | print_i64 | | -| variables.rs:284:15:284:16 | b4 | variables.rs:284:5:284:17 | CallExpr | | +| variables.rs:284:15:284:16 | b4 | variables.rs:284:5:284:17 | print_i64(...) | | | variables.rs:285:5:285:13 | print_i64 | variables.rs:285:15:285:16 | c2 | | -| variables.rs:285:5:285:17 | CallExpr | variables.rs:287:5:295:6 | ExprStmt | | +| variables.rs:285:5:285:17 | print_i64(...) | variables.rs:287:5:295:6 | ExprStmt | | | variables.rs:285:5:285:18 | ExprStmt | variables.rs:285:5:285:13 | print_i64 | | -| variables.rs:285:15:285:16 | c2 | variables.rs:285:5:285:17 | CallExpr | | +| variables.rs:285:15:285:16 | c2 | variables.rs:285:5:285:17 | print_i64(...) | | | variables.rs:287:5:291:5 | TupleExpr | variables.rs:292:9:292:11 | a10 | | | variables.rs:287:5:295:5 | ... = ... | variables.rs:296:5:296:19 | ExprStmt | | | variables.rs:287:5:295:6 | ExprStmt | variables.rs:288:9:288:10 | c2 | | @@ -631,105 +631,105 @@ edges | variables.rs:293:9:293:10 | b4 | variables.rs:294:9:294:10 | c2 | | | variables.rs:294:9:294:10 | c2 | variables.rs:291:9:295:5 | TupleExpr | | | variables.rs:296:5:296:13 | print_i64 | variables.rs:296:15:296:17 | a10 | | -| variables.rs:296:5:296:18 | CallExpr | variables.rs:297:5:297:18 | ExprStmt | | +| variables.rs:296:5:296:18 | print_i64(...) | variables.rs:297:5:297:18 | ExprStmt | | | variables.rs:296:5:296:19 | ExprStmt | variables.rs:296:5:296:13 | print_i64 | | -| variables.rs:296:15:296:17 | a10 | variables.rs:296:5:296:18 | CallExpr | | +| variables.rs:296:15:296:17 | a10 | variables.rs:296:5:296:18 | print_i64(...) | | | variables.rs:297:5:297:13 | print_i64 | variables.rs:297:15:297:16 | b4 | | -| variables.rs:297:5:297:17 | CallExpr | variables.rs:298:5:298:18 | ExprStmt | | +| variables.rs:297:5:297:17 | print_i64(...) | variables.rs:298:5:298:18 | ExprStmt | | | variables.rs:297:5:297:18 | ExprStmt | variables.rs:297:5:297:13 | print_i64 | | -| variables.rs:297:15:297:16 | b4 | variables.rs:297:5:297:17 | CallExpr | | +| variables.rs:297:15:297:16 | b4 | variables.rs:297:5:297:17 | print_i64(...) | | | variables.rs:298:5:298:13 | print_i64 | variables.rs:298:15:298:16 | c2 | | -| variables.rs:298:5:298:17 | CallExpr | variables.rs:300:5:308:5 | ExprStmt | | +| variables.rs:298:5:298:17 | print_i64(...) | variables.rs:300:5:308:5 | ExprStmt | | | variables.rs:298:5:298:18 | ExprStmt | variables.rs:298:5:298:13 | print_i64 | | -| variables.rs:298:15:298:16 | c2 | variables.rs:298:5:298:17 | CallExpr | | +| variables.rs:298:15:298:16 | c2 | variables.rs:298:5:298:17 | print_i64(...) | | | variables.rs:300:5:308:5 | ExprStmt | variables.rs:300:12:300:12 | 4 | | -| variables.rs:300:5:308:5 | MatchExpr | variables.rs:310:5:310:19 | ExprStmt | | +| variables.rs:300:5:308:5 | match ... { ... } | variables.rs:310:5:310:19 | ExprStmt | | | variables.rs:300:11:300:16 | TupleExpr | variables.rs:301:9:304:9 | TuplePat | | | variables.rs:300:12:300:12 | 4 | variables.rs:300:15:300:15 | 5 | | | variables.rs:300:15:300:15 | 5 | variables.rs:300:11:300:16 | TupleExpr | | | variables.rs:301:9:304:9 | TuplePat | variables.rs:302:13:302:15 | a10 | match | | variables.rs:302:13:302:15 | a10 | variables.rs:303:13:303:14 | b4 | match | | variables.rs:303:13:303:14 | b4 | variables.rs:305:13:305:27 | ExprStmt | match | -| variables.rs:304:14:307:9 | BlockExpr | variables.rs:300:5:308:5 | MatchExpr | | +| variables.rs:304:14:307:9 | { ... } | variables.rs:300:5:308:5 | match ... { ... } | | | variables.rs:305:13:305:21 | print_i64 | variables.rs:305:23:305:25 | a10 | | -| variables.rs:305:13:305:26 | CallExpr | variables.rs:306:13:306:26 | ExprStmt | | +| variables.rs:305:13:305:26 | print_i64(...) | variables.rs:306:13:306:26 | ExprStmt | | | variables.rs:305:13:305:27 | ExprStmt | variables.rs:305:13:305:21 | print_i64 | | -| variables.rs:305:23:305:25 | a10 | variables.rs:305:13:305:26 | CallExpr | | +| variables.rs:305:23:305:25 | a10 | variables.rs:305:13:305:26 | print_i64(...) | | | variables.rs:306:13:306:21 | print_i64 | variables.rs:306:23:306:24 | b4 | | -| variables.rs:306:13:306:25 | CallExpr | variables.rs:304:14:307:9 | BlockExpr | | +| variables.rs:306:13:306:25 | print_i64(...) | variables.rs:304:14:307:9 | { ... } | | | variables.rs:306:13:306:26 | ExprStmt | variables.rs:306:13:306:21 | print_i64 | | -| variables.rs:306:23:306:24 | b4 | variables.rs:306:13:306:25 | CallExpr | | +| variables.rs:306:23:306:24 | b4 | variables.rs:306:13:306:25 | print_i64(...) | | | variables.rs:310:5:310:13 | print_i64 | variables.rs:310:15:310:17 | a10 | | -| variables.rs:310:5:310:18 | CallExpr | variables.rs:311:5:311:18 | ExprStmt | | +| variables.rs:310:5:310:18 | print_i64(...) | variables.rs:311:5:311:18 | ExprStmt | | | variables.rs:310:5:310:19 | ExprStmt | variables.rs:310:5:310:13 | print_i64 | | -| variables.rs:310:15:310:17 | a10 | variables.rs:310:5:310:18 | CallExpr | | +| variables.rs:310:15:310:17 | a10 | variables.rs:310:5:310:18 | print_i64(...) | | | variables.rs:311:5:311:13 | print_i64 | variables.rs:311:15:311:16 | b4 | | -| variables.rs:311:5:311:17 | CallExpr | variables.rs:277:26:312:1 | BlockExpr | | +| variables.rs:311:5:311:17 | print_i64(...) | variables.rs:277:26:312:1 | { ... } | | | variables.rs:311:5:311:18 | ExprStmt | variables.rs:311:5:311:13 | print_i64 | | -| variables.rs:311:15:311:16 | b4 | variables.rs:311:5:311:17 | CallExpr | | -| variables.rs:314:1:329:1 | enter closure_variable | variables.rs:315:5:317:10 | LetStmt | | -| variables.rs:314:1:329:1 | exit closure_variable (normal) | variables.rs:314:1:329:1 | exit closure_variable | | -| variables.rs:314:23:329:1 | BlockExpr | variables.rs:314:1:329:1 | exit closure_variable (normal) | | -| variables.rs:315:5:317:10 | LetStmt | variables.rs:316:9:317:9 | ClosureExpr | | -| variables.rs:315:9:315:23 | example_closure | variables.rs:318:5:319:27 | LetStmt | match | -| variables.rs:316:9:317:9 | ClosureExpr | variables.rs:315:9:315:23 | example_closure | | -| variables.rs:316:9:317:9 | enter ClosureExpr | variables.rs:316:10:316:10 | x | | -| variables.rs:316:9:317:9 | exit ClosureExpr (normal) | variables.rs:316:9:317:9 | exit ClosureExpr | | -| variables.rs:316:10:316:10 | x | variables.rs:316:10:316:15 | Param | match | -| variables.rs:316:10:316:15 | Param | variables.rs:317:9:317:9 | x | | -| variables.rs:317:9:317:9 | x | variables.rs:316:9:317:9 | exit ClosureExpr (normal) | | -| variables.rs:318:5:319:27 | LetStmt | variables.rs:319:9:319:23 | example_closure | | +| variables.rs:311:15:311:16 | b4 | variables.rs:311:5:311:17 | print_i64(...) | | +| variables.rs:314:1:329:1 | enter fn closure_variable | variables.rs:315:5:317:10 | let ... = ... | | +| variables.rs:314:1:329:1 | exit fn closure_variable (normal) | variables.rs:314:1:329:1 | exit fn closure_variable | | +| variables.rs:314:23:329:1 | { ... } | variables.rs:314:1:329:1 | exit fn closure_variable (normal) | | +| variables.rs:315:5:317:10 | let ... = ... | variables.rs:316:9:317:9 | \|...\| x | | +| variables.rs:315:9:315:23 | example_closure | variables.rs:318:5:319:27 | let ... = ... | match | +| variables.rs:316:9:317:9 | \|...\| x | variables.rs:315:9:315:23 | example_closure | | +| variables.rs:316:9:317:9 | enter \|...\| x | variables.rs:316:10:316:10 | x | | +| variables.rs:316:9:317:9 | exit \|...\| x (normal) | variables.rs:316:9:317:9 | exit \|...\| x | | +| variables.rs:316:10:316:10 | x | variables.rs:316:10:316:15 | ...: i64 | match | +| variables.rs:316:10:316:15 | ...: i64 | variables.rs:317:9:317:9 | x | | +| variables.rs:317:9:317:9 | x | variables.rs:316:9:317:9 | exit \|...\| x (normal) | | +| variables.rs:318:5:319:27 | let ... = ... | variables.rs:319:9:319:23 | example_closure | | | variables.rs:318:9:318:10 | n1 | variables.rs:320:5:320:18 | ExprStmt | match | | variables.rs:319:9:319:23 | example_closure | variables.rs:319:25:319:25 | 5 | | -| variables.rs:319:9:319:26 | CallExpr | variables.rs:318:9:318:10 | n1 | | -| variables.rs:319:25:319:25 | 5 | variables.rs:319:9:319:26 | CallExpr | | +| variables.rs:319:9:319:26 | example_closure(...) | variables.rs:318:9:318:10 | n1 | | +| variables.rs:319:25:319:25 | 5 | variables.rs:319:9:319:26 | example_closure(...) | | | variables.rs:320:5:320:13 | print_i64 | variables.rs:320:15:320:16 | n1 | | -| variables.rs:320:5:320:17 | CallExpr | variables.rs:322:5:322:25 | ExprStmt | | +| variables.rs:320:5:320:17 | print_i64(...) | variables.rs:322:5:322:25 | ExprStmt | | | variables.rs:320:5:320:18 | ExprStmt | variables.rs:320:5:320:13 | print_i64 | | -| variables.rs:320:15:320:16 | n1 | variables.rs:320:5:320:17 | CallExpr | | -| variables.rs:322:5:322:22 | immutable_variable | variables.rs:322:5:322:24 | CallExpr | | -| variables.rs:322:5:322:24 | CallExpr | variables.rs:323:5:325:10 | LetStmt | | +| variables.rs:320:15:320:16 | n1 | variables.rs:320:5:320:17 | print_i64(...) | | +| variables.rs:322:5:322:22 | immutable_variable | variables.rs:322:5:322:24 | immutable_variable(...) | | +| variables.rs:322:5:322:24 | immutable_variable(...) | variables.rs:323:5:325:10 | let ... = ... | | | variables.rs:322:5:322:25 | ExprStmt | variables.rs:322:5:322:22 | immutable_variable | | -| variables.rs:323:5:325:10 | LetStmt | variables.rs:324:9:325:9 | ClosureExpr | | -| variables.rs:323:9:323:26 | immutable_variable | variables.rs:326:5:327:30 | LetStmt | match | -| variables.rs:324:9:325:9 | ClosureExpr | variables.rs:323:9:323:26 | immutable_variable | | -| variables.rs:324:9:325:9 | enter ClosureExpr | variables.rs:324:10:324:10 | x | | -| variables.rs:324:9:325:9 | exit ClosureExpr (normal) | variables.rs:324:9:325:9 | exit ClosureExpr | | -| variables.rs:324:10:324:10 | x | variables.rs:324:10:324:15 | Param | match | -| variables.rs:324:10:324:15 | Param | variables.rs:325:9:325:9 | x | | -| variables.rs:325:9:325:9 | x | variables.rs:324:9:325:9 | exit ClosureExpr (normal) | | -| variables.rs:326:5:327:30 | LetStmt | variables.rs:327:9:327:26 | immutable_variable | | +| variables.rs:323:5:325:10 | let ... = ... | variables.rs:324:9:325:9 | \|...\| x | | +| variables.rs:323:9:323:26 | immutable_variable | variables.rs:326:5:327:30 | let ... = ... | match | +| variables.rs:324:9:325:9 | \|...\| x | variables.rs:323:9:323:26 | immutable_variable | | +| variables.rs:324:9:325:9 | enter \|...\| x | variables.rs:324:10:324:10 | x | | +| variables.rs:324:9:325:9 | exit \|...\| x (normal) | variables.rs:324:9:325:9 | exit \|...\| x | | +| variables.rs:324:10:324:10 | x | variables.rs:324:10:324:15 | ...: i64 | match | +| variables.rs:324:10:324:15 | ...: i64 | variables.rs:325:9:325:9 | x | | +| variables.rs:325:9:325:9 | x | variables.rs:324:9:325:9 | exit \|...\| x (normal) | | +| variables.rs:326:5:327:30 | let ... = ... | variables.rs:327:9:327:26 | immutable_variable | | | variables.rs:326:9:326:10 | n2 | variables.rs:328:5:328:18 | ExprStmt | match | | variables.rs:327:9:327:26 | immutable_variable | variables.rs:327:28:327:28 | 6 | | -| variables.rs:327:9:327:29 | CallExpr | variables.rs:326:9:326:10 | n2 | | -| variables.rs:327:28:327:28 | 6 | variables.rs:327:9:327:29 | CallExpr | | +| variables.rs:327:9:327:29 | immutable_variable(...) | variables.rs:326:9:326:10 | n2 | | +| variables.rs:327:28:327:28 | 6 | variables.rs:327:9:327:29 | immutable_variable(...) | | | variables.rs:328:5:328:13 | print_i64 | variables.rs:328:15:328:16 | n2 | | -| variables.rs:328:5:328:17 | CallExpr | variables.rs:314:23:329:1 | BlockExpr | | +| variables.rs:328:5:328:17 | print_i64(...) | variables.rs:314:23:329:1 | { ... } | | | variables.rs:328:5:328:18 | ExprStmt | variables.rs:328:5:328:13 | print_i64 | | -| variables.rs:328:15:328:16 | n2 | variables.rs:328:5:328:17 | CallExpr | | -| variables.rs:331:1:338:1 | enter for_variable | variables.rs:332:5:332:42 | LetStmt | | -| variables.rs:331:1:338:1 | exit for_variable (normal) | variables.rs:331:1:338:1 | exit for_variable | | -| variables.rs:331:19:338:1 | BlockExpr | variables.rs:331:1:338:1 | exit for_variable (normal) | | -| variables.rs:332:5:332:42 | LetStmt | variables.rs:332:15:332:22 | "apples" | | +| variables.rs:328:15:328:16 | n2 | variables.rs:328:5:328:17 | print_i64(...) | | +| variables.rs:331:1:338:1 | enter fn for_variable | variables.rs:332:5:332:42 | let ... = ... | | +| variables.rs:331:1:338:1 | exit fn for_variable (normal) | variables.rs:331:1:338:1 | exit fn for_variable | | +| variables.rs:331:19:338:1 | { ... } | variables.rs:331:1:338:1 | exit fn for_variable (normal) | | +| variables.rs:332:5:332:42 | let ... = ... | variables.rs:332:15:332:22 | "apples" | | | variables.rs:332:9:332:9 | v | variables.rs:335:12:335:12 | v | match | -| variables.rs:332:13:332:41 | RefExpr | variables.rs:332:9:332:9 | v | | -| variables.rs:332:14:332:41 | ArrayExpr | variables.rs:332:13:332:41 | RefExpr | | +| variables.rs:332:13:332:41 | &... | variables.rs:332:9:332:9 | v | | +| variables.rs:332:14:332:41 | [...] | variables.rs:332:13:332:41 | &... | | | variables.rs:332:15:332:22 | "apples" | variables.rs:332:25:332:30 | "cake" | | | variables.rs:332:25:332:30 | "cake" | variables.rs:332:33:332:40 | "coffee" | | -| variables.rs:332:33:332:40 | "coffee" | variables.rs:332:14:332:41 | ArrayExpr | | -| variables.rs:334:5:337:5 | ForExpr | variables.rs:331:19:338:1 | BlockExpr | | -| variables.rs:334:9:334:12 | text | variables.rs:334:5:337:5 | ForExpr | no-match | +| variables.rs:332:33:332:40 | "coffee" | variables.rs:332:14:332:41 | [...] | | +| variables.rs:334:5:337:5 | for ... in ... { ... } | variables.rs:331:19:338:1 | { ... } | | +| variables.rs:334:9:334:12 | text | variables.rs:334:5:337:5 | for ... in ... { ... } | no-match | | variables.rs:334:9:334:12 | text | variables.rs:336:9:336:24 | ExprStmt | match | | variables.rs:335:12:335:12 | v | variables.rs:334:9:334:12 | text | | -| variables.rs:335:14:337:5 | BlockExpr | variables.rs:334:9:334:12 | text | | +| variables.rs:335:14:337:5 | { ... } | variables.rs:334:9:334:12 | text | | | variables.rs:336:9:336:17 | print_str | variables.rs:336:19:336:22 | text | | -| variables.rs:336:9:336:23 | CallExpr | variables.rs:335:14:337:5 | BlockExpr | | +| variables.rs:336:9:336:23 | print_str(...) | variables.rs:335:14:337:5 | { ... } | | | variables.rs:336:9:336:24 | ExprStmt | variables.rs:336:9:336:17 | print_str | | -| variables.rs:336:19:336:22 | text | variables.rs:336:9:336:23 | CallExpr | | -| variables.rs:340:1:346:1 | enter add_assign | variables.rs:341:5:341:18 | LetStmt | | -| variables.rs:340:1:346:1 | exit add_assign (normal) | variables.rs:340:1:346:1 | exit add_assign | | -| variables.rs:340:17:346:1 | BlockExpr | variables.rs:340:1:346:1 | exit add_assign (normal) | | -| variables.rs:341:5:341:18 | LetStmt | variables.rs:341:17:341:17 | 0 | | +| variables.rs:336:19:336:22 | text | variables.rs:336:9:336:23 | print_str(...) | | +| variables.rs:340:1:346:1 | enter fn add_assign | variables.rs:341:5:341:18 | let ... = 0 | | +| variables.rs:340:1:346:1 | exit fn add_assign (normal) | variables.rs:340:1:346:1 | exit fn add_assign | | +| variables.rs:340:17:346:1 | { ... } | variables.rs:340:1:346:1 | exit fn add_assign (normal) | | +| variables.rs:341:5:341:18 | let ... = 0 | variables.rs:341:17:341:17 | 0 | | | variables.rs:341:9:341:13 | a | variables.rs:342:5:342:11 | ExprStmt | match | | variables.rs:341:17:341:17 | 0 | variables.rs:341:9:341:13 | a | | | variables.rs:342:5:342:5 | a | variables.rs:342:10:342:10 | 1 | | @@ -737,41 +737,41 @@ edges | variables.rs:342:5:342:11 | ExprStmt | variables.rs:342:5:342:5 | a | | | variables.rs:342:10:342:10 | 1 | variables.rs:342:5:342:10 | ... += ... | | | variables.rs:343:5:343:13 | print_i64 | variables.rs:343:15:343:15 | a | | -| variables.rs:343:5:343:16 | CallExpr | variables.rs:344:5:344:28 | ExprStmt | | +| variables.rs:343:5:343:16 | print_i64(...) | variables.rs:344:5:344:28 | ExprStmt | | | variables.rs:343:5:343:17 | ExprStmt | variables.rs:343:5:343:13 | print_i64 | | -| variables.rs:343:15:343:15 | a | variables.rs:343:5:343:16 | CallExpr | | +| variables.rs:343:15:343:15 | a | variables.rs:343:5:343:16 | print_i64(...) | | | variables.rs:344:5:344:27 | ... .add_assign(...) | variables.rs:345:5:345:17 | ExprStmt | | | variables.rs:344:5:344:28 | ExprStmt | variables.rs:344:11:344:11 | a | | -| variables.rs:344:6:344:11 | RefExpr | variables.rs:344:25:344:26 | 10 | | -| variables.rs:344:11:344:11 | a | variables.rs:344:6:344:11 | RefExpr | | +| variables.rs:344:6:344:11 | &mut a | variables.rs:344:25:344:26 | 10 | | +| variables.rs:344:11:344:11 | a | variables.rs:344:6:344:11 | &mut a | | | variables.rs:344:25:344:26 | 10 | variables.rs:344:5:344:27 | ... .add_assign(...) | | | variables.rs:345:5:345:13 | print_i64 | variables.rs:345:15:345:15 | a | | -| variables.rs:345:5:345:16 | CallExpr | variables.rs:340:17:346:1 | BlockExpr | | +| variables.rs:345:5:345:16 | print_i64(...) | variables.rs:340:17:346:1 | { ... } | | | variables.rs:345:5:345:17 | ExprStmt | variables.rs:345:5:345:13 | print_i64 | | -| variables.rs:345:15:345:15 | a | variables.rs:345:5:345:16 | CallExpr | | -| variables.rs:348:1:354:1 | enter mutate | variables.rs:349:5:349:18 | LetStmt | | -| variables.rs:348:1:354:1 | exit mutate (normal) | variables.rs:348:1:354:1 | exit mutate | | -| variables.rs:348:13:354:1 | BlockExpr | variables.rs:348:1:354:1 | exit mutate (normal) | | -| variables.rs:349:5:349:18 | LetStmt | variables.rs:349:17:349:17 | 1 | | -| variables.rs:349:9:349:13 | i | variables.rs:350:5:351:15 | LetStmt | match | +| variables.rs:345:15:345:15 | a | variables.rs:345:5:345:16 | print_i64(...) | | +| variables.rs:348:1:354:1 | enter fn mutate | variables.rs:349:5:349:18 | let ... = 1 | | +| variables.rs:348:1:354:1 | exit fn mutate (normal) | variables.rs:348:1:354:1 | exit fn mutate | | +| variables.rs:348:13:354:1 | { ... } | variables.rs:348:1:354:1 | exit fn mutate (normal) | | +| variables.rs:349:5:349:18 | let ... = 1 | variables.rs:349:17:349:17 | 1 | | +| variables.rs:349:9:349:13 | i | variables.rs:350:5:351:15 | let ... = ... | match | | variables.rs:349:17:349:17 | 1 | variables.rs:349:9:349:13 | i | | -| variables.rs:350:5:351:15 | LetStmt | variables.rs:351:14:351:14 | i | | +| variables.rs:350:5:351:15 | let ... = ... | variables.rs:351:14:351:14 | i | | | variables.rs:350:9:350:13 | ref_i | variables.rs:352:5:352:15 | ExprStmt | match | -| variables.rs:351:9:351:14 | RefExpr | variables.rs:350:9:350:13 | ref_i | | -| variables.rs:351:14:351:14 | i | variables.rs:351:9:351:14 | RefExpr | | +| variables.rs:351:9:351:14 | &mut i | variables.rs:350:9:350:13 | ref_i | | +| variables.rs:351:14:351:14 | i | variables.rs:351:9:351:14 | &mut i | | | variables.rs:352:5:352:10 | * ... | variables.rs:352:14:352:14 | 2 | | | variables.rs:352:5:352:14 | ... = ... | variables.rs:353:5:353:17 | ExprStmt | | | variables.rs:352:5:352:15 | ExprStmt | variables.rs:352:6:352:10 | ref_i | | | variables.rs:352:6:352:10 | ref_i | variables.rs:352:5:352:10 | * ... | | | variables.rs:352:14:352:14 | 2 | variables.rs:352:5:352:14 | ... = ... | | | variables.rs:353:5:353:13 | print_i64 | variables.rs:353:15:353:15 | i | | -| variables.rs:353:5:353:16 | CallExpr | variables.rs:348:13:354:1 | BlockExpr | | +| variables.rs:353:5:353:16 | print_i64(...) | variables.rs:348:13:354:1 | { ... } | | | variables.rs:353:5:353:17 | ExprStmt | variables.rs:353:5:353:13 | print_i64 | | -| variables.rs:353:15:353:15 | i | variables.rs:353:5:353:16 | CallExpr | | -| variables.rs:356:1:361:1 | enter mutate_param | variables.rs:356:17:356:17 | x | | -| variables.rs:356:1:361:1 | exit mutate_param (normal) | variables.rs:356:1:361:1 | exit mutate_param | | -| variables.rs:356:17:356:17 | x | variables.rs:356:17:356:28 | Param | match | -| variables.rs:356:17:356:28 | Param | variables.rs:357:5:359:11 | ExprStmt | | +| variables.rs:353:15:353:15 | i | variables.rs:353:5:353:16 | print_i64(...) | | +| variables.rs:356:1:361:1 | enter fn mutate_param | variables.rs:356:17:356:17 | x | | +| variables.rs:356:1:361:1 | exit fn mutate_param (normal) | variables.rs:356:1:361:1 | exit fn mutate_param | | +| variables.rs:356:17:356:17 | x | variables.rs:356:17:356:28 | ...: ... | match | +| variables.rs:356:17:356:28 | ...: ... | variables.rs:357:5:359:11 | ExprStmt | | | variables.rs:357:5:357:6 | * ... | variables.rs:358:10:358:10 | x | | | variables.rs:357:5:359:10 | ... = ... | variables.rs:360:5:360:13 | ExprStmt | | | variables.rs:357:5:359:11 | ExprStmt | variables.rs:357:6:357:6 | x | | @@ -781,16 +781,16 @@ edges | variables.rs:358:10:358:10 | x | variables.rs:358:9:358:10 | * ... | | | variables.rs:359:9:359:10 | * ... | variables.rs:358:9:359:10 | ... + ... | | | variables.rs:359:10:359:10 | x | variables.rs:359:9:359:10 | * ... | | -| variables.rs:360:5:360:12 | ReturnExpr | variables.rs:356:1:361:1 | exit mutate_param (normal) | return | +| variables.rs:360:5:360:12 | return x | variables.rs:356:1:361:1 | exit fn mutate_param (normal) | return | | variables.rs:360:5:360:13 | ExprStmt | variables.rs:360:12:360:12 | x | | -| variables.rs:360:12:360:12 | x | variables.rs:360:5:360:12 | ReturnExpr | | -| variables.rs:363:1:369:1 | enter mutate_param2 | variables.rs:363:22:363:22 | x | | -| variables.rs:363:1:369:1 | exit mutate_param2 (normal) | variables.rs:363:1:369:1 | exit mutate_param2 | | -| variables.rs:363:22:363:22 | x | variables.rs:363:22:363:36 | Param | match | -| variables.rs:363:22:363:36 | Param | variables.rs:363:39:363:39 | y | | -| variables.rs:363:39:363:39 | y | variables.rs:363:39:363:57 | Param | match | -| variables.rs:363:39:363:57 | Param | variables.rs:364:5:366:11 | ExprStmt | | -| variables.rs:363:60:369:1 | BlockExpr | variables.rs:363:1:369:1 | exit mutate_param2 (normal) | | +| variables.rs:360:12:360:12 | x | variables.rs:360:5:360:12 | return x | | +| variables.rs:363:1:369:1 | enter fn mutate_param2 | variables.rs:363:22:363:22 | x | | +| variables.rs:363:1:369:1 | exit fn mutate_param2 (normal) | variables.rs:363:1:369:1 | exit fn mutate_param2 | | +| variables.rs:363:22:363:22 | x | variables.rs:363:22:363:36 | ...: ... | match | +| variables.rs:363:22:363:36 | ...: ... | variables.rs:363:39:363:39 | y | | +| variables.rs:363:39:363:39 | y | variables.rs:363:39:363:57 | ...: ... | match | +| variables.rs:363:39:363:57 | ...: ... | variables.rs:364:5:366:11 | ExprStmt | | +| variables.rs:363:60:369:1 | { ... } | variables.rs:363:1:369:1 | exit fn mutate_param2 (normal) | | | variables.rs:364:5:364:6 | * ... | variables.rs:365:10:365:10 | x | | | variables.rs:364:5:366:10 | ... = ... | variables.rs:367:5:368:10 | ExprStmt | | | variables.rs:364:5:366:11 | ExprStmt | variables.rs:364:6:364:6 | x | | @@ -801,45 +801,45 @@ edges | variables.rs:366:9:366:10 | * ... | variables.rs:365:9:366:10 | ... + ... | | | variables.rs:366:10:366:10 | x | variables.rs:366:9:366:10 | * ... | | | variables.rs:367:5:367:6 | * ... | variables.rs:368:9:368:9 | x | | -| variables.rs:367:5:368:9 | ... = ... | variables.rs:363:60:369:1 | BlockExpr | | +| variables.rs:367:5:368:9 | ... = ... | variables.rs:363:60:369:1 | { ... } | | | variables.rs:367:5:368:10 | ExprStmt | variables.rs:367:6:367:6 | y | | | variables.rs:367:6:367:6 | y | variables.rs:367:5:367:6 | * ... | | | variables.rs:368:9:368:9 | x | variables.rs:367:5:368:9 | ... = ... | | -| variables.rs:371:1:389:1 | enter mutate_arg | variables.rs:372:5:372:18 | LetStmt | | -| variables.rs:371:1:389:1 | exit mutate_arg (normal) | variables.rs:371:1:389:1 | exit mutate_arg | | -| variables.rs:371:17:389:1 | BlockExpr | variables.rs:371:1:389:1 | exit mutate_arg (normal) | | -| variables.rs:372:5:372:18 | LetStmt | variables.rs:372:17:372:17 | 2 | | -| variables.rs:372:9:372:13 | x | variables.rs:373:5:374:29 | LetStmt | match | +| variables.rs:371:1:389:1 | enter fn mutate_arg | variables.rs:372:5:372:18 | let ... = 2 | | +| variables.rs:371:1:389:1 | exit fn mutate_arg (normal) | variables.rs:371:1:389:1 | exit fn mutate_arg | | +| variables.rs:371:17:389:1 | { ... } | variables.rs:371:1:389:1 | exit fn mutate_arg (normal) | | +| variables.rs:372:5:372:18 | let ... = 2 | variables.rs:372:17:372:17 | 2 | | +| variables.rs:372:9:372:13 | x | variables.rs:373:5:374:29 | let ... = ... | match | | variables.rs:372:17:372:17 | 2 | variables.rs:372:9:372:13 | x | | -| variables.rs:373:5:374:29 | LetStmt | variables.rs:374:9:374:20 | mutate_param | | +| variables.rs:373:5:374:29 | let ... = ... | variables.rs:374:9:374:20 | mutate_param | | | variables.rs:373:9:373:9 | y | variables.rs:375:5:375:12 | ExprStmt | match | | variables.rs:374:9:374:20 | mutate_param | variables.rs:374:27:374:27 | x | | -| variables.rs:374:9:374:28 | CallExpr | variables.rs:373:9:373:9 | y | | -| variables.rs:374:22:374:27 | RefExpr | variables.rs:374:9:374:28 | CallExpr | | -| variables.rs:374:27:374:27 | x | variables.rs:374:22:374:27 | RefExpr | | +| variables.rs:374:9:374:28 | mutate_param(...) | variables.rs:373:9:373:9 | y | | +| variables.rs:374:22:374:27 | &mut x | variables.rs:374:9:374:28 | mutate_param(...) | | +| variables.rs:374:27:374:27 | x | variables.rs:374:22:374:27 | &mut x | | | variables.rs:375:5:375:6 | * ... | variables.rs:375:10:375:11 | 10 | | | variables.rs:375:5:375:11 | ... = ... | variables.rs:377:5:377:17 | ExprStmt | | | variables.rs:375:5:375:12 | ExprStmt | variables.rs:375:6:375:6 | y | | | variables.rs:375:6:375:6 | y | variables.rs:375:5:375:6 | * ... | | | variables.rs:375:10:375:11 | 10 | variables.rs:375:5:375:11 | ... = ... | | | variables.rs:377:5:377:13 | print_i64 | variables.rs:377:15:377:15 | x | | -| variables.rs:377:5:377:16 | CallExpr | variables.rs:379:5:379:18 | LetStmt | | +| variables.rs:377:5:377:16 | print_i64(...) | variables.rs:379:5:379:18 | let ... = 4 | | | variables.rs:377:5:377:17 | ExprStmt | variables.rs:377:5:377:13 | print_i64 | | -| variables.rs:377:15:377:15 | x | variables.rs:377:5:377:16 | CallExpr | | -| variables.rs:379:5:379:18 | LetStmt | variables.rs:379:17:379:17 | 4 | | -| variables.rs:379:9:379:13 | z | variables.rs:380:5:381:20 | LetStmt | match | +| variables.rs:377:15:377:15 | x | variables.rs:377:5:377:16 | print_i64(...) | | +| variables.rs:379:5:379:18 | let ... = 4 | variables.rs:379:17:379:17 | 4 | | +| variables.rs:379:9:379:13 | z | variables.rs:380:5:381:20 | let ... = ... | match | | variables.rs:379:17:379:17 | 4 | variables.rs:379:9:379:13 | z | | -| variables.rs:380:5:381:20 | LetStmt | variables.rs:381:19:381:19 | x | | +| variables.rs:380:5:381:20 | let ... = ... | variables.rs:381:19:381:19 | x | | | variables.rs:380:9:380:9 | w | variables.rs:382:5:385:6 | ExprStmt | match | -| variables.rs:381:9:381:19 | RefExpr | variables.rs:380:9:380:9 | w | | -| variables.rs:381:14:381:19 | RefExpr | variables.rs:381:9:381:19 | RefExpr | | -| variables.rs:381:19:381:19 | x | variables.rs:381:14:381:19 | RefExpr | | +| variables.rs:381:9:381:19 | &mut ... | variables.rs:380:9:380:9 | w | | +| variables.rs:381:14:381:19 | &mut x | variables.rs:381:9:381:19 | &mut ... | | +| variables.rs:381:19:381:19 | x | variables.rs:381:14:381:19 | &mut x | | | variables.rs:382:5:382:17 | mutate_param2 | variables.rs:383:14:383:14 | z | | -| variables.rs:382:5:385:5 | CallExpr | variables.rs:386:5:386:13 | ExprStmt | | +| variables.rs:382:5:385:5 | mutate_param2(...) | variables.rs:386:5:386:13 | ExprStmt | | | variables.rs:382:5:385:6 | ExprStmt | variables.rs:382:5:382:17 | mutate_param2 | | -| variables.rs:383:9:383:14 | RefExpr | variables.rs:384:9:384:9 | w | | -| variables.rs:383:14:383:14 | z | variables.rs:383:9:383:14 | RefExpr | | -| variables.rs:384:9:384:9 | w | variables.rs:382:5:385:5 | CallExpr | | +| variables.rs:383:9:383:14 | &mut z | variables.rs:384:9:384:9 | w | | +| variables.rs:383:14:383:14 | z | variables.rs:383:9:383:14 | &mut z | | +| variables.rs:384:9:384:9 | w | variables.rs:382:5:385:5 | mutate_param2(...) | | | variables.rs:386:5:386:7 | * ... | variables.rs:386:11:386:12 | 11 | | | variables.rs:386:5:386:12 | ... = ... | variables.rs:388:5:388:17 | ExprStmt | | | variables.rs:386:5:386:13 | ExprStmt | variables.rs:386:7:386:7 | w | | @@ -847,422 +847,432 @@ edges | variables.rs:386:7:386:7 | w | variables.rs:386:6:386:7 | * ... | | | variables.rs:386:11:386:12 | 11 | variables.rs:386:5:386:12 | ... = ... | | | variables.rs:388:5:388:13 | print_i64 | variables.rs:388:15:388:15 | z | | -| variables.rs:388:5:388:16 | CallExpr | variables.rs:371:17:389:1 | BlockExpr | | +| variables.rs:388:5:388:16 | print_i64(...) | variables.rs:371:17:389:1 | { ... } | | | variables.rs:388:5:388:17 | ExprStmt | variables.rs:388:5:388:13 | print_i64 | | -| variables.rs:388:15:388:15 | z | variables.rs:388:5:388:16 | CallExpr | | -| variables.rs:391:1:397:1 | enter alias | variables.rs:392:5:392:18 | LetStmt | | -| variables.rs:391:1:397:1 | exit alias (normal) | variables.rs:391:1:397:1 | exit alias | | -| variables.rs:391:12:397:1 | BlockExpr | variables.rs:391:1:397:1 | exit alias (normal) | | -| variables.rs:392:5:392:18 | LetStmt | variables.rs:392:17:392:17 | 1 | | -| variables.rs:392:9:392:13 | x | variables.rs:393:5:394:15 | LetStmt | match | +| variables.rs:388:15:388:15 | z | variables.rs:388:5:388:16 | print_i64(...) | | +| variables.rs:391:1:397:1 | enter fn alias | variables.rs:392:5:392:18 | let ... = 1 | | +| variables.rs:391:1:397:1 | exit fn alias (normal) | variables.rs:391:1:397:1 | exit fn alias | | +| variables.rs:391:12:397:1 | { ... } | variables.rs:391:1:397:1 | exit fn alias (normal) | | +| variables.rs:392:5:392:18 | let ... = 1 | variables.rs:392:17:392:17 | 1 | | +| variables.rs:392:9:392:13 | x | variables.rs:393:5:394:15 | let ... = ... | match | | variables.rs:392:17:392:17 | 1 | variables.rs:392:9:392:13 | x | | -| variables.rs:393:5:394:15 | LetStmt | variables.rs:394:14:394:14 | x | | +| variables.rs:393:5:394:15 | let ... = ... | variables.rs:394:14:394:14 | x | | | variables.rs:393:9:393:9 | y | variables.rs:395:5:395:11 | ExprStmt | match | -| variables.rs:394:9:394:14 | RefExpr | variables.rs:393:9:393:9 | y | | -| variables.rs:394:14:394:14 | x | variables.rs:394:9:394:14 | RefExpr | | +| variables.rs:394:9:394:14 | &mut x | variables.rs:393:9:393:9 | y | | +| variables.rs:394:14:394:14 | x | variables.rs:394:9:394:14 | &mut x | | | variables.rs:395:5:395:6 | * ... | variables.rs:395:10:395:10 | 2 | | | variables.rs:395:5:395:10 | ... = ... | variables.rs:396:5:396:17 | ExprStmt | | | variables.rs:395:5:395:11 | ExprStmt | variables.rs:395:6:395:6 | y | | | variables.rs:395:6:395:6 | y | variables.rs:395:5:395:6 | * ... | | | variables.rs:395:10:395:10 | 2 | variables.rs:395:5:395:10 | ... = ... | | | variables.rs:396:5:396:13 | print_i64 | variables.rs:396:15:396:15 | x | | -| variables.rs:396:5:396:16 | CallExpr | variables.rs:391:12:397:1 | BlockExpr | | +| variables.rs:396:5:396:16 | print_i64(...) | variables.rs:391:12:397:1 | { ... } | | | variables.rs:396:5:396:17 | ExprStmt | variables.rs:396:5:396:13 | print_i64 | | -| variables.rs:396:15:396:15 | x | variables.rs:396:5:396:16 | CallExpr | | -| variables.rs:399:1:407:1 | enter capture_immut | variables.rs:400:5:400:16 | LetStmt | | -| variables.rs:399:1:407:1 | exit capture_immut (normal) | variables.rs:399:1:407:1 | exit capture_immut | | -| variables.rs:399:20:407:1 | BlockExpr | variables.rs:399:1:407:1 | exit capture_immut (normal) | | -| variables.rs:400:5:400:16 | LetStmt | variables.rs:400:13:400:15 | 100 | | -| variables.rs:400:9:400:9 | x | variables.rs:402:5:404:6 | LetStmt | match | +| variables.rs:396:15:396:15 | x | variables.rs:396:5:396:16 | print_i64(...) | | +| variables.rs:399:1:407:1 | enter fn capture_immut | variables.rs:400:5:400:16 | let ... = 100 | | +| variables.rs:399:1:407:1 | exit fn capture_immut (normal) | variables.rs:399:1:407:1 | exit fn capture_immut | | +| variables.rs:399:20:407:1 | { ... } | variables.rs:399:1:407:1 | exit fn capture_immut (normal) | | +| variables.rs:400:5:400:16 | let ... = 100 | variables.rs:400:13:400:15 | 100 | | +| variables.rs:400:9:400:9 | x | variables.rs:402:5:404:6 | let ... = ... | match | | variables.rs:400:13:400:15 | 100 | variables.rs:400:9:400:9 | x | | -| variables.rs:402:5:404:6 | LetStmt | variables.rs:402:15:404:5 | ClosureExpr | | +| variables.rs:402:5:404:6 | let ... = ... | variables.rs:402:15:404:5 | \|...\| ... | | | variables.rs:402:9:402:11 | cap | variables.rs:405:5:405:10 | ExprStmt | match | -| variables.rs:402:15:404:5 | ClosureExpr | variables.rs:402:9:402:11 | cap | | -| variables.rs:402:15:404:5 | enter ClosureExpr | variables.rs:403:9:403:21 | ExprStmt | | -| variables.rs:402:15:404:5 | exit ClosureExpr (normal) | variables.rs:402:15:404:5 | exit ClosureExpr | | -| variables.rs:402:18:404:5 | BlockExpr | variables.rs:402:15:404:5 | exit ClosureExpr (normal) | | +| variables.rs:402:15:404:5 | \|...\| ... | variables.rs:402:9:402:11 | cap | | +| variables.rs:402:15:404:5 | enter \|...\| ... | variables.rs:403:9:403:21 | ExprStmt | | +| variables.rs:402:15:404:5 | exit \|...\| ... (normal) | variables.rs:402:15:404:5 | exit \|...\| ... | | +| variables.rs:402:18:404:5 | { ... } | variables.rs:402:15:404:5 | exit \|...\| ... (normal) | | | variables.rs:403:9:403:17 | print_i64 | variables.rs:403:19:403:19 | x | | -| variables.rs:403:9:403:20 | CallExpr | variables.rs:402:18:404:5 | BlockExpr | | +| variables.rs:403:9:403:20 | print_i64(...) | variables.rs:402:18:404:5 | { ... } | | | variables.rs:403:9:403:21 | ExprStmt | variables.rs:403:9:403:17 | print_i64 | | -| variables.rs:403:19:403:19 | x | variables.rs:403:9:403:20 | CallExpr | | -| variables.rs:405:5:405:7 | cap | variables.rs:405:5:405:9 | CallExpr | | -| variables.rs:405:5:405:9 | CallExpr | variables.rs:406:5:406:17 | ExprStmt | | +| variables.rs:403:19:403:19 | x | variables.rs:403:9:403:20 | print_i64(...) | | +| variables.rs:405:5:405:7 | cap | variables.rs:405:5:405:9 | cap(...) | | +| variables.rs:405:5:405:9 | cap(...) | variables.rs:406:5:406:17 | ExprStmt | | | variables.rs:405:5:405:10 | ExprStmt | variables.rs:405:5:405:7 | cap | | | variables.rs:406:5:406:13 | print_i64 | variables.rs:406:15:406:15 | x | | -| variables.rs:406:5:406:16 | CallExpr | variables.rs:399:20:407:1 | BlockExpr | | +| variables.rs:406:5:406:16 | print_i64(...) | variables.rs:399:20:407:1 | { ... } | | | variables.rs:406:5:406:17 | ExprStmt | variables.rs:406:5:406:13 | print_i64 | | -| variables.rs:406:15:406:15 | x | variables.rs:406:5:406:16 | CallExpr | | -| variables.rs:409:1:433:1 | enter capture_mut | variables.rs:410:5:410:18 | LetStmt | | -| variables.rs:409:1:433:1 | exit capture_mut (normal) | variables.rs:409:1:433:1 | exit capture_mut | | -| variables.rs:409:18:433:1 | BlockExpr | variables.rs:409:1:433:1 | exit capture_mut (normal) | | -| variables.rs:410:5:410:18 | LetStmt | variables.rs:410:17:410:17 | 1 | | -| variables.rs:410:9:410:13 | x | variables.rs:412:5:414:6 | LetStmt | match | +| variables.rs:406:15:406:15 | x | variables.rs:406:5:406:16 | print_i64(...) | | +| variables.rs:409:1:433:1 | enter fn capture_mut | variables.rs:410:5:410:18 | let ... = 1 | | +| variables.rs:409:1:433:1 | exit fn capture_mut (normal) | variables.rs:409:1:433:1 | exit fn capture_mut | | +| variables.rs:409:18:433:1 | { ... } | variables.rs:409:1:433:1 | exit fn capture_mut (normal) | | +| variables.rs:410:5:410:18 | let ... = 1 | variables.rs:410:17:410:17 | 1 | | +| variables.rs:410:9:410:13 | x | variables.rs:412:5:414:6 | let ... = ... | match | | variables.rs:410:17:410:17 | 1 | variables.rs:410:9:410:13 | x | | -| variables.rs:412:5:414:6 | LetStmt | variables.rs:412:20:414:5 | ClosureExpr | | +| variables.rs:412:5:414:6 | let ... = ... | variables.rs:412:20:414:5 | \|...\| ... | | | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:15 | ExprStmt | match | -| variables.rs:412:20:414:5 | ClosureExpr | variables.rs:412:9:412:16 | closure1 | | -| variables.rs:412:20:414:5 | enter ClosureExpr | variables.rs:413:9:413:21 | ExprStmt | | -| variables.rs:412:20:414:5 | exit ClosureExpr (normal) | variables.rs:412:20:414:5 | exit ClosureExpr | | -| variables.rs:412:23:414:5 | BlockExpr | variables.rs:412:20:414:5 | exit ClosureExpr (normal) | | +| variables.rs:412:20:414:5 | \|...\| ... | variables.rs:412:9:412:16 | closure1 | | +| variables.rs:412:20:414:5 | enter \|...\| ... | variables.rs:413:9:413:21 | ExprStmt | | +| variables.rs:412:20:414:5 | exit \|...\| ... (normal) | variables.rs:412:20:414:5 | exit \|...\| ... | | +| variables.rs:412:23:414:5 | { ... } | variables.rs:412:20:414:5 | exit \|...\| ... (normal) | | | variables.rs:413:9:413:17 | print_i64 | variables.rs:413:19:413:19 | x | | -| variables.rs:413:9:413:20 | CallExpr | variables.rs:412:23:414:5 | BlockExpr | | +| variables.rs:413:9:413:20 | print_i64(...) | variables.rs:412:23:414:5 | { ... } | | | variables.rs:413:9:413:21 | ExprStmt | variables.rs:413:9:413:17 | print_i64 | | -| variables.rs:413:19:413:19 | x | variables.rs:413:9:413:20 | CallExpr | | -| variables.rs:415:5:415:12 | closure1 | variables.rs:415:5:415:14 | CallExpr | | -| variables.rs:415:5:415:14 | CallExpr | variables.rs:416:5:416:17 | ExprStmt | | +| variables.rs:413:19:413:19 | x | variables.rs:413:9:413:20 | print_i64(...) | | +| variables.rs:415:5:415:12 | closure1 | variables.rs:415:5:415:14 | closure1(...) | | +| variables.rs:415:5:415:14 | closure1(...) | variables.rs:416:5:416:17 | ExprStmt | | | variables.rs:415:5:415:15 | ExprStmt | variables.rs:415:5:415:12 | closure1 | | | variables.rs:416:5:416:13 | print_i64 | variables.rs:416:15:416:15 | x | | -| variables.rs:416:5:416:16 | CallExpr | variables.rs:418:5:418:18 | LetStmt | | +| variables.rs:416:5:416:16 | print_i64(...) | variables.rs:418:5:418:18 | let ... = 2 | | | variables.rs:416:5:416:17 | ExprStmt | variables.rs:416:5:416:13 | print_i64 | | -| variables.rs:416:15:416:15 | x | variables.rs:416:5:416:16 | CallExpr | | -| variables.rs:418:5:418:18 | LetStmt | variables.rs:418:17:418:17 | 2 | | -| variables.rs:418:9:418:13 | y | variables.rs:420:5:422:6 | LetStmt | match | +| variables.rs:416:15:416:15 | x | variables.rs:416:5:416:16 | print_i64(...) | | +| variables.rs:418:5:418:18 | let ... = 2 | variables.rs:418:17:418:17 | 2 | | +| variables.rs:418:9:418:13 | y | variables.rs:420:5:422:6 | let ... = ... | match | | variables.rs:418:17:418:17 | 2 | variables.rs:418:9:418:13 | y | | -| variables.rs:420:5:422:6 | LetStmt | variables.rs:420:24:422:5 | ClosureExpr | | +| variables.rs:420:5:422:6 | let ... = ... | variables.rs:420:24:422:5 | \|...\| ... | | | variables.rs:420:9:420:20 | closure2 | variables.rs:423:5:423:15 | ExprStmt | match | -| variables.rs:420:24:422:5 | ClosureExpr | variables.rs:420:9:420:20 | closure2 | | -| variables.rs:420:24:422:5 | enter ClosureExpr | variables.rs:421:9:421:14 | ExprStmt | | -| variables.rs:420:24:422:5 | exit ClosureExpr (normal) | variables.rs:420:24:422:5 | exit ClosureExpr | | -| variables.rs:420:27:422:5 | BlockExpr | variables.rs:420:24:422:5 | exit ClosureExpr (normal) | | +| variables.rs:420:24:422:5 | \|...\| ... | variables.rs:420:9:420:20 | closure2 | | +| variables.rs:420:24:422:5 | enter \|...\| ... | variables.rs:421:9:421:14 | ExprStmt | | +| variables.rs:420:24:422:5 | exit \|...\| ... (normal) | variables.rs:420:24:422:5 | exit \|...\| ... | | +| variables.rs:420:27:422:5 | { ... } | variables.rs:420:24:422:5 | exit \|...\| ... (normal) | | | variables.rs:421:9:421:9 | y | variables.rs:421:13:421:13 | 3 | | -| variables.rs:421:9:421:13 | ... = ... | variables.rs:420:27:422:5 | BlockExpr | | +| variables.rs:421:9:421:13 | ... = ... | variables.rs:420:27:422:5 | { ... } | | | variables.rs:421:9:421:14 | ExprStmt | variables.rs:421:9:421:9 | y | | | variables.rs:421:13:421:13 | 3 | variables.rs:421:9:421:13 | ... = ... | | -| variables.rs:423:5:423:12 | closure2 | variables.rs:423:5:423:14 | CallExpr | | -| variables.rs:423:5:423:14 | CallExpr | variables.rs:424:5:424:17 | ExprStmt | | +| variables.rs:423:5:423:12 | closure2 | variables.rs:423:5:423:14 | closure2(...) | | +| variables.rs:423:5:423:14 | closure2(...) | variables.rs:424:5:424:17 | ExprStmt | | | variables.rs:423:5:423:15 | ExprStmt | variables.rs:423:5:423:12 | closure2 | | | variables.rs:424:5:424:13 | print_i64 | variables.rs:424:15:424:15 | y | | -| variables.rs:424:5:424:16 | CallExpr | variables.rs:426:5:426:18 | LetStmt | | +| variables.rs:424:5:424:16 | print_i64(...) | variables.rs:426:5:426:18 | let ... = 2 | | | variables.rs:424:5:424:17 | ExprStmt | variables.rs:424:5:424:13 | print_i64 | | -| variables.rs:424:15:424:15 | y | variables.rs:424:5:424:16 | CallExpr | | -| variables.rs:426:5:426:18 | LetStmt | variables.rs:426:17:426:17 | 2 | | -| variables.rs:426:9:426:13 | z | variables.rs:428:5:430:6 | LetStmt | match | +| variables.rs:424:15:424:15 | y | variables.rs:424:5:424:16 | print_i64(...) | | +| variables.rs:426:5:426:18 | let ... = 2 | variables.rs:426:17:426:17 | 2 | | +| variables.rs:426:9:426:13 | z | variables.rs:428:5:430:6 | let ... = ... | match | | variables.rs:426:17:426:17 | 2 | variables.rs:426:9:426:13 | z | | -| variables.rs:428:5:430:6 | LetStmt | variables.rs:428:24:430:5 | ClosureExpr | | +| variables.rs:428:5:430:6 | let ... = ... | variables.rs:428:24:430:5 | \|...\| ... | | | variables.rs:428:9:428:20 | closure3 | variables.rs:431:5:431:15 | ExprStmt | match | -| variables.rs:428:24:430:5 | ClosureExpr | variables.rs:428:9:428:20 | closure3 | | -| variables.rs:428:24:430:5 | enter ClosureExpr | variables.rs:429:9:429:24 | ExprStmt | | -| variables.rs:428:24:430:5 | exit ClosureExpr (normal) | variables.rs:428:24:430:5 | exit ClosureExpr | | -| variables.rs:428:27:430:5 | BlockExpr | variables.rs:428:24:430:5 | exit ClosureExpr (normal) | | +| variables.rs:428:24:430:5 | \|...\| ... | variables.rs:428:9:428:20 | closure3 | | +| variables.rs:428:24:430:5 | enter \|...\| ... | variables.rs:429:9:429:24 | ExprStmt | | +| variables.rs:428:24:430:5 | exit \|...\| ... (normal) | variables.rs:428:24:430:5 | exit \|...\| ... | | +| variables.rs:428:27:430:5 | { ... } | variables.rs:428:24:430:5 | exit \|...\| ... (normal) | | | variables.rs:429:9:429:9 | z | variables.rs:429:22:429:22 | 1 | | -| variables.rs:429:9:429:23 | ... .add_assign(...) | variables.rs:428:27:430:5 | BlockExpr | | +| variables.rs:429:9:429:23 | ... .add_assign(...) | variables.rs:428:27:430:5 | { ... } | | | variables.rs:429:9:429:24 | ExprStmt | variables.rs:429:9:429:9 | z | | | variables.rs:429:22:429:22 | 1 | variables.rs:429:9:429:23 | ... .add_assign(...) | | -| variables.rs:431:5:431:12 | closure3 | variables.rs:431:5:431:14 | CallExpr | | -| variables.rs:431:5:431:14 | CallExpr | variables.rs:432:5:432:17 | ExprStmt | | +| variables.rs:431:5:431:12 | closure3 | variables.rs:431:5:431:14 | closure3(...) | | +| variables.rs:431:5:431:14 | closure3(...) | variables.rs:432:5:432:17 | ExprStmt | | | variables.rs:431:5:431:15 | ExprStmt | variables.rs:431:5:431:12 | closure3 | | | variables.rs:432:5:432:13 | print_i64 | variables.rs:432:15:432:15 | z | | -| variables.rs:432:5:432:16 | CallExpr | variables.rs:409:18:433:1 | BlockExpr | | +| variables.rs:432:5:432:16 | print_i64(...) | variables.rs:409:18:433:1 | { ... } | | | variables.rs:432:5:432:17 | ExprStmt | variables.rs:432:5:432:13 | print_i64 | | -| variables.rs:432:15:432:15 | z | variables.rs:432:5:432:16 | CallExpr | | -| variables.rs:435:1:443:1 | enter async_block_capture | variables.rs:436:5:436:23 | LetStmt | | -| variables.rs:435:1:443:1 | exit async_block_capture (normal) | variables.rs:435:1:443:1 | exit async_block_capture | | -| variables.rs:435:32:443:1 | BlockExpr | variables.rs:435:1:443:1 | exit async_block_capture (normal) | | -| variables.rs:436:5:436:23 | LetStmt | variables.rs:436:22:436:22 | 0 | | -| variables.rs:436:9:436:13 | i | variables.rs:437:5:439:6 | LetStmt | match | +| variables.rs:432:15:432:15 | z | variables.rs:432:5:432:16 | print_i64(...) | | +| variables.rs:435:1:443:1 | enter fn async_block_capture | variables.rs:436:5:436:23 | let ... = 0 | | +| variables.rs:435:1:443:1 | exit fn async_block_capture (normal) | variables.rs:435:1:443:1 | exit fn async_block_capture | | +| variables.rs:435:32:443:1 | { ... } | variables.rs:435:1:443:1 | exit fn async_block_capture (normal) | | +| variables.rs:436:5:436:23 | let ... = 0 | variables.rs:436:22:436:22 | 0 | | +| variables.rs:436:9:436:13 | i | variables.rs:437:5:439:6 | let ... = ... | match | | variables.rs:436:22:436:22 | 0 | variables.rs:436:9:436:13 | i | | -| variables.rs:437:5:439:6 | LetStmt | variables.rs:437:17:439:5 | BlockExpr | | +| variables.rs:437:5:439:6 | let ... = ... | variables.rs:437:17:439:5 | { ... } | | | variables.rs:437:9:437:13 | block | variables.rs:441:5:441:16 | ExprStmt | match | -| variables.rs:437:17:439:5 | BlockExpr | variables.rs:437:9:437:13 | block | | -| variables.rs:437:17:439:5 | enter BlockExpr | variables.rs:438:9:438:14 | ExprStmt | | -| variables.rs:437:17:439:5 | exit BlockExpr (normal) | variables.rs:437:17:439:5 | exit BlockExpr | | +| variables.rs:437:17:439:5 | enter { ... } | variables.rs:438:9:438:14 | ExprStmt | | +| variables.rs:437:17:439:5 | exit { ... } (normal) | variables.rs:437:17:439:5 | exit { ... } | | +| variables.rs:437:17:439:5 | { ... } | variables.rs:437:9:437:13 | block | | | variables.rs:438:9:438:9 | i | variables.rs:438:13:438:13 | 1 | | -| variables.rs:438:9:438:13 | ... = ... | variables.rs:437:17:439:5 | exit BlockExpr (normal) | | +| variables.rs:438:9:438:13 | ... = ... | variables.rs:437:17:439:5 | exit { ... } (normal) | | | variables.rs:438:9:438:14 | ExprStmt | variables.rs:438:9:438:9 | i | | | variables.rs:438:13:438:13 | 1 | variables.rs:438:9:438:13 | ... = ... | | -| variables.rs:441:5:441:9 | block | variables.rs:441:5:441:15 | AwaitExpr | | -| variables.rs:441:5:441:15 | AwaitExpr | variables.rs:442:5:442:17 | ExprStmt | | +| variables.rs:441:5:441:9 | block | variables.rs:441:5:441:15 | await block | | +| variables.rs:441:5:441:15 | await block | variables.rs:442:5:442:17 | ExprStmt | | | variables.rs:441:5:441:16 | ExprStmt | variables.rs:441:5:441:9 | block | | | variables.rs:442:5:442:13 | print_i64 | variables.rs:442:15:442:15 | i | | -| variables.rs:442:5:442:16 | CallExpr | variables.rs:435:32:443:1 | BlockExpr | | +| variables.rs:442:5:442:16 | print_i64(...) | variables.rs:435:32:443:1 | { ... } | | | variables.rs:442:5:442:17 | ExprStmt | variables.rs:442:5:442:13 | print_i64 | | -| variables.rs:442:15:442:15 | i | variables.rs:442:5:442:16 | CallExpr | | -| variables.rs:445:1:459:1 | enter phi | variables.rs:445:8:445:8 | b | | -| variables.rs:445:1:459:1 | exit phi (normal) | variables.rs:445:1:459:1 | exit phi | | -| variables.rs:445:8:445:8 | b | variables.rs:445:8:445:15 | Param | match | -| variables.rs:445:8:445:15 | Param | variables.rs:446:5:446:18 | LetStmt | | -| variables.rs:445:18:459:1 | BlockExpr | variables.rs:445:1:459:1 | exit phi (normal) | | -| variables.rs:446:5:446:18 | LetStmt | variables.rs:446:17:446:17 | 1 | | +| variables.rs:442:15:442:15 | i | variables.rs:442:5:442:16 | print_i64(...) | | +| variables.rs:445:1:459:1 | enter fn phi | variables.rs:445:8:445:8 | b | | +| variables.rs:445:1:459:1 | exit fn phi (normal) | variables.rs:445:1:459:1 | exit fn phi | | +| variables.rs:445:8:445:8 | b | variables.rs:445:8:445:15 | ...: bool | match | +| variables.rs:445:8:445:15 | ...: bool | variables.rs:446:5:446:18 | let ... = 1 | | +| variables.rs:445:18:459:1 | { ... } | variables.rs:445:1:459:1 | exit fn phi (normal) | | +| variables.rs:446:5:446:18 | let ... = 1 | variables.rs:446:17:446:17 | 1 | | | variables.rs:446:9:446:13 | x | variables.rs:447:5:447:17 | ExprStmt | match | | variables.rs:446:17:446:17 | 1 | variables.rs:446:9:446:13 | x | | | variables.rs:447:5:447:13 | print_i64 | variables.rs:447:15:447:15 | x | | -| variables.rs:447:5:447:16 | CallExpr | variables.rs:448:5:448:21 | ExprStmt | | +| variables.rs:447:5:447:16 | print_i64(...) | variables.rs:448:5:448:21 | ExprStmt | | | variables.rs:447:5:447:17 | ExprStmt | variables.rs:447:5:447:13 | print_i64 | | -| variables.rs:447:15:447:15 | x | variables.rs:447:5:447:16 | CallExpr | | +| variables.rs:447:15:447:15 | x | variables.rs:447:5:447:16 | print_i64(...) | | | variables.rs:448:5:448:13 | print_i64 | variables.rs:448:15:448:15 | x | | -| variables.rs:448:5:448:20 | CallExpr | variables.rs:449:5:457:5 | ExprStmt | | +| variables.rs:448:5:448:20 | print_i64(...) | variables.rs:449:5:457:5 | ExprStmt | | | variables.rs:448:5:448:21 | ExprStmt | variables.rs:448:5:448:13 | print_i64 | | | variables.rs:448:15:448:15 | x | variables.rs:448:19:448:19 | 1 | | -| variables.rs:448:15:448:19 | ... + ... | variables.rs:448:5:448:20 | CallExpr | | +| variables.rs:448:15:448:19 | ... + ... | variables.rs:448:5:448:20 | print_i64(...) | | | variables.rs:448:19:448:19 | 1 | variables.rs:448:15:448:19 | ... + ... | | | variables.rs:449:5:457:5 | ExprStmt | variables.rs:449:8:449:8 | b | | -| variables.rs:449:5:457:5 | IfExpr | variables.rs:458:5:458:17 | ExprStmt | | +| variables.rs:449:5:457:5 | if b {...} else {...} | variables.rs:458:5:458:17 | ExprStmt | | | variables.rs:449:8:449:8 | b | variables.rs:450:9:450:14 | ExprStmt | true | | variables.rs:449:8:449:8 | b | variables.rs:454:9:454:14 | ExprStmt | false | -| variables.rs:449:10:453:5 | BlockExpr | variables.rs:449:5:457:5 | IfExpr | | +| variables.rs:449:10:453:5 | { ... } | variables.rs:449:5:457:5 | if b {...} else {...} | | | variables.rs:450:9:450:9 | x | variables.rs:450:13:450:13 | 2 | | | variables.rs:450:9:450:13 | ... = ... | variables.rs:451:9:451:21 | ExprStmt | | | variables.rs:450:9:450:14 | ExprStmt | variables.rs:450:9:450:9 | x | | | variables.rs:450:13:450:13 | 2 | variables.rs:450:9:450:13 | ... = ... | | | variables.rs:451:9:451:17 | print_i64 | variables.rs:451:19:451:19 | x | | -| variables.rs:451:9:451:20 | CallExpr | variables.rs:452:9:452:25 | ExprStmt | | +| variables.rs:451:9:451:20 | print_i64(...) | variables.rs:452:9:452:25 | ExprStmt | | | variables.rs:451:9:451:21 | ExprStmt | variables.rs:451:9:451:17 | print_i64 | | -| variables.rs:451:19:451:19 | x | variables.rs:451:9:451:20 | CallExpr | | +| variables.rs:451:19:451:19 | x | variables.rs:451:9:451:20 | print_i64(...) | | | variables.rs:452:9:452:17 | print_i64 | variables.rs:452:19:452:19 | x | | -| variables.rs:452:9:452:24 | CallExpr | variables.rs:449:10:453:5 | BlockExpr | | +| variables.rs:452:9:452:24 | print_i64(...) | variables.rs:449:10:453:5 | { ... } | | | variables.rs:452:9:452:25 | ExprStmt | variables.rs:452:9:452:17 | print_i64 | | | variables.rs:452:19:452:19 | x | variables.rs:452:23:452:23 | 1 | | -| variables.rs:452:19:452:23 | ... + ... | variables.rs:452:9:452:24 | CallExpr | | +| variables.rs:452:19:452:23 | ... + ... | variables.rs:452:9:452:24 | print_i64(...) | | | variables.rs:452:23:452:23 | 1 | variables.rs:452:19:452:23 | ... + ... | | -| variables.rs:453:12:457:5 | BlockExpr | variables.rs:449:5:457:5 | IfExpr | | +| variables.rs:453:12:457:5 | { ... } | variables.rs:449:5:457:5 | if b {...} else {...} | | | variables.rs:454:9:454:9 | x | variables.rs:454:13:454:13 | 3 | | | variables.rs:454:9:454:13 | ... = ... | variables.rs:455:9:455:21 | ExprStmt | | | variables.rs:454:9:454:14 | ExprStmt | variables.rs:454:9:454:9 | x | | | variables.rs:454:13:454:13 | 3 | variables.rs:454:9:454:13 | ... = ... | | | variables.rs:455:9:455:17 | print_i64 | variables.rs:455:19:455:19 | x | | -| variables.rs:455:9:455:20 | CallExpr | variables.rs:456:9:456:25 | ExprStmt | | +| variables.rs:455:9:455:20 | print_i64(...) | variables.rs:456:9:456:25 | ExprStmt | | | variables.rs:455:9:455:21 | ExprStmt | variables.rs:455:9:455:17 | print_i64 | | -| variables.rs:455:19:455:19 | x | variables.rs:455:9:455:20 | CallExpr | | +| variables.rs:455:19:455:19 | x | variables.rs:455:9:455:20 | print_i64(...) | | | variables.rs:456:9:456:17 | print_i64 | variables.rs:456:19:456:19 | x | | -| variables.rs:456:9:456:24 | CallExpr | variables.rs:453:12:457:5 | BlockExpr | | +| variables.rs:456:9:456:24 | print_i64(...) | variables.rs:453:12:457:5 | { ... } | | | variables.rs:456:9:456:25 | ExprStmt | variables.rs:456:9:456:17 | print_i64 | | | variables.rs:456:19:456:19 | x | variables.rs:456:23:456:23 | 1 | | -| variables.rs:456:19:456:23 | ... + ... | variables.rs:456:9:456:24 | CallExpr | | +| variables.rs:456:19:456:23 | ... + ... | variables.rs:456:9:456:24 | print_i64(...) | | | variables.rs:456:23:456:23 | 1 | variables.rs:456:19:456:23 | ... + ... | | | variables.rs:458:5:458:13 | print_i64 | variables.rs:458:15:458:15 | x | | -| variables.rs:458:5:458:16 | CallExpr | variables.rs:445:18:459:1 | BlockExpr | | +| variables.rs:458:5:458:16 | print_i64(...) | variables.rs:445:18:459:1 | { ... } | | | variables.rs:458:5:458:17 | ExprStmt | variables.rs:458:5:458:13 | print_i64 | | -| variables.rs:458:15:458:15 | x | variables.rs:458:5:458:16 | CallExpr | | -| variables.rs:461:1:474:1 | enter phi_read | variables.rs:461:13:461:14 | b1 | | -| variables.rs:461:1:474:1 | exit phi_read (normal) | variables.rs:461:1:474:1 | exit phi_read | | -| variables.rs:461:13:461:14 | b1 | variables.rs:461:13:461:21 | Param | match | -| variables.rs:461:13:461:21 | Param | variables.rs:461:24:461:25 | b2 | | -| variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:32 | Param | match | -| variables.rs:461:24:461:32 | Param | variables.rs:462:5:462:14 | LetStmt | | -| variables.rs:461:35:474:1 | BlockExpr | variables.rs:461:1:474:1 | exit phi_read (normal) | | -| variables.rs:462:5:462:14 | LetStmt | variables.rs:462:13:462:13 | 1 | | +| variables.rs:458:15:458:15 | x | variables.rs:458:5:458:16 | print_i64(...) | | +| variables.rs:461:1:474:1 | enter fn phi_read | variables.rs:461:13:461:14 | b1 | | +| variables.rs:461:1:474:1 | exit fn phi_read (normal) | variables.rs:461:1:474:1 | exit fn phi_read | | +| variables.rs:461:13:461:14 | b1 | variables.rs:461:13:461:21 | ...: bool | match | +| variables.rs:461:13:461:21 | ...: bool | variables.rs:461:24:461:25 | b2 | | +| variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:32 | ...: bool | match | +| variables.rs:461:24:461:32 | ...: bool | variables.rs:462:5:462:14 | let ... = 1 | | +| variables.rs:461:35:474:1 | { ... } | variables.rs:461:1:474:1 | exit fn phi_read (normal) | | +| variables.rs:462:5:462:14 | let ... = 1 | variables.rs:462:13:462:13 | 1 | | | variables.rs:462:9:462:9 | x | variables.rs:463:5:467:5 | ExprStmt | match | | variables.rs:462:13:462:13 | 1 | variables.rs:462:9:462:9 | x | | | variables.rs:463:5:467:5 | ExprStmt | variables.rs:463:8:463:9 | b1 | | -| variables.rs:463:5:467:5 | IfExpr | variables.rs:469:8:469:9 | b2 | | +| variables.rs:463:5:467:5 | if b1 {...} else {...} | variables.rs:469:8:469:9 | b2 | | | variables.rs:463:8:463:9 | b1 | variables.rs:464:9:464:21 | ExprStmt | true | | variables.rs:463:8:463:9 | b1 | variables.rs:466:9:466:21 | ExprStmt | false | -| variables.rs:463:11:465:5 | BlockExpr | variables.rs:463:5:467:5 | IfExpr | | +| variables.rs:463:11:465:5 | { ... } | variables.rs:463:5:467:5 | if b1 {...} else {...} | | | variables.rs:464:9:464:17 | print_i64 | variables.rs:464:19:464:19 | x | | -| variables.rs:464:9:464:20 | CallExpr | variables.rs:463:11:465:5 | BlockExpr | | +| variables.rs:464:9:464:20 | print_i64(...) | variables.rs:463:11:465:5 | { ... } | | | variables.rs:464:9:464:21 | ExprStmt | variables.rs:464:9:464:17 | print_i64 | | -| variables.rs:464:19:464:19 | x | variables.rs:464:9:464:20 | CallExpr | | -| variables.rs:465:12:467:5 | BlockExpr | variables.rs:463:5:467:5 | IfExpr | | +| variables.rs:464:19:464:19 | x | variables.rs:464:9:464:20 | print_i64(...) | | +| variables.rs:465:12:467:5 | { ... } | variables.rs:463:5:467:5 | if b1 {...} else {...} | | | variables.rs:466:9:466:17 | print_i64 | variables.rs:466:19:466:19 | x | | -| variables.rs:466:9:466:20 | CallExpr | variables.rs:465:12:467:5 | BlockExpr | | +| variables.rs:466:9:466:20 | print_i64(...) | variables.rs:465:12:467:5 | { ... } | | | variables.rs:466:9:466:21 | ExprStmt | variables.rs:466:9:466:17 | print_i64 | | -| variables.rs:466:19:466:19 | x | variables.rs:466:9:466:20 | CallExpr | | -| variables.rs:469:5:473:5 | IfExpr | variables.rs:461:35:474:1 | BlockExpr | | +| variables.rs:466:19:466:19 | x | variables.rs:466:9:466:20 | print_i64(...) | | +| variables.rs:469:5:473:5 | if b2 {...} else {...} | variables.rs:461:35:474:1 | { ... } | | | variables.rs:469:8:469:9 | b2 | variables.rs:470:9:470:21 | ExprStmt | true | | variables.rs:469:8:469:9 | b2 | variables.rs:472:9:472:21 | ExprStmt | false | -| variables.rs:469:11:471:5 | BlockExpr | variables.rs:469:5:473:5 | IfExpr | | +| variables.rs:469:11:471:5 | { ... } | variables.rs:469:5:473:5 | if b2 {...} else {...} | | | variables.rs:470:9:470:17 | print_i64 | variables.rs:470:19:470:19 | x | | -| variables.rs:470:9:470:20 | CallExpr | variables.rs:469:11:471:5 | BlockExpr | | +| variables.rs:470:9:470:20 | print_i64(...) | variables.rs:469:11:471:5 | { ... } | | | variables.rs:470:9:470:21 | ExprStmt | variables.rs:470:9:470:17 | print_i64 | | -| variables.rs:470:19:470:19 | x | variables.rs:470:9:470:20 | CallExpr | | -| variables.rs:471:12:473:5 | BlockExpr | variables.rs:469:5:473:5 | IfExpr | | +| variables.rs:470:19:470:19 | x | variables.rs:470:9:470:20 | print_i64(...) | | +| variables.rs:471:12:473:5 | { ... } | variables.rs:469:5:473:5 | if b2 {...} else {...} | | | variables.rs:472:9:472:17 | print_i64 | variables.rs:472:19:472:19 | x | | -| variables.rs:472:9:472:20 | CallExpr | variables.rs:471:12:473:5 | BlockExpr | | +| variables.rs:472:9:472:20 | print_i64(...) | variables.rs:471:12:473:5 | { ... } | | | variables.rs:472:9:472:21 | ExprStmt | variables.rs:472:9:472:17 | print_i64 | | -| variables.rs:472:19:472:19 | x | variables.rs:472:9:472:20 | CallExpr | | -| variables.rs:482:5:484:5 | enter my_get | variables.rs:483:9:483:24 | ExprStmt | | -| variables.rs:482:5:484:5 | exit my_get (normal) | variables.rs:482:5:484:5 | exit my_get | | -| variables.rs:483:9:483:23 | ReturnExpr | variables.rs:482:5:484:5 | exit my_get (normal) | return | +| variables.rs:472:19:472:19 | x | variables.rs:472:9:472:20 | print_i64(...) | | +| variables.rs:482:5:484:5 | enter fn my_get | variables.rs:482:20:482:23 | self | | +| variables.rs:482:5:484:5 | exit fn my_get (normal) | variables.rs:482:5:484:5 | exit fn my_get | | +| variables.rs:482:15:482:23 | SelfParam | variables.rs:483:9:483:24 | ExprStmt | | +| variables.rs:482:20:482:23 | self | variables.rs:482:15:482:23 | SelfParam | | +| variables.rs:483:9:483:23 | return ... | variables.rs:482:5:484:5 | exit fn my_get (normal) | return | | variables.rs:483:9:483:24 | ExprStmt | variables.rs:483:16:483:19 | self | | -| variables.rs:483:16:483:19 | self | variables.rs:483:16:483:23 | FieldExpr | | -| variables.rs:483:16:483:23 | FieldExpr | variables.rs:483:9:483:23 | ReturnExpr | | -| variables.rs:487:1:494:1 | enter structs | variables.rs:488:5:488:36 | LetStmt | | -| variables.rs:487:1:494:1 | exit structs (normal) | variables.rs:487:1:494:1 | exit structs | | -| variables.rs:487:14:494:1 | BlockExpr | variables.rs:487:1:494:1 | exit structs (normal) | | -| variables.rs:488:5:488:36 | LetStmt | variables.rs:488:33:488:33 | 1 | | -| variables.rs:488:9:488:13 | a | variables.rs:489:5:489:26 | ExprStmt | match | -| variables.rs:488:17:488:35 | RecordExpr | variables.rs:488:9:488:13 | a | | -| variables.rs:488:33:488:33 | 1 | variables.rs:488:17:488:35 | RecordExpr | | -| variables.rs:489:5:489:13 | print_i64 | variables.rs:489:15:489:15 | a | | -| variables.rs:489:5:489:25 | CallExpr | variables.rs:490:5:490:14 | ExprStmt | | -| variables.rs:489:5:489:26 | ExprStmt | variables.rs:489:5:489:13 | print_i64 | | -| variables.rs:489:15:489:15 | a | variables.rs:489:15:489:24 | ... .my_get(...) | | -| variables.rs:489:15:489:24 | ... .my_get(...) | variables.rs:489:5:489:25 | CallExpr | | -| variables.rs:490:5:490:5 | a | variables.rs:490:5:490:9 | FieldExpr | | -| variables.rs:490:5:490:9 | FieldExpr | variables.rs:490:13:490:13 | 5 | | -| variables.rs:490:5:490:13 | ... = ... | variables.rs:491:5:491:26 | ExprStmt | | -| variables.rs:490:5:490:14 | ExprStmt | variables.rs:490:5:490:5 | a | | -| variables.rs:490:13:490:13 | 5 | variables.rs:490:5:490:13 | ... = ... | | -| variables.rs:491:5:491:13 | print_i64 | variables.rs:491:15:491:15 | a | | -| variables.rs:491:5:491:25 | CallExpr | variables.rs:492:5:492:28 | ExprStmt | | -| variables.rs:491:5:491:26 | ExprStmt | variables.rs:491:5:491:13 | print_i64 | | -| variables.rs:491:15:491:15 | a | variables.rs:491:15:491:24 | ... .my_get(...) | | -| variables.rs:491:15:491:24 | ... .my_get(...) | variables.rs:491:5:491:25 | CallExpr | | -| variables.rs:492:5:492:5 | a | variables.rs:492:25:492:25 | 2 | | -| variables.rs:492:5:492:27 | ... = ... | variables.rs:493:5:493:26 | ExprStmt | | -| variables.rs:492:5:492:28 | ExprStmt | variables.rs:492:5:492:5 | a | | -| variables.rs:492:9:492:27 | RecordExpr | variables.rs:492:5:492:27 | ... = ... | | -| variables.rs:492:25:492:25 | 2 | variables.rs:492:9:492:27 | RecordExpr | | +| variables.rs:483:16:483:19 | self | variables.rs:483:16:483:23 | self.val | | +| variables.rs:483:16:483:23 | self.val | variables.rs:483:9:483:23 | return ... | | +| variables.rs:486:5:488:5 | enter fn id | variables.rs:486:11:486:14 | self | | +| variables.rs:486:5:488:5 | exit fn id (normal) | variables.rs:486:5:488:5 | exit fn id | | +| variables.rs:486:11:486:14 | SelfParam | variables.rs:487:9:487:12 | self | | +| variables.rs:486:11:486:14 | self | variables.rs:486:11:486:14 | SelfParam | | +| variables.rs:486:25:488:5 | { ... } | variables.rs:486:5:488:5 | exit fn id (normal) | | +| variables.rs:487:9:487:12 | self | variables.rs:486:25:488:5 | { ... } | | +| variables.rs:491:1:498:1 | enter fn structs | variables.rs:492:5:492:36 | let ... = ... | | +| variables.rs:491:1:498:1 | exit fn structs (normal) | variables.rs:491:1:498:1 | exit fn structs | | +| variables.rs:491:14:498:1 | { ... } | variables.rs:491:1:498:1 | exit fn structs (normal) | | +| variables.rs:492:5:492:36 | let ... = ... | variables.rs:492:33:492:33 | 1 | | +| variables.rs:492:9:492:13 | a | variables.rs:493:5:493:26 | ExprStmt | match | +| variables.rs:492:17:492:35 | MyStruct {...} | variables.rs:492:9:492:13 | a | | +| variables.rs:492:33:492:33 | 1 | variables.rs:492:17:492:35 | MyStruct {...} | | | variables.rs:493:5:493:13 | print_i64 | variables.rs:493:15:493:15 | a | | -| variables.rs:493:5:493:25 | CallExpr | variables.rs:487:14:494:1 | BlockExpr | | +| variables.rs:493:5:493:25 | print_i64(...) | variables.rs:494:5:494:14 | ExprStmt | | | variables.rs:493:5:493:26 | ExprStmt | variables.rs:493:5:493:13 | print_i64 | | | variables.rs:493:15:493:15 | a | variables.rs:493:15:493:24 | ... .my_get(...) | | -| variables.rs:493:15:493:24 | ... .my_get(...) | variables.rs:493:5:493:25 | CallExpr | | -| variables.rs:496:1:503:1 | enter ref_arg | variables.rs:497:5:497:15 | LetStmt | | -| variables.rs:496:1:503:1 | exit ref_arg (normal) | variables.rs:496:1:503:1 | exit ref_arg | | -| variables.rs:496:14:503:1 | BlockExpr | variables.rs:496:1:503:1 | exit ref_arg (normal) | | -| variables.rs:497:5:497:15 | LetStmt | variables.rs:497:13:497:14 | 16 | | -| variables.rs:497:9:497:9 | x | variables.rs:498:5:498:22 | ExprStmt | match | -| variables.rs:497:13:497:14 | 16 | variables.rs:497:9:497:9 | x | | -| variables.rs:498:5:498:17 | print_i64_ref | variables.rs:498:20:498:20 | x | | -| variables.rs:498:5:498:21 | CallExpr | variables.rs:499:5:499:17 | ExprStmt | | -| variables.rs:498:5:498:22 | ExprStmt | variables.rs:498:5:498:17 | print_i64_ref | | -| variables.rs:498:19:498:20 | RefExpr | variables.rs:498:5:498:21 | CallExpr | | -| variables.rs:498:20:498:20 | x | variables.rs:498:19:498:20 | RefExpr | | -| variables.rs:499:5:499:13 | print_i64 | variables.rs:499:15:499:15 | x | | -| variables.rs:499:5:499:16 | CallExpr | variables.rs:501:5:501:15 | LetStmt | | -| variables.rs:499:5:499:17 | ExprStmt | variables.rs:499:5:499:13 | print_i64 | | -| variables.rs:499:15:499:15 | x | variables.rs:499:5:499:16 | CallExpr | | -| variables.rs:501:5:501:15 | LetStmt | variables.rs:501:13:501:14 | 17 | | -| variables.rs:501:9:501:9 | z | variables.rs:502:5:502:22 | ExprStmt | match | -| variables.rs:501:13:501:14 | 17 | variables.rs:501:9:501:9 | z | | -| variables.rs:502:5:502:17 | print_i64_ref | variables.rs:502:20:502:20 | z | | -| variables.rs:502:5:502:21 | CallExpr | variables.rs:496:14:503:1 | BlockExpr | | +| variables.rs:493:15:493:24 | ... .my_get(...) | variables.rs:493:5:493:25 | print_i64(...) | | +| variables.rs:494:5:494:5 | a | variables.rs:494:5:494:9 | a.val | | +| variables.rs:494:5:494:9 | a.val | variables.rs:494:13:494:13 | 5 | | +| variables.rs:494:5:494:13 | ... = ... | variables.rs:495:5:495:26 | ExprStmt | | +| variables.rs:494:5:494:14 | ExprStmt | variables.rs:494:5:494:5 | a | | +| variables.rs:494:13:494:13 | 5 | variables.rs:494:5:494:13 | ... = ... | | +| variables.rs:495:5:495:13 | print_i64 | variables.rs:495:15:495:15 | a | | +| variables.rs:495:5:495:25 | print_i64(...) | variables.rs:496:5:496:28 | ExprStmt | | +| variables.rs:495:5:495:26 | ExprStmt | variables.rs:495:5:495:13 | print_i64 | | +| variables.rs:495:15:495:15 | a | variables.rs:495:15:495:24 | ... .my_get(...) | | +| variables.rs:495:15:495:24 | ... .my_get(...) | variables.rs:495:5:495:25 | print_i64(...) | | +| variables.rs:496:5:496:5 | a | variables.rs:496:25:496:25 | 2 | | +| variables.rs:496:5:496:27 | ... = ... | variables.rs:497:5:497:26 | ExprStmt | | +| variables.rs:496:5:496:28 | ExprStmt | variables.rs:496:5:496:5 | a | | +| variables.rs:496:9:496:27 | MyStruct {...} | variables.rs:496:5:496:27 | ... = ... | | +| variables.rs:496:25:496:25 | 2 | variables.rs:496:9:496:27 | MyStruct {...} | | +| variables.rs:497:5:497:13 | print_i64 | variables.rs:497:15:497:15 | a | | +| variables.rs:497:5:497:25 | print_i64(...) | variables.rs:491:14:498:1 | { ... } | | +| variables.rs:497:5:497:26 | ExprStmt | variables.rs:497:5:497:13 | print_i64 | | +| variables.rs:497:15:497:15 | a | variables.rs:497:15:497:24 | ... .my_get(...) | | +| variables.rs:497:15:497:24 | ... .my_get(...) | variables.rs:497:5:497:25 | print_i64(...) | | +| variables.rs:500:1:507:1 | enter fn ref_arg | variables.rs:501:5:501:15 | let ... = 16 | | +| variables.rs:500:1:507:1 | exit fn ref_arg (normal) | variables.rs:500:1:507:1 | exit fn ref_arg | | +| variables.rs:500:14:507:1 | { ... } | variables.rs:500:1:507:1 | exit fn ref_arg (normal) | | +| variables.rs:501:5:501:15 | let ... = 16 | variables.rs:501:13:501:14 | 16 | | +| variables.rs:501:9:501:9 | x | variables.rs:502:5:502:22 | ExprStmt | match | +| variables.rs:501:13:501:14 | 16 | variables.rs:501:9:501:9 | x | | +| variables.rs:502:5:502:17 | print_i64_ref | variables.rs:502:20:502:20 | x | | +| variables.rs:502:5:502:21 | print_i64_ref(...) | variables.rs:503:5:503:17 | ExprStmt | | | variables.rs:502:5:502:22 | ExprStmt | variables.rs:502:5:502:17 | print_i64_ref | | -| variables.rs:502:19:502:20 | RefExpr | variables.rs:502:5:502:21 | CallExpr | | -| variables.rs:502:20:502:20 | z | variables.rs:502:19:502:20 | RefExpr | | -| variables.rs:510:3:512:3 | enter bar | variables.rs:511:5:511:32 | ExprStmt | | -| variables.rs:510:3:512:3 | exit bar (normal) | variables.rs:510:3:512:3 | exit bar | | -| variables.rs:510:21:512:3 | BlockExpr | variables.rs:510:3:512:3 | exit bar (normal) | | -| variables.rs:511:5:511:9 | * ... | variables.rs:511:29:511:29 | 3 | | -| variables.rs:511:5:511:31 | ... = ... | variables.rs:510:21:512:3 | BlockExpr | | -| variables.rs:511:5:511:32 | ExprStmt | variables.rs:511:6:511:9 | self | | -| variables.rs:511:6:511:9 | self | variables.rs:511:5:511:9 | * ... | | -| variables.rs:511:13:511:31 | RecordExpr | variables.rs:511:5:511:31 | ... = ... | | -| variables.rs:511:29:511:29 | 3 | variables.rs:511:13:511:31 | RecordExpr | | -| variables.rs:515:1:520:1 | enter ref_methodcall_receiver | variables.rs:516:3:516:34 | LetStmt | | -| variables.rs:515:1:520:1 | exit ref_methodcall_receiver (normal) | variables.rs:515:1:520:1 | exit ref_methodcall_receiver | | -| variables.rs:515:30:520:1 | BlockExpr | variables.rs:515:1:520:1 | exit ref_methodcall_receiver (normal) | | -| variables.rs:516:3:516:34 | LetStmt | variables.rs:516:31:516:31 | 1 | | -| variables.rs:516:7:516:11 | a | variables.rs:517:3:517:10 | ExprStmt | match | -| variables.rs:516:15:516:33 | RecordExpr | variables.rs:516:7:516:11 | a | | -| variables.rs:516:31:516:31 | 1 | variables.rs:516:15:516:33 | RecordExpr | | -| variables.rs:517:3:517:3 | a | variables.rs:517:3:517:9 | ... .bar(...) | | -| variables.rs:517:3:517:9 | ... .bar(...) | variables.rs:519:3:519:19 | ExprStmt | | -| variables.rs:517:3:517:10 | ExprStmt | variables.rs:517:3:517:3 | a | | -| variables.rs:519:3:519:11 | print_i64 | variables.rs:519:13:519:13 | a | | -| variables.rs:519:3:519:18 | CallExpr | variables.rs:515:30:520:1 | BlockExpr | | -| variables.rs:519:3:519:19 | ExprStmt | variables.rs:519:3:519:11 | print_i64 | | -| variables.rs:519:13:519:13 | a | variables.rs:519:13:519:17 | FieldExpr | | -| variables.rs:519:13:519:17 | FieldExpr | variables.rs:519:3:519:18 | CallExpr | | -| variables.rs:522:1:556:1 | enter main | variables.rs:523:5:523:25 | ExprStmt | | -| variables.rs:522:1:556:1 | exit main (normal) | variables.rs:522:1:556:1 | exit main | | -| variables.rs:522:11:556:1 | BlockExpr | variables.rs:522:1:556:1 | exit main (normal) | | -| variables.rs:523:5:523:22 | immutable_variable | variables.rs:523:5:523:24 | CallExpr | | -| variables.rs:523:5:523:24 | CallExpr | variables.rs:524:5:524:23 | ExprStmt | | -| variables.rs:523:5:523:25 | ExprStmt | variables.rs:523:5:523:22 | immutable_variable | | -| variables.rs:524:5:524:20 | mutable_variable | variables.rs:524:5:524:22 | CallExpr | | -| variables.rs:524:5:524:22 | CallExpr | variables.rs:525:5:525:40 | ExprStmt | | -| variables.rs:524:5:524:23 | ExprStmt | variables.rs:524:5:524:20 | mutable_variable | | -| variables.rs:525:5:525:37 | mutable_variable_immutable_borrow | variables.rs:525:5:525:39 | CallExpr | | -| variables.rs:525:5:525:39 | CallExpr | variables.rs:526:5:526:23 | ExprStmt | | -| variables.rs:525:5:525:40 | ExprStmt | variables.rs:525:5:525:37 | mutable_variable_immutable_borrow | | -| variables.rs:526:5:526:20 | variable_shadow1 | variables.rs:526:5:526:22 | CallExpr | | -| variables.rs:526:5:526:22 | CallExpr | variables.rs:527:5:527:23 | ExprStmt | | -| variables.rs:526:5:526:23 | ExprStmt | variables.rs:526:5:526:20 | variable_shadow1 | | -| variables.rs:527:5:527:20 | variable_shadow2 | variables.rs:527:5:527:22 | CallExpr | | -| variables.rs:527:5:527:22 | CallExpr | variables.rs:528:5:528:19 | ExprStmt | | -| variables.rs:527:5:527:23 | ExprStmt | variables.rs:527:5:527:20 | variable_shadow2 | | -| variables.rs:528:5:528:16 | let_pattern1 | variables.rs:528:5:528:18 | CallExpr | | -| variables.rs:528:5:528:18 | CallExpr | variables.rs:529:5:529:19 | ExprStmt | | -| variables.rs:528:5:528:19 | ExprStmt | variables.rs:528:5:528:16 | let_pattern1 | | -| variables.rs:529:5:529:16 | let_pattern2 | variables.rs:529:5:529:18 | CallExpr | | -| variables.rs:529:5:529:18 | CallExpr | variables.rs:530:5:530:19 | ExprStmt | | -| variables.rs:529:5:529:19 | ExprStmt | variables.rs:529:5:529:16 | let_pattern2 | | -| variables.rs:530:5:530:16 | let_pattern3 | variables.rs:530:5:530:18 | CallExpr | | -| variables.rs:530:5:530:18 | CallExpr | variables.rs:531:5:531:19 | ExprStmt | | -| variables.rs:530:5:530:19 | ExprStmt | variables.rs:530:5:530:16 | let_pattern3 | | -| variables.rs:531:5:531:16 | let_pattern4 | variables.rs:531:5:531:18 | CallExpr | | -| variables.rs:531:5:531:18 | CallExpr | variables.rs:532:5:532:21 | ExprStmt | | -| variables.rs:531:5:531:19 | ExprStmt | variables.rs:531:5:531:16 | let_pattern4 | | -| variables.rs:532:5:532:18 | match_pattern1 | variables.rs:532:5:532:20 | CallExpr | | -| variables.rs:532:5:532:20 | CallExpr | variables.rs:533:5:533:21 | ExprStmt | | -| variables.rs:532:5:532:21 | ExprStmt | variables.rs:532:5:532:18 | match_pattern1 | | -| variables.rs:533:5:533:18 | match_pattern2 | variables.rs:533:5:533:20 | CallExpr | | -| variables.rs:533:5:533:20 | CallExpr | variables.rs:534:5:534:21 | ExprStmt | | -| variables.rs:533:5:533:21 | ExprStmt | variables.rs:533:5:533:18 | match_pattern2 | | -| variables.rs:534:5:534:18 | match_pattern3 | variables.rs:534:5:534:20 | CallExpr | | -| variables.rs:534:5:534:20 | CallExpr | variables.rs:535:5:535:21 | ExprStmt | | -| variables.rs:534:5:534:21 | ExprStmt | variables.rs:534:5:534:18 | match_pattern3 | | -| variables.rs:535:5:535:18 | match_pattern4 | variables.rs:535:5:535:20 | CallExpr | | -| variables.rs:535:5:535:20 | CallExpr | variables.rs:536:5:536:21 | ExprStmt | | -| variables.rs:535:5:535:21 | ExprStmt | variables.rs:535:5:535:18 | match_pattern4 | | -| variables.rs:536:5:536:18 | match_pattern5 | variables.rs:536:5:536:20 | CallExpr | | -| variables.rs:536:5:536:20 | CallExpr | variables.rs:537:5:537:21 | ExprStmt | | -| variables.rs:536:5:536:21 | ExprStmt | variables.rs:536:5:536:18 | match_pattern5 | | -| variables.rs:537:5:537:18 | match_pattern6 | variables.rs:537:5:537:20 | CallExpr | | -| variables.rs:537:5:537:20 | CallExpr | variables.rs:538:5:538:21 | ExprStmt | | -| variables.rs:537:5:537:21 | ExprStmt | variables.rs:537:5:537:18 | match_pattern6 | | -| variables.rs:538:5:538:18 | match_pattern7 | variables.rs:538:5:538:20 | CallExpr | | -| variables.rs:538:5:538:20 | CallExpr | variables.rs:539:5:539:21 | ExprStmt | | -| variables.rs:538:5:538:21 | ExprStmt | variables.rs:538:5:538:18 | match_pattern7 | | -| variables.rs:539:5:539:18 | match_pattern8 | variables.rs:539:5:539:20 | CallExpr | | -| variables.rs:539:5:539:20 | CallExpr | variables.rs:540:5:540:21 | ExprStmt | | -| variables.rs:539:5:539:21 | ExprStmt | variables.rs:539:5:539:18 | match_pattern8 | | -| variables.rs:540:5:540:18 | match_pattern9 | variables.rs:540:5:540:20 | CallExpr | | -| variables.rs:540:5:540:20 | CallExpr | variables.rs:541:5:541:36 | ExprStmt | | -| variables.rs:540:5:540:21 | ExprStmt | variables.rs:540:5:540:18 | match_pattern9 | | -| variables.rs:541:5:541:18 | param_pattern1 | variables.rs:541:20:541:22 | "a" | | -| variables.rs:541:5:541:35 | CallExpr | variables.rs:542:5:542:37 | ExprStmt | | -| variables.rs:541:5:541:36 | ExprStmt | variables.rs:541:5:541:18 | param_pattern1 | | -| variables.rs:541:20:541:22 | "a" | variables.rs:541:26:541:28 | "b" | | -| variables.rs:541:25:541:34 | TupleExpr | variables.rs:541:5:541:35 | CallExpr | | -| variables.rs:541:26:541:28 | "b" | variables.rs:541:31:541:33 | "c" | | -| variables.rs:541:31:541:33 | "c" | variables.rs:541:25:541:34 | TupleExpr | | -| variables.rs:542:5:542:18 | param_pattern2 | variables.rs:542:20:542:31 | Either::Left | | -| variables.rs:542:5:542:36 | CallExpr | variables.rs:543:5:543:26 | ExprStmt | | -| variables.rs:542:5:542:37 | ExprStmt | variables.rs:542:5:542:18 | param_pattern2 | | -| variables.rs:542:20:542:31 | Either::Left | variables.rs:542:33:542:34 | 45 | | -| variables.rs:542:20:542:35 | CallExpr | variables.rs:542:5:542:36 | CallExpr | | -| variables.rs:542:33:542:34 | 45 | variables.rs:542:20:542:35 | CallExpr | | -| variables.rs:543:5:543:23 | destruct_assignment | variables.rs:543:5:543:25 | CallExpr | | -| variables.rs:543:5:543:25 | CallExpr | variables.rs:544:5:544:23 | ExprStmt | | -| variables.rs:543:5:543:26 | ExprStmt | variables.rs:543:5:543:23 | destruct_assignment | | -| variables.rs:544:5:544:20 | closure_variable | variables.rs:544:5:544:22 | CallExpr | | -| variables.rs:544:5:544:22 | CallExpr | variables.rs:545:5:545:19 | ExprStmt | | -| variables.rs:544:5:544:23 | ExprStmt | variables.rs:544:5:544:20 | closure_variable | | -| variables.rs:545:5:545:16 | for_variable | variables.rs:545:5:545:18 | CallExpr | | -| variables.rs:545:5:545:18 | CallExpr | variables.rs:546:5:546:17 | ExprStmt | | -| variables.rs:545:5:545:19 | ExprStmt | variables.rs:545:5:545:16 | for_variable | | -| variables.rs:546:5:546:14 | add_assign | variables.rs:546:5:546:16 | CallExpr | | -| variables.rs:546:5:546:16 | CallExpr | variables.rs:547:5:547:13 | ExprStmt | | -| variables.rs:546:5:546:17 | ExprStmt | variables.rs:546:5:546:14 | add_assign | | -| variables.rs:547:5:547:10 | mutate | variables.rs:547:5:547:12 | CallExpr | | -| variables.rs:547:5:547:12 | CallExpr | variables.rs:548:5:548:17 | ExprStmt | | -| variables.rs:547:5:547:13 | ExprStmt | variables.rs:547:5:547:10 | mutate | | -| variables.rs:548:5:548:14 | mutate_arg | variables.rs:548:5:548:16 | CallExpr | | -| variables.rs:548:5:548:16 | CallExpr | variables.rs:549:5:549:12 | ExprStmt | | -| variables.rs:548:5:548:17 | ExprStmt | variables.rs:548:5:548:14 | mutate_arg | | -| variables.rs:549:5:549:9 | alias | variables.rs:549:5:549:11 | CallExpr | | -| variables.rs:549:5:549:11 | CallExpr | variables.rs:550:5:550:18 | ExprStmt | | -| variables.rs:549:5:549:12 | ExprStmt | variables.rs:549:5:549:9 | alias | | -| variables.rs:550:5:550:15 | capture_mut | variables.rs:550:5:550:17 | CallExpr | | -| variables.rs:550:5:550:17 | CallExpr | variables.rs:551:5:551:20 | ExprStmt | | -| variables.rs:550:5:550:18 | ExprStmt | variables.rs:550:5:550:15 | capture_mut | | -| variables.rs:551:5:551:17 | capture_immut | variables.rs:551:5:551:19 | CallExpr | | -| variables.rs:551:5:551:19 | CallExpr | variables.rs:552:5:552:26 | ExprStmt | | -| variables.rs:551:5:551:20 | ExprStmt | variables.rs:551:5:551:17 | capture_immut | | -| variables.rs:552:5:552:23 | async_block_capture | variables.rs:552:5:552:25 | CallExpr | | -| variables.rs:552:5:552:25 | CallExpr | variables.rs:553:5:553:14 | ExprStmt | | -| variables.rs:552:5:552:26 | ExprStmt | variables.rs:552:5:552:23 | async_block_capture | | -| variables.rs:553:5:553:11 | structs | variables.rs:553:5:553:13 | CallExpr | | -| variables.rs:553:5:553:13 | CallExpr | variables.rs:554:5:554:14 | ExprStmt | | -| variables.rs:553:5:553:14 | ExprStmt | variables.rs:553:5:553:11 | structs | | -| variables.rs:554:5:554:11 | ref_arg | variables.rs:554:5:554:13 | CallExpr | | -| variables.rs:554:5:554:13 | CallExpr | variables.rs:555:5:555:30 | ExprStmt | | -| variables.rs:554:5:554:14 | ExprStmt | variables.rs:554:5:554:11 | ref_arg | | -| variables.rs:555:5:555:27 | ref_methodcall_receiver | variables.rs:555:5:555:29 | CallExpr | | -| variables.rs:555:5:555:29 | CallExpr | variables.rs:522:11:556:1 | BlockExpr | | -| variables.rs:555:5:555:30 | ExprStmt | variables.rs:555:5:555:27 | ref_methodcall_receiver | | +| variables.rs:502:19:502:20 | &x | variables.rs:502:5:502:21 | print_i64_ref(...) | | +| variables.rs:502:20:502:20 | x | variables.rs:502:19:502:20 | &x | | +| variables.rs:503:5:503:13 | print_i64 | variables.rs:503:15:503:15 | x | | +| variables.rs:503:5:503:16 | print_i64(...) | variables.rs:505:5:505:15 | let ... = 17 | | +| variables.rs:503:5:503:17 | ExprStmt | variables.rs:503:5:503:13 | print_i64 | | +| variables.rs:503:15:503:15 | x | variables.rs:503:5:503:16 | print_i64(...) | | +| variables.rs:505:5:505:15 | let ... = 17 | variables.rs:505:13:505:14 | 17 | | +| variables.rs:505:9:505:9 | z | variables.rs:506:5:506:22 | ExprStmt | match | +| variables.rs:505:13:505:14 | 17 | variables.rs:505:9:505:9 | z | | +| variables.rs:506:5:506:17 | print_i64_ref | variables.rs:506:20:506:20 | z | | +| variables.rs:506:5:506:21 | print_i64_ref(...) | variables.rs:500:14:507:1 | { ... } | | +| variables.rs:506:5:506:22 | ExprStmt | variables.rs:506:5:506:17 | print_i64_ref | | +| variables.rs:506:19:506:20 | &z | variables.rs:506:5:506:21 | print_i64_ref(...) | | +| variables.rs:506:20:506:20 | z | variables.rs:506:19:506:20 | &z | | +| variables.rs:514:3:516:3 | enter fn bar | variables.rs:514:15:514:18 | self | | +| variables.rs:514:3:516:3 | exit fn bar (normal) | variables.rs:514:3:516:3 | exit fn bar | | +| variables.rs:514:10:514:18 | SelfParam | variables.rs:515:5:515:32 | ExprStmt | | +| variables.rs:514:15:514:18 | self | variables.rs:514:10:514:18 | SelfParam | | +| variables.rs:514:21:516:3 | { ... } | variables.rs:514:3:516:3 | exit fn bar (normal) | | +| variables.rs:515:5:515:9 | * ... | variables.rs:515:29:515:29 | 3 | | +| variables.rs:515:5:515:31 | ... = ... | variables.rs:514:21:516:3 | { ... } | | +| variables.rs:515:5:515:32 | ExprStmt | variables.rs:515:6:515:9 | self | | +| variables.rs:515:6:515:9 | self | variables.rs:515:5:515:9 | * ... | | +| variables.rs:515:13:515:31 | MyStruct {...} | variables.rs:515:5:515:31 | ... = ... | | +| variables.rs:515:29:515:29 | 3 | variables.rs:515:13:515:31 | MyStruct {...} | | +| variables.rs:519:1:524:1 | enter fn ref_methodcall_receiver | variables.rs:520:3:520:34 | let ... = ... | | +| variables.rs:519:1:524:1 | exit fn ref_methodcall_receiver (normal) | variables.rs:519:1:524:1 | exit fn ref_methodcall_receiver | | +| variables.rs:519:30:524:1 | { ... } | variables.rs:519:1:524:1 | exit fn ref_methodcall_receiver (normal) | | +| variables.rs:520:3:520:34 | let ... = ... | variables.rs:520:31:520:31 | 1 | | +| variables.rs:520:7:520:11 | a | variables.rs:521:3:521:10 | ExprStmt | match | +| variables.rs:520:15:520:33 | MyStruct {...} | variables.rs:520:7:520:11 | a | | +| variables.rs:520:31:520:31 | 1 | variables.rs:520:15:520:33 | MyStruct {...} | | +| variables.rs:521:3:521:3 | a | variables.rs:521:3:521:9 | ... .bar(...) | | +| variables.rs:521:3:521:9 | ... .bar(...) | variables.rs:523:3:523:19 | ExprStmt | | +| variables.rs:521:3:521:10 | ExprStmt | variables.rs:521:3:521:3 | a | | +| variables.rs:523:3:523:11 | print_i64 | variables.rs:523:13:523:13 | a | | +| variables.rs:523:3:523:18 | print_i64(...) | variables.rs:519:30:524:1 | { ... } | | +| variables.rs:523:3:523:19 | ExprStmt | variables.rs:523:3:523:11 | print_i64 | | +| variables.rs:523:13:523:13 | a | variables.rs:523:13:523:17 | a.val | | +| variables.rs:523:13:523:17 | a.val | variables.rs:523:3:523:18 | print_i64(...) | | +| variables.rs:526:1:560:1 | enter fn main | variables.rs:527:5:527:25 | ExprStmt | | +| variables.rs:526:1:560:1 | exit fn main (normal) | variables.rs:526:1:560:1 | exit fn main | | +| variables.rs:526:11:560:1 | { ... } | variables.rs:526:1:560:1 | exit fn main (normal) | | +| variables.rs:527:5:527:22 | immutable_variable | variables.rs:527:5:527:24 | immutable_variable(...) | | +| variables.rs:527:5:527:24 | immutable_variable(...) | variables.rs:528:5:528:23 | ExprStmt | | +| variables.rs:527:5:527:25 | ExprStmt | variables.rs:527:5:527:22 | immutable_variable | | +| variables.rs:528:5:528:20 | mutable_variable | variables.rs:528:5:528:22 | mutable_variable(...) | | +| variables.rs:528:5:528:22 | mutable_variable(...) | variables.rs:529:5:529:40 | ExprStmt | | +| variables.rs:528:5:528:23 | ExprStmt | variables.rs:528:5:528:20 | mutable_variable | | +| variables.rs:529:5:529:37 | mutable_variable_immutable_borrow | variables.rs:529:5:529:39 | mutable_variable_immutable_borrow(...) | | +| variables.rs:529:5:529:39 | mutable_variable_immutable_borrow(...) | variables.rs:530:5:530:23 | ExprStmt | | +| variables.rs:529:5:529:40 | ExprStmt | variables.rs:529:5:529:37 | mutable_variable_immutable_borrow | | +| variables.rs:530:5:530:20 | variable_shadow1 | variables.rs:530:5:530:22 | variable_shadow1(...) | | +| variables.rs:530:5:530:22 | variable_shadow1(...) | variables.rs:531:5:531:23 | ExprStmt | | +| variables.rs:530:5:530:23 | ExprStmt | variables.rs:530:5:530:20 | variable_shadow1 | | +| variables.rs:531:5:531:20 | variable_shadow2 | variables.rs:531:5:531:22 | variable_shadow2(...) | | +| variables.rs:531:5:531:22 | variable_shadow2(...) | variables.rs:532:5:532:19 | ExprStmt | | +| variables.rs:531:5:531:23 | ExprStmt | variables.rs:531:5:531:20 | variable_shadow2 | | +| variables.rs:532:5:532:16 | let_pattern1 | variables.rs:532:5:532:18 | let_pattern1(...) | | +| variables.rs:532:5:532:18 | let_pattern1(...) | variables.rs:533:5:533:19 | ExprStmt | | +| variables.rs:532:5:532:19 | ExprStmt | variables.rs:532:5:532:16 | let_pattern1 | | +| variables.rs:533:5:533:16 | let_pattern2 | variables.rs:533:5:533:18 | let_pattern2(...) | | +| variables.rs:533:5:533:18 | let_pattern2(...) | variables.rs:534:5:534:19 | ExprStmt | | +| variables.rs:533:5:533:19 | ExprStmt | variables.rs:533:5:533:16 | let_pattern2 | | +| variables.rs:534:5:534:16 | let_pattern3 | variables.rs:534:5:534:18 | let_pattern3(...) | | +| variables.rs:534:5:534:18 | let_pattern3(...) | variables.rs:535:5:535:19 | ExprStmt | | +| variables.rs:534:5:534:19 | ExprStmt | variables.rs:534:5:534:16 | let_pattern3 | | +| variables.rs:535:5:535:16 | let_pattern4 | variables.rs:535:5:535:18 | let_pattern4(...) | | +| variables.rs:535:5:535:18 | let_pattern4(...) | variables.rs:536:5:536:21 | ExprStmt | | +| variables.rs:535:5:535:19 | ExprStmt | variables.rs:535:5:535:16 | let_pattern4 | | +| variables.rs:536:5:536:18 | match_pattern1 | variables.rs:536:5:536:20 | match_pattern1(...) | | +| variables.rs:536:5:536:20 | match_pattern1(...) | variables.rs:537:5:537:21 | ExprStmt | | +| variables.rs:536:5:536:21 | ExprStmt | variables.rs:536:5:536:18 | match_pattern1 | | +| variables.rs:537:5:537:18 | match_pattern2 | variables.rs:537:5:537:20 | match_pattern2(...) | | +| variables.rs:537:5:537:20 | match_pattern2(...) | variables.rs:538:5:538:21 | ExprStmt | | +| variables.rs:537:5:537:21 | ExprStmt | variables.rs:537:5:537:18 | match_pattern2 | | +| variables.rs:538:5:538:18 | match_pattern3 | variables.rs:538:5:538:20 | match_pattern3(...) | | +| variables.rs:538:5:538:20 | match_pattern3(...) | variables.rs:539:5:539:21 | ExprStmt | | +| variables.rs:538:5:538:21 | ExprStmt | variables.rs:538:5:538:18 | match_pattern3 | | +| variables.rs:539:5:539:18 | match_pattern4 | variables.rs:539:5:539:20 | match_pattern4(...) | | +| variables.rs:539:5:539:20 | match_pattern4(...) | variables.rs:540:5:540:21 | ExprStmt | | +| variables.rs:539:5:539:21 | ExprStmt | variables.rs:539:5:539:18 | match_pattern4 | | +| variables.rs:540:5:540:18 | match_pattern5 | variables.rs:540:5:540:20 | match_pattern5(...) | | +| variables.rs:540:5:540:20 | match_pattern5(...) | variables.rs:541:5:541:21 | ExprStmt | | +| variables.rs:540:5:540:21 | ExprStmt | variables.rs:540:5:540:18 | match_pattern5 | | +| variables.rs:541:5:541:18 | match_pattern6 | variables.rs:541:5:541:20 | match_pattern6(...) | | +| variables.rs:541:5:541:20 | match_pattern6(...) | variables.rs:542:5:542:21 | ExprStmt | | +| variables.rs:541:5:541:21 | ExprStmt | variables.rs:541:5:541:18 | match_pattern6 | | +| variables.rs:542:5:542:18 | match_pattern7 | variables.rs:542:5:542:20 | match_pattern7(...) | | +| variables.rs:542:5:542:20 | match_pattern7(...) | variables.rs:543:5:543:21 | ExprStmt | | +| variables.rs:542:5:542:21 | ExprStmt | variables.rs:542:5:542:18 | match_pattern7 | | +| variables.rs:543:5:543:18 | match_pattern8 | variables.rs:543:5:543:20 | match_pattern8(...) | | +| variables.rs:543:5:543:20 | match_pattern8(...) | variables.rs:544:5:544:21 | ExprStmt | | +| variables.rs:543:5:543:21 | ExprStmt | variables.rs:543:5:543:18 | match_pattern8 | | +| variables.rs:544:5:544:18 | match_pattern9 | variables.rs:544:5:544:20 | match_pattern9(...) | | +| variables.rs:544:5:544:20 | match_pattern9(...) | variables.rs:545:5:545:36 | ExprStmt | | +| variables.rs:544:5:544:21 | ExprStmt | variables.rs:544:5:544:18 | match_pattern9 | | +| variables.rs:545:5:545:18 | param_pattern1 | variables.rs:545:20:545:22 | "a" | | +| variables.rs:545:5:545:35 | param_pattern1(...) | variables.rs:546:5:546:37 | ExprStmt | | +| variables.rs:545:5:545:36 | ExprStmt | variables.rs:545:5:545:18 | param_pattern1 | | +| variables.rs:545:20:545:22 | "a" | variables.rs:545:26:545:28 | "b" | | +| variables.rs:545:25:545:34 | TupleExpr | variables.rs:545:5:545:35 | param_pattern1(...) | | +| variables.rs:545:26:545:28 | "b" | variables.rs:545:31:545:33 | "c" | | +| variables.rs:545:31:545:33 | "c" | variables.rs:545:25:545:34 | TupleExpr | | +| variables.rs:546:5:546:18 | param_pattern2 | variables.rs:546:20:546:31 | ...::Left | | +| variables.rs:546:5:546:36 | param_pattern2(...) | variables.rs:547:5:547:26 | ExprStmt | | +| variables.rs:546:5:546:37 | ExprStmt | variables.rs:546:5:546:18 | param_pattern2 | | +| variables.rs:546:20:546:31 | ...::Left | variables.rs:546:33:546:34 | 45 | | +| variables.rs:546:20:546:35 | ...::Left(...) | variables.rs:546:5:546:36 | param_pattern2(...) | | +| variables.rs:546:33:546:34 | 45 | variables.rs:546:20:546:35 | ...::Left(...) | | +| variables.rs:547:5:547:23 | destruct_assignment | variables.rs:547:5:547:25 | destruct_assignment(...) | | +| variables.rs:547:5:547:25 | destruct_assignment(...) | variables.rs:548:5:548:23 | ExprStmt | | +| variables.rs:547:5:547:26 | ExprStmt | variables.rs:547:5:547:23 | destruct_assignment | | +| variables.rs:548:5:548:20 | closure_variable | variables.rs:548:5:548:22 | closure_variable(...) | | +| variables.rs:548:5:548:22 | closure_variable(...) | variables.rs:549:5:549:19 | ExprStmt | | +| variables.rs:548:5:548:23 | ExprStmt | variables.rs:548:5:548:20 | closure_variable | | +| variables.rs:549:5:549:16 | for_variable | variables.rs:549:5:549:18 | for_variable(...) | | +| variables.rs:549:5:549:18 | for_variable(...) | variables.rs:550:5:550:17 | ExprStmt | | +| variables.rs:549:5:549:19 | ExprStmt | variables.rs:549:5:549:16 | for_variable | | +| variables.rs:550:5:550:14 | add_assign | variables.rs:550:5:550:16 | add_assign(...) | | +| variables.rs:550:5:550:16 | add_assign(...) | variables.rs:551:5:551:13 | ExprStmt | | +| variables.rs:550:5:550:17 | ExprStmt | variables.rs:550:5:550:14 | add_assign | | +| variables.rs:551:5:551:10 | mutate | variables.rs:551:5:551:12 | mutate(...) | | +| variables.rs:551:5:551:12 | mutate(...) | variables.rs:552:5:552:17 | ExprStmt | | +| variables.rs:551:5:551:13 | ExprStmt | variables.rs:551:5:551:10 | mutate | | +| variables.rs:552:5:552:14 | mutate_arg | variables.rs:552:5:552:16 | mutate_arg(...) | | +| variables.rs:552:5:552:16 | mutate_arg(...) | variables.rs:553:5:553:12 | ExprStmt | | +| variables.rs:552:5:552:17 | ExprStmt | variables.rs:552:5:552:14 | mutate_arg | | +| variables.rs:553:5:553:9 | alias | variables.rs:553:5:553:11 | alias(...) | | +| variables.rs:553:5:553:11 | alias(...) | variables.rs:554:5:554:18 | ExprStmt | | +| variables.rs:553:5:553:12 | ExprStmt | variables.rs:553:5:553:9 | alias | | +| variables.rs:554:5:554:15 | capture_mut | variables.rs:554:5:554:17 | capture_mut(...) | | +| variables.rs:554:5:554:17 | capture_mut(...) | variables.rs:555:5:555:20 | ExprStmt | | +| variables.rs:554:5:554:18 | ExprStmt | variables.rs:554:5:554:15 | capture_mut | | +| variables.rs:555:5:555:17 | capture_immut | variables.rs:555:5:555:19 | capture_immut(...) | | +| variables.rs:555:5:555:19 | capture_immut(...) | variables.rs:556:5:556:26 | ExprStmt | | +| variables.rs:555:5:555:20 | ExprStmt | variables.rs:555:5:555:17 | capture_immut | | +| variables.rs:556:5:556:23 | async_block_capture | variables.rs:556:5:556:25 | async_block_capture(...) | | +| variables.rs:556:5:556:25 | async_block_capture(...) | variables.rs:557:5:557:14 | ExprStmt | | +| variables.rs:556:5:556:26 | ExprStmt | variables.rs:556:5:556:23 | async_block_capture | | +| variables.rs:557:5:557:11 | structs | variables.rs:557:5:557:13 | structs(...) | | +| variables.rs:557:5:557:13 | structs(...) | variables.rs:558:5:558:14 | ExprStmt | | +| variables.rs:557:5:557:14 | ExprStmt | variables.rs:557:5:557:11 | structs | | +| variables.rs:558:5:558:11 | ref_arg | variables.rs:558:5:558:13 | ref_arg(...) | | +| variables.rs:558:5:558:13 | ref_arg(...) | variables.rs:559:5:559:30 | ExprStmt | | +| variables.rs:558:5:558:14 | ExprStmt | variables.rs:558:5:558:11 | ref_arg | | +| variables.rs:559:5:559:27 | ref_methodcall_receiver | variables.rs:559:5:559:29 | ref_methodcall_receiver(...) | | +| variables.rs:559:5:559:29 | ref_methodcall_receiver(...) | variables.rs:526:11:560:1 | { ... } | | +| variables.rs:559:5:559:30 | ExprStmt | variables.rs:559:5:559:27 | ref_methodcall_receiver | | breakTarget continueTarget diff --git a/rust/ql/test/library-tests/variables/Ssa.expected b/rust/ql/test/library-tests/variables/Ssa.expected index f17152793a3e..ac6ec176a29a 100644 --- a/rust/ql/test/library-tests/variables/Ssa.expected +++ b/rust/ql/test/library-tests/variables/Ssa.expected @@ -5,8 +5,8 @@ nonSsaVariable | variables.rs:379:13:379:13 | z | | variables.rs:392:13:392:13 | x | | variables.rs:426:13:426:13 | z | -| variables.rs:488:13:488:13 | a | -| variables.rs:516:11:516:11 | a | +| variables.rs:492:13:492:13 | a | +| variables.rs:520:11:520:11 | a | definition | variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | | variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | @@ -120,12 +120,12 @@ definition | variables.rs:418:9:418:13 | y | variables.rs:418:13:418:13 | y | | variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | | variables.rs:421:9:421:9 | y | variables.rs:418:13:418:13 | y | -| variables.rs:423:5:423:14 | CallExpr | variables.rs:418:13:418:13 | y | +| variables.rs:423:5:423:14 | closure2(...) | variables.rs:418:13:418:13 | y | | variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | | variables.rs:436:9:436:13 | i | variables.rs:436:13:436:13 | i | | variables.rs:437:9:437:13 | block | variables.rs:437:9:437:13 | block | | variables.rs:438:9:438:9 | i | variables.rs:436:13:436:13 | i | -| variables.rs:441:5:441:15 | AwaitExpr | variables.rs:436:13:436:13 | i | +| variables.rs:441:5:441:15 | await block | variables.rs:436:13:436:13 | i | | variables.rs:445:8:445:8 | b | variables.rs:445:8:445:8 | b | | variables.rs:446:9:446:13 | x | variables.rs:446:13:446:13 | x | | variables.rs:449:5:457:5 | phi | variables.rs:446:13:446:13 | x | @@ -134,8 +134,11 @@ definition | variables.rs:461:13:461:14 | b1 | variables.rs:461:13:461:14 | b1 | | variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:25 | b2 | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | -| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | -| variables.rs:501:9:501:9 | z | variables.rs:501:9:501:9 | z | +| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | +| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | +| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | +| variables.rs:505:9:505:9 | z | variables.rs:505:9:505:9 | z | +| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | read | variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | variables.rs:4:20:4:20 | s | | variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | variables.rs:8:20:8:20 | i | @@ -239,10 +242,10 @@ read | variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:12 | closure1 | | variables.rs:412:20:414:5 | x | variables.rs:410:13:410:13 | x | variables.rs:413:19:413:19 | x | | variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | variables.rs:423:5:423:12 | closure2 | -| variables.rs:423:5:423:14 | CallExpr | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y | +| variables.rs:423:5:423:14 | closure2(...) | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y | | variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | variables.rs:431:5:431:12 | closure3 | | variables.rs:437:9:437:13 | block | variables.rs:437:9:437:13 | block | variables.rs:441:5:441:9 | block | -| variables.rs:441:5:441:15 | AwaitExpr | variables.rs:436:13:436:13 | i | variables.rs:442:15:442:15 | i | +| variables.rs:441:5:441:15 | await block | variables.rs:436:13:436:13 | i | variables.rs:442:15:442:15 | i | | variables.rs:445:8:445:8 | b | variables.rs:445:8:445:8 | b | variables.rs:449:8:449:8 | b | | variables.rs:446:9:446:13 | x | variables.rs:446:13:446:13 | x | variables.rs:447:15:447:15 | x | | variables.rs:446:9:446:13 | x | variables.rs:446:13:446:13 | x | variables.rs:448:15:448:15 | x | @@ -257,7 +260,10 @@ read | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:466:19:466:19 | x | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:470:19:470:19 | x | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:472:19:472:19 | x | -| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | variables.rs:499:15:499:15 | x | +| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | variables.rs:483:16:483:19 | self | +| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | variables.rs:487:9:487:12 | self | +| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | variables.rs:503:15:503:15 | x | +| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | variables.rs:515:6:515:9 | self | firstRead | variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | variables.rs:4:20:4:20 | s | | variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | variables.rs:8:20:8:20 | i | @@ -343,10 +349,10 @@ firstRead | variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:12 | closure1 | | variables.rs:412:20:414:5 | x | variables.rs:410:13:410:13 | x | variables.rs:413:19:413:19 | x | | variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | variables.rs:423:5:423:12 | closure2 | -| variables.rs:423:5:423:14 | CallExpr | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y | +| variables.rs:423:5:423:14 | closure2(...) | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y | | variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | variables.rs:431:5:431:12 | closure3 | | variables.rs:437:9:437:13 | block | variables.rs:437:9:437:13 | block | variables.rs:441:5:441:9 | block | -| variables.rs:441:5:441:15 | AwaitExpr | variables.rs:436:13:436:13 | i | variables.rs:442:15:442:15 | i | +| variables.rs:441:5:441:15 | await block | variables.rs:436:13:436:13 | i | variables.rs:442:15:442:15 | i | | variables.rs:445:8:445:8 | b | variables.rs:445:8:445:8 | b | variables.rs:449:8:449:8 | b | | variables.rs:446:9:446:13 | x | variables.rs:446:13:446:13 | x | variables.rs:447:15:447:15 | x | | variables.rs:449:5:457:5 | phi | variables.rs:446:13:446:13 | x | variables.rs:458:15:458:15 | x | @@ -356,7 +362,10 @@ firstRead | variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:25 | b2 | variables.rs:469:8:469:9 | b2 | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:464:19:464:19 | x | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:466:19:466:19 | x | -| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | variables.rs:499:15:499:15 | x | +| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | variables.rs:483:16:483:19 | self | +| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | variables.rs:487:9:487:12 | self | +| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | variables.rs:503:15:503:15 | x | +| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | variables.rs:515:6:515:9 | self | lastRead | variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | variables.rs:4:20:4:20 | s | | variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | variables.rs:8:20:8:20 | i | @@ -443,10 +452,10 @@ lastRead | variables.rs:412:9:412:16 | closure1 | variables.rs:412:9:412:16 | closure1 | variables.rs:415:5:415:12 | closure1 | | variables.rs:412:20:414:5 | x | variables.rs:410:13:410:13 | x | variables.rs:413:19:413:19 | x | | variables.rs:420:9:420:20 | closure2 | variables.rs:420:13:420:20 | closure2 | variables.rs:423:5:423:12 | closure2 | -| variables.rs:423:5:423:14 | CallExpr | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y | +| variables.rs:423:5:423:14 | closure2(...) | variables.rs:418:13:418:13 | y | variables.rs:424:15:424:15 | y | | variables.rs:428:9:428:20 | closure3 | variables.rs:428:13:428:20 | closure3 | variables.rs:431:5:431:12 | closure3 | | variables.rs:437:9:437:13 | block | variables.rs:437:9:437:13 | block | variables.rs:441:5:441:9 | block | -| variables.rs:441:5:441:15 | AwaitExpr | variables.rs:436:13:436:13 | i | variables.rs:442:15:442:15 | i | +| variables.rs:441:5:441:15 | await block | variables.rs:436:13:436:13 | i | variables.rs:442:15:442:15 | i | | variables.rs:445:8:445:8 | b | variables.rs:445:8:445:8 | b | variables.rs:449:8:449:8 | b | | variables.rs:446:9:446:13 | x | variables.rs:446:13:446:13 | x | variables.rs:448:15:448:15 | x | | variables.rs:449:5:457:5 | phi | variables.rs:446:13:446:13 | x | variables.rs:458:15:458:15 | x | @@ -456,7 +465,10 @@ lastRead | variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:25 | b2 | variables.rs:469:8:469:9 | b2 | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:470:19:470:19 | x | | variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:472:19:472:19 | x | -| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | variables.rs:499:15:499:15 | x | +| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | variables.rs:483:16:483:19 | self | +| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | variables.rs:487:9:487:12 | self | +| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | variables.rs:503:15:503:15 | x | +| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | variables.rs:515:6:515:9 | self | adjacentReads | variables.rs:35:9:35:10 | x3 | variables.rs:35:9:35:10 | x3 | variables.rs:36:15:36:16 | x3 | variables.rs:38:9:38:10 | x3 | | variables.rs:43:9:43:10 | x4 | variables.rs:43:9:43:10 | x4 | variables.rs:44:15:44:16 | x4 | variables.rs:49:15:49:16 | x4 | diff --git a/rust/ql/test/library-tests/variables/variables.expected b/rust/ql/test/library-tests/variables/variables.expected index 6760f9bcdde3..9abee1df82e4 100644 --- a/rust/ql/test/library-tests/variables/variables.expected +++ b/rust/ql/test/library-tests/variables/variables.expected @@ -95,10 +95,13 @@ variable | variables.rs:461:13:461:14 | b1 | | variables.rs:461:24:461:25 | b2 | | variables.rs:462:9:462:9 | x | -| variables.rs:488:13:488:13 | a | -| variables.rs:497:9:497:9 | x | -| variables.rs:501:9:501:9 | z | -| variables.rs:516:11:516:11 | a | +| variables.rs:482:20:482:23 | self | +| variables.rs:486:11:486:14 | self | +| variables.rs:492:13:492:13 | a | +| variables.rs:501:9:501:9 | x | +| variables.rs:505:9:505:9 | z | +| variables.rs:514:15:514:18 | self | +| variables.rs:520:11:520:11 | a | variableAccess | variables.rs:4:20:4:20 | s | variables.rs:3:14:3:14 | s | | variables.rs:8:20:8:20 | i | variables.rs:7:14:7:14 | i | @@ -246,16 +249,19 @@ variableAccess | variables.rs:469:8:469:9 | b2 | variables.rs:461:24:461:25 | b2 | | variables.rs:470:19:470:19 | x | variables.rs:462:9:462:9 | x | | variables.rs:472:19:472:19 | x | variables.rs:462:9:462:9 | x | -| variables.rs:489:15:489:15 | a | variables.rs:488:13:488:13 | a | -| variables.rs:490:5:490:5 | a | variables.rs:488:13:488:13 | a | -| variables.rs:491:15:491:15 | a | variables.rs:488:13:488:13 | a | -| variables.rs:492:5:492:5 | a | variables.rs:488:13:488:13 | a | -| variables.rs:493:15:493:15 | a | variables.rs:488:13:488:13 | a | -| variables.rs:498:20:498:20 | x | variables.rs:497:9:497:9 | x | -| variables.rs:499:15:499:15 | x | variables.rs:497:9:497:9 | x | -| variables.rs:502:20:502:20 | z | variables.rs:501:9:501:9 | z | -| variables.rs:517:3:517:3 | a | variables.rs:516:11:516:11 | a | -| variables.rs:519:13:519:13 | a | variables.rs:516:11:516:11 | a | +| variables.rs:483:16:483:19 | self | variables.rs:482:20:482:23 | self | +| variables.rs:487:9:487:12 | self | variables.rs:486:11:486:14 | self | +| variables.rs:493:15:493:15 | a | variables.rs:492:13:492:13 | a | +| variables.rs:494:5:494:5 | a | variables.rs:492:13:492:13 | a | +| variables.rs:495:15:495:15 | a | variables.rs:492:13:492:13 | a | +| variables.rs:496:5:496:5 | a | variables.rs:492:13:492:13 | a | +| variables.rs:497:15:497:15 | a | variables.rs:492:13:492:13 | a | +| variables.rs:502:20:502:20 | x | variables.rs:501:9:501:9 | x | +| variables.rs:503:15:503:15 | x | variables.rs:501:9:501:9 | x | +| variables.rs:506:20:506:20 | z | variables.rs:505:9:505:9 | z | +| variables.rs:515:6:515:9 | self | variables.rs:514:15:514:18 | self | +| variables.rs:521:3:521:3 | a | variables.rs:520:11:520:11 | a | +| variables.rs:523:13:523:13 | a | variables.rs:520:11:520:11 | a | variableWriteAccess | variables.rs:23:5:23:6 | x2 | variables.rs:21:13:21:14 | x2 | | variables.rs:30:5:30:5 | x | variables.rs:28:13:28:13 | x | @@ -266,7 +272,7 @@ variableWriteAccess | variables.rs:438:9:438:9 | i | variables.rs:436:13:436:13 | i | | variables.rs:450:9:450:9 | x | variables.rs:446:13:446:13 | x | | variables.rs:454:9:454:9 | x | variables.rs:446:13:446:13 | x | -| variables.rs:492:5:492:5 | a | variables.rs:488:13:488:13 | a | +| variables.rs:496:5:496:5 | a | variables.rs:492:13:492:13 | a | variableReadAccess | variables.rs:4:20:4:20 | s | variables.rs:3:14:3:14 | s | | variables.rs:8:20:8:20 | i | variables.rs:7:14:7:14 | i | @@ -396,13 +402,16 @@ variableReadAccess | variables.rs:469:8:469:9 | b2 | variables.rs:461:24:461:25 | b2 | | variables.rs:470:19:470:19 | x | variables.rs:462:9:462:9 | x | | variables.rs:472:19:472:19 | x | variables.rs:462:9:462:9 | x | -| variables.rs:489:15:489:15 | a | variables.rs:488:13:488:13 | a | -| variables.rs:490:5:490:5 | a | variables.rs:488:13:488:13 | a | -| variables.rs:491:15:491:15 | a | variables.rs:488:13:488:13 | a | -| variables.rs:493:15:493:15 | a | variables.rs:488:13:488:13 | a | -| variables.rs:499:15:499:15 | x | variables.rs:497:9:497:9 | x | -| variables.rs:517:3:517:3 | a | variables.rs:516:11:516:11 | a | -| variables.rs:519:13:519:13 | a | variables.rs:516:11:516:11 | a | +| variables.rs:483:16:483:19 | self | variables.rs:482:20:482:23 | self | +| variables.rs:487:9:487:12 | self | variables.rs:486:11:486:14 | self | +| variables.rs:493:15:493:15 | a | variables.rs:492:13:492:13 | a | +| variables.rs:494:5:494:5 | a | variables.rs:492:13:492:13 | a | +| variables.rs:495:15:495:15 | a | variables.rs:492:13:492:13 | a | +| variables.rs:497:15:497:15 | a | variables.rs:492:13:492:13 | a | +| variables.rs:503:15:503:15 | x | variables.rs:501:9:501:9 | x | +| variables.rs:515:6:515:9 | self | variables.rs:514:15:514:18 | self | +| variables.rs:521:3:521:3 | a | variables.rs:520:11:520:11 | a | +| variables.rs:523:13:523:13 | a | variables.rs:520:11:520:11 | a | variableInitializer | variables.rs:16:9:16:10 | x1 | variables.rs:16:14:16:16 | "a" | | variables.rs:21:13:21:14 | x2 | variables.rs:21:18:21:18 | 4 | @@ -411,49 +420,49 @@ variableInitializer | variables.rs:37:9:37:10 | x3 | variables.rs:38:9:38:14 | ... + ... | | variables.rs:43:9:43:10 | x4 | variables.rs:43:14:43:16 | "a" | | variables.rs:46:13:46:14 | x4 | variables.rs:46:18:46:20 | "b" | -| variables.rs:75:9:75:10 | p1 | variables.rs:75:14:75:37 | RecordExpr | -| variables.rs:85:9:85:10 | s1 | variables.rs:85:14:85:41 | CallExpr | -| variables.rs:102:9:102:10 | s1 | variables.rs:102:14:102:41 | CallExpr | -| variables.rs:111:9:111:10 | x6 | variables.rs:111:14:111:20 | CallExpr | +| variables.rs:75:9:75:10 | p1 | variables.rs:75:14:75:37 | Point {...} | +| variables.rs:85:9:85:10 | s1 | variables.rs:85:14:85:41 | Some(...) | +| variables.rs:102:9:102:10 | s1 | variables.rs:102:14:102:41 | Some(...) | +| variables.rs:111:9:111:10 | x6 | variables.rs:111:14:111:20 | Some(...) | | variables.rs:112:9:112:10 | y1 | variables.rs:112:14:112:15 | 10 | | variables.rs:128:9:128:15 | numbers | variables.rs:128:19:128:35 | TupleExpr | -| variables.rs:155:9:155:10 | p2 | variables.rs:155:14:155:37 | RecordExpr | -| variables.rs:169:9:169:11 | msg | variables.rs:169:15:169:38 | RecordExpr | -| variables.rs:189:9:189:14 | either | variables.rs:189:18:189:33 | CallExpr | -| variables.rs:203:9:203:10 | tv | variables.rs:203:14:203:36 | CallExpr | -| variables.rs:219:9:219:14 | either | variables.rs:219:18:219:33 | CallExpr | -| variables.rs:229:9:229:14 | either | variables.rs:229:18:229:33 | CallExpr | -| variables.rs:253:9:253:10 | fv | variables.rs:253:14:253:35 | CallExpr | -| variables.rs:315:9:315:23 | example_closure | variables.rs:316:9:317:9 | ClosureExpr | -| variables.rs:318:9:318:10 | n1 | variables.rs:319:9:319:26 | CallExpr | -| variables.rs:323:9:323:26 | immutable_variable | variables.rs:324:9:325:9 | ClosureExpr | -| variables.rs:326:9:326:10 | n2 | variables.rs:327:9:327:29 | CallExpr | -| variables.rs:332:9:332:9 | v | variables.rs:332:13:332:41 | RefExpr | +| variables.rs:155:9:155:10 | p2 | variables.rs:155:14:155:37 | Point {...} | +| variables.rs:169:9:169:11 | msg | variables.rs:169:15:169:38 | ...::Hello {...} | +| variables.rs:189:9:189:14 | either | variables.rs:189:18:189:33 | ...::Left(...) | +| variables.rs:203:9:203:10 | tv | variables.rs:203:14:203:36 | ...::Second(...) | +| variables.rs:219:9:219:14 | either | variables.rs:219:18:219:33 | ...::Left(...) | +| variables.rs:229:9:229:14 | either | variables.rs:229:18:229:33 | ...::Left(...) | +| variables.rs:253:9:253:10 | fv | variables.rs:253:14:253:35 | ...::Second(...) | +| variables.rs:315:9:315:23 | example_closure | variables.rs:316:9:317:9 | \|...\| x | +| variables.rs:318:9:318:10 | n1 | variables.rs:319:9:319:26 | example_closure(...) | +| variables.rs:323:9:323:26 | immutable_variable | variables.rs:324:9:325:9 | \|...\| x | +| variables.rs:326:9:326:10 | n2 | variables.rs:327:9:327:29 | immutable_variable(...) | +| variables.rs:332:9:332:9 | v | variables.rs:332:13:332:41 | &... | | variables.rs:341:13:341:13 | a | variables.rs:341:17:341:17 | 0 | | variables.rs:349:13:349:13 | i | variables.rs:349:17:349:17 | 1 | -| variables.rs:350:9:350:13 | ref_i | variables.rs:351:9:351:14 | RefExpr | +| variables.rs:350:9:350:13 | ref_i | variables.rs:351:9:351:14 | &mut i | | variables.rs:372:13:372:13 | x | variables.rs:372:17:372:17 | 2 | -| variables.rs:373:9:373:9 | y | variables.rs:374:9:374:28 | CallExpr | +| variables.rs:373:9:373:9 | y | variables.rs:374:9:374:28 | mutate_param(...) | | variables.rs:379:13:379:13 | z | variables.rs:379:17:379:17 | 4 | -| variables.rs:380:9:380:9 | w | variables.rs:381:9:381:19 | RefExpr | +| variables.rs:380:9:380:9 | w | variables.rs:381:9:381:19 | &mut ... | | variables.rs:392:13:392:13 | x | variables.rs:392:17:392:17 | 1 | -| variables.rs:393:9:393:9 | y | variables.rs:394:9:394:14 | RefExpr | +| variables.rs:393:9:393:9 | y | variables.rs:394:9:394:14 | &mut x | | variables.rs:400:9:400:9 | x | variables.rs:400:13:400:15 | 100 | -| variables.rs:402:9:402:11 | cap | variables.rs:402:15:404:5 | ClosureExpr | +| variables.rs:402:9:402:11 | cap | variables.rs:402:15:404:5 | \|...\| ... | | variables.rs:410:13:410:13 | x | variables.rs:410:17:410:17 | 1 | -| variables.rs:412:9:412:16 | closure1 | variables.rs:412:20:414:5 | ClosureExpr | +| variables.rs:412:9:412:16 | closure1 | variables.rs:412:20:414:5 | \|...\| ... | | variables.rs:418:13:418:13 | y | variables.rs:418:17:418:17 | 2 | -| variables.rs:420:13:420:20 | closure2 | variables.rs:420:24:422:5 | ClosureExpr | +| variables.rs:420:13:420:20 | closure2 | variables.rs:420:24:422:5 | \|...\| ... | | variables.rs:426:13:426:13 | z | variables.rs:426:17:426:17 | 2 | -| variables.rs:428:13:428:20 | closure3 | variables.rs:428:24:430:5 | ClosureExpr | +| variables.rs:428:13:428:20 | closure3 | variables.rs:428:24:430:5 | \|...\| ... | | variables.rs:436:13:436:13 | i | variables.rs:436:22:436:22 | 0 | -| variables.rs:437:9:437:13 | block | variables.rs:437:17:439:5 | BlockExpr | +| variables.rs:437:9:437:13 | block | variables.rs:437:17:439:5 | { ... } | | variables.rs:446:13:446:13 | x | variables.rs:446:17:446:17 | 1 | | variables.rs:462:9:462:9 | x | variables.rs:462:13:462:13 | 1 | -| variables.rs:488:13:488:13 | a | variables.rs:488:17:488:35 | RecordExpr | -| variables.rs:497:9:497:9 | x | variables.rs:497:13:497:14 | 16 | -| variables.rs:501:9:501:9 | z | variables.rs:501:13:501:14 | 17 | -| variables.rs:516:11:516:11 | a | variables.rs:516:15:516:33 | RecordExpr | +| variables.rs:492:13:492:13 | a | variables.rs:492:17:492:35 | MyStruct {...} | +| variables.rs:501:9:501:9 | x | variables.rs:501:13:501:14 | 16 | +| variables.rs:505:9:505:9 | z | variables.rs:505:13:505:14 | 17 | +| variables.rs:520:11:520:11 | a | variables.rs:520:15:520:33 | MyStruct {...} | capturedVariable | variables.rs:400:9:400:9 | x | | variables.rs:410:13:410:13 | x | diff --git a/rust/ql/test/library-tests/variables/variables.rs b/rust/ql/test/library-tests/variables/variables.rs index 8dd00c7ebb27..4bab6d12aea9 100644 --- a/rust/ql/test/library-tests/variables/variables.rs +++ b/rust/ql/test/library-tests/variables/variables.rs @@ -117,7 +117,7 @@ fn match_pattern1() { => { print_i64(y1)// $ read_access=y1_2 - } + } None => print_str("NONE"), } @@ -480,7 +480,11 @@ struct MyStruct { impl MyStruct { fn my_get(&mut self) -> i64 { - return self.val; + return self.val; // $ read_access=self + } + + fn id(self) -> Self { + self // $ read_access=self } } @@ -508,7 +512,7 @@ trait Bar { impl MyStruct { fn bar(&mut self) { - *self = MyStruct { val: 3 }; + *self = MyStruct { val: 3 }; // $ read_access=self } } diff --git a/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected index bdfa4a9792dd..f1c469a407da 100644 --- a/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected +++ b/rust/ql/test/query-tests/diagnostics/CONSISTENCY/ExtractionConsistency.expected @@ -4,5 +4,5 @@ extractionWarning | does_not_compile.rs:2:13:2:12 | expected SEMICOLON | | does_not_compile.rs:2:21:2:20 | expected SEMICOLON | | does_not_compile.rs:2:26:2:25 | expected SEMICOLON | -| does_not_compile.rs:2:32:2:31 | expected field name or number | | error.rs:2:5:2:17 | An error! | +| my_macro.rs:17:9:17:27 | macro expansion failed: could not resolve macro 'myUndefinedMacro' | diff --git a/rust/ql/test/query-tests/diagnostics/CfgConsistencyCounts.expected b/rust/ql/test/query-tests/diagnostics/CfgConsistencyCounts.expected index 7df2863da9e8..7056936908c0 100644 --- a/rust/ql/test/query-tests/diagnostics/CfgConsistencyCounts.expected +++ b/rust/ql/test/query-tests/diagnostics/CfgConsistencyCounts.expected @@ -1,5 +1,6 @@ | CFG scope lacks initial AST node | 0 | | Dead end | 0 | +| Missing CFG child | 0 | | Multiple successors of the same type | 0 | | Multiple toStrings | 0 | | Non-PostOrderTree Expr node | 0 | diff --git a/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected index 1ebd7e232214..7f14093f20e5 100644 --- a/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected +++ b/rust/ql/test/query-tests/diagnostics/ExtractionWarnings.expected @@ -3,5 +3,5 @@ | does_not_compile.rs:2:13:2:12 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | | does_not_compile.rs:2:21:2:20 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | | does_not_compile.rs:2:26:2:25 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 | -| does_not_compile.rs:2:32:2:31 | expected field name or number | Extraction warning in does_not_compile.rs with message expected field name or number | 1 | | error.rs:2:5:2:17 | An error! | Extraction warning in error.rs with message An error! | 1 | +| my_macro.rs:17:9:17:27 | macro expansion failed: could not resolve macro 'myUndefinedMacro' | Extraction warning in my_macro.rs with message macro expansion failed: could not resolve macro 'myUndefinedMacro' | 1 | diff --git a/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected b/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected index 6facd293859d..5fa7b20e01bb 100644 --- a/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected +++ b/rust/ql/test/query-tests/diagnostics/LinesOfCode.expected @@ -1 +1 @@ -| 59 | +| 60 | diff --git a/rust/ql/test/query-tests/diagnostics/LinesOfUserCode.expected b/rust/ql/test/query-tests/diagnostics/LinesOfUserCode.expected index 6facd293859d..5fa7b20e01bb 100644 --- a/rust/ql/test/query-tests/diagnostics/LinesOfUserCode.expected +++ b/rust/ql/test/query-tests/diagnostics/LinesOfUserCode.expected @@ -1 +1 @@ -| 59 | +| 60 | diff --git a/rust/ql/test/query-tests/diagnostics/LinesOfUserCodeInFiles.expected b/rust/ql/test/query-tests/diagnostics/LinesOfUserCodeInFiles.expected index b34654710961..0a58a05feed2 100644 --- a/rust/ql/test/query-tests/diagnostics/LinesOfUserCodeInFiles.expected +++ b/rust/ql/test/query-tests/diagnostics/LinesOfUserCodeInFiles.expected @@ -1,7 +1,7 @@ | my_struct.rs:0:0:0:0 | my_struct.rs | 20 | | comments.rs:0:0:0:0 | comments.rs | 13 | | main.rs:0:0:0:0 | main.rs | 8 | -| my_macro.rs:0:0:0:0 | my_macro.rs | 7 | +| my_macro.rs:0:0:0:0 | my_macro.rs | 8 | | lib.rs:0:0:0:0 | lib.rs | 5 | | does_not_compile.rs:0:0:0:0 | does_not_compile.rs | 3 | | error.rs:0:0:0:0 | error.rs | 3 | diff --git a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected index aeba0ac1ee6c..74e1e461c6fe 100644 --- a/rust/ql/test/query-tests/diagnostics/SummaryStats.expected +++ b/rust/ql/test/query-tests/diagnostics/SummaryStats.expected @@ -1,12 +1,17 @@ -| Elements extracted | 376 | +| Elements extracted | 382 | | Elements unextracted | 0 | | Extraction errors | 0 | | Extraction warnings | 7 | | Files extracted - total | 8 | -| Files extracted - with errors | 2 | -| Files extracted - without errors | 6 | +| Files extracted - with errors | 3 | +| Files extracted - without errors | 5 | | Inconsistencies - AST | 0 | | Inconsistencies - CFG | 0 | | Inconsistencies - data flow | 0 | -| Lines of code extracted | 59 | -| Lines of user code extracted | 59 | +| Lines of code extracted | 60 | +| Lines of user code extracted | 60 | +| Macro calls - resolved | 8 | +| Macro calls - total | 9 | +| Macro calls - unresolved | 1 | +| Taint sources - active | 0 | +| Taint sources - total | 0 | diff --git a/rust/ql/test/query-tests/diagnostics/UnresolvedMacroCalls.expected b/rust/ql/test/query-tests/diagnostics/UnresolvedMacroCalls.expected new file mode 100644 index 000000000000..72f78794ab29 --- /dev/null +++ b/rust/ql/test/query-tests/diagnostics/UnresolvedMacroCalls.expected @@ -0,0 +1 @@ +| my_macro.rs:17:9:17:27 | myUndefinedMacro!... | Macro call was not resolved to a target. | diff --git a/rust/ql/test/query-tests/diagnostics/UnresolvedMacroCalls.qlref b/rust/ql/test/query-tests/diagnostics/UnresolvedMacroCalls.qlref new file mode 100644 index 000000000000..77f337e27032 --- /dev/null +++ b/rust/ql/test/query-tests/diagnostics/UnresolvedMacroCalls.qlref @@ -0,0 +1 @@ +queries/diagnostics/UnresolvedMacroCalls.ql diff --git a/rust/ql/test/query-tests/diagnostics/does_not_compile.rs b/rust/ql/test/query-tests/diagnostics/does_not_compile.rs index 9aedaffcd93a..15f85e1ab4bf 100644 --- a/rust/ql/test/query-tests/diagnostics/does_not_compile.rs +++ b/rust/ql/test/query-tests/diagnostics/does_not_compile.rs @@ -1,3 +1,3 @@ pub fn my_func() { - This is not correct Rust code. + This is not correct Rust code } diff --git a/rust/ql/test/query-tests/diagnostics/my_macro.rs b/rust/ql/test/query-tests/diagnostics/my_macro.rs index d8a0cc2812bd..3b24857aa6c8 100644 --- a/rust/ql/test/query-tests/diagnostics/my_macro.rs +++ b/rust/ql/test/query-tests/diagnostics/my_macro.rs @@ -1,6 +1,6 @@ /** - * total lines in this file: 18 - * of which code: 10 + * total lines in this file: 19 + * of which code: 11 * of which only comments: 6 * of which blank: 2 */ @@ -14,5 +14,6 @@ macro_rules! myMacro { pub fn my_func() { if true { myMacro!(); + myUndefinedMacro!(); } } diff --git a/rust/ql/test/query-tests/security/CWE-089/.gitignore b/rust/ql/test/query-tests/security/CWE-089/.gitignore new file mode 100644 index 000000000000..bdcfa82b5d5c --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/.gitignore @@ -0,0 +1,2 @@ +# sqlite database +*.db* diff --git a/rust/ql/test/query-tests/security/CWE-089/.sqlx/query-c996a36820ff0b98021fa553b09b6da5ed65c28f666a68c4d73a1918f0eaa6f6.json b/rust/ql/test/query-tests/security/CWE-089/.sqlx/query-c996a36820ff0b98021fa553b09b6da5ed65c28f666a68c4d73a1918f0eaa6f6.json new file mode 100644 index 000000000000..a4493e90c37d --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/.sqlx/query-c996a36820ff0b98021fa553b09b6da5ed65c28f666a68c4d73a1918f0eaa6f6.json @@ -0,0 +1,32 @@ +{ + "db_name": "SQLite", + "query": "SELECT * FROM people WHERE firstname=$1", + "describe": { + "columns": [ + { + "name": "id", + "ordinal": 0, + "type_info": "Integer" + }, + { + "name": "firstname", + "ordinal": 1, + "type_info": "Text" + }, + { + "name": "lastname", + "ordinal": 2, + "type_info": "Text" + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "c996a36820ff0b98021fa553b09b6da5ed65c28f666a68c4d73a1918f0eaa6f6" +} diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected new file mode 100644 index 000000000000..58f42bec0c84 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.expected @@ -0,0 +1,4 @@ +#select +edges +nodes +subpaths diff --git a/rust/ql/test/query-tests/security/CWE-089/SqlInjection.qlref b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.qlref new file mode 100644 index 000000000000..504d27ff30cc --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/SqlInjection.qlref @@ -0,0 +1,2 @@ +query: queries/security/CWE-089/SqlInjection.ql +postprocess: utils/InlineExpectationsTestQuery.ql diff --git a/rust/ql/test/query-tests/security/CWE-089/cargo.toml.manual b/rust/ql/test/query-tests/security/CWE-089/cargo.toml.manual new file mode 100644 index 000000000000..0f9f0b75510e --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/cargo.toml.manual @@ -0,0 +1,15 @@ +[workspace] + +[package] +name = "CWE-089-Test" +version = "0.1.0" +edition = "2021" + +[dependencies] +reqwest = { version = "0.12.9", features = ["blocking"] } +sqlx = { version = "0.8", features = ["mysql", "sqlite", "postgres", "runtime-async-std", "tls-native-tls"] } +futures = { version = "0.3" } + +[[bin]] +name = "sqlx" +path = "./sqlx.rs" diff --git a/rust/ql/test/query-tests/security/CWE-089/migrations/20241031153051_create.sql b/rust/ql/test/query-tests/security/CWE-089/migrations/20241031153051_create.sql new file mode 100644 index 000000000000..c7d989a7258c --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/migrations/20241031153051_create.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS people +( + id INTEGER PRIMARY KEY NOT NULL, + firstname TEXT NOT NULL, + lastname TEXT NOT NULL +); + +INSERT INTO people +VALUES (1, "Alice", "Adams"); + +INSERT INTO people +VALUES (2, "Bob", "Becket"); diff --git a/rust/ql/test/query-tests/security/CWE-089/options.yml b/rust/ql/test/query-tests/security/CWE-089/options.yml new file mode 100644 index 000000000000..24744b7dfb45 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/options.yml @@ -0,0 +1,5 @@ +qltest_cargo_check: true +qltest_dependencies: + - reqwest = { version = "0.12.9", features = ["blocking"] } + - sqlx = { version = "0.8", features = ["mysql", "sqlite", "postgres", "runtime-async-std", "tls-native-tls"] } + - futures = { version = "0.3" } diff --git a/rust/ql/test/query-tests/security/CWE-089/sqlx.rs b/rust/ql/test/query-tests/security/CWE-089/sqlx.rs new file mode 100644 index 000000000000..b5cc25000f99 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-089/sqlx.rs @@ -0,0 +1,218 @@ +use sqlx::Connection; +use sqlx::Executor; + +/** + * This test is designed to be "run" in two ways: + * - you can extract and analyze the code here using the CodeQL test runner in the usual way, + * verifying the that various vulnerabilities are detected. + * - you can compile and run the code using `cargo`, verifying that it really is a complete + * program that compiles, runs and executes SQL commands (the sqlite ones, at least). + * + * To do the latter: + * + * Install `sqlx`: + * ``` + * cargo install sqlx-cli + * ``` + * + * Create the database: + * ``` + * export DATABASE_URL="sqlite:sqlite_database.db" + * sqlx db create + * sqlx migrate run + * ``` + * + * Build and run with the provided `cargo.toml.manual`: + * ``` + * cp cargo.toml.manual cargo.toml + * cargo run + * ``` + * + * You can also rebuild the sqlx 'query cache' in the `.sqlx` subdirectory + * with: + * ``` + * cargo sqlx prepare + * ``` + * This allows the code (in particular the `prepare!` macro) to be built + * in the test without setting `DATABASE_URL` first. + */ + +async fn test_sqlx_mysql(url: &str, enable_remote: bool) -> Result<(), sqlx::Error> { + // connect through a MySql connection pool + let pool = sqlx::mysql::MySqlPool::connect(url).await?; + let mut conn = pool.acquire().await?; + + // construct queries (with extra variants) + let const_string = String::from("Alice"); + let arg_string = std::env::args().nth(1).unwrap_or(String::from("Alice")); // $ MISSING Source=args1 + let remote_string = reqwest::blocking::get("http://example.com/").unwrap().text().unwrap_or(String::from("Alice")); // $ MISSING Source=remote1 + let remote_number = remote_string.parse::().unwrap_or(0); + let safe_query_1 = String::from("SELECT * FROM people WHERE firstname='Alice'"); + let safe_query_2 = String::from("SELECT * FROM people WHERE firstname='") + &const_string + "'"; + let safe_query_3 = format!("SELECT * FROM people WHERE firstname='{remote_number}'"); + let unsafe_query_1 = &arg_string; + let unsafe_query_2 = &remote_string; + let unsafe_query_3 = String::from("SELECT * FROM people WHERE firstname='") + &remote_string + "'"; + let unsafe_query_4 = format!("SELECT * FROM people WHERE firstname='{remote_string}'"); + let prepared_query_1 = String::from("SELECT * FROM people WHERE firstname=?"); // (prepared arguments are safe) + + // direct execution + let _ = conn.execute(safe_query_1.as_str()).await?; + let _ = conn.execute(safe_query_2.as_str()).await?; + let _ = conn.execute(safe_query_3.as_str()).await?; + let _ = conn.execute(unsafe_query_1.as_str()).await?; // $ MISSING Alert[sql-injection]=args1 + if enable_remote { + let _ = conn.execute(unsafe_query_2.as_str()).await?; // $ MISSING Alert[sql-injection]=remote1 + let _ = conn.execute(unsafe_query_3.as_str()).await?; // $ MISSING Alert[sql-injection]=remote1 + let _ = conn.execute(unsafe_query_4.as_str()).await?; // $ MISSING Alert[sql-injection]=remote1 + } + + // prepared queries + let _ = sqlx::query(safe_query_1.as_str()).execute(&pool).await?; + let _ = sqlx::query(safe_query_2.as_str()).execute(&pool).await?; + let _ = sqlx::query(safe_query_3.as_str()).execute(&pool).await?; + let _ = sqlx::query(unsafe_query_1.as_str()).execute(&pool).await?; // $ MISSING Alert[sql-injection]=args1 + if enable_remote { + let _ = sqlx::query(unsafe_query_2.as_str()).execute(&pool).await?; // $ MISSING Alert[sql-injection]=remote1 + let _ = sqlx::query(unsafe_query_3.as_str()).execute(&pool).await?; // $ MISSING Alert[sql-injection]=remote1 + let _ = sqlx::query(unsafe_query_4.as_str()).execute(&pool).await?; // $ MISSING Alert[sql-injection]=remote1 + } + let _ = sqlx::query(prepared_query_1.as_str()).bind(const_string).execute(&pool).await?; + let _ = sqlx::query(prepared_query_1.as_str()).bind(arg_string).execute(&pool).await?; + if enable_remote { + let _ = sqlx::query(prepared_query_1.as_str()).bind(remote_string).execute(&pool).await?; + let _ = sqlx::query(prepared_query_1.as_str()).bind(remote_number).execute(&pool).await?; + } + + Ok(()) +} + +async fn test_sqlx_sqlite(url: &str, enable_remote: bool) -> Result<(), sqlx::Error> { + // connect through Sqlite, no connection pool + let mut conn = sqlx::sqlite::SqliteConnection::connect(url).await?; + + // construct queries + let const_string = String::from("Alice"); + let remote_string = reqwest::blocking::get("http://example.com/").unwrap().text().unwrap_or(String::from("Alice")); // $ MISSING Source=remote2 + let safe_query_1 = String::from("SELECT * FROM people WHERE firstname='") + &const_string + "'"; + let unsafe_query_1 = String::from("SELECT * FROM people WHERE firstname='") + &remote_string + "'"; + let prepared_query_1 = String::from("SELECT * FROM people WHERE firstname=?"); // (prepared arguments are safe) + + // direct execution (with extra variants) + let _ = conn.execute(safe_query_1.as_str()).await?; + if enable_remote { + let _ = conn.execute(unsafe_query_1.as_str()).await?; // $ MISSING Alert[sql-injection]=remote2 + } + // ... + let _ = sqlx::raw_sql(safe_query_1.as_str()).execute(&mut conn).await?; + if enable_remote { + let _ = sqlx::raw_sql(unsafe_query_1.as_str()).execute(&mut conn).await?; // $ MISSING Alert[sql-injection]=remote2 + } + + // prepared queries (with extra variants) + let _ = sqlx::query(safe_query_1.as_str()).execute(&mut conn).await?; + let _ = sqlx::query(prepared_query_1.as_str()).bind(&const_string).execute(&mut conn).await?; + if enable_remote { + let _ = sqlx::query(unsafe_query_1.as_str()).execute(&mut conn).await?; // $ MISSING Alert[sql-injection]=remote2 + let _ = sqlx::query(prepared_query_1.as_str()).bind(&remote_string).execute(&mut conn).await?; + } + // ... + let _ = sqlx::query(safe_query_1.as_str()).fetch(&mut conn); + let _ = sqlx::query(prepared_query_1.as_str()).bind(&const_string).fetch(&mut conn); + if enable_remote { + let _ = sqlx::query(unsafe_query_1.as_str()).fetch(&mut conn); // $ MISSING Alert[sql-injection]=remote2 + let _ = sqlx::query(prepared_query_1.as_str()).bind(&remote_string).fetch(&mut conn); + } + // ... + let row1: (i64, String, String) = sqlx::query_as(safe_query_1.as_str()).fetch_one(&mut conn).await?; + println!(" row1 = {:?}", row1); + let row2: (i64, String, String) = sqlx::query_as(prepared_query_1.as_str()).bind(&const_string).fetch_one(&mut conn).await?; + println!(" row2 = {:?}", row2); + if enable_remote { + let _: (i64, String, String) = sqlx::query_as(unsafe_query_1.as_str()).fetch_one(&mut conn).await?; // $ MISSING Alert[sql-injection]=remote2 + let _: (i64, String, String) = sqlx::query_as(prepared_query_1.as_str()).bind(&remote_string).fetch_one(&mut conn).await?; + } + // ... + let row3: (i64, String, String) = sqlx::query_as(safe_query_1.as_str()).fetch_optional(&mut conn).await?.expect("no data"); + println!(" row3 = {:?}", row3); + let row4: (i64, String, String) = sqlx::query_as(prepared_query_1.as_str()).bind(&const_string).fetch_optional(&mut conn).await?.expect("no data"); + println!(" row4 = {:?}", row4); + if enable_remote { + let _: (i64, String, String) = sqlx::query_as(unsafe_query_1.as_str()).fetch_optional(&mut conn).await?.expect("no data"); // $ MISSING Alert[sql-injection]=remote2 + let _: (i64, String, String) = sqlx::query_as(prepared_query_1.as_str()).bind(&remote_string).fetch_optional(&mut conn).await?.expect("no data"); + } + // ... + let _ = sqlx::query(safe_query_1.as_str()).fetch_all(&mut conn).await?; + let _ = sqlx::query(prepared_query_1.as_str()).bind(&const_string).fetch_all(&mut conn).await?; + let _ = sqlx::query("SELECT * FROM people WHERE firstname=?").bind(&const_string).fetch_all(&mut conn).await?; + if enable_remote { + let _ = sqlx::query(unsafe_query_1.as_str()).fetch_all(&mut conn).await?; // $ MISSING Alert[sql-injection]=remote2 + let _ = sqlx::query(prepared_query_1.as_str()).bind(&remote_string).fetch_all(&mut conn).await?; + let _ = sqlx::query("SELECT * FROM people WHERE firstname=?").bind(&remote_string).fetch_all(&mut conn).await?; + } + // ... + let _ = sqlx::query!("SELECT * FROM people WHERE firstname=$1", const_string).fetch_all(&mut conn).await?; // (only takes string literals, so can't be vulnerable) + if enable_remote { + let _ = sqlx::query!("SELECT * FROM people WHERE firstname=$1", remote_string).fetch_all(&mut conn).await?; + } + + Ok(()) +} + +async fn test_sqlx_postgres(url: &str, enable_remote: bool) -> Result<(), sqlx::Error> { + // connect through a PostGres connection pool + let pool = sqlx::postgres::PgPool::connect(url).await?; + let mut conn = pool.acquire().await?; + + // construct queries + let const_string = String::from("Alice"); + let remote_string = reqwest::blocking::get("http://example.com/").unwrap().text().unwrap_or(String::from("Alice")); // $ MISSING Source=remote3 + let safe_query_1 = String::from("SELECT * FROM people WHERE firstname='") + &const_string + "'"; + let unsafe_query_1 = String::from("SELECT * FROM people WHERE firstname='") + &remote_string + "'"; + let prepared_query_1 = String::from("SELECT * FROM people WHERE firstname=$1"); // (prepared arguments are safe) + + // direct execution + let _ = conn.execute(safe_query_1.as_str()).await?; + if enable_remote { + let _ = conn.execute(unsafe_query_1.as_str()).await?; // $ MISSING Alert[sql-injection]=remote3 + } + + // prepared queries + let _ = sqlx::query(safe_query_1.as_str()).execute(&pool).await?; + let _ = sqlx::query(prepared_query_1.as_str()).bind(&const_string).execute(&pool).await?; + if enable_remote { + let _ = sqlx::query(unsafe_query_1.as_str()).execute(&pool).await?; // $ MISSING Alert[sql-injection]=remote3 + let _ = sqlx::query(prepared_query_1.as_str()).bind(&remote_string).execute(&pool).await?; + } + + Ok(()) +} + +fn main() { + println!("--- CWE-089 sqlx.rs test ---"); + + // we don't *actually* use data from a remote source unless we're explicitly told to at the + // command line; that's because this test is designed to be runnable, and we don't really + // want to expose the test database to potential SQL injection from http://example.com/ - + // no matter how unlikely, local and compartmentalized that may seem. + let enable_remote = std::env::args().nth(1) == Some(String::from("ENABLE_REMOTE")); + println!("enable_remote = {enable_remote}"); + + println!("test_sqlx_mysql..."); + match futures::executor::block_on(test_sqlx_mysql("", enable_remote)) { + Ok(_) => println!(" successful!"), + Err(e) => println!(" error: {}", e), + } + + println!("test_sqlx_sqlite..."); + match futures::executor::block_on(test_sqlx_sqlite("sqlite:sqlite_database.db", enable_remote)) { + Ok(_) => println!(" successful!"), + Err(e) => println!(" error: {}", e), + } + + println!("test_sqlx_postgres..."); + match futures::executor::block_on(test_sqlx_postgres("", enable_remote)) { + Ok(_) => println!(" successful!"), + Err(e) => println!(" error: {}", e), + } +} diff --git a/rust/ql/test/query-tests/unusedentities/CONSISTENCY/DataFlowConsistency.expected b/rust/ql/test/query-tests/unusedentities/CONSISTENCY/DataFlowConsistency.expected deleted file mode 100644 index 0a61a151c204..000000000000 --- a/rust/ql/test/query-tests/unusedentities/CONSISTENCY/DataFlowConsistency.expected +++ /dev/null @@ -1,5 +0,0 @@ -uniqueEnclosingCallable -| main.rs:194:25:194:25 | x | Node should have one enclosing callable but has 0. | -| main.rs:198:28:198:28 | x | Node should have one enclosing callable but has 0. | -| main.rs:202:28:202:28 | x | Node should have one enclosing callable but has 0. | -| main.rs:206:28:206:28 | x | Node should have one enclosing callable but has 0. | diff --git a/rust/ql/test/utils/InlineFlowTest.qll b/rust/ql/test/utils/InlineFlowTest.qll index b4960a055ee1..dcf8ad8c4459 100644 --- a/rust/ql/test/utils/InlineFlowTest.qll +++ b/rust/ql/test/utils/InlineFlowTest.qll @@ -5,26 +5,27 @@ import rust private import codeql.dataflow.test.InlineFlowTest +private import codeql.rust.controlflow.CfgNodes private import codeql.rust.dataflow.DataFlow private import codeql.rust.dataflow.internal.DataFlowImpl private import codeql.rust.dataflow.internal.TaintTrackingImpl private import internal.InlineExpectationsTestImpl as InlineExpectationsTestImpl // Holds if the target expression of `call` is a path and the string representation of the path is `name`. -private predicate callTargetName(CallExpr call, string name) { - call.getExpr().(PathExpr).toString() = name +private predicate callTargetName(CallExprCfgNode call, string name) { + call.getFunction().(PathExprCfgNode).toString() = name } private module FlowTestImpl implements InputSig { predicate defaultSource(DataFlow::Node source) { callTargetName(source.asExpr(), "source") } predicate defaultSink(DataFlow::Node sink) { - any(CallExpr call | callTargetName(call, "sink")).getArgList().getAnArg() = sink.asExpr() + any(CallExprCfgNode call | callTargetName(call, "sink")).getArgument(_) = sink.asExpr() } private string getSourceArgString(DataFlow::Node src) { defaultSource(src) and - result = src.asExpr().(CallExpr).getArgList().getArg(0).toString() + result = src.asExpr().(CallExprCfgNode).getArgument(0).toString() } bindingset[src, sink] diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index d8e9835b16a6..b0d7296dbad5 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -1,6 +1,19 @@ from misc.codegen.lib.schemadefs import * from .ast import * +class LabelableExpr(Expr): + """ + The base class for expressions that can be labeled (`LoopExpr`, `ForExpr`, `WhileExpr` or `BlockExpr`). + """ + label: optional[Label] | child + +class LoopingExpr(LabelableExpr): + """ + The base class for expressions that loop (`LoopExpr`, `ForExpr` or `WhileExpr`). + """ + loop_body: optional["BlockExpr"] | child + + @annotate(Module) @rust.doc_test_signature(None) @@ -18,14 +31,14 @@ class _: """ -@annotate(Expr) +@annotate(Expr, cfg = True) class _: """ The base class for expressions. """ -@annotate(Pat) +@annotate(Pat, cfg = True) class _: """ The base class for patterns. @@ -68,6 +81,7 @@ class _: """ A path. For example: ```rust + use some_crate::some_module::some_item; foo::bar; ``` """ @@ -106,7 +120,8 @@ class PathExprBase(Expr): """ -@annotate(PathExpr, replace_bases={Expr: PathExprBase}) +@annotate(PathExpr, replace_bases={Expr: PathExprBase}, cfg = True) +@qltest.test_with(Path) class _: """ A path expression. For example: @@ -119,7 +134,7 @@ class _: """ -@annotate(IfExpr) +@annotate(IfExpr, cfg = True) class _: """ An `if` expression. For example: @@ -138,7 +153,7 @@ class _: """ -@annotate(LetExpr) +@annotate(LetExpr, cfg = True) @rust.doc_test_signature("(maybe_some: Option) -> ()") class _: """ @@ -151,7 +166,7 @@ class _: """ -@annotate(BlockExpr) +@annotate(BlockExpr, replace_bases={Expr: LabelableExpr}, cfg = True) class _: """ A block expression. For example: @@ -167,9 +182,10 @@ class _: } ``` """ + label: drop -@annotate(LoopExpr) +@annotate(LoopExpr, replace_bases={Expr: LoopingExpr}, cfg = True) class _: """ A loop expression. For example: @@ -195,6 +211,8 @@ class _: }; ``` """ + label: drop + loop_body: drop class CallExprBase(Expr): @@ -205,7 +223,7 @@ class CallExprBase(Expr): attrs: list["Attr"] | child -@annotate(CallExpr, replace_bases={Expr: CallExprBase}) +@annotate(CallExpr, replace_bases={Expr: CallExprBase}, cfg = True) class _: """ A function call expression. For example: @@ -220,7 +238,7 @@ class _: attrs: drop -@annotate(MethodCallExpr, replace_bases={Expr: CallExprBase}, add_bases=(Resolvable,)) +@annotate(MethodCallExpr, replace_bases={Expr: CallExprBase}, add_bases=(Resolvable,), cfg = True) class _: """ A method call expression. For example: @@ -253,7 +271,7 @@ class _: """ -@annotate(MatchExpr) +@annotate(MatchExpr, cfg = True) @rust.doc_test_signature("(x: i32) -> i32") class _: """ @@ -271,9 +289,10 @@ class _: } ``` """ + scrutinee: _ | doc("scrutinee (the expression being matched) of this match expression") -@annotate(ContinueExpr) +@annotate(ContinueExpr, cfg = True) class _: """ A continue expression. For example: @@ -294,7 +313,7 @@ class _: """ -@annotate(BreakExpr) +@annotate(BreakExpr, cfg = True) class _: """ A break expression. For example: @@ -323,7 +342,7 @@ class _: """ -@annotate(ReturnExpr) +@annotate(ReturnExpr, cfg = True) @rust.doc_test_signature(None) class _: """ @@ -341,7 +360,7 @@ class _: """ -@annotate(BecomeExpr) +@annotate(BecomeExpr, cfg = True) @rust.doc_test_signature(None) class _: """ @@ -358,7 +377,7 @@ class _: """ -@annotate(YieldExpr) +@annotate(YieldExpr, cfg = True) class _: """ A `yield` expression. For example: @@ -371,7 +390,7 @@ class _: """ -@annotate(YeetExpr) +@annotate(YeetExpr, cfg = True) class _: """ A `yeet` expression. For example: @@ -393,7 +412,7 @@ class _: """ -@annotate(RecordExpr) +@annotate(RecordExpr, cfg = True) class _: """ A record expression. For example: @@ -406,7 +425,7 @@ class _: """ -@annotate(FieldExpr) +@annotate(FieldExpr, cfg = True) class _: """ A field access expression. For example: @@ -416,7 +435,7 @@ class _: """ -@annotate(AwaitExpr) +@annotate(AwaitExpr, cfg = True) class _: """ An `await` expression. For example: @@ -439,7 +458,7 @@ class _: """ -@annotate(RefExpr) +@annotate(RefExpr, cfg = True) class _: """ A reference expression. For example: @@ -452,7 +471,7 @@ class _: """ -@annotate(PrefixExpr) +@annotate(PrefixExpr, cfg = True) class _: """ A unary operation expression. For example: @@ -464,7 +483,7 @@ class _: """ -@annotate(BinaryExpr) +@annotate(BinaryExpr, cfg = True) class _: """ A binary operation expression. For example: @@ -478,7 +497,7 @@ class _: """ -@annotate(RangeExpr) +@annotate(RangeExpr, cfg = True) class _: """ A range expression. For example: @@ -493,7 +512,7 @@ class _: """ -@annotate(IndexExpr) +@annotate(IndexExpr, cfg = True) class _: """ An index expression. For example: @@ -520,7 +539,7 @@ class _: """ -@annotate(TupleExpr) +@annotate(TupleExpr, cfg = True) class _: """ A tuple expression. For example: @@ -531,7 +550,7 @@ class _: """ -@annotate(ArrayExpr) +@annotate(ArrayExpr, cfg = True) class _: """ An array expression. For example: @@ -542,7 +561,7 @@ class _: """ -@annotate(LiteralExpr) +@annotate(LiteralExpr, cfg = True) class _: """ A literal expression. For example: @@ -559,7 +578,7 @@ class _: """ -@annotate(UnderscoreExpr) +@annotate(UnderscoreExpr, cfg = True) class _: """ An underscore expression. For example: @@ -569,7 +588,7 @@ class _: """ -@annotate(OffsetOfExpr) +@annotate(OffsetOfExpr, cfg = True) class _: """ An `offset_of` expression. For example: @@ -579,7 +598,7 @@ class _: """ -@annotate(AsmExpr) +@annotate(AsmExpr, cfg = True) class _: """ An inline assembly expression. For example: @@ -591,7 +610,7 @@ class _: """ -@annotate(LetStmt) +@annotate(LetStmt, cfg = True) class _: """ A let statement. For example: @@ -620,7 +639,7 @@ class _: """ -@annotate(WildcardPat) +@annotate(WildcardPat, cfg = True) class _: """ A wildcard pattern. For example: @@ -630,7 +649,7 @@ class _: """ -@annotate(TuplePat) +@annotate(TuplePat, cfg = True) class _: """ A tuple pattern. For example: @@ -641,7 +660,7 @@ class _: """ -@annotate(OrPat) +@annotate(OrPat, cfg = True) class _: """ An or pattern. For example: @@ -663,7 +682,7 @@ class _: """ -@annotate(RecordPat) +@annotate(RecordPat, cfg = True) class _: """ A record pattern. For example: @@ -676,7 +695,7 @@ class _: """ -@annotate(RangePat) +@annotate(RangePat, cfg = True) class _: """ A range pattern. For example: @@ -690,7 +709,7 @@ class _: """ -@annotate(SlicePat) +@annotate(SlicePat, cfg = True) class _: """ A slice pattern. For example: @@ -704,7 +723,8 @@ class _: """ -@annotate(PathPat) +@annotate(PathPat, cfg = True) +@qltest.test_with(Path) class _: """ A path pattern. For example: @@ -717,7 +737,7 @@ class _: """ -@annotate(LiteralPat) +@annotate(LiteralPat, cfg = True) class _: """ A literal pattern. For example: @@ -730,7 +750,7 @@ class _: """ -@annotate(IdentPat) +@annotate(IdentPat, cfg = True) class _: """ A binding pattern. For example: @@ -749,7 +769,7 @@ class _: """ -@annotate(TupleStructPat) +@annotate(TupleStructPat, cfg = True) class _: """ A tuple struct pattern. For example: @@ -763,7 +783,7 @@ class _: """ -@annotate(RefPat) +@annotate(RefPat, cfg = True) class _: """ A reference pattern. For example: @@ -776,7 +796,7 @@ class _: """ -@annotate(BoxPat) +@annotate(BoxPat, cfg = True) class _: """ A box pattern. For example: @@ -789,7 +809,7 @@ class _: """ -@annotate(ConstBlockPat) +@annotate(ConstBlockPat, cfg = True) class _: """ A const block pattern. For example: @@ -990,7 +1010,7 @@ class _: """ -@annotate(ForExpr) +@annotate(ForExpr, replace_bases={Expr: LoopingExpr}, cfg = True) class _: """ A ForExpr. For example: @@ -998,6 +1018,8 @@ class _: todo!() ``` """ + label: drop + loop_body: drop @annotate(ForType) @@ -1011,6 +1033,7 @@ class _: @annotate(FormatArgsArg) +@qltest.test_with(FormatArgsExpr) class _: """ A FormatArgsArg. For example: @@ -1020,14 +1043,19 @@ class _: """ -@annotate(FormatArgsExpr) +@annotate(FormatArgsExpr, cfg = True) class _: """ A FormatArgsExpr. For example: ```rust - todo!() + format_args!("no args"); + format_args!("{} foo {:?}", 1, 2); + format_args!("{b} foo {a:?}", a=1, b=2); + let (x, y) = (1, 42); + format_args!("{x}, {y}"); ``` """ + formats: list["Format"] | child | synth @annotate(GenericArg) @@ -1150,7 +1178,7 @@ class _: """ -@annotate(MacroCall) +@annotate(MacroCall, cfg = True) class _: """ A MacroCall. For example: @@ -1171,7 +1199,7 @@ class _: """ -@annotate(MacroExpr) +@annotate(MacroExpr, cfg = True) class _: """ A MacroExpr. For example: @@ -1194,7 +1222,7 @@ class _: """ -@annotate(MacroPat) +@annotate(MacroPat, cfg = True) class _: """ A MacroPat. For example: @@ -1297,14 +1325,29 @@ class _: """ -@annotate(Param) +class ParamBase(AstNode): + """ + A normal parameter, `Param`, or a self parameter `SelfParam`. + """ + attrs: list["Attr"] | child + ty: optional["TypeRef"] | child + +@annotate(ParamBase, cfg = True) +class _: + pass + +@annotate(Param, replace_bases={AstNode: ParamBase}, cfg = True) class _: """ - A Param. For example: + A parameter in a function or method. For example `x` in: ```rust - todo!() + fn new(x: T) -> Foo { + // ... + } ``` """ + attrs: drop + ty: drop @annotate(ParamList) @@ -1348,21 +1391,21 @@ class _: @annotate(PathSegment) +@qltest.test_with(Path) class _: """ - A PathSegment. For example: - ```rust - todo!() - ``` + A path segment, which is one part of a whole path. """ @annotate(PathType) +@qltest.test_with(Path) class _: """ - A PathType. For example: + A type referring to a path. For example: ```rust - todo!() + type X = std::collections::HashMap; + type Y = X::Item; ``` """ @@ -1437,7 +1480,7 @@ class _: """ -@annotate(RestPat) +@annotate(RestPat, cfg = True) class _: """ A RestPat. For example: @@ -1467,14 +1510,18 @@ class _: """ -@annotate(SelfParam) +@annotate(SelfParam, replace_bases={AstNode: ParamBase}, cfg = True) class _: """ - A SelfParam. For example: + A `self` parameter. For example `self` in: ```rust - todo!() + fn push(&mut self, value: T) { + // ... + } ``` """ + attrs: drop + ty: drop @annotate(SliceType) @@ -1564,7 +1611,7 @@ class _: """ -@annotate(TryExpr) +@annotate(TryExpr, cfg = True) class _: """ A TryExpr. For example: @@ -1694,7 +1741,7 @@ class _: """ -@annotate(Variant) +@annotate(Variant, replace_bases={AstNode: Addressable}) class _: """ A Variant. For example: @@ -1744,7 +1791,7 @@ class _: """ -@annotate(WhileExpr) +@annotate(WhileExpr, replace_bases={Expr: LoopingExpr}, cfg = True) class _: """ A WhileExpr. For example: @@ -1752,6 +1799,8 @@ class _: todo!() ``` """ + label: drop + loop_body: drop @annotate(Function, add_bases=[Callable]) @@ -1766,14 +1815,15 @@ class _: attrs: drop -@qltest.skip @synth.on_arguments(parent="FormatArgsExpr", index=int, kind=int) +@qltest.test_with(FormatArgsExpr) class FormatTemplateVariableAccess(PathExprBase): pass -@qltest.skip @synth.on_arguments(parent=FormatArgsExpr, index=int, text=string, offset=int) +@qltest.test_with(FormatArgsExpr) + class Format(Locatable): """ A format element in a formatting template. For example the `{}` in: @@ -1783,10 +1833,11 @@ class Format(Locatable): """ parent: FormatArgsExpr index: int + argument: optional["FormatArgument"] | child -@qltest.skip @synth.on_arguments(parent=FormatArgsExpr, index=int, kind=int, name=string, positional=boolean, offset=int) +@qltest.test_with(FormatArgsExpr) class FormatArgument(Locatable): """ An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: @@ -1799,12 +1850,8 @@ class FormatArgument(Locatable): ``` """ parent: Format + variable: optional[FormatTemplateVariableAccess] | child -@annotate(Item) +@annotate(Item, add_bases=(Addressable,)) class _: - extended_canonical_path: optional[string] | desc(""" - Either a canonical path (see https://doc.rust-lang.org/reference/paths.html#canonical-paths), - or `{}::name` for addressable items defined in an anonymous block (and only - addressable there-in). - """) | rust.detach | ql.internal - crate_origin: optional[string] | desc("One of `rustc:`, `repo::` or `lang:`.") | rust.detach | ql.internal + pass diff --git a/rust/schema/ast.py b/rust/schema/ast.py index bdbb1990d308..1f5a35d7bc21 100644 --- a/rust/schema/ast.py +++ b/rust/schema/ast.py @@ -103,7 +103,7 @@ class BreakExpr(Expr): class CallExpr(Expr): arg_list: optional["ArgList"] | child attrs: list["Attr"] | child - expr: optional["Expr"] | child + function: optional["Expr"] | child class CastExpr(Expr): attrs: list["Attr"] | child @@ -285,7 +285,7 @@ class LetElse(AstNode): class LetExpr(Expr): attrs: list["Attr"] | child - expr: optional["Expr"] | child + scrutinee: optional["Expr"] | child pat: optional["Pat"] | child class LetStmt(Stmt): @@ -364,7 +364,7 @@ class MatchArmList(AstNode): class MatchExpr(Expr): attrs: list["Attr"] | child - expr: optional["Expr"] | child + scrutinee: optional["Expr"] | child match_arm_list: optional["MatchArmList"] | child class MatchGuard(AstNode): diff --git a/rust/schema/prelude.py b/rust/schema/prelude.py index 60de626e59cb..ffd65959b5ab 100644 --- a/rust/schema/prelude.py +++ b/rust/schema/prelude.py @@ -73,6 +73,20 @@ class Callable(AstNode): attrs: list["Attr"] | child +class Addressable(AstNode): + """ + Something that can be addressed by a path. + + TODO: This does not yet include all possible cases. + """ + extended_canonical_path: optional[string] | desc(""" + Either a canonical path (see https://doc.rust-lang.org/reference/paths.html#canonical-paths), + or `{}::name` for addressable items defined in an anonymous block (and only + addressable there-in). + """) | rust.detach | ql.internal + crate_origin: optional[string] | desc("One of `rustc:`, `repo::` or `lang:`.") | rust.detach | ql.internal + + class Resolvable(AstNode): """ Either a `Path`, or a `MethodCallExpr`. diff --git a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll index 81f9946126db..e477913a59bd 100644 --- a/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll +++ b/shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll @@ -678,6 +678,8 @@ module MakeImplCommon Lang> { class CcNoCall = CallContextNoCall; + class CcReturn = CallContextReturn; + Cc ccNone() { result instanceof CallContextAny } CcCall ccSomeCall() { result instanceof CallContextSomeCall } @@ -1338,6 +1340,7 @@ module MakeImplCommon Lang> { * or summarized as a single read step with before and after types recorded * in the `ReadStepTypesOption` parameter. * - Types are checked using the `compatibleTypes()` relation. + * - Call contexts are taken into account. */ private module Final { /** @@ -1348,8 +1351,12 @@ module MakeImplCommon Lang> { * If a read step was taken, then `read` captures the `Content`, the * container type, and the content type. */ - predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read, string model) { - parameterValueFlow0(p, node, read, model) and + predicate parameterValueFlow( + ParamNode p, Node node, ReadStepTypesOption read, string model, + CachedCallContextSensitivity::CcNoCall ctx + ) { + parameterValueFlow0(p, node, read, model, ctx) and + Cand::cand(p, node) and if node instanceof CastingNode then // normal flow through @@ -1369,16 +1376,18 @@ module MakeImplCommon Lang> { pragma[nomagic] private predicate parameterValueFlow0( - ParamNode p, Node node, ReadStepTypesOption read, string model + ParamNode p, Node node, ReadStepTypesOption read, string model, + CachedCallContextSensitivity::CcNoCall ctx ) { p = node and Cand::cand(p, _) and read = TReadStepTypesNone() and - model = "" + model = "" and + CachedCallContextSensitivity::viableImplNotCallContextReducedReverse(ctx) or // local flow exists(Node mid, string model1, string model2 | - parameterValueFlow(p, mid, read, model1) and + parameterValueFlow(p, mid, read, model1, ctx) and simpleLocalFlowStep(mid, node, model2) and validParameterAliasStep(mid, node) and model = mergeModels(model1, model2) @@ -1386,67 +1395,97 @@ module MakeImplCommon Lang> { or // read exists(Node mid | - parameterValueFlow(p, mid, TReadStepTypesNone(), model) and + parameterValueFlow(p, mid, TReadStepTypesNone(), model, ctx) and readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, read.getContentType()) and Cand::parameterValueFlowReturnCand(p, _, true) and compatibleTypesFilter(getNodeDataFlowType(p), read.getContainerType()) ) or - parameterValueFlow0_0(TReadStepTypesNone(), p, node, read, model) + parameterValueFlow0_0(TReadStepTypesNone(), p, node, read, model, ctx) + } + + bindingset[ctx1, ctx2] + pragma[inline_late] + private CachedCallContextSensitivity::CcNoCall mergeContexts( + CachedCallContextSensitivity::CcNoCall ctx1, CachedCallContextSensitivity::CcNoCall ctx2 + ) { + if CachedCallContextSensitivity::viableImplNotCallContextReducedReverse(ctx1) + then result = ctx2 + else + if CachedCallContextSensitivity::viableImplNotCallContextReducedReverse(ctx2) + then result = ctx1 + else + // check that `ctx1` is compatible with `ctx2` for at least _some_ outer call, + // and then (arbitrarily) continue with `ctx2` + exists(DataFlowCall someOuterCall, DataFlowCallable callable | + someOuterCall = + CachedCallContextSensitivity::viableImplCallContextReducedReverse(callable, ctx1) and + someOuterCall = + CachedCallContextSensitivity::viableImplCallContextReducedReverse(callable, ctx2) and + result = ctx2 + ) } pragma[nomagic] private predicate parameterValueFlow0_0( ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read, - string model + string model, CachedCallContextSensitivity::CcNoCall ctx ) { - // flow through: no prior read - exists(ArgNode arg, string model1, string model2 | - parameterValueFlowArg(p, arg, mustBeNone, model1) and - argumentValueFlowsThrough(arg, read, node, model2) and - model = mergeModels(model1, model2) - ) - or - // flow through: no read inside method - exists(ArgNode arg, string model1, string model2 | - parameterValueFlowArg(p, arg, read, model1) and - argumentValueFlowsThrough(arg, mustBeNone, node, model2) and - model = mergeModels(model1, model2) + exists( + ArgNode arg, string model1, string model2, CachedCallContextSensitivity::CcNoCall ctx1, + CachedCallContextSensitivity::CcNoCall ctx2 + | + model = mergeModels(model1, model2) and + ctx = mergeContexts(ctx1, ctx2) + | + // flow through: no prior read + parameterValueFlowArg(p, arg, mustBeNone, model1, ctx1) and + argumentValueFlowsThrough(arg, read, node, model2, ctx2) + or + // flow through: no read inside method + parameterValueFlowArg(p, arg, read, model1, ctx1) and + argumentValueFlowsThrough(arg, mustBeNone, node, model2, ctx2) ) } pragma[nomagic] private predicate parameterValueFlowArg( - ParamNode p, ArgNode arg, ReadStepTypesOption read, string model + ParamNode p, ArgNode arg, ReadStepTypesOption read, string model, + CachedCallContextSensitivity::CcNoCall ctx ) { - parameterValueFlow(p, arg, read, model) and + parameterValueFlow(p, arg, read, model, ctx) and Cand::argumentValueFlowsThroughCand(arg, _, _) } pragma[nomagic] private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read, string model + DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read, string model, + CachedCallContextSensitivity::CcNoCall outerCtx ) { - exists(ParamNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, read, model) + exists( + ParamNode param, DataFlowCallable callable, + CachedCallContextSensitivity::CcNoCall innerCtx + | + viableParamArg(call, param, arg) and + parameterValueFlowReturn(param, kind, read, model, innerCtx) and + callable = nodeGetEnclosingCallable(param) and + outerCtx = CachedCallContextSensitivity::getCallContextReturn(callable, call) + | + CachedCallContextSensitivity::viableImplNotCallContextReducedReverse(innerCtx) + or + call = + CachedCallContextSensitivity::viableImplCallContextReducedReverse(callable, innerCtx) ) } - /** - * Holds if `arg` flows to `out` through a call using only - * value-preserving steps and possibly a single read step, not taking - * call contexts into account. - * - * If a read step was taken, then `read` captures the `Content`, the - * container type, and the content type. - */ - cached - predicate argumentValueFlowsThrough( - ArgNode arg, ReadStepTypesOption read, Node out, string model + pragma[nomagic] + private predicate argumentValueFlowsThrough( + ArgNode arg, ReadStepTypesOption read, Node out, string model, + CachedCallContextSensitivity::CcNoCall ctx ) { exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, read, model) and + argumentValueFlowsThrough0(call, arg, kind, read, model, ctx) and out = getAnOutNode(call, kind) | // normal flow through @@ -1459,6 +1498,21 @@ module MakeImplCommon Lang> { ) } + /** + * Holds if `arg` flows to `out` through a call using only + * value-preserving steps and possibly a single read step, not taking + * call contexts into account. + * + * If a read step was taken, then `read` captures the `Content`, the + * container type, and the content type. + */ + cached + predicate argumentValueFlowsThrough( + ArgNode arg, ReadStepTypesOption read, Node out, string model + ) { + argumentValueFlowsThrough(arg, read, out, model, _) + } + /** * Holds if `arg` flows to `out` through a call using only * value-preserving steps and a single read step, not taking call @@ -1479,10 +1533,11 @@ module MakeImplCommon Lang> { * container type, and the content type. */ private predicate parameterValueFlowReturn( - ParamNode p, ReturnKind kind, ReadStepTypesOption read, string model + ParamNode p, ReturnKind kind, ReadStepTypesOption read, string model, + CachedCallContextSensitivity::CcNoCall ctx ) { exists(ReturnNode ret | - parameterValueFlow(p, ret, read, model) and + parameterValueFlow(p, ret, read, model, ctx) and kind = ret.getKind() ) } @@ -1498,7 +1553,7 @@ module MakeImplCommon Lang> { * node `n`, in the same callable, using only value-preserving steps. */ private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone(), _) + parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone(), _, _) } cached diff --git a/shared/util/codeql/util/DenseRank.qll b/shared/util/codeql/util/DenseRank.qll index d1ba4ae4b62c..0dccbbd48803 100644 --- a/shared/util/codeql/util/DenseRank.qll +++ b/shared/util/codeql/util/DenseRank.qll @@ -58,12 +58,12 @@ module DenseRank { rnk = rank[result](int rnk0 | rnk0 = getRank(_) | rnk0) } - /** Gets the dense rank of `r`. */ - int denseRank(Ranked r) { result = rankRank(r, getRank(r)) } + /** Gets the `Ranked` value for which the dense rank is `rnk`. */ + Ranked denseRank(int rnk) { rnk = rankRank(result, getRank(result)) } } -/** Provides the input to `DenseRank2`. */ -signature module DenseRankInputSig2 { +/** Provides the input to `DenseRank1`. */ +signature module DenseRankInputSig1 { /** A ranking context. */ bindingset[this] class C; @@ -77,7 +77,7 @@ signature module DenseRankInputSig2 { } /** Same as `DenseRank`, but allows for a context consisting of one element. */ -module DenseRank2 { +module DenseRank1 { private import Input private int rankRank(C c, Ranked r, int rnk) { @@ -85,17 +85,15 @@ module DenseRank2 { rnk = rank[result](int rnk0 | rnk0 = getRank(c, _) | rnk0) } - /** Gets the dense rank of `r` in the context provided by `c`. */ - int denseRank(C c, Ranked r) { - exists(int rnk | - result = rankRank(c, r, rnk) and - rnk = getRank(c, r) - ) - } + /** + * Gets the `Ranked` value for which the dense rank in the context provided by + * `c` is `rnk`. + */ + Ranked denseRank(C c, int rnk) { rnk = rankRank(c, result, getRank(c, result)) } } -/** Provides the input to `DenseRank3`. */ -signature module DenseRankInputSig3 { +/** Provides the input to `DenseRank2`. */ +signature module DenseRankInputSig2 { /** A ranking context. */ bindingset[this] class C1; @@ -113,7 +111,7 @@ signature module DenseRankInputSig3 { } /** Same as `DenseRank`, but allows for a context consisting of two elements. */ -module DenseRank3 { +module DenseRank2 { private import Input private int rankRank(C1 c1, C2 c2, Ranked r, int rnk) { @@ -121,11 +119,11 @@ module DenseRank3 { rnk = rank[result](int rnk0 | rnk0 = getRank(c1, c2, _) | rnk0) } - /** Gets the dense rank of `r` in the context provided by `c1` and `c2`. */ - int denseRank(C1 c1, C2 c2, Ranked r) { - exists(int rnk | - result = rankRank(c1, c2, r, rnk) and - rnk = getRank(c1, c2, r) - ) + /** + * Gets the `Ranked` value for which the dense rank in the context provided by + * `c1` and `c2` is `rnk`. + */ + Ranked denseRank(C1 c1, C2 c2, int rnk) { + rnk = rankRank(c1, c2, result, getRank(c1, c2, result)) } } diff --git a/shared/util/codeql/util/Option.qll b/shared/util/codeql/util/Option.qll index 31df747afe87..8ba4d8e840bc 100644 --- a/shared/util/codeql/util/Option.qll +++ b/shared/util/codeql/util/Option.qll @@ -2,6 +2,7 @@ /** A type with `toString`. */ private signature class TypeWithToString { + bindingset[this] string toString(); }