PSprites with an ID of 0 can be created infinitely

Bugs that have been investigated and resolved somehow.

Moderator: GZDoom Developers

Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.
User avatar
Boondorl
Posts: 127
Joined: Wed Jul 11, 2018 10:57 pm

PSprites with an ID of 0 can be created infinitely

Post by Boondorl »

As the title suggests, there's currently an oversight with PSprites that are assigned an ID of 0. While PSprites with that ID can be created freely via GetPSprite(), the issue arises with FindPSprite(). If an argument of 0 is passed it will always return null. This forces GetPSprite() to create a new PSprite every time. Normally PSprites do a duplicate check on creation to make sure copies aren't created, but this check is specifically ignored if the ID is 0. This means any time GetPSprite() with an argument of 0 is called, a new PSprite will be created. This can be verified in-game:

Code: Select all

class CustomActor : Actor
{
    override void PostBeginPlay()
    {
        super.PostBeginPlay();

        players[consoleplayer].GetPSprite(0);
        players[consoleplayer].GetPSprite(0);
        players[consoleplayer].GetPSprite(0);
        players[consoleplayer].GetPSprite(0);
        players[consoleplayer].GetPSprite(0);

        let psp = players[consoleplayer].psprites;
        while (psp)
        {
            if (psp.id == 0)
            {
                console.printf("PSprite with id 0 exists");
                if (!players[consoleplayer].FindPSprite(0))
                    console.printf("Cannot find layer 0 despite existing");
            }

            psp = psp.next;
        }
    }
}
Summon the actor via the console and this code will print 5 times. Tested on the latest GZDoom build (4.7.1).
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 47995
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: PSprites with an ID of 0 can be created infinitely

Post by Graf Zahl »

ID 0 is considered special, the use case described here is simply undefined. 0 is treated in several places as "use the caller's id", so it cannot be handed out to user data without breaking stuff. All I can do is to unconditionally return null when this function is being called with 0.

This all is the result of a design flaw in the original implementation that did not even consider the idea of failure, so even for invalid IDs it returned something. This was later addressed, but this case overlooked.

Return to “Closed Bugs”