Skip to content

PayloadCodegen.FindObject bare-name match can pick the wrong object.value on cross-package short-name collision #219

Description

@dmealing

Context

Discovered while reviewing #389255c57 (fix(csharp): payload-generator resolves bare @payloadRef in a named package).

PayloadCodegen.FindObject (server/csharp/MetaObjects.Codegen/PayloadCodegen.cs:44) matches an object.value by bare short name only:

private static MetaData? FindObject(MetaData root, string name) =>
    root.Children().FirstOrDefault(c => c.Type == TYPE_OBJECT && c.Name == name);

The just-merged fix strips the package qualifier off a resolved @payloadRef before calling FindObject — correct for the common case, but it means the top-level payload lookup now inherits the same cross-package short-name collision risk that fixtures/template-output-render-conformance/xpkg-collision/ was built to describe (see that fixture's README: "the two colliding VOs share the BARE payload-record type name Note; each port's runner hand-authors ... the payload record for that reason").

Failure scenario

Two different packages each declare an object.value named Note with different fields. A template.output's bare @payloadRef resolves (ADR-0042) to pkgB::Note, gets stripped to Note, and FindObject returns whichever Note root.Children() enumerates first — silently emitting the WRONG package's shape under the right file/record name, with no error.

Note

This is a pre-existing, systemic characteristic of the C# port's bare-name-match convention — the SAME pattern (CSharpNaming.StripPkg + bare FindObject) is used by ~7 other generators (RoutesGenerator, EntityGenerator, M2MNavigation, OutputParserGenerator, DbContextGenerator, ReverseFinders, PackageBindingResolver), so this isn't unique to PayloadCodegen — fixing it properly likely means auditing/fixing the pattern port-wide, not just here. PayloadCodegen already has an FQN-exact resolver (ResolveObjectRef, used by the verify field-tree path) that could be a model for a safer variant.

Suggested fix direction

Prefer FQN-exact resolution when the ref contains :: (mirroring ResolveObjectRef's own logic) before falling back to bare-name match, across the affected generators — scoped as its own effort given the number of call sites.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions