Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReferenceLoopHandling.Ignore unexpectedly skips objects - false positive if Equals/HashCode result is the same #2979

Open
janseris opened this issue Aug 23, 2024 · 0 comments

Comments

@janseris
Copy link

janseris commented Aug 23, 2024

This is probably directly related to: #401
The serializer detects false positive "reference loops" when there are more objects with the same Equals/Hashcode and not actually any reference loop.
This is a bug.
When ReferenceLoopHandling.Error is used, these false positives are blocking the code from executing.
When ReferenceLoopHandling.Serialize is used, I receive access denied and crash.
When ReferenceLoopHandling.Ignore is used, such objects are not serialized (skipped).
I think the very dangerous error here might be that even if it's not the same BaseClass which causes my code to have false positive "reference loops" (actually matching Equals/Hashcode result), this can happen for random code where Equals/Hashcode collides because there are just 4 billion possible results and the collision can happen.

public class Building : NamedEntity
{
    public BuildingType Type { get; set; }
}

public class NamedEntity : INamedEntity 
{
}

public interface INamedEntity : IEntity, INamed
{
        public virtual int ID { get; set; }
        public virtual string Name { get; set; }

        public override bool Equals(object obj)
        {
            return obj is NamedEntity entity &&
                   ID == entity.ID;
        }

        public override int GetHashCode()
        {
            return 1213502048 + ID.GetHashCode();
        }
}

public interface IEntity
{
    int ID { get; set; }
}

public interface INamed
{
    string Name { get; set; }
}

public class BuildingType : NamedEntity
{
    public string Code { get; set; }
}

When Building ID 100 contains BuildingType ID 100 in original data, then the object BuildingType in Building ID 100 is not added to serialized JSON.

Similar situation:

public class GlobalRole : NamedEntity
{
        public List<GlobalUserRight> Rights { get; set; }
}

public class GlobalUserRight : NamedEntity 
{
}

When GlobalRole ID 1 contains GlobalRight ID 1, it is not serialized into the list of global rights (the one object with ID 1 is skipped).

Expected behavior

Objects are not skipped
I suppose this is not a reference loop.
There is no loop in 1:1 relation where 1 object contains another object and in 1:N where 1 object contains N objects.
The inner object does not have any reference back to the outer object so there cannot be reference loop.

Actual behavior

Objects are skipped

Steps to reproduce

default ASP.NET Core Web API serialization
with this setting:
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

@janseris janseris changed the title Nested object is not serialized if it has the same ID as parent object Nested object is not serialized if it has the same ID as parent object and implements the same base class Aug 23, 2024
@janseris janseris changed the title Nested object is not serialized if it has the same ID as parent object and implements the same base class Nested object is not serialized if it has the same ID as parent object and implements the same base class with ReferenceLoopHandling.Ignore Aug 23, 2024
@janseris janseris changed the title Nested object is not serialized if it has the same ID as parent object and implements the same base class with ReferenceLoopHandling.Ignore ReferenceLoopHandling.Ignore unexpectedly skips objects - nested object is not serialized if it has the same ID as parent object and implements the same base class Aug 23, 2024
@janseris janseris changed the title ReferenceLoopHandling.Ignore unexpectedly skips objects - nested object is not serialized if it has the same ID as parent object and implements the same base class ReferenceLoopHandling.Ignore unexpectedly skips objects - false positive if Equals/HashCode result is the same Aug 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant