From 0a09c68a0f05fa44d1a97046e8b09cb5c0d97956 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Sat, 10 Jan 2026 18:58:48 +0100 Subject: [PATCH] Harden parameter name selection in the funcletizer --- .../Internal/ExpressionTreeFuncletizer.cs | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs b/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs index b4e927adf85..e04943567e5 100644 --- a/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs +++ b/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs @@ -2078,14 +2078,24 @@ bool PreserveConvertNode(Expression expression) { var value = EvaluateCore(expression, ref evaluateAsParameter, out var tempParameterName, out isContextAccessor); - if (evaluateAsParameter) + if (!evaluateAsParameter) + { + parameterName = string.Empty; + return value; + } + + if (tempParameterName is null) { - parameterName = string.IsNullOrWhiteSpace(tempParameterName) ? "p" : tempParameterName; + parameterName = "p"; + } + else + { + parameterName = tempParameterName; // The VB compiler prefixes closure member names with $VB$Local_, remove that (#33150) if (parameterName.StartsWith("$VB$Local_", StringComparison.Ordinal)) { - parameterName = parameterName.Substring("$VB$Local_".Length); + parameterName = parameterName["$VB$Local_".Length..]; } // In many databases, parameter names must start with a letter or underscore. @@ -2096,15 +2106,21 @@ bool PreserveConvertNode(Expression expression) parameterName = "_" + parameterName; } - parameterName = Uniquifier.Uniquify(parameterName, _parameterNames, maxLength: int.MaxValue, uniquifier: _parameterNames.Count); - - _parameterNames.Add(parameterName); - } - else - { - parameterName = string.Empty; + // Just as a safety guard, if there's any problematic character in the name for any reason, fall back to "p". + foreach (var c in parameterName) + { + if (!char.IsLetterOrDigit(c) && c != '_') + { + parameterName = "p"; + break; + } + } } + parameterName = Uniquifier.Uniquify(parameterName, _parameterNames, maxLength: int.MaxValue, uniquifier: _parameterNames.Count); + + _parameterNames.Add(parameterName); + return value; object? EvaluateCore(Expression? expression, ref bool evaluateAsParameter, out string? parameterName, out bool isContextAccessor)