From 4e58760e4ac29abd478200fd7d9f62dea8d247c0 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Wed, 16 Oct 2024 22:54:21 +0200 Subject: [PATCH 01/11] Rust: parse formatting templates --- rust/ql/.generated.list | 1 - rust/ql/.gitattributes | 1 - .../codeql/rust/elements/FormatTemplate.qll | 248 ++++++++++++++++++ .../elements/internal/FormatArgsExprImpl.qll | 13 +- .../formatstrings/FormatTemplate.expected | 132 ++++++++++ .../formatstrings/FormatTemplate.ql | 19 ++ .../test/library-tests/formatstrings/main.rs | 77 ++++++ 7 files changed, 487 insertions(+), 4 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/FormatTemplate.qll create mode 100644 rust/ql/test/library-tests/formatstrings/FormatTemplate.expected create mode 100644 rust/ql/test/library-tests/formatstrings/FormatTemplate.ql create mode 100644 rust/ql/test/library-tests/formatstrings/main.rs diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index b097424364484..5fb8d706e3432 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -233,7 +233,6 @@ lib/codeql/rust/elements/internal/ForTypeImpl.qll b515639844778d0fbe51e6161a2ec1 lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll 8bd9b4e035ef8adeb3ac510dd68043934c0140facb933be1f240096d01cdfa11 74e9d3bbd8882ae59a7e88935d468e0a90a6529a4e2af6a3d83e93944470f0ee lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll 601f7715e9a65bcfa7cea1979fa30d694b5bea29650d799d7dd3080b8eea58e9 ecb0800cdb8c0f93277982dad295ac6a5332e42eff4fb5c8ff19f903b9857003 lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll ce29ff5a839b885b1ab7a02d6a381ae474ab1be3e6ee7dcfd7595bdf28e4b558 63bf957426871905a51ea319662a59e38104c197a1024360aca364dc145b11e8 -lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll bdb992ebc6be59311b486f40325b39f52a69921cfc66a731085cb184da00050f 6336e7770f9cb700f1b3914fd940c3423ab4e971b34ed8fcc79da80c1f1cdba3 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 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 7ce14ee732eb8..6780ca9b55c9c 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -235,7 +235,6 @@ /lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll linguist-generated /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 diff --git a/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll b/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll new file mode 100644 index 0000000000000..a2c7138fde283 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll @@ -0,0 +1,248 @@ +/** + * This module provides the classes modeling formatting templates. See also https://doc.rust-lang.org/std/fmt + */ + +private import FormatArgsExpr +private import LiteralExpr + +/** + * A regular expression for matching format elements in a formatting template. The + * regular expression is generated from the following python code: + * + * ```python + * identifier = "([A-Za-z_][A-Za-z0-9_]*)" + * integer = "([0-9]+)" + * + * # argument := integer | identifier + * argument = "({integer}|{identifier})".format(integer=integer, identifier=identifier) + * + * # parameter := argument '$' + * parameter = "(({argument})\\$)".format(argument=argument) + * + * # count := parameter | integer + * count = "({parameter}|{integer})".format(integer=integer, parameter=parameter) + * + * # fill := character + * fill = "(.)" + * + * # align := '<' | '^' | '>' + * align = "([<^>])" + * + * # sign := '+' | '-' + * sign = "([+-])" + * + * # width := count + * width = count + * + * # precision := count | '*' + * precision = "({count}|(\\*))".format(count=count) + * + * # type := '' | '?' | 'x?' | 'X?' | identifier + * type = "(|\\?|x\\?|X\\?|{identifier})".format(identifier=identifier) + * + * # format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type + * format_spec = "({fill}?{align})?{sign}?(#)?(0)?{width}?(\\.{precision})?{type}".format(fill=fill, align=align, sign=sign, width=width, precision=precision, type=type) + * + * # format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' + * format = "(\\{{{argument}?(:{format_spec})?\s*}\\})".format(argument=argument, format_spec=format_spec) + * + * ``` + */ +private string formatRegex() { + result = + "(\\{(([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))?(:((.)?([<^>]))?([+-])?(#)?(0)?(((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))?(\\.((((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))|(\\*)))?(|\\?|x\\?|X\\?|([A-Za-z_][A-Za-z0-9_]*)))?\\s*\\})" +} + +private string textRegex() { result = "([^{}]|\\{\\{|\\}\\})+" } + +private string part(FormatArgsExpr parent, int occurrenceIndex, int occurrenceOffset) { + result = + parent + .getTemplate() + .(LiteralExpr) + .getTextValue() + // TODO: should also handle surrounding quotes and escaped characters + .regexpFind(textRegex() + "|" + formatRegex(), occurrenceIndex, occurrenceOffset) +} + +private newtype TFormatTemplateElem = + TFormat(FormatArgsExpr parent, string text, int index, int offset) { + text = part(parent, index, offset) and text.regexpMatch(formatRegex()) + } + +private newtype TFormatArgumentKind = + TElement() or + TWidth() or + TPrecision() + +private newtype TFormatArgumentT = + TFormatArgument( + TFormat parent, TFormatArgumentKind kind, string value, boolean positional, int offset + ) { + exists(string text, int formatOffset, int group | + group = [3, 4] and offset = formatOffset + 1 and kind = TElement() + or + group = [15, 16] and + offset = formatOffset + min(text.indexOf(value + "$")) and + kind = TWidth() + or + group = [23, 24] and + offset = formatOffset + max(text.indexOf(value + "$")) and + kind = TPrecision() + | + parent = TFormat(_, text, _, formatOffset) and + value = text.regexpCapture(formatRegex(), group) and + if group % 2 = 1 then positional = true else positional = false + ) + } + +/** + * A format element in a formatting template. For example the `{}` in: + * ```rust + * println!("Hello {}", "world"); + * ``` + */ +class Format extends TFormat { + private FormatArgsExpr parent; + private string text; + private int index; + private int offset; + + Format() { this = TFormat(parent, text, index, offset) } + + /** Gets a textual representation of this element. */ + string toString() { result = text } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + parent + .getTemplate() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and + endline = startline and + endcolumn = startcolumn + text.length() - 1 + } + + /** Gets a the parent of this `Format`. */ + FormatArgsExpr getParent() { result = parent } + + /** Gets the index of this `Format` node. */ + int getIndex() { result = index } + + /** + * Gets the name or position reference of this format, if any. For example `name` and `0` in: + * ```rust + * let name = "Alice"; + * println!("{name} in wonderland"); + * println!("{0} in wonderland", name); + * ``` + */ + FormatArgument getArgumentRef() { + result.getParent() = this and result = TFormatArgument(_, TElement(), _, _, _) + } + + /** + * Gets the name or position reference of the width parameter in this format, if any. For example `width` and `1` in: + * ```rust + * let width = 6; + * println!("{:width$}", PI); + * println!("{:1$}", PI, width); + * ``` + */ + FormatArgument getWidthArgument() { + result.getParent() = this and result = TFormatArgument(_, TWidth(), _, _, _) + } + + /** + * Gets the name or position reference of the width parameter in this format, if any. For example `prec` and `1` in: + * ```rust + * let prec = 6; + * println!("{:.prec$}", PI); + * println!("{:.1$}", PI, prec); + * ``` + */ + FormatArgument getPrecisionArgument() { + result.getParent() = this and result = TFormatArgument(_, TPrecision(), _, _, _) + } +} + +/** + * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: + * ```rust + * println!("Value {value:#width$.precision$}"); + * ``` + * or the `0`, `1` and `2` in: + * ```rust + * println!("Value {0:#1$.2$}", value, width, precision); + * ``` + */ +class FormatArgument extends TFormatArgumentT { + private Format parent; + string name; + private int offset; + + FormatArgument() { this = TFormatArgument(parent, _, name, _, offset) } + + /** Gets a textual representation of this element. */ + string toString() { result = name } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + // TODO: handle locations in multi-line comments + // TODO: handle the case where the template is from a nested macro call + parent + .getParent() + .getTemplate() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and + endline = startline and + endcolumn = startcolumn + name.length() - 1 + } + + /** Gets a the parent of this `FormatArgument`. */ + Format getParent() { result = parent } +} + +/** + * A positional `FormatArgument`. For example `0` in + * ```rust + * let name = "Alice"; + * println!("{0} in wonderland", name); + * ``` + */ +class PositionalFormatArgument extends FormatArgument { + PositionalFormatArgument() { this = TFormatArgument(_, _, _, true, _) } + + /** Gets the index of this positional argument */ + int getIndex() { result = name.toInt() } +} + +/** + * A named `FormatArgument`. For example `name` in + * ```rust + * let name = "Alice"; + * println!("{name} in wonderland"); + * ``` + */ +class NamedFormatArgument extends FormatArgument { + NamedFormatArgument() { this = TFormatArgument(_, _, _, false, _) } + + /** Gets the name of this named argument */ + string getName() { result = name } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll index 0cf47a9ed1fe0..7524a385e9efb 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.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 `FormatArgsExpr`. * @@ -6,17 +5,27 @@ */ private import codeql.rust.elements.internal.generated.FormatArgsExpr +private import codeql.rust.elements.FormatTemplate /** * INTERNAL: This module contains the customizable definition of `FormatArgsExpr` 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 FormatArgsExpr. For example: * ```rust * todo!() * ``` */ - class FormatArgsExpr extends Generated::FormatArgsExpr { } + class FormatArgsExpr extends Generated::FormatArgsExpr { + /** + * Gets the `index`th format of this `FormatArgsExpr`'s formatting template (0-based). + */ + 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/test/library-tests/formatstrings/FormatTemplate.expected b/rust/ql/test/library-tests/formatstrings/FormatTemplate.expected new file mode 100644 index 0000000000000..6750a5dc5f03f --- /dev/null +++ b/rust/ql/test/library-tests/formatstrings/FormatTemplate.expected @@ -0,0 +1,132 @@ +getFormat +| main.rs:5:14:5:61 | FormatArgsExpr | main.rs:5:21:5:46 | {value:#width$.precision$} | 0 | +| main.rs:6:14:6:56 | FormatArgsExpr | main.rs:6:21:6:30 | {0:#1$.2$} | 0 | +| main.rs:7:14:7:40 | FormatArgsExpr | main.rs:7:21:7:22 | {} | 0 | +| main.rs:7:14:7:40 | FormatArgsExpr | main.rs:7:24:7:25 | {} | 1 | +| main.rs:11:14:11:34 | FormatArgsExpr | main.rs:11:22:11:23 | {} | 0 | +| main.rs:12:14:12:34 | FormatArgsExpr | main.rs:12:29:12:30 | {} | 0 | +| main.rs:13:14:13:27 | FormatArgsExpr | main.rs:13:15:13:18 | {:?} | 0 | +| main.rs:14:14:14:33 | FormatArgsExpr | main.rs:14:15:14:21 | {value} | 0 | +| main.rs:16:14:16:30 | FormatArgsExpr | main.rs:16:21:16:28 | {people} | 0 | +| main.rs:17:14:17:26 | FormatArgsExpr | main.rs:17:15:17:16 | {} | 0 | +| main.rs:17:14:17:26 | FormatArgsExpr | main.rs:17:18:17:19 | {} | 1 | +| main.rs:18:14:18:24 | FormatArgsExpr | main.rs:18:15:18:19 | {:04} | 0 | +| main.rs:19:14:19:32 | FormatArgsExpr | main.rs:19:15:19:19 | {:#?} | 0 | +| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:15:21:17 | {1} | 0 | +| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:19:21:20 | {} | 1 | +| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:22:21:24 | {0} | 2 | +| main.rs:21:14:21:34 | FormatArgsExpr | main.rs:21:26:21:27 | {} | 3 | +| main.rs:22:14:22:31 | FormatArgsExpr | main.rs:22:21:22:24 | {:5} | 0 | +| main.rs:23:14:23:35 | FormatArgsExpr | main.rs:23:21:23:25 | {:1$} | 0 | +| main.rs:24:14:24:36 | FormatArgsExpr | main.rs:24:21:24:26 | {1:0$} | 0 | +| main.rs:25:14:25:47 | FormatArgsExpr | main.rs:25:21:25:29 | {:width$} | 0 | +| main.rs:27:14:27:36 | FormatArgsExpr | main.rs:27:21:27:29 | {:width$} | 0 | +| main.rs:28:24:28:42 | FormatArgsExpr | main.rs:28:31:28:35 | {:<5} | 0 | +| main.rs:29:24:29:43 | FormatArgsExpr | main.rs:29:31:29:36 | {:-<5} | 0 | +| main.rs:30:24:30:42 | FormatArgsExpr | main.rs:30:31:30:35 | {:^5} | 0 | +| main.rs:31:24:31:42 | FormatArgsExpr | main.rs:31:31:31:35 | {:>5} | 0 | +| main.rs:32:14:32:57 | FormatArgsExpr | main.rs:32:21:32:26 | {:^15} | 0 | +| main.rs:32:39:32:56 | FormatArgsExpr | main.rs:32:40:32:43 | {:?} | 0 | +| main.rs:33:24:33:39 | FormatArgsExpr | main.rs:33:31:33:34 | {:+} | 0 | +| main.rs:34:24:34:35 | FormatArgsExpr | main.rs:34:25:34:29 | {:#x} | 0 | +| main.rs:35:24:35:40 | FormatArgsExpr | main.rs:35:31:35:35 | {:05} | 0 | +| main.rs:36:24:36:41 | FormatArgsExpr | main.rs:36:31:36:35 | {:05} | 0 | +| main.rs:37:24:37:38 | FormatArgsExpr | main.rs:37:25:37:32 | {:#010x} | 0 | +| main.rs:39:14:39:45 | FormatArgsExpr | main.rs:39:21:39:23 | {0} | 0 | +| main.rs:39:14:39:45 | FormatArgsExpr | main.rs:39:28:39:33 | {1:.5} | 1 | +| main.rs:41:14:41:49 | FormatArgsExpr | main.rs:41:21:41:23 | {1} | 0 | +| main.rs:41:14:41:49 | FormatArgsExpr | main.rs:41:28:41:34 | {2:.0$} | 1 | +| main.rs:43:14:43:49 | FormatArgsExpr | main.rs:43:21:43:23 | {0} | 0 | +| main.rs:43:14:43:49 | FormatArgsExpr | main.rs:43:28:43:34 | {2:.1$} | 1 | +| main.rs:45:14:45:46 | FormatArgsExpr | main.rs:45:21:45:22 | {} | 0 | +| main.rs:45:14:45:46 | FormatArgsExpr | main.rs:45:27:45:31 | {:.*} | 1 | +| main.rs:47:14:47:48 | FormatArgsExpr | main.rs:47:21:47:23 | {1} | 0 | +| main.rs:47:14:47:48 | FormatArgsExpr | main.rs:47:28:47:33 | {2:.*} | 1 | +| main.rs:48:14:48:47 | FormatArgsExpr | main.rs:48:21:48:22 | {} | 0 | +| main.rs:48:14:48:47 | FormatArgsExpr | main.rs:48:27:48:32 | {2:.*} | 1 | +| main.rs:49:14:49:72 | FormatArgsExpr | main.rs:49:21:49:22 | {} | 0 | +| main.rs:49:14:49:72 | FormatArgsExpr | main.rs:49:27:49:41 | {number:.prec$} | 1 | +| main.rs:52:9:55:22 | FormatArgsExpr | main.rs:52:10:52:11 | {} | 0 | +| main.rs:52:9:55:22 | FormatArgsExpr | main.rs:52:15:52:23 | {name:.*} | 1 | +| main.rs:58:9:61:24 | FormatArgsExpr | main.rs:58:10:58:11 | {} | 0 | +| main.rs:58:9:61:24 | FormatArgsExpr | main.rs:58:15:58:23 | {name:.*} | 1 | +| main.rs:64:9:67:24 | FormatArgsExpr | main.rs:64:10:64:11 | {} | 0 | +| main.rs:64:9:67:24 | FormatArgsExpr | main.rs:64:15:64:25 | {name:>8.*} | 1 | +| main.rs:70:12:70:31 | FormatArgsExpr | main.rs:70:13:70:20 | {0:.1$e} | 0 | +| main.rs:71:12:71:31 | FormatArgsExpr | main.rs:71:13:71:20 | {0:.1$e} | 0 | +| main.rs:73:14:73:35 | FormatArgsExpr | main.rs:73:28:73:29 | {} | 0 | +getArgumentRef +| main.rs:5:21:5:46 | {value:#width$.precision$} | main.rs:5:22:5:26 | value | +| main.rs:6:21:6:30 | {0:#1$.2$} | main.rs:6:22:6:22 | 0 | +| main.rs:14:15:14:21 | {value} | main.rs:14:16:14:20 | value | +| main.rs:16:21:16:28 | {people} | main.rs:16:22:16:27 | people | +| main.rs:21:15:21:17 | {1} | main.rs:21:16:21:16 | 1 | +| main.rs:21:22:21:24 | {0} | main.rs:21:23:21:23 | 0 | +| main.rs:24:21:24:26 | {1:0$} | main.rs:24:22:24:22 | 1 | +| main.rs:39:21:39:23 | {0} | main.rs:39:22:39:22 | 0 | +| main.rs:39:28:39:33 | {1:.5} | main.rs:39:29:39:29 | 1 | +| main.rs:41:21:41:23 | {1} | main.rs:41:22:41:22 | 1 | +| main.rs:41:28:41:34 | {2:.0$} | main.rs:41:29:41:29 | 2 | +| main.rs:43:21:43:23 | {0} | main.rs:43:22:43:22 | 0 | +| main.rs:43:28:43:34 | {2:.1$} | main.rs:43:29:43:29 | 2 | +| main.rs:47:21:47:23 | {1} | main.rs:47:22:47:22 | 1 | +| main.rs:47:28:47:33 | {2:.*} | main.rs:47:29:47:29 | 2 | +| main.rs:48:27:48:32 | {2:.*} | main.rs:48:28:48:28 | 2 | +| main.rs:49:27:49:41 | {number:.prec$} | main.rs:49:28:49:33 | number | +| main.rs:52:15:52:23 | {name:.*} | main.rs:52:16:52:19 | name | +| main.rs:58:15:58:23 | {name:.*} | main.rs:58:16:58:19 | name | +| main.rs:64:15:64:25 | {name:>8.*} | main.rs:64:16:64:19 | name | +| main.rs:70:13:70:20 | {0:.1$e} | main.rs:70:14:70:14 | 0 | +| main.rs:71:13:71:20 | {0:.1$e} | main.rs:71:14:71:14 | 0 | +getWidthArgument +| main.rs:5:21:5:46 | {value:#width$.precision$} | main.rs:5:29:5:33 | width | +| main.rs:6:21:6:30 | {0:#1$.2$} | main.rs:6:25:6:25 | 1 | +| main.rs:23:21:23:25 | {:1$} | main.rs:23:23:23:23 | 1 | +| main.rs:24:21:24:26 | {1:0$} | main.rs:24:24:24:24 | 0 | +| main.rs:25:21:25:29 | {:width$} | main.rs:25:23:25:27 | width | +| main.rs:27:21:27:29 | {:width$} | main.rs:27:23:27:27 | width | +getPrecisionArgument +| main.rs:5:21:5:46 | {value:#width$.precision$} | main.rs:5:36:5:44 | precision | +| main.rs:6:21:6:30 | {0:#1$.2$} | main.rs:6:28:6:28 | 2 | +| main.rs:41:28:41:34 | {2:.0$} | main.rs:41:32:41:32 | 0 | +| main.rs:43:28:43:34 | {2:.1$} | main.rs:43:32:43:32 | 1 | +| main.rs:49:27:49:41 | {number:.prec$} | main.rs:49:36:49:39 | prec | +| main.rs:70:13:70:20 | {0:.1$e} | main.rs:70:17:70:17 | 1 | +| main.rs:71:13:71:20 | {0:.1$e} | main.rs:71:17:71:17 | 1 | +getIndex +| main.rs:6:22:6:22 | 0 | 0 | +| main.rs:6:25:6:25 | 1 | 1 | +| main.rs:6:28:6:28 | 2 | 2 | +| main.rs:21:16:21:16 | 1 | 1 | +| main.rs:21:23:21:23 | 0 | 0 | +| main.rs:23:23:23:23 | 1 | 1 | +| main.rs:24:22:24:22 | 1 | 1 | +| main.rs:24:24:24:24 | 0 | 0 | +| main.rs:39:22:39:22 | 0 | 0 | +| main.rs:39:29:39:29 | 1 | 1 | +| main.rs:41:22:41:22 | 1 | 1 | +| main.rs:41:29:41:29 | 2 | 2 | +| main.rs:41:32:41:32 | 0 | 0 | +| main.rs:43:22:43:22 | 0 | 0 | +| main.rs:43:29:43:29 | 2 | 2 | +| main.rs:43:32:43:32 | 1 | 1 | +| main.rs:47:22:47:22 | 1 | 1 | +| main.rs:47:29:47:29 | 2 | 2 | +| main.rs:48:28:48:28 | 2 | 2 | +| main.rs:70:14:70:14 | 0 | 0 | +| main.rs:70:17:70:17 | 1 | 1 | +| main.rs:71:14:71:14 | 0 | 0 | +| main.rs:71:17:71:17 | 1 | 1 | +getName +| main.rs:5:22:5:26 | value | value | +| main.rs:5:29:5:33 | width | width | +| main.rs:5:36:5:44 | precision | precision | +| main.rs:14:16:14:20 | value | value | +| main.rs:16:22:16:27 | people | people | +| main.rs:25:23:25:27 | width | width | +| main.rs:27:23:27:27 | width | width | +| main.rs:49:28:49:33 | number | number | +| main.rs:49:36:49:39 | prec | prec | +| main.rs:52:16:52:19 | name | name | +| main.rs:58:16:58:19 | name | name | +| main.rs:64:16:64:19 | name | name | diff --git a/rust/ql/test/library-tests/formatstrings/FormatTemplate.ql b/rust/ql/test/library-tests/formatstrings/FormatTemplate.ql new file mode 100644 index 0000000000000..a1e068a61bb7d --- /dev/null +++ b/rust/ql/test/library-tests/formatstrings/FormatTemplate.ql @@ -0,0 +1,19 @@ +import rust + +query predicate getFormat(FormatArgsExpr arg, Format format, int index) { + format = arg.getFormat(index) +} + +query predicate getArgumentRef(Format format, FormatArgument arg) { arg = format.getArgumentRef() } + +query predicate getWidthArgument(Format format, FormatArgument arg) { + arg = format.getWidthArgument() +} + +query predicate getPrecisionArgument(Format format, FormatArgument arg) { + arg = format.getPrecisionArgument() +} + +query predicate getIndex(PositionalFormatArgument arg, int index) { arg.getIndex() = index } + +query predicate getName(NamedFormatArgument arg, string name) { arg.getName() = name } diff --git a/rust/ql/test/library-tests/formatstrings/main.rs b/rust/ql/test/library-tests/formatstrings/main.rs new file mode 100644 index 0000000000000..b056262f46fbd --- /dev/null +++ b/rust/ql/test/library-tests/formatstrings/main.rs @@ -0,0 +1,77 @@ +fn main() { + let width = 4; + let precision = 2; + let value = 10; + println!("Value {value:#width$.precision$}", value = 10.5); + println!("Value {0:#1$.2$}", value, width, precision); + println!("Value {} {}", value, width); + + // Examples from https://doc.rust-lang.org/std/fmt + println!("Hello"); + println!("Hello, {}!", "world"); + println!("The number is {}", 1); + println!("{:?}", (3, 4)); + println!("{value}", value = 4); + let people = "Rustaceans"; + println!("Hello {people}!"); + println!("{} {}", 1, 2); + println!("{:04}", 42); + println!("{:#?}", (100, 200)); + + println!("{1} {} {0} {}", 1, 2); + println!("Hello {:5}!", "x"); + println!("Hello {:1$}!", "x", 5); + println!("Hello {1:0$}!", 5, "x"); + println!("Hello {:width$}!", "x", width = 5); + let width = 5; + println!("Hello {:width$}!", "x"); + assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); + assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!"); + assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !"); + assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!"); + println!("Hello {:^15}!", format!("{:?}", Some("hi"))); + assert_eq!(format!("Hello {:+}!", 5), "Hello +5!"); + assert_eq!(format!("{:#x}!", 27), "0x1b!"); + assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!"); + assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!"); + assert_eq!(format!("{:#010x}!", 27), "0x0000001b!"); + + println!("Hello {0} is {1:.5}", "x", 0.01); + + println!("Hello {1} is {2:.0$}", 5, "x", 0.01); + + println!("Hello {0} is {2:.1$}", "x", 5, 0.01); + + println!("Hello {} is {:.*}", "x", 5, 0.01); + + println!("Hello {1} is {2:.*}", 5, "x", 0.01); + println!("Hello {} is {2:.*}", "x", 5, 0.01); + println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); + + println!( + "{}, `{name:.*}` has 3 fractional digits", + "Hello", + 3, + name = 1234.56 + ); + println!( + "{}, `{name:.*}` has 3 characters", + "Hello", + 3, + name = "1234.56" + ); + println!( + "{}, `{name:>8.*}` has 3 right-aligned characters", + "Hello", + 3, + name = "1234.56" + ); + + print!("{0:.1$e}", 12345, 3); + print!("{0:.1$e}", 12355, 3); + + println!("The value is {}", 1.5); + + assert_eq!(format!("Hello {{}}"), "Hello {}"); + assert_eq!(format!("{{ Hello"), "{ Hello"); +} From 9e14dae272fb14a18e965a9192b7994ddd7d7334 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 16:31:27 +0200 Subject: [PATCH 02/11] Rust: add ImplicitVariableAccess class --- rust/ql/.generated.list | 12 +++-- rust/ql/.gitattributes | 2 + rust/ql/lib/codeql/rust/elements.qll | 1 + .../rust/elements/ImplicitVariableAccess.qll | 9 ++++ .../ImplicitVariableAccessConstructor.qll | 38 ++++++++++++++ .../internal/ImplicitVariableAccessImpl.qll | 49 +++++++++++++++++++ .../generated/ImplicitVariableAccess.qll | 23 +++++++++ .../internal/generated/ParentChild.qll | 17 +++++++ .../generated/PureSynthConstructors.qll | 1 + .../elements/internal/generated/Synth.qll | 31 ++++++++++-- .../internal/generated/SynthConstructors.qll | 1 + rust/schema/annotations.py | 9 ++++ 12 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/ImplicitVariableAccess.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/generated/ImplicitVariableAccess.qll diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 5fb8d706e3432..5378555019a27 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -51,6 +51,7 @@ lib/codeql/rust/elements/IdentPat.qll ad5f202316d4eeee3ca81ea445728f4ad7eb6bb7d8 lib/codeql/rust/elements/IfExpr.qll f62153e8098b3eb08b569d4e25c750bc686665651579db4bc9e11dcef8e75d63 55006a55d612f189e73caa02f7b4deda388c692f0a801cdda9f833f2afdca778 lib/codeql/rust/elements/Impl.qll 9593c47af4fa08afb19c52aab7d0bac6740fed7ec60201f47e7bc46f13bfb329 4ec840401563ab6136b99491b881c9a10108240de972b19ec64227e1e7d73e65 lib/codeql/rust/elements/ImplTraitType.qll f7241044f6666a509cfbc01bf6df3db5360e67dd0f9baba4a323566701359203 350636d0b1c7a77e006170cbfa9108c259dd5831b0f242da76c10be3ecc32870 +lib/codeql/rust/elements/ImplicitVariableAccess.qll bc3cd90231216c41ddfcb7ac33974c3105b24b4fd712d1b7147cd0e1a7d84ac0 d8c6114b596cd27421fc7a11ec96439e2ad12396e0e4b3ec3dfa121a9b595c03 lib/codeql/rust/elements/IndexExpr.qll 0e2e9f018d06ae72be0fc4ddbc019a9aacd8a06f42b4c4431760bd149e7f2290 2bcfd557abd53a48e48de7915c4f2089107c62dfb3e732a904848248dfd3727b lib/codeql/rust/elements/InferType.qll c71184ae6aa181be94e299882503350e057493e17f1133a1e96162a0e5cbd1ef f0f19b611708df45a6ff811f8066c8042a8e1ac9b7bd94910514547ea430d3d5 lib/codeql/rust/elements/Item.qll 5c9148ff0eaeb4404c2d8156e7df0ef5753fd44ead972da05a49659ddaa25480 78446f788617e40525d4d4b489848e75f2143a90e18d40974c3bff7b1e7c825c @@ -504,6 +505,7 @@ lib/codeql/rust/elements/internal/generated/IdentPat.qll a1269182132b2f52c5d842e lib/codeql/rust/elements/internal/generated/IfExpr.qll 413dd7a20c6b98c0d2ad2e5b50981c14bf96c1a719ace3e341d78926219a5af7 c9a2d44e3baa6a265a29a683ca3c1683352457987c92f599c5771b4f3b4bafff lib/codeql/rust/elements/internal/generated/Impl.qll e33ef5d3e49e64beca0ca9d5c0ba972d99007e5011eeedc11e67d3fbb569ab4a 5c5d88110864f4fd3d966b1ad973eaabd7a9c5a07adc18bff01dc09395214825 lib/codeql/rust/elements/internal/generated/ImplTraitType.qll 3c29684f5ef386b883b79dc9758441d97f090e065be177ffc8240aaf0f3d1e7b 03ea42c2a95cf917ec73d88b7b4ca5e53e10d7b046074f59100c0ec6c2c1ed6d +lib/codeql/rust/elements/internal/generated/ImplicitVariableAccess.qll 2fec3cc89735a89e0301edb89c392c75216906b0936331a957b26e281b9833ae f5eb6de1cb9d82e0fc5de8393a42823134ed19b6c0b1a091a7efe8eb06f29b85 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 70930ebfea4d0b56c0c47bede0c7aa21ec119210467fecc58a850273efb9080d c3bce1b435c3370083a3ef95da7647e720ca4e636b83dfa0ccecbf11f7ecd34b @@ -545,7 +547,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b 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 823b35d9802fab617be5c76327d65a3e52abd4be72bbc36d93e673cea7a9baaf 9d58eb407d0a929aefc0f4d532ef39dded81f6a370b6735ef581709c82ff9bc6 +lib/codeql/rust/elements/internal/generated/ParentChild.qll 5fe79a0186d964592ba3f0c6e699a08ee6aa0a2a5462820d913c6b747ce10e36 ce3c5cd0cb5651eba00e97cb2c057e5c63d4c7c1a511311675389bd8fd5eb1bf lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4 lib/codeql/rust/elements/internal/generated/Path.qll 299abce24762a5ab023f3cf1ab9718b83047e171aed42a8092e7a155914b1657 db1a23d18640c548f08c9f94823838b5e019ac85877c7b15df2d1493d1846572 lib/codeql/rust/elements/internal/generated/PathExpr.qll 17cdb0a7393258a207450f08e37178fc9d35d167f064ba6015be94246f3dc933 a75fdd280aff6d87e083a92030e041c2eb52b57cf7151d4a6989fcd31d6a64bf @@ -554,7 +556,7 @@ lib/codeql/rust/elements/internal/generated/PathSegment.qll 4621597fd86246f788b8 lib/codeql/rust/elements/internal/generated/PathType.qll 45de78e5374d6eb0446e2112ec72d3692c2811df9fa2ad03d0127e426940abe3 622cf70408413a565a0dac58f451035ac1339c8d0ee5b24f630680201cb0aa48 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 dc03515d678ba052c2ff2dd9f0883e0bce54cac740ba9a15e5173f292c1b6971 dc03515d678ba052c2ff2dd9f0883e0bce54cac740ba9a15e5173f292c1b6971 +lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll 65b9266ae7f55d2cd64ed7440a75f9074dfefb9dde7a5b3ed78a71b726148c97 65b9266ae7f55d2cd64ed7440a75f9074dfefb9dde7a5b3ed78a71b726148c97 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 429057964308876b8186a0ca901634273d91b783e4bb85aa5e47860010f4da0b feb8231d0b724fedb1d9d2a65d4a8759ae58baec902b44e3bebdb81a7fbc1fd1 @@ -582,8 +584,8 @@ 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 dd9d72a46cf446af025cd7b0085f3780ee7bf7d09a458d3ae6f495e999d342c8 cda06e3155f1a3eecc5ee8ec8097d5362234b44f815aff9bc3940860435262b3 -lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 5d30b6d4f36791637f250734ee38820102c64f196454e20f79e30097da1a8e20 5d30b6d4f36791637f250734ee38820102c64f196454e20f79e30097da1a8e20 +lib/codeql/rust/elements/internal/generated/Synth.qll 9513585ad92c4dc9070a73355778f16f3fb104cfc8589e438f0d39965bc2dcfd 34847da4b696dc41d57420f165b2fde5b5cdc8aaa958c50875fb3cbfbad8cb7a +lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 822945db0182edf1571f8fcba6b18fc11c017cd50a177ecc4772d68ca0e7154f 822945db0182edf1571f8fcba6b18fc11c017cd50a177ecc4772d68ca0e7154f lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c lib/codeql/rust/elements/internal/generated/Trait.qll a570fa93d0b78a35766b00d5ca256c102f824564248b9d8b678a981d6eea3e2e d9c7475e5102e21cfdee3b1791f89a4f9cdba5a4200349ff706532b704c02664 @@ -617,7 +619,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll fec8a9211b82a80601bf73 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 ef8063c90411cb957c776756837a4c7ad43aa4eeb52595786e8b2b96dc10ebff ef8063c90411cb957c776756837a4c7ad43aa4eeb52595786e8b2b96dc10ebff +lib/codeql/rust/elements.qll 9b838fb5bccee1cfd470ba62d3830790de120eaf05186f865aa885438c7fe5ff 9b838fb5bccee1cfd470ba62d3830790de120eaf05186f865aa885438c7fe5ff 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 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 6780ca9b55c9c..2063a973ad80a 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -53,6 +53,7 @@ /lib/codeql/rust/elements/IfExpr.qll linguist-generated /lib/codeql/rust/elements/Impl.qll linguist-generated /lib/codeql/rust/elements/ImplTraitType.qll linguist-generated +/lib/codeql/rust/elements/ImplicitVariableAccess.qll linguist-generated /lib/codeql/rust/elements/IndexExpr.qll linguist-generated /lib/codeql/rust/elements/InferType.qll linguist-generated /lib/codeql/rust/elements/Item.qll linguist-generated @@ -506,6 +507,7 @@ /lib/codeql/rust/elements/internal/generated/IfExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Impl.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ImplTraitType.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/ImplicitVariableAccess.qll linguist-generated /lib/codeql/rust/elements/internal/generated/IndexExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/InferType.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Item.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/elements.qll b/rust/ql/lib/codeql/rust/elements.qll index a88f22e9e7fa0..813ddac7bd2cf 100644 --- a/rust/ql/lib/codeql/rust/elements.qll +++ b/rust/ql/lib/codeql/rust/elements.qll @@ -56,6 +56,7 @@ import codeql.rust.elements.IdentPat import codeql.rust.elements.IfExpr import codeql.rust.elements.Impl import codeql.rust.elements.ImplTraitType +import codeql.rust.elements.ImplicitVariableAccess import codeql.rust.elements.IndexExpr import codeql.rust.elements.InferType import codeql.rust.elements.Item diff --git a/rust/ql/lib/codeql/rust/elements/ImplicitVariableAccess.qll b/rust/ql/lib/codeql/rust/elements/ImplicitVariableAccess.qll new file mode 100644 index 0000000000000..aca8f1953a17d --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/ImplicitVariableAccess.qll @@ -0,0 +1,9 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `ImplicitVariableAccess`. + */ + +private import internal.ImplicitVariableAccessImpl +import codeql.rust.elements.Expr + +final class ImplicitVariableAccess = Impl::ImplicitVariableAccess; diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll new file mode 100644 index 0000000000000..bf0d648bb8815 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll @@ -0,0 +1,38 @@ +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `ImplicitVariableAccess` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.Raw +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.FormatTemplate + +/** + * The characteristic predicate of `ImplicitVariableAccess` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructImplicitVariableAccess(Raw::FormatArgsExpr parent, int index, int kind) { + exists(NamedFormatArgument arg | unboundNamedFormatArgument(parent, index, kind, arg)) +} + +/** + * A named format argument for which no binding is found in the parent `FormatArgsExpr::getArg(_)`. + * INTERNAL: Do not use. + */ +predicate unboundNamedFormatArgument( + Raw::FormatArgsExpr parent, int index, int kind, NamedFormatArgument arg +) { + exists(Format format, string name | + not parent.getArg(_).getName().getText() = name and + name = arg.getName() and + Synth::convertFormatArgsExprToRaw(format.getParent()) = parent and + format.getIndex() = index + | + arg = format.getArgumentRef() and kind = 0 + or + arg = format.getWidthArgument() and kind = 1 + or + arg = format.getPrecisionArgument() and kind = 2 + ) +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll new file mode 100644 index 0000000000000..06b1882733f18 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll @@ -0,0 +1,49 @@ +/** + * This module provides a hand-modifiable wrapper around the generated class `ImplicitVariableAccess`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.ImplicitVariableAccess +private import codeql.rust.elements.internal.ImplicitVariableAccessConstructor +private import codeql.rust.elements.internal.generated.Raw +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.FormatTemplate + +/** + * INTERNAL: This module contains the customizable definition of `ImplicitVariableAccess` and should not + * be referenced directly. + */ +module Impl { + class ImplicitVariableAccess extends Generated::ImplicitVariableAccess { + private NamedFormatArgument argument; + + ImplicitVariableAccess() { + exists(Raw::FormatArgsExpr parent, int index, int kind | + this = Synth::TImplicitVariableAccess(parent, index, kind) and + unboundNamedFormatArgument(parent, index, kind, argument) + ) + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + argument.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + override string toString() { result = this.getName() } + + /** Gets the name of the variable */ + string getName() { result = argument.getName() } + + /** Gets the underlying `NamedFormatArgument` . */ + NamedFormatArgument getArgument() { result = argument } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/ImplicitVariableAccess.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/ImplicitVariableAccess.qll new file mode 100644 index 0000000000000..f97241cbae24e --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ImplicitVariableAccess.qll @@ -0,0 +1,23 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `ImplicitVariableAccess`. + * 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 + +/** + * INTERNAL: This module contains the fully generated definition of `ImplicitVariableAccess` and should not + * be referenced directly. + */ +module Generated { + /** + * INTERNAL: Do not reference the `Generated::ImplicitVariableAccess` class directly. + * Use the subclass `ImplicitVariableAccess`, where the following predicates are available. + */ + class ImplicitVariableAccess extends Synth::TImplicitVariableAccess, ExprImpl::Expr { + override string getAPrimaryQlClass() { result = "ImplicitVariableAccess" } + } +} 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 0db824800bdb8..f0967cd7263dc 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll @@ -1829,6 +1829,21 @@ private module Impl { ) } + private Element getImmediateChildOfImplicitVariableAccess( + ImplicitVariableAccess e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfIndexExpr(IndexExpr e, int index, string partialPredicateCall) { exists(int b, int bExpr, int n, int nAttr, int nBase, int nIndex | b = 0 and @@ -3611,6 +3626,8 @@ private module Impl { or result = getImmediateChildOfImplTraitType(e, index, partialAccessor) or + result = getImmediateChildOfImplicitVariableAccess(e, index, partialAccessor) + or result = getImmediateChildOfIndexExpr(e, index, partialAccessor) or result = getImmediateChildOfInferType(e, index, partialAccessor) diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll index 100f7f4a756ec..2ed56ea512baf 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll @@ -3,3 +3,4 @@ * This module exports all modules providing `Element` subclasses. */ +import codeql.rust.elements.internal.ImplicitVariableAccessConstructor 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 2d174d52d2936..722e0ea844245 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll @@ -186,6 +186,12 @@ module Synth { * INTERNAL: Do not use. */ TImplTraitType(Raw::ImplTraitType id) { constructImplTraitType(id) } or + /** + * INTERNAL: Do not use. + */ + TImplicitVariableAccess(Raw::FormatArgsExpr parent, int index, int kind) { + constructImplicitVariableAccess(parent, index, kind) + } or /** * INTERNAL: Do not use. */ @@ -627,10 +633,11 @@ module Synth { 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 TPathExpr or - TPrefixExpr or TRangeExpr or TRecordExpr or TRefExpr or TReturnExpr or TTryExpr or - TTupleExpr or TUnderscoreExpr or TWhileExpr or TYeetExpr or TYieldExpr; + TForExpr or TFormatArgsExpr or TIfExpr or TImplicitVariableAccess or TIndexExpr or + TLetExpr or TLiteralExpr or TLoopExpr or TMacroExpr or TMatchExpr or TOffsetOfExpr or + TParenExpr or TPathExpr or TPrefixExpr or TRangeExpr or TRecordExpr or TRefExpr or + TReturnExpr or TTryExpr or TTupleExpr or TUnderscoreExpr or TWhileExpr or TYeetExpr or + TYieldExpr; /** * INTERNAL: Do not use. @@ -954,6 +961,12 @@ module Synth { */ TImplTraitType convertImplTraitTypeFromRaw(Raw::Element e) { result = TImplTraitType(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TImplicitVariableAccess`, if possible. + */ + TImplicitVariableAccess convertImplicitVariableAccessFromRaw(Raw::Element e) { none() } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TIndexExpr`, if possible. @@ -1765,6 +1778,8 @@ module Synth { or result = convertIfExprFromRaw(e) or + result = convertImplicitVariableAccessFromRaw(e) + or result = convertIndexExprFromRaw(e) or result = convertLetExprFromRaw(e) @@ -2260,6 +2275,12 @@ module Synth { */ Raw::Element convertImplTraitTypeToRaw(TImplTraitType e) { e = TImplTraitType(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TImplicitVariableAccess` to a raw DB element, if possible. + */ + Raw::Element convertImplicitVariableAccessToRaw(TImplicitVariableAccess e) { none() } + /** * INTERNAL: Do not use. * Converts a synthesized `TIndexExpr` to a raw DB element, if possible. @@ -3071,6 +3092,8 @@ module Synth { or result = convertIfExprToRaw(e) or + result = convertImplicitVariableAccessToRaw(e) + or result = convertIndexExprToRaw(e) or result = convertLetExprToRaw(e) diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll index 3d02f199e78ef..9c61c2f67b16d 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll @@ -46,6 +46,7 @@ import codeql.rust.elements.internal.IdentPatConstructor import codeql.rust.elements.internal.IfExprConstructor import codeql.rust.elements.internal.ImplConstructor import codeql.rust.elements.internal.ImplTraitTypeConstructor +import codeql.rust.elements.internal.ImplicitVariableAccessConstructor import codeql.rust.elements.internal.IndexExprConstructor import codeql.rust.elements.internal.InferTypeConstructor import codeql.rust.elements.internal.ItemListConstructor diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index f5e91c9928f84..b166701460963 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -191,6 +191,7 @@ class _: ``` """ + class CallExprBase(Expr): """ A function or method call expression. See `CallExpr` and `MethodCallExpr` for further details. @@ -213,6 +214,7 @@ class _: arg_list: drop attrs: drop + @annotate(MethodCallExpr, replace_bases={Expr: CallExprBase}) class _: """ @@ -1741,6 +1743,7 @@ class _: ``` """ + @annotate(Function, add_bases=[Callable]) class _: param_list: drop @@ -1751,3 +1754,9 @@ class _: class _: param_list: drop attrs: drop + + +@qltest.skip +@synth.on_arguments(parent="FormatArgsExpr", index=int, kind=int) +class ImplicitVariableAccess(Expr): + pass From 7d3c2015a213f1ceefacaa56166b4dc41ab8bb53 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 17:10:16 +0200 Subject: [PATCH 03/11] Rust: CFG for ImplicitVariableAccess --- .../internal/ControlFlowGraphImpl.qll | 17 +++++++++++++++++ rust/ql/lib/rust.qll | 1 + 2 files changed, 18 insertions(+) diff --git a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll index f6587bf765546..690098b69e4e0 100644 --- a/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll +++ b/rust/ql/lib/codeql/rust/controlflow/internal/ControlFlowGraphImpl.qll @@ -278,9 +278,26 @@ class FormatArgsExprTree extends StandardPostOrderTree, FormatArgsExpr { i = -1 and result = this.getTemplate() or result = this.getArg(i).getExpr() + or + result = + any(ImplicitVariableAccess v, Format f, int index, int kind | + f = this.getFormat(index) and + ( + v.getArgument() = f.getArgumentRef() and kind = 0 + or + v.getArgument() = f.getWidthArgument() and kind = 1 + or + v.getArgument() = f.getPrecisionArgument() and kind = 2 + ) and + i = this.getNumberOfArgs() + index * 3 + kind + | + v + ) } } +class ImplictVariableAccessTree extends LeafTree, ImplicitVariableAccess { } + class IndexExprTree extends StandardPostOrderTree instanceof IndexExpr { override AstNode getChildNode(int i) { i = 0 and result = super.getBase() diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index 58425b6490e80..45e593ed56e9d 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -6,3 +6,4 @@ import codeql.files.FileSystem import codeql.rust.elements.AssignmentOperation import codeql.rust.elements.LogicalOperation import codeql.rust.elements.Variable +import codeql.rust.elements.FormatTemplate From e4efbdb2d63864f0ff504f82d95b9a0b63fc9c9f Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 17:54:08 +0200 Subject: [PATCH 04/11] Rust: add Locatable::hasLocationInfo --- .../internal/ImplicitVariableAccessImpl.qll | 9 +------- .../rust/elements/internal/LocatableImpl.qll | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll index 06b1882733f18..abc74771d6b35 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll @@ -25,14 +25,7 @@ module Impl { ) } - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( + override predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { argument.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) diff --git a/rust/ql/lib/codeql/rust/elements/internal/LocatableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/LocatableImpl.qll index 570992497f122..89a7fbf10ea55 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/LocatableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/LocatableImpl.qll @@ -19,15 +19,26 @@ module Impl { final Location getLocation() { exists(Raw::Locatable raw | raw = Synth::convertLocatableToRaw(this) and - ( - locatable_locations(raw, result) - or - not exists(Location loc | locatable_locations(raw, loc)) and - result instanceof EmptyLocation - ) + locatable_locations(raw, result) ) } + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + or + not exists(this.getLocation()) and + any(EmptyLocation e).hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + /** * Gets the primary file where this element occurs. */ From 088e4d31b967cae4a633de3197d3f325df5e7012 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 17:56:19 +0200 Subject: [PATCH 05/11] Rust: make ImplicitVariableAccess instance of VariableAccess --- .../rust/elements/internal/VariableImpl.qll | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll index 2895a33d94bd4..8796e55a125fd 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll @@ -1,6 +1,6 @@ private import rust private import codeql.rust.elements.internal.generated.ParentChild -private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl +private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl private import codeql.util.DenseRank module Impl { @@ -138,12 +138,12 @@ module Impl { } /** A path expression that may access a local variable. */ - private class VariableAccessCand extends PathExpr { + private class VariableAccessCand extends TVariableAccess { string name_; VariableAccessCand() { exists(Path p, PathSegment ps | - p = this.getPath() and + p = this.(PathExpr).getPath() and not p.hasQualifier() and ps = p.getPart() and not ps.hasGenericArgList() and @@ -152,9 +152,23 @@ module Impl { not ps.hasReturnTypeSyntax() and name_ = ps.getNameRef().getText() ) + or + this.(ImplicitVariableAccess).getName() = name_ } + string toString() { result = name_ } + string getName() { result = name_ } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.(PathExpr) + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.(ImplicitVariableAccess) + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } } private AstNode getAnAncestorInVariableScope(AstNode n) { @@ -164,7 +178,10 @@ module Impl { n instanceof LetStmt or n instanceof VariableScope ) and - exists(AstNode n0 | result = getImmediateParent(n0) | + exists(AstNode n0 | + result = getImmediateParent(n0) or + result = n0.(ImplicitVariableAccess).getArgument().getParent().getParent() + | n0 = n or n0 = getAnAncestorInVariableScope(n) and @@ -272,7 +289,7 @@ module Impl { ) { name = cand.getName() and scope = [cand.(VariableScope), getEnclosingScope(cand)] and - cand.getLocation().hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and + cand.hasLocationInfo(_, startline, startcolumn, endline, endcolumn) and nestLevel = 0 or exists(VariableScope inner | @@ -347,8 +364,14 @@ module Impl { result = this.asVariable().toString() or result = this.asVariableAccessCand().toString() } - Location getLocation() { - result = this.asVariable().getLocation() or result = this.asVariableAccessCand().getLocation() + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asVariable() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.asVariableAccessCand() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } pragma[nomagic] @@ -422,9 +445,12 @@ module Impl { } private import codeql.rust.controlflow.internal.Scope + private import codeql.rust.elements.internal.generated.Synth + + private class TVariableAccess = Synth::TPathExpr or Synth::TImplicitVariableAccess; /** A variable access. */ - class VariableAccess extends PathExprImpl::PathExpr instanceof VariableAccessCand { + class VariableAccess extends ExprImpl::Expr, TVariableAccess instanceof VariableAccessCand { private string name; private Variable v; From 1ea41c70e777fcb558afb7a089cf9a1ba9368f2a Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 18:58:33 +0200 Subject: [PATCH 06/11] Rust: avoid multiple PrimaryQLClass warnings Fixes things like: ``` multiplePrimaryQlClasses | x | PathExpr,VariableAccess | ``` --- .../rust/elements/internal/VariableImpl.qll | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll index 8796e55a125fd..9300c2c6109c7 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/VariableImpl.qll @@ -1,6 +1,8 @@ private import rust private import codeql.rust.elements.internal.generated.ParentChild private import codeql.rust.elements.internal.ExprImpl::Impl as ExprImpl +private import codeql.rust.elements.internal.PathExprImpl::Impl as PathExprImpl +private import codeql.rust.elements.internal.ImplicitVariableAccessImpl::Impl as ImplicitVariableAccessImpl private import codeql.util.DenseRank module Impl { @@ -450,7 +452,8 @@ module Impl { private class TVariableAccess = Synth::TPathExpr or Synth::TImplicitVariableAccess; /** A variable access. */ - class VariableAccess extends ExprImpl::Expr, TVariableAccess instanceof VariableAccessCand { + abstract class VariableAccess extends ExprImpl::Expr, TVariableAccess instanceof VariableAccessCand + { private string name; private Variable v; @@ -467,6 +470,18 @@ module Impl { override string getAPrimaryQlClass() { result = "VariableAccess" } } + private class VariableAccessPathExpr extends VariableAccess, PathExprImpl::PathExpr { + override string getAPrimaryQlClass() { result = VariableAccess.super.getAPrimaryQlClass() } + } + + private class VariableAccessImplicitVariableAccess extends VariableAccess, + ImplicitVariableAccessImpl::ImplicitVariableAccess + { + override string toString() { result = VariableAccess.super.toString() } + + override string getAPrimaryQlClass() { result = VariableAccess.super.getAPrimaryQlClass() } + } + /** Holds if `e` occurs in the LHS of an assignment or compound assignment. */ private predicate assignmentExprDescendant(Expr e) { e = any(AssignmentExpr ae).getLhs() From 9f85759c41f21f4583e378aa8eb2f501c6c13a59 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 21:06:39 +0200 Subject: [PATCH 07/11] Rust: update expected output --- .../test/query-tests/unusedentities/UnusedVariable.expected | 2 -- rust/ql/test/query-tests/unusedentities/main.rs | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/rust/ql/test/query-tests/unusedentities/UnusedVariable.expected b/rust/ql/test/query-tests/unusedentities/UnusedVariable.expected index 58a47494907d2..42baff65e1684 100644 --- a/rust/ql/test/query-tests/unusedentities/UnusedVariable.expected +++ b/rust/ql/test/query-tests/unusedentities/UnusedVariable.expected @@ -2,8 +2,6 @@ | main.rs:90:13:90:13 | d | Variable is not used. | | main.rs:141:5:141:5 | y | Variable is not used. | | main.rs:168:9:168:9 | x | Variable is not used. | -| main.rs:196:9:196:9 | x | Variable is not used. | -| main.rs:201:9:201:9 | x | Variable is not used. | | main.rs:250:17:250:17 | a | Variable is not used. | | main.rs:258:20:258:22 | val | Variable is not used. | | main.rs:272:14:272:16 | val | Variable is not used. | diff --git a/rust/ql/test/query-tests/unusedentities/main.rs b/rust/ql/test/query-tests/unusedentities/main.rs index c56bac83b0888..3bb78d49dc9de 100644 --- a/rust/ql/test/query-tests/unusedentities/main.rs +++ b/rust/ql/test/query-tests/unusedentities/main.rs @@ -193,12 +193,12 @@ fn loops() { } } - for x // SPURIOUS: unused variable + for x in 1..10 { println!("x is {x}"); } - for x // SPURIOUS: unused variable + for x in 1..10 { _ = format!("x is {x}"); // SPURIOUS: unused value `res` } From ee23b47b1fd0ec6c28377daff00baea4d974b148 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 17 Oct 2024 21:25:05 +0200 Subject: [PATCH 08/11] Apply suggestion --- .../elements/internal/ImplicitVariableAccessConstructor.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll index bf0d648bb8815..9515e1cd82af2 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll @@ -13,7 +13,7 @@ private import codeql.rust.elements.FormatTemplate * INTERNAL: Do not use. */ predicate constructImplicitVariableAccess(Raw::FormatArgsExpr parent, int index, int kind) { - exists(NamedFormatArgument arg | unboundNamedFormatArgument(parent, index, kind, arg)) + unboundNamedFormatArgument(parent, index, kind, _) } /** From d7e5747936d2c23fd20defad9c134eb053b01b49 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 18 Oct 2024 10:11:35 +0200 Subject: [PATCH 09/11] Rust: define Format and FormatArgument in schema --- rust/schema/annotations.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/rust/schema/annotations.py b/rust/schema/annotations.py index b166701460963..67de68610e581 100644 --- a/rust/schema/annotations.py +++ b/rust/schema/annotations.py @@ -1760,3 +1760,32 @@ class _: @synth.on_arguments(parent="FormatArgsExpr", index=int, kind=int) class ImplicitVariableAccess(Expr): pass + + +@qltest.skip +@synth.on_arguments(parent=FormatArgsExpr, index=int) +class Format(Locatable): + """ + A format element in a formatting template. For example the `{}` in: + ```rust + println!("Hello {}", "world"); + ``` + """ + parent: FormatArgsExpr + index: int + + +@qltest.skip +@synth.on_arguments(parent=FormatArgsExpr, index=int, kind=int) +class FormatArgument(Locatable): + """ + An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: + ```rust + println!("Value {value:#width$.precision$}"); + ``` + or the `0`, `1` and `2` in: + ```rust + println!("Value {0:#1$.2$}", value, width, precision); + ``` + """ + parent: Format From 9d7120b8fdcba3c14b8b5484c5f51ab4188950a8 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 18 Oct 2024 10:53:05 +0200 Subject: [PATCH 10/11] Rust: run codegen --- rust/ql/.generated.list | 18 +++++-- rust/ql/.gitattributes | 8 +++ rust/ql/lib/codeql/rust/elements.qll | 2 + rust/ql/lib/codeql/rust/elements/Format.qll | 16 ++++++ .../codeql/rust/elements/FormatArgument.qll | 20 +++++++ .../internal/FormatArgumentConstructor.qll | 14 +++++ .../elements/internal/FormatArgumentImpl.qll | 39 ++++++++++++++ .../elements/internal/FormatConstructor.qll | 14 +++++ .../rust/elements/internal/FormatImpl.qll | 30 +++++++++++ .../elements/internal/generated/Format.qll | 38 ++++++++++++++ .../internal/generated/FormatArgument.qll | 37 +++++++++++++ .../internal/generated/ParentChild.qll | 32 ++++++++++++ .../generated/PureSynthConstructors.qll | 2 + .../elements/internal/generated/Synth.qll | 52 +++++++++++++++++-- .../internal/generated/SynthConstructors.qll | 2 + 15 files changed, 316 insertions(+), 8 deletions(-) create mode 100644 rust/ql/lib/codeql/rust/elements/Format.qll create mode 100644 rust/ql/lib/codeql/rust/elements/FormatArgument.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll create mode 100644 rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index 5378555019a27..a8450ac3d0148 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -40,8 +40,10 @@ lib/codeql/rust/elements/FieldList.qll bd243adc4696c60f636055a1c2da28039fe202847 lib/codeql/rust/elements/FnPtrType.qll c4a90dc660cf620972dc23b95494f5caf9f050eabd4bdb52fdc061f8797ba9a1 f8defc91582fa503607664668f9e2e6c2cd8b320c7c449610f21e52e332a129f lib/codeql/rust/elements/ForExpr.qll 312804d53dd9236a2f2a15c9d6ec348b46e139a54eb5893e7e12487725df7444 fa5e20099b1179033bc209bad3548e3d1d4019c7fe0e455cec8ca1a9d48692ab lib/codeql/rust/elements/ForType.qll 0036bed8749358c356d78c4a0eef40d73e2796284293cde5604ae70ddd6d0470 4edcaf8f7c67d42ebe3ebb1be6a7643758717d4fe88f5f648b6a1c5ff4ee4de7 +lib/codeql/rust/elements/Format.qll 506172d176f4b965f428585c032464f4abe07a0e47c574f8e011d8641ec45370 653e81bf233b8729649064de64f4a7a8533f8864ac6d2ea913f347088c924c60 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/Function.qll 2c76c2c7036891996b1f0ebde16c414edf37ebb44ff9c3483088dc6218733e07 d84d017d98aa240bf3bee6502a030aa8cfb7ed95425ffa9853e73b41485e1f4a lib/codeql/rust/elements/GenericArg.qll 5f11ce0e3c5f08de84db61f56ba1b984652455ba6b95a8b8a5b5a235913d4072 756b6a73d66fde45bdcc65ce2362a5b1391af2927e6d54b6550b3ecd5fd11e75 lib/codeql/rust/elements/GenericArgList.qll dcf274db517b0e8f19e4545d77f86cdd4066ff2805e68c808d0bb5750b49f569 1055a82929e850264e501b367ef4d314a3e6bb8943ec95f4284d157fb4d0092f @@ -234,6 +236,10 @@ lib/codeql/rust/elements/internal/ForTypeImpl.qll b515639844778d0fbe51e6161a2ec1 lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll 8bd9b4e035ef8adeb3ac510dd68043934c0140facb933be1f240096d01cdfa11 74e9d3bbd8882ae59a7e88935d468e0a90a6529a4e2af6a3d83e93944470f0ee lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll 601f7715e9a65bcfa7cea1979fa30d694b5bea29650d799d7dd3080b8eea58e9 ecb0800cdb8c0f93277982dad295ac6a5332e42eff4fb5c8ff19f903b9857003 lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll ce29ff5a839b885b1ab7a02d6a381ae474ab1be3e6ee7dcfd7595bdf28e4b558 63bf957426871905a51ea319662a59e38104c197a1024360aca364dc145b11e8 +lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll dea59a9e64681583b2b57c60b1d71f567af9d490bfd60a4cb118201c0e45e0bd aeeaffa43919ae7fed76c0a4be74547c657dc530c2af0fd94bc0c95cbf5a8194 +lib/codeql/rust/elements/internal/FormatArgumentImpl.qll e8115612cf08af743545e36091c4d06f00eb5ece8da8eee534bf3d269432da1c 88cae5f265f85f20f96ca2fdb7d353463ef16eebc6e86dd2ab023bc4f36f35f7 +lib/codeql/rust/elements/internal/FormatConstructor.qll 21cb51ec160d04cd4539d9c9488a21ac2a5d6a1eb35670429f7da1a6676d7d46 bcb7231ae549ec86d33581f5c89a4c346c190a02ed96fa7acd0ecba77240419e +lib/codeql/rust/elements/internal/FormatImpl.qll 4cebae0a808c68577976f38e45ae4bcb4d31ae3875afc36f560bfa23e5df3a83 67e0afd957254966f874af1137da1f293570f1fec519650a2572c0a932f5258f 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 @@ -494,8 +500,10 @@ lib/codeql/rust/elements/internal/generated/FieldList.qll 43c13c6e3c9ba75a7a4cb8 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/ForType.qll 3d43d044a1189281f09c55caafb6c8020a836f49e2866077086101925a573cf2 646b59bfd1b428aaf7211f574c49f79cb4c6a79ca151aa0663b2b31480298721 +lib/codeql/rust/elements/internal/generated/Format.qll 37ad20cf2bf363b4027a8913d095292c8a4eb8ccdf2a9965f2fb7d41930f9bfe 329b89cdd75ce951269273dd18897e32ff5cfcc94f451001c64143386c1e48dd 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/Function.qll f285ee0c771f897eba6db34a7e98f3cfb7db91b0df252ff4b37fc9d779de0bfb 07401e832565ff376acda219514c2e2bbe4ae5058c76a73b40ca6ca66f1626c7 lib/codeql/rust/elements/internal/generated/GenericArg.qll 464da0ba1c5ddcd1be68617167f177773d99b5ac4775ec8ea24d503e789a9099 6faa1033d59baf7c210ac4837a55781cfc054b7acbad8027faf4630dbfa6e101 lib/codeql/rust/elements/internal/generated/GenericArgList.qll b8cd936bba6f28344e28c98acf38acb8ef43af6ecf8367d79ed487e5b9da17cb 8b14331261e49d004807285b02fca190aafd62bfb9378b05c7d9c1e95525fe7b @@ -547,7 +555,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b 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 5fe79a0186d964592ba3f0c6e699a08ee6aa0a2a5462820d913c6b747ce10e36 ce3c5cd0cb5651eba00e97cb2c057e5c63d4c7c1a511311675389bd8fd5eb1bf +lib/codeql/rust/elements/internal/generated/ParentChild.qll b23c62ed9b5402b8c8ac81270c3d7710deb8a0fbc3dfd3f406a980f2d4886f1e 3c2e9618592c8da2be069d1b4fc32062866072d0c5f594bf2983edbd0c3223ce lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4 lib/codeql/rust/elements/internal/generated/Path.qll 299abce24762a5ab023f3cf1ab9718b83047e171aed42a8092e7a155914b1657 db1a23d18640c548f08c9f94823838b5e019ac85877c7b15df2d1493d1846572 lib/codeql/rust/elements/internal/generated/PathExpr.qll 17cdb0a7393258a207450f08e37178fc9d35d167f064ba6015be94246f3dc933 a75fdd280aff6d87e083a92030e041c2eb52b57cf7151d4a6989fcd31d6a64bf @@ -556,7 +564,7 @@ lib/codeql/rust/elements/internal/generated/PathSegment.qll 4621597fd86246f788b8 lib/codeql/rust/elements/internal/generated/PathType.qll 45de78e5374d6eb0446e2112ec72d3692c2811df9fa2ad03d0127e426940abe3 622cf70408413a565a0dac58f451035ac1339c8d0ee5b24f630680201cb0aa48 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 65b9266ae7f55d2cd64ed7440a75f9074dfefb9dde7a5b3ed78a71b726148c97 65b9266ae7f55d2cd64ed7440a75f9074dfefb9dde7a5b3ed78a71b726148c97 +lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll b8e03f4c85c5ec208c0ba57ab1be3b2fc80e0d122198571b5f95dffe247af79b b8e03f4c85c5ec208c0ba57ab1be3b2fc80e0d122198571b5f95dffe247af79b 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 429057964308876b8186a0ca901634273d91b783e4bb85aa5e47860010f4da0b feb8231d0b724fedb1d9d2a65d4a8759ae58baec902b44e3bebdb81a7fbc1fd1 @@ -584,8 +592,8 @@ 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 9513585ad92c4dc9070a73355778f16f3fb104cfc8589e438f0d39965bc2dcfd 34847da4b696dc41d57420f165b2fde5b5cdc8aaa958c50875fb3cbfbad8cb7a -lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 822945db0182edf1571f8fcba6b18fc11c017cd50a177ecc4772d68ca0e7154f 822945db0182edf1571f8fcba6b18fc11c017cd50a177ecc4772d68ca0e7154f +lib/codeql/rust/elements/internal/generated/Synth.qll 9707fb1875b20c0b98ada41e7007c5d66b122e8770e232fc75c3b50c74363a4d cce150b2f7fd99e6b771f52683fd93f3d8e10393d1b747a8b6a78620a487c64b +lib/codeql/rust/elements/internal/generated/SynthConstructors.qll 44355a9dd08cbb357907f1ff94333fc0ec946c315c3be34e34d82abbc47c9a68 44355a9dd08cbb357907f1ff94333fc0ec946c315c3be34e34d82abbc47c9a68 lib/codeql/rust/elements/internal/generated/Token.qll 77a91a25ca5669703cf3a4353b591cef4d72caa6b0b9db07bb9e005d69c848d1 2fdffc4882ed3a6ca9ac6d1fb5f1ac5a471ca703e2ffdc642885fa558d6e373b lib/codeql/rust/elements/internal/generated/TokenTree.qll 8577c2b097c1be2f0f7daa5acfcf146f78674a424d99563e08a84dd3e6d91b46 d2f30764e84dbfc0a6a5d3d8a5f935cd432413688cb32da9c94e420fbc10665c lib/codeql/rust/elements/internal/generated/Trait.qll a570fa93d0b78a35766b00d5ca256c102f824564248b9d8b678a981d6eea3e2e d9c7475e5102e21cfdee3b1791f89a4f9cdba5a4200349ff706532b704c02664 @@ -619,7 +627,7 @@ lib/codeql/rust/elements/internal/generated/WhileExpr.qll fec8a9211b82a80601bf73 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 9b838fb5bccee1cfd470ba62d3830790de120eaf05186f865aa885438c7fe5ff 9b838fb5bccee1cfd470ba62d3830790de120eaf05186f865aa885438c7fe5ff +lib/codeql/rust/elements.qll 478d84148363d1141a9c0bddd25b82ee1219c3f8a7872aaaa3388b83ee3a3ffd 478d84148363d1141a9c0bddd25b82ee1219c3f8a7872aaaa3388b83ee3a3ffd 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 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 2063a973ad80a..2f97b19b0163d 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -42,8 +42,10 @@ /lib/codeql/rust/elements/FnPtrType.qll linguist-generated /lib/codeql/rust/elements/ForExpr.qll linguist-generated /lib/codeql/rust/elements/ForType.qll linguist-generated +/lib/codeql/rust/elements/Format.qll linguist-generated /lib/codeql/rust/elements/FormatArgsArg.qll linguist-generated /lib/codeql/rust/elements/FormatArgsExpr.qll linguist-generated +/lib/codeql/rust/elements/FormatArgument.qll linguist-generated /lib/codeql/rust/elements/Function.qll linguist-generated /lib/codeql/rust/elements/GenericArg.qll linguist-generated /lib/codeql/rust/elements/GenericArgList.qll linguist-generated @@ -236,6 +238,10 @@ /lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll linguist-generated +/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll linguist-generated +/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll linguist-generated +/lib/codeql/rust/elements/internal/FormatConstructor.qll linguist-generated +/lib/codeql/rust/elements/internal/FormatImpl.qll linguist-generated /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 @@ -496,8 +502,10 @@ /lib/codeql/rust/elements/internal/generated/FnPtrType.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ForExpr.qll linguist-generated /lib/codeql/rust/elements/internal/generated/ForType.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/Format.qll linguist-generated /lib/codeql/rust/elements/internal/generated/FormatArgsArg.qll linguist-generated /lib/codeql/rust/elements/internal/generated/FormatArgsExpr.qll linguist-generated +/lib/codeql/rust/elements/internal/generated/FormatArgument.qll linguist-generated /lib/codeql/rust/elements/internal/generated/Function.qll linguist-generated /lib/codeql/rust/elements/internal/generated/GenericArg.qll linguist-generated /lib/codeql/rust/elements/internal/generated/GenericArgList.qll linguist-generated diff --git a/rust/ql/lib/codeql/rust/elements.qll b/rust/ql/lib/codeql/rust/elements.qll index 813ddac7bd2cf..6451298d8bcac 100644 --- a/rust/ql/lib/codeql/rust/elements.qll +++ b/rust/ql/lib/codeql/rust/elements.qll @@ -45,8 +45,10 @@ import codeql.rust.elements.FieldList import codeql.rust.elements.FnPtrType import codeql.rust.elements.ForExpr import codeql.rust.elements.ForType +import codeql.rust.elements.Format import codeql.rust.elements.FormatArgsArg import codeql.rust.elements.FormatArgsExpr +import codeql.rust.elements.FormatArgument import codeql.rust.elements.Function import codeql.rust.elements.GenericArg import codeql.rust.elements.GenericArgList diff --git a/rust/ql/lib/codeql/rust/elements/Format.qll b/rust/ql/lib/codeql/rust/elements/Format.qll new file mode 100644 index 0000000000000..0c8b5d1c54132 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/Format.qll @@ -0,0 +1,16 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `Format`. + */ + +private import internal.FormatImpl +import codeql.rust.elements.FormatArgsExpr +import codeql.rust.elements.Locatable + +/** + * A format element in a formatting template. For example the `{}` in: + * ```rust + * println!("Hello {}", "world"); + * ``` + */ +final class Format = Impl::Format; diff --git a/rust/ql/lib/codeql/rust/elements/FormatArgument.qll b/rust/ql/lib/codeql/rust/elements/FormatArgument.qll new file mode 100644 index 0000000000000..62313c5237275 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/FormatArgument.qll @@ -0,0 +1,20 @@ +// generated by codegen, do not edit +/** + * This module provides the public class `FormatArgument`. + */ + +private import internal.FormatArgumentImpl +import codeql.rust.elements.Format +import codeql.rust.elements.Locatable + +/** + * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: + * ```rust + * println!("Value {value:#width$.precision$}"); + * ``` + * or the `0`, `1` and `2` in: + * ```rust + * println!("Value {0:#1$.2$}", value, width, precision); + * ``` + */ +final class FormatArgument = Impl::FormatArgument; diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll new file mode 100644 index 0000000000000..9b72c80860733 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll @@ -0,0 +1,14 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `FormatArgument` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.Raw + +/** + * The characteristic predicate of `FormatArgument` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructFormatArgument(Raw::FormatArgsExpr parent, int index, int kind) { none() } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll new file mode 100644 index 0000000000000..c1d6ef1de6f1c --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll @@ -0,0 +1,39 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `FormatArgument`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.FormatArgument +private import codeql.rust.elements.internal.generated.Raw +private import codeql.rust.elements.internal.generated.Synth + +/** + * INTERNAL: This module contains the customizable definition of `FormatArgument` and should not + * be referenced directly. + */ +module Impl { + /** + * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: + * ```rust + * println!("Value {value:#width$.precision$}"); + * ``` + * or the `0`, `1` and `2` in: + * ```rust + * println!("Value {0:#1$.2$}", value, width, precision); + * ``` + */ + class FormatArgument extends Generated::FormatArgument { + cached + private Raw::FormatArgsExpr getUnderlyingParent() { + this = Synth::TFormatArgument(result, _, _) + } + + cached + private int getUnderlyingIndex() { this = Synth::TFormatArgument(_, result, _) } + + cached + private int getUnderlyingKind() { this = Synth::TFormatArgument(_, _, result) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll new file mode 100644 index 0000000000000..e238e69f5546b --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll @@ -0,0 +1,14 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module defines the hook used internally to tweak the characteristic predicate of + * `Format` synthesized instances. + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.Raw + +/** + * The characteristic predicate of `Format` synthesized instances. + * INTERNAL: Do not use. + */ +predicate constructFormat(Raw::FormatArgsExpr parent, int index) { none() } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll new file mode 100644 index 0000000000000..1f41597f61ef6 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll @@ -0,0 +1,30 @@ +// generated by codegen, remove this comment if you wish to edit this file +/** + * This module provides a hand-modifiable wrapper around the generated class `Format`. + * + * INTERNAL: Do not use. + */ + +private import codeql.rust.elements.internal.generated.Format +private import codeql.rust.elements.internal.generated.Raw +private import codeql.rust.elements.internal.generated.Synth + +/** + * INTERNAL: This module contains the customizable definition of `Format` and should not + * be referenced directly. + */ +module Impl { + /** + * A format element in a formatting template. For example the `{}` in: + * ```rust + * println!("Hello {}", "world"); + * ``` + */ + class Format extends Generated::Format { + cached + private Raw::FormatArgsExpr getUnderlyingParent() { this = Synth::TFormat(result, _) } + + cached + private int getUnderlyingIndex() { this = Synth::TFormat(_, result) } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll new file mode 100644 index 0000000000000..f2ade708ffaa4 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Format.qll @@ -0,0 +1,38 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `Format`. + * 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.FormatArgsExpr +import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl + +/** + * INTERNAL: This module contains the fully generated definition of `Format` and should not + * be referenced directly. + */ +module Generated { + /** + * A format element in a formatting template. For example the `{}` in: + * ```rust + * println!("Hello {}", "world"); + * ``` + * INTERNAL: Do not reference the `Generated::Format` class directly. + * Use the subclass `Format`, where the following predicates are available. + */ + class Format extends Synth::TFormat, LocatableImpl::Locatable { + override string getAPrimaryQlClass() { result = "Format" } + + /** + * Gets the parent of this format. + */ + FormatArgsExpr getParent() { none() } + + /** + * Gets the index of this format. + */ + int getIndex() { none() } + } +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll new file mode 100644 index 0000000000000..658d6b92e7a57 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/FormatArgument.qll @@ -0,0 +1,37 @@ +// generated by codegen, do not edit +/** + * This module provides the generated definition of `FormatArgument`. + * 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.Format +import codeql.rust.elements.internal.LocatableImpl::Impl as LocatableImpl + +/** + * INTERNAL: This module contains the fully generated definition of `FormatArgument` and should not + * be referenced directly. + */ +module Generated { + /** + * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: + * ```rust + * println!("Value {value:#width$.precision$}"); + * ``` + * or the `0`, `1` and `2` in: + * ```rust + * println!("Value {0:#1$.2$}", value, width, precision); + * ``` + * INTERNAL: Do not reference the `Generated::FormatArgument` class directly. + * Use the subclass `FormatArgument`, where the following predicates are available. + */ + class FormatArgument extends Synth::TFormatArgument, LocatableImpl::Locatable { + override string getAPrimaryQlClass() { result = "FormatArgument" } + + /** + * Gets the parent of this format argument. + */ + Format getParent() { none() } + } +} 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 f0967cd7263dc..ff8d2b460521f 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/ParentChild.qll @@ -51,6 +51,34 @@ private module Impl { ) } + private Element getImmediateChildOfFormat(Format e, int index, string partialPredicateCall) { + exists(int b, int bLocatable, int n | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFormatArgument( + FormatArgument e, int index, string partialPredicateCall + ) { + exists(int b, int bLocatable, int n | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + ) + ) + } + private Element getImmediateChildOfMissing(Missing e, int index, string partialPredicateCall) { exists(int b, int bUnextracted, int n | b = 0 and @@ -3474,6 +3502,10 @@ private module Impl { // * none() simplifies generation, as we can append `or ...` without a special case for the first item none() or + result = getImmediateChildOfFormat(e, index, partialAccessor) + or + result = getImmediateChildOfFormatArgument(e, index, partialAccessor) + or result = getImmediateChildOfMissing(e, index, partialAccessor) or result = getImmediateChildOfUnimplemented(e, index, partialAccessor) diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll index 2ed56ea512baf..72e1a2aa6ec53 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll @@ -3,4 +3,6 @@ * This module exports all modules providing `Element` subclasses. */ +import codeql.rust.elements.internal.FormatConstructor +import codeql.rust.elements.internal.FormatArgumentConstructor import codeql.rust.elements.internal.ImplicitVariableAccessConstructor 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 722e0ea844245..b693e68147973 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/Synth.qll @@ -150,6 +150,10 @@ module Synth { * INTERNAL: Do not use. */ TForType(Raw::ForType id) { constructForType(id) } or + /** + * INTERNAL: Do not use. + */ + TFormat(Raw::FormatArgsExpr parent, int index) { constructFormat(parent, index) } or /** * INTERNAL: Do not use. */ @@ -158,6 +162,12 @@ module Synth { * INTERNAL: Do not use. */ TFormatArgsExpr(Raw::FormatArgsExpr id) { constructFormatArgsExpr(id) } or + /** + * INTERNAL: Do not use. + */ + TFormatArgument(Raw::FormatArgsExpr parent, int index, int kind) { + constructFormatArgument(parent, index, kind) + } or /** * INTERNAL: Do not use. */ @@ -670,7 +680,7 @@ module Synth { /** * INTERNAL: Do not use. */ - class TLocatable = TAstNode; + class TLocatable = TAstNode or TFormat or TFormatArgument; /** * INTERNAL: Do not use. @@ -907,6 +917,12 @@ module Synth { */ TForType convertForTypeFromRaw(Raw::Element e) { result = TForType(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TFormat`, if possible. + */ + TFormat convertFormatFromRaw(Raw::Element e) { none() } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TFormatArgsArg`, if possible. @@ -919,6 +935,12 @@ module Synth { */ TFormatArgsExpr convertFormatArgsExprFromRaw(Raw::Element e) { result = TFormatArgsExpr(e) } + /** + * INTERNAL: Do not use. + * Converts a raw element to a synthesized `TFormatArgument`, if possible. + */ + TFormatArgument convertFormatArgumentFromRaw(Raw::Element e) { none() } + /** * INTERNAL: Do not use. * Converts a raw element to a synthesized `TFunction`, if possible. @@ -1915,7 +1937,13 @@ module Synth { * INTERNAL: Do not use. * Converts a raw DB element to a synthesized `TLocatable`, if possible. */ - TLocatable convertLocatableFromRaw(Raw::Element e) { result = convertAstNodeFromRaw(e) } + TLocatable convertLocatableFromRaw(Raw::Element e) { + result = convertAstNodeFromRaw(e) + or + result = convertFormatFromRaw(e) + or + result = convertFormatArgumentFromRaw(e) + } /** * INTERNAL: Do not use. @@ -2221,6 +2249,12 @@ module Synth { */ Raw::Element convertForTypeToRaw(TForType e) { e = TForType(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TFormat` to a raw DB element, if possible. + */ + Raw::Element convertFormatToRaw(TFormat e) { none() } + /** * INTERNAL: Do not use. * Converts a synthesized `TFormatArgsArg` to a raw DB element, if possible. @@ -2233,6 +2267,12 @@ module Synth { */ Raw::Element convertFormatArgsExprToRaw(TFormatArgsExpr e) { e = TFormatArgsExpr(result) } + /** + * INTERNAL: Do not use. + * Converts a synthesized `TFormatArgument` to a raw DB element, if possible. + */ + Raw::Element convertFormatArgumentToRaw(TFormatArgument e) { none() } + /** * INTERNAL: Do not use. * Converts a synthesized `TFunction` to a raw DB element, if possible. @@ -3229,7 +3269,13 @@ module Synth { * INTERNAL: Do not use. * Converts a synthesized `TLocatable` to a raw DB element, if possible. */ - Raw::Element convertLocatableToRaw(TLocatable e) { result = convertAstNodeToRaw(e) } + Raw::Element convertLocatableToRaw(TLocatable e) { + result = convertAstNodeToRaw(e) + or + result = convertFormatToRaw(e) + or + result = convertFormatArgumentToRaw(e) + } /** * INTERNAL: Do not use. diff --git a/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll b/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll index 9c61c2f67b16d..371bc8b720aac 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/generated/SynthConstructors.qll @@ -37,8 +37,10 @@ import codeql.rust.elements.internal.FieldExprConstructor import codeql.rust.elements.internal.FnPtrTypeConstructor import codeql.rust.elements.internal.ForExprConstructor import codeql.rust.elements.internal.ForTypeConstructor +import codeql.rust.elements.internal.FormatConstructor import codeql.rust.elements.internal.FormatArgsArgConstructor import codeql.rust.elements.internal.FormatArgsExprConstructor +import codeql.rust.elements.internal.FormatArgumentConstructor import codeql.rust.elements.internal.FunctionConstructor import codeql.rust.elements.internal.GenericArgListConstructor import codeql.rust.elements.internal.GenericParamListConstructor From 08b4b79cb7291c70c7ab3c89febc6cd7cf6721a0 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Fri, 18 Oct 2024 11:19:11 +0200 Subject: [PATCH 11/11] Rust: implement Format and FormatArgument classes --- rust/ql/.generated.list | 4 - rust/ql/.gitattributes | 4 - .../codeql/rust/elements/FormatTemplate.qll | 248 ------------------ .../rust/elements/NamedFormatArgument.qll | 7 + .../elements/PositionalFormatArgument.qll | 7 + .../elements/internal/FormatArgsExprImpl.qll | 2 +- .../internal/FormatArgumentConstructor.qll | 27 +- .../elements/internal/FormatArgumentImpl.qll | 63 ++++- .../elements/internal/FormatConstructor.qll | 68 ++++- .../rust/elements/internal/FormatImpl.qll | 68 ++++- .../ImplicitVariableAccessConstructor.qll | 3 +- .../internal/ImplicitVariableAccessImpl.qll | 3 +- rust/ql/lib/rust.qll | 3 +- 13 files changed, 230 insertions(+), 277 deletions(-) delete mode 100644 rust/ql/lib/codeql/rust/elements/FormatTemplate.qll create mode 100644 rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll create mode 100644 rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll diff --git a/rust/ql/.generated.list b/rust/ql/.generated.list index a8450ac3d0148..4db40d43f2f09 100644 --- a/rust/ql/.generated.list +++ b/rust/ql/.generated.list @@ -236,10 +236,6 @@ lib/codeql/rust/elements/internal/ForTypeImpl.qll b515639844778d0fbe51e6161a2ec1 lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll 8bd9b4e035ef8adeb3ac510dd68043934c0140facb933be1f240096d01cdfa11 74e9d3bbd8882ae59a7e88935d468e0a90a6529a4e2af6a3d83e93944470f0ee lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll 601f7715e9a65bcfa7cea1979fa30d694b5bea29650d799d7dd3080b8eea58e9 ecb0800cdb8c0f93277982dad295ac6a5332e42eff4fb5c8ff19f903b9857003 lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll ce29ff5a839b885b1ab7a02d6a381ae474ab1be3e6ee7dcfd7595bdf28e4b558 63bf957426871905a51ea319662a59e38104c197a1024360aca364dc145b11e8 -lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll dea59a9e64681583b2b57c60b1d71f567af9d490bfd60a4cb118201c0e45e0bd aeeaffa43919ae7fed76c0a4be74547c657dc530c2af0fd94bc0c95cbf5a8194 -lib/codeql/rust/elements/internal/FormatArgumentImpl.qll e8115612cf08af743545e36091c4d06f00eb5ece8da8eee534bf3d269432da1c 88cae5f265f85f20f96ca2fdb7d353463ef16eebc6e86dd2ab023bc4f36f35f7 -lib/codeql/rust/elements/internal/FormatConstructor.qll 21cb51ec160d04cd4539d9c9488a21ac2a5d6a1eb35670429f7da1a6676d7d46 bcb7231ae549ec86d33581f5c89a4c346c190a02ed96fa7acd0ecba77240419e -lib/codeql/rust/elements/internal/FormatImpl.qll 4cebae0a808c68577976f38e45ae4bcb4d31ae3875afc36f560bfa23e5df3a83 67e0afd957254966f874af1137da1f293570f1fec519650a2572c0a932f5258f 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 diff --git a/rust/ql/.gitattributes b/rust/ql/.gitattributes index 2f97b19b0163d..13abe120cc739 100644 --- a/rust/ql/.gitattributes +++ b/rust/ql/.gitattributes @@ -238,10 +238,6 @@ /lib/codeql/rust/elements/internal/FormatArgsArgConstructor.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsArgImpl.qll linguist-generated /lib/codeql/rust/elements/internal/FormatArgsExprConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatConstructor.qll linguist-generated -/lib/codeql/rust/elements/internal/FormatImpl.qll linguist-generated /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 diff --git a/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll b/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll deleted file mode 100644 index a2c7138fde283..0000000000000 --- a/rust/ql/lib/codeql/rust/elements/FormatTemplate.qll +++ /dev/null @@ -1,248 +0,0 @@ -/** - * This module provides the classes modeling formatting templates. See also https://doc.rust-lang.org/std/fmt - */ - -private import FormatArgsExpr -private import LiteralExpr - -/** - * A regular expression for matching format elements in a formatting template. The - * regular expression is generated from the following python code: - * - * ```python - * identifier = "([A-Za-z_][A-Za-z0-9_]*)" - * integer = "([0-9]+)" - * - * # argument := integer | identifier - * argument = "({integer}|{identifier})".format(integer=integer, identifier=identifier) - * - * # parameter := argument '$' - * parameter = "(({argument})\\$)".format(argument=argument) - * - * # count := parameter | integer - * count = "({parameter}|{integer})".format(integer=integer, parameter=parameter) - * - * # fill := character - * fill = "(.)" - * - * # align := '<' | '^' | '>' - * align = "([<^>])" - * - * # sign := '+' | '-' - * sign = "([+-])" - * - * # width := count - * width = count - * - * # precision := count | '*' - * precision = "({count}|(\\*))".format(count=count) - * - * # type := '' | '?' | 'x?' | 'X?' | identifier - * type = "(|\\?|x\\?|X\\?|{identifier})".format(identifier=identifier) - * - * # format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type - * format_spec = "({fill}?{align})?{sign}?(#)?(0)?{width}?(\\.{precision})?{type}".format(fill=fill, align=align, sign=sign, width=width, precision=precision, type=type) - * - * # format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' - * format = "(\\{{{argument}?(:{format_spec})?\s*}\\})".format(argument=argument, format_spec=format_spec) - * - * ``` - */ -private string formatRegex() { - result = - "(\\{(([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))?(:((.)?([<^>]))?([+-])?(#)?(0)?(((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))?(\\.((((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))|(\\*)))?(|\\?|x\\?|X\\?|([A-Za-z_][A-Za-z0-9_]*)))?\\s*\\})" -} - -private string textRegex() { result = "([^{}]|\\{\\{|\\}\\})+" } - -private string part(FormatArgsExpr parent, int occurrenceIndex, int occurrenceOffset) { - result = - parent - .getTemplate() - .(LiteralExpr) - .getTextValue() - // TODO: should also handle surrounding quotes and escaped characters - .regexpFind(textRegex() + "|" + formatRegex(), occurrenceIndex, occurrenceOffset) -} - -private newtype TFormatTemplateElem = - TFormat(FormatArgsExpr parent, string text, int index, int offset) { - text = part(parent, index, offset) and text.regexpMatch(formatRegex()) - } - -private newtype TFormatArgumentKind = - TElement() or - TWidth() or - TPrecision() - -private newtype TFormatArgumentT = - TFormatArgument( - TFormat parent, TFormatArgumentKind kind, string value, boolean positional, int offset - ) { - exists(string text, int formatOffset, int group | - group = [3, 4] and offset = formatOffset + 1 and kind = TElement() - or - group = [15, 16] and - offset = formatOffset + min(text.indexOf(value + "$")) and - kind = TWidth() - or - group = [23, 24] and - offset = formatOffset + max(text.indexOf(value + "$")) and - kind = TPrecision() - | - parent = TFormat(_, text, _, formatOffset) and - value = text.regexpCapture(formatRegex(), group) and - if group % 2 = 1 then positional = true else positional = false - ) - } - -/** - * A format element in a formatting template. For example the `{}` in: - * ```rust - * println!("Hello {}", "world"); - * ``` - */ -class Format extends TFormat { - private FormatArgsExpr parent; - private string text; - private int index; - private int offset; - - Format() { this = TFormat(parent, text, index, offset) } - - /** Gets a textual representation of this element. */ - string toString() { result = text } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - parent - .getTemplate() - .getLocation() - .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and - endline = startline and - endcolumn = startcolumn + text.length() - 1 - } - - /** Gets a the parent of this `Format`. */ - FormatArgsExpr getParent() { result = parent } - - /** Gets the index of this `Format` node. */ - int getIndex() { result = index } - - /** - * Gets the name or position reference of this format, if any. For example `name` and `0` in: - * ```rust - * let name = "Alice"; - * println!("{name} in wonderland"); - * println!("{0} in wonderland", name); - * ``` - */ - FormatArgument getArgumentRef() { - result.getParent() = this and result = TFormatArgument(_, TElement(), _, _, _) - } - - /** - * Gets the name or position reference of the width parameter in this format, if any. For example `width` and `1` in: - * ```rust - * let width = 6; - * println!("{:width$}", PI); - * println!("{:1$}", PI, width); - * ``` - */ - FormatArgument getWidthArgument() { - result.getParent() = this and result = TFormatArgument(_, TWidth(), _, _, _) - } - - /** - * Gets the name or position reference of the width parameter in this format, if any. For example `prec` and `1` in: - * ```rust - * let prec = 6; - * println!("{:.prec$}", PI); - * println!("{:.1$}", PI, prec); - * ``` - */ - FormatArgument getPrecisionArgument() { - result.getParent() = this and result = TFormatArgument(_, TPrecision(), _, _, _) - } -} - -/** - * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: - * ```rust - * println!("Value {value:#width$.precision$}"); - * ``` - * or the `0`, `1` and `2` in: - * ```rust - * println!("Value {0:#1$.2$}", value, width, precision); - * ``` - */ -class FormatArgument extends TFormatArgumentT { - private Format parent; - string name; - private int offset; - - FormatArgument() { this = TFormatArgument(parent, _, name, _, offset) } - - /** Gets a textual representation of this element. */ - string toString() { result = name } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Providing locations in CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - // TODO: handle locations in multi-line comments - // TODO: handle the case where the template is from a nested macro call - parent - .getParent() - .getTemplate() - .getLocation() - .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and - endline = startline and - endcolumn = startcolumn + name.length() - 1 - } - - /** Gets a the parent of this `FormatArgument`. */ - Format getParent() { result = parent } -} - -/** - * A positional `FormatArgument`. For example `0` in - * ```rust - * let name = "Alice"; - * println!("{0} in wonderland", name); - * ``` - */ -class PositionalFormatArgument extends FormatArgument { - PositionalFormatArgument() { this = TFormatArgument(_, _, _, true, _) } - - /** Gets the index of this positional argument */ - int getIndex() { result = name.toInt() } -} - -/** - * A named `FormatArgument`. For example `name` in - * ```rust - * let name = "Alice"; - * println!("{name} in wonderland"); - * ``` - */ -class NamedFormatArgument extends FormatArgument { - NamedFormatArgument() { this = TFormatArgument(_, _, _, false, _) } - - /** Gets the name of this named argument */ - string getName() { result = name } -} diff --git a/rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll b/rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll new file mode 100644 index 0000000000000..ff22b67454366 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/NamedFormatArgument.qll @@ -0,0 +1,7 @@ +/** + * This module provides the public class `NamedFormatArgument`. + */ + +private import internal.FormatArgumentImpl + +final class NamedFormatArgument = Impl::NamedFormatArgument; diff --git a/rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll b/rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll new file mode 100644 index 0000000000000..e5fc88b14c4b3 --- /dev/null +++ b/rust/ql/lib/codeql/rust/elements/PositionalFormatArgument.qll @@ -0,0 +1,7 @@ +/** + * This module provides the public class `PositionalFormatArgument`. + */ + +private import internal.FormatArgumentImpl + +final class PositionalFormatArgument = Impl::PositionalFormatArgument; diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll index 7524a385e9efb..667439777b1ab 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgsExprImpl.qll @@ -5,7 +5,7 @@ */ private import codeql.rust.elements.internal.generated.FormatArgsExpr -private import codeql.rust.elements.FormatTemplate +private import codeql.rust.elements.Format /** * INTERNAL: This module contains the customizable definition of `FormatArgsExpr` and should not diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll index 9b72c80860733..d7b801f3dd9d8 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentConstructor.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module defines the hook used internally to tweak the characteristic predicate of * `FormatArgument` synthesized instances. @@ -6,9 +5,33 @@ */ private import codeql.rust.elements.internal.generated.Raw +private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.FormatConstructor /** * The characteristic predicate of `FormatArgument` synthesized instances. * INTERNAL: Do not use. */ -predicate constructFormatArgument(Raw::FormatArgsExpr parent, int index, int kind) { none() } +predicate constructFormatArgument(Raw::FormatArgsExpr parent, int index, int kind) { + formatArgument(parent, index, kind, _, _, _) +} + +predicate formatArgument( + Raw::FormatArgsExpr parent, int index, int kind, string value, boolean positional, int offset +) { + exists(string text, int formatOffset, int group | + group = [3, 4] and offset = formatOffset + 1 and kind = 0 + or + group = [15, 16] and + offset = formatOffset + min(text.indexOf(value + "$")) and + kind = 1 + or + group = [23, 24] and + offset = formatOffset + max(text.indexOf(value + "$")) and + kind = 2 + | + text = formatElement(parent, index, formatOffset) and + value = text.regexpCapture(formatRegex(), group) and + if group % 2 = 1 then positional = true else positional = false + ) +} diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll index c1d6ef1de6f1c..6230c394ee5d8 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatArgumentImpl.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 `FormatArgument`. * @@ -8,12 +7,14 @@ private import codeql.rust.elements.internal.generated.FormatArgument private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.FormatArgumentConstructor /** * INTERNAL: This module contains the customizable definition of `FormatArgument` 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 /** * An argument in a format element in a formatting template. For example the `width`, `precision`, and `value` in: * ```rust @@ -25,15 +26,61 @@ module Impl { * ``` */ class FormatArgument extends Generated::FormatArgument { - cached - private Raw::FormatArgsExpr getUnderlyingParent() { - this = Synth::TFormatArgument(result, _, _) + Raw::FormatArgsExpr parent; + int index; + int kind; + string name; + private int offset; + + FormatArgument() { + this = Synth::TFormatArgument(parent, index, kind) and + formatArgument(parent, index, kind, name, _, offset) } - cached - private int getUnderlyingIndex() { this = Synth::TFormatArgument(_, result, _) } + override string toString() { result = name } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + // TODO: handle locations in multi-line comments + // TODO: handle the case where the template is from a nested macro call + Synth::convertFormatArgsExprFromRaw(parent) + .(FormatArgsExpr) + .getTemplate() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and + endline = startline and + endcolumn = startcolumn + name.length() - 1 + } + + override Format getParent() { result = Synth::TFormat(parent, index) } + } + + /** + * A positional `FormatArgument`. For example `0` in + * ```rust + * let name = "Alice"; + * println!("{0} in wonderland", name); + * ``` + */ + class PositionalFormatArgument extends FormatArgument { + PositionalFormatArgument() { formatArgument(parent, index, kind, _, true, _) } + + /** Gets the index of this positional argument */ + int getIndex() { result = name.toInt() } + } + + /** + * A named `FormatArgument`. For example `name` in + * ```rust + * let name = "Alice"; + * println!("{name} in wonderland"); + * ``` + */ + class NamedFormatArgument extends FormatArgument { + NamedFormatArgument() { formatArgument(parent, index, kind, _, false, _) } - cached - private int getUnderlyingKind() { this = Synth::TFormatArgument(_, _, result) } + /** Gets the name of this named argument */ + string getName() { result = name } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll index e238e69f5546b..6ffd3b177f3d9 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatConstructor.qll @@ -1,4 +1,3 @@ -// generated by codegen, remove this comment if you wish to edit this file /** * This module defines the hook used internally to tweak the characteristic predicate of * `Format` synthesized instances. @@ -11,4 +10,69 @@ private import codeql.rust.elements.internal.generated.Raw * The characteristic predicate of `Format` synthesized instances. * INTERNAL: Do not use. */ -predicate constructFormat(Raw::FormatArgsExpr parent, int index) { none() } +predicate constructFormat(Raw::FormatArgsExpr parent, int index) { + formatElement(parent, index, _).regexpMatch(formatRegex()) +} + +/** + * Match an element of a format string, either text (`Hello`) or a format placeholder (`{}`). + */ +string formatElement(Raw::FormatArgsExpr parent, int occurrenceIndex, int occurrenceOffset) { + result = + parent + .getTemplate() + .(Raw::LiteralExpr) + .getTextValue() + // TODO: should also handle surrounding quotes and escaped characters + .regexpFind(textRegex() + "|" + formatRegex(), occurrenceIndex, occurrenceOffset) +} + +/** + * A regular expression for matching format elements in a formatting template. The + * regular expression is generated from the following python code: + * + * ```python + * identifier = "([A-Za-z_][A-Za-z0-9_]*)" + * integer = "([0-9]+)" + * + * # argument := integer | identifier + * argument = "({integer}|{identifier})".format(integer=integer, identifier=identifier) + * + * # parameter := argument '$' + * parameter = "(({argument})\\$)".format(argument=argument) + * + * # count := parameter | integer + * count = "({parameter}|{integer})".format(integer=integer, parameter=parameter) + * + * # fill := character + * fill = "(.)" + * + * # align := '<' | '^' | '>' + * align = "([<^>])" + * + * # sign := '+' | '-' + * sign = "([+-])" + * + * # width := count + * width = count + * + * # precision := count | '*' + * precision = "({count}|(\\*))".format(count=count) + * + * # type := '' | '?' | 'x?' | 'X?' | identifier + * type = "(|\\?|x\\?|X\\?|{identifier})".format(identifier=identifier) + * + * # format_spec := [[fill]align][sign]['#']['0'][width]['.' precision]type + * format_spec = "({fill}?{align})?{sign}?(#)?(0)?{width}?(\\.{precision})?{type}".format(fill=fill, align=align, sign=sign, width=width, precision=precision, type=type) + * + * # format := '{' [ argument ] [ ':' format_spec ] [ ws ] * '}' + * format = "(\\{{{argument}?(:{format_spec})?\s*}\\})".format(argument=argument, format_spec=format_spec) + * + * ``` + */ +string formatRegex() { + result = + "(\\{(([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))?(:((.)?([<^>]))?([+-])?(#)?(0)?(((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))?(\\.((((([0-9]+)|([A-Za-z_][A-Za-z0-9_]*))\\$)|([0-9]+))|(\\*)))?(|\\?|x\\?|X\\?|([A-Za-z_][A-Za-z0-9_]*)))?\\s*\\})" +} + +private string textRegex() { result = "([^{}]|\\{\\{|\\}\\})+" } diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll index 1f41597f61ef6..e2ff2ece42c32 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatImpl.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 `Format`. * @@ -8,12 +7,15 @@ private import codeql.rust.elements.internal.generated.Format private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth +private import codeql.rust.elements.internal.FormatConstructor +import codeql.rust.elements.FormatArgument /** * INTERNAL: This module contains the customizable definition of `Format` 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 format element in a formatting template. For example the `{}` in: * ```rust @@ -21,10 +23,66 @@ module Impl { * ``` */ class Format extends Generated::Format { - cached - private Raw::FormatArgsExpr getUnderlyingParent() { this = Synth::TFormat(result, _) } + private Raw::FormatArgsExpr parent; + private string text; + private int index; + private int offset; - cached - private int getUnderlyingIndex() { this = Synth::TFormat(_, result) } + Format() { + this = Synth::TFormat(parent, index) and text = formatElement(parent, index, offset) + } + + override string toString() { result = text } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getParent() + .getTemplate() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn - offset, _, _) and + endline = startline and + endcolumn = startcolumn + text.length() - 1 + } + + override FormatArgsExpr getParent() { result = Synth::convertFormatArgsExprFromRaw(parent) } + + override int getIndex() { result = index } + + /** + * Gets the name or position reference of this format, if any. For example `name` and `0` in: + * ```rust + * let name = "Alice"; + * println!("{name} in wonderland"); + * println!("{0} in wonderland", name); + * ``` + */ + FormatArgument getArgumentRef() { + result.getParent() = this and result = Synth::TFormatArgument(_, _, 0) + } + + /** + * Gets the name or position reference of the width parameter in this format, if any. For example `width` and `1` in: + * ```rust + * let width = 6; + * println!("{:width$}", PI); + * println!("{:1$}", PI, width); + * ``` + */ + FormatArgument getWidthArgument() { + result.getParent() = this and result = Synth::TFormatArgument(_, _, 1) + } + + /** + * Gets the name or position reference of the width parameter in this format, if any. For example `prec` and `1` in: + * ```rust + * let prec = 6; + * println!("{:.prec$}", PI); + * println!("{:.1$}", PI, prec); + * ``` + */ + FormatArgument getPrecisionArgument() { + result.getParent() = this and result = Synth::TFormatArgument(_, _, 2) + } } } diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll index 9515e1cd82af2..0ecf191795c9a 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessConstructor.qll @@ -6,7 +6,8 @@ private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth -private import codeql.rust.elements.FormatTemplate +private import codeql.rust.elements.Format +private import codeql.rust.elements.NamedFormatArgument /** * The characteristic predicate of `ImplicitVariableAccess` synthesized instances. diff --git a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll index abc74771d6b35..4ab1ee5a5da63 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/ImplicitVariableAccessImpl.qll @@ -8,7 +8,8 @@ private import codeql.rust.elements.internal.generated.ImplicitVariableAccess private import codeql.rust.elements.internal.ImplicitVariableAccessConstructor private import codeql.rust.elements.internal.generated.Raw private import codeql.rust.elements.internal.generated.Synth -private import codeql.rust.elements.FormatTemplate +private import codeql.rust.elements.Format +private import codeql.rust.elements.NamedFormatArgument /** * INTERNAL: This module contains the customizable definition of `ImplicitVariableAccess` and should not diff --git a/rust/ql/lib/rust.qll b/rust/ql/lib/rust.qll index 45e593ed56e9d..c61e177883eac 100644 --- a/rust/ql/lib/rust.qll +++ b/rust/ql/lib/rust.qll @@ -6,4 +6,5 @@ import codeql.files.FileSystem import codeql.rust.elements.AssignmentOperation import codeql.rust.elements.LogicalOperation import codeql.rust.elements.Variable -import codeql.rust.elements.FormatTemplate +import codeql.rust.elements.NamedFormatArgument +import codeql.rust.elements.PositionalFormatArgument