From ec063d0dbdc9d20ba7e50f2d84b3f5f5cac5069c Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 5 Mar 2025 20:56:27 +0100 Subject: [PATCH] Rust: Fix bad joins ``` Evaluated relational algebra for predicate _Synth::Synth::TFormatArgument#5cbf2ffd_63#join_rhs__Format::Format.getArgumentRef/0#dispred#38d664c__#antijoin_rhs@889ee4br with tuple counts: 11356 ~0% {5} r1 = JOIN `_Format::Format.getArgumentRef/0#dispred#38d664cb_Format::Format.getParent/0#dispred#f6ec3e8b_10#joi__#shared` WITH Synth::Synth::TFormatArgument#5cbf2ffd_63#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.0 19631351 ~0% {6} | JOIN WITH name_texts_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.0 45933 ~0% {6} | JOIN WITH format_args_arg_names_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5 747 ~0% {5} | JOIN WITH format_args_expr_args_02#join_rhs ON FIRST 2 OUTPUT Lhs.0, Lhs.2, Lhs.3, Lhs.4, Lhs.5 return r1 Evaluated relational algebra for predicate __Format::Format.getParent/0#dispred#f6ec3e8b_FormatArgument::FormatArgument.getParent/0#dispred#864__#antijoin_rhs@01d9d70k with tuple counts: 19631351 ~1% {6} r1 = JOIN `_Format::Format.getParent/0#dispred#f6ec3e8b_FormatArgument::FormatArgument.getParent/0#dispred#8641__#shared` WITH name_texts_10#join_rhs ON FIRST 1 OUTPUT Lhs.4, Lhs.0, Lhs.1, Lhs.2, Lhs.3, Rhs.1 5173010 ~0% {7} | JOIN WITH format_args_expr_args ON FIRST 1 OUTPUT Rhs.2, Lhs.5, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.0 747 ~0% {5} | JOIN WITH format_args_arg_names ON FIRST 2 OUTPUT Lhs.2, Lhs.3, Lhs.4, Lhs.5, Lhs.6 return r1 Evaluated relational algebra for predicate _NamedFormatArgument::NamedFormatArgument#18940f8e__Format::Format.getParent/0#dispred#f6ec3e8b_10#j__#antijoin_rhs@dafbd6hr with tuple counts: 11356 ~0% {5} r1 = JOIN `_Format::Format.getParent/0#dispred#f6ec3e8b_10#join_rhs_FormatArgument::FormatArgument.getParent/0#__#shared` WITH NamedFormatArgument::NamedFormatArgument#18940f8e ON FIRST 1 OUTPUT Rhs.4, Lhs.1, Lhs.2, Lhs.3, Lhs.0 19631351 ~0% {6} | JOIN WITH name_texts_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.0 45933 ~0% {6} | JOIN WITH format_args_arg_names_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1, Lhs.2, Lhs.3, Lhs.4, Lhs.5 747 ~0% {5} | JOIN WITH format_args_expr_args_02#join_rhs ON FIRST 2 OUTPUT Lhs.0, Lhs.2, Lhs.3, Lhs.4, Lhs.5 return r1 ``` --- ...ormatTemplateVariableAccessConstructor.qll | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/rust/ql/lib/codeql/rust/elements/internal/FormatTemplateVariableAccessConstructor.qll b/rust/ql/lib/codeql/rust/elements/internal/FormatTemplateVariableAccessConstructor.qll index 7682d14ce46c..40cb174a0710 100644 --- a/rust/ql/lib/codeql/rust/elements/internal/FormatTemplateVariableAccessConstructor.qll +++ b/rust/ql/lib/codeql/rust/elements/internal/FormatTemplateVariableAccessConstructor.qll @@ -17,17 +17,13 @@ predicate constructFormatTemplateVariableAccess(Raw::FormatArgsExpr parent, int unboundNamedFormatArgument(parent, index, kind, _) } -/** - * 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 +pragma[nomagic] +private predicate formatArgsHasArg( + Raw::FormatArgsExpr parent, NamedFormatArgument arg, string name, int index, int kind ) { - exists(Format format, string name | - not parent.getArg(_).getName().getText() = name and + exists(Format format | + parent = Synth::convertFormatArgsExprToRaw(format.getParent()) and name = arg.getName() and - Synth::convertFormatArgsExprToRaw(format.getParent()) = parent and format.getIndex() = index | arg = format.getArgumentRef() and kind = 0 @@ -37,3 +33,21 @@ predicate unboundNamedFormatArgument( arg = format.getPrecisionArgument() and kind = 2 ) } + +pragma[nomagic] +private predicate formatArgsHasArgName(Raw::FormatArgsExpr parent, string name) { + parent.getArg(_).getName().getText() = name +} + +/** + * 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(string name | + formatArgsHasArg(parent, arg, name, index, kind) and + not formatArgsHasArgName(parent, name) + ) +}