Skip to content

Precompiled query generation emits expression variable names verbatim, producing invalid C# for names that are not identifiers #39061

Description

@philcarbone

Bug description

LinqToCSharpSyntaxTranslator turns EF's shaper expression trees into C# for precompiled queries. Block variables and lambda parameters keep the names they were given when the expression tree was built. The translator uniquifies those names (UniquifyVariableName) but does not check that they are valid identifiers, and emits them directly (VariableDeclarator(Identifier(name))).

Expression tree variable names are arbitrary strings. In the relational shaper some are derived from model configuration: the JSON materializer names runtime constants after JSON property names (already sanitized by PrecompiledQueryCodeGenerator.SanitizeIdentifierName, see Invalid_identifier_json_property_name), and any block variable named the same way is emitted unsanitized. During review of #39014, a block variable named <jsonPropertyName>Read for a complex collection whose JSON name was 1!NOT VALID COLLECTION; produced:

Test.EFInterceptors.InvalidNameContext.g.cs(127,26): error CS1001: Identifier expected

That PR avoided the problem by leaving the variable unnamed, but the translator remains one named variable away from the same failure.

Expected behavior

Any variable or parameter name the translator emits is a valid C# identifier, the same way runtime constant names already are (1!NOT VALID; becomes _1_NOT_VALID_).

Proposed fix

Move the identifier sanitizer from PrecompiledQueryCodeGenerator into LinqToCSharpSyntaxTranslator as a shared method and apply it in UniquifyVariableName, which every emitted variable and lambda parameter name already passes through. The generator calls the shared method for runtime constants. One translator unit test:

var i = Parameter(typeof(int), "1!not valid;");
AssertStatement(Block(variables: [i], Assign(i, Constant(3))), """
{
    var _1_not_valid_ = 3;
}
""");

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions