Skip to content

Stop EntRefToEntIndex returning garbage if a bad parameter is passed#1323

Merged
psychonic merged 5 commits intoalliedmodders:masterfrom
c0rp3n:entreftoentindex-no-garbage
Apr 25, 2024
Merged

Stop EntRefToEntIndex returning garbage if a bad parameter is passed#1323
psychonic merged 5 commits intoalliedmodders:masterfrom
c0rp3n:entreftoentindex-no-garbage

Conversation

@c0rp3n
Copy link
Contributor

@c0rp3n c0rp3n commented Jul 25, 2020

Seen multiple bad usage of this function that works only because whatever was passed in was returned as it wasnt an entity reference.
This code should have worked and would be expected to have returned something invalid but instead the the input was returned which allowed the code to work when really it is bad code.

Really I would like this to return -1 or INVALID_ENT_REFERENCE

See this code below GetObject returns an entity index, this has been in TTT for years and really the code is malformed and should never have worked.

iEntity = GetObject(client, false);

if (iEntity == -1)
{
    return;
}

iEntity = EntRefToEntIndex(iEntity);

if (iEntity == INVALID_ENT_REFERENCE)
{
    return;
}

You can see how long this has been present here.

Seen multiple bad usage of this function that works only because whatever was passed in was returned as it wasnt an entity reference.
This code should have worked and would be expected to have returned something invalid but instead the the input was returned which allowed the code to work when really it is bad code.
See for one such case https://discordapp.com/channels/335290997317697536/335290997317697536/736518488314871868
Copy link
Member

@asherkin asherkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the PR, however this passthrough behaviour is intentional - it takes what SourceMod calls a BCompatRef which can be either an entity reference or an entity index. This is important in the general case for handling values from functions that can be either networked or non-networked entities (but obviously not here, as non-networked can't be turned into an index).

Is there a user-facing bug you're looking to solve with this change? One thing I know has surprised people in the past is that the non-ent-ref path doesn't validate the index is valid - that is something I'd definitely be open to changing, but I think this change is a deviation from the general ent ref behaviour in the SM API and will cause widespread breakage.

Added the error text saying what shall be returned when a invalid parameter is passed.
@c0rp3n
Copy link
Contributor Author

c0rp3n commented Jul 25, 2020

My concern was more that it does it does not seem correct from a usage perspective as generally you would presume a entity reference and a index are seperate things, so when a none reference is passed it shouldnt return something that could be valid.

I think validation should atleast be inplace here though and I can change this to be that, just from my understanding the above code shouldnt have worked but the entity index was already validated so it carried on its was through the code with no problems in this case.

Not sure if it needs this much validation but this just mirrors how IsValidEntity works, so the entity index returned should be valid else INVALID_EHANDLE_INDEX is returned.
@c0rp3n
Copy link
Contributor Author

c0rp3n commented Jul 25, 2020

I've made it so that the return value for a passed entity index is now validated instead of just returning INVALID_EHANDLE_INDEX, this just mirrors the code involved with IsValidEntity.

@KyleSanderson
Copy link
Member

Asher is right, the previous code with GetEntData was ridiculously broken and has been largely discouraged for nearly a decade. There's still obvious performance issues here like GetEntPropArraySize in a loop. If you need help absolutely feel free to reach out on IRC, the forums, or Discord.

@c0rp3n
Copy link
Contributor Author

c0rp3n commented Jul 26, 2020

This has nothing todo with GetEntData, this was about EntRefToEntIndex returning bad indexs if something invalid was passed @KyleSanderson think you got the wrong one :)

@asherkin asherkin reopened this Jul 26, 2020
Copy link
Member

@asherkin asherkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - that should hopefully save people some debugging pain. One minor doc point.

Feel free to expand the doc comment if you think it would help to further reduce confusion - a note that it can take an entity reference or index, and it'll validate that the returned index is valid and refers to the same entity probably wouldn't go amiss.

@c0rp3n
Copy link
Contributor Author

c0rp3n commented Jul 28, 2020

Sorry didnt specify that this should be done, less someone with more knowledge has any further suggestions for the documentation changes.

@KyleSanderson
Copy link
Member

@c0rp3n So, I don't want to leave this in-limbo as that's unfair to you. Asher's been traveling for a bit but we chatted about this one offline.

My concern is in a Spawn hook IServerUnknown (what we call it atleast) is actually not assigned on some entities until after the entity is spawned. There's other situations (readas: a lot) where we have a valid reference / index but these member objects are not set by the game quite yet. There are detours and similar out there that hook even before Spawn (I remember in one-case I was even hooking edict allocations and doing all kinds of weird stuff to them in pawn). Basically, I'm worried that this is going to break existing plugins and multiple use-cases, I haven't reviewed what happens to logical entities with this but that's also a concern as they do not follow any traditional paths.

@asherkin what do you think about adding an additional param, similar to what we did with GetClientAuthString, and defaulting it to "true" for validate. That way we can protect new consumers with a new set of includes, and old consumers will work as-is?

@KyleSanderson
Copy link
Member

@asherkin any update on this one? I still feel that this is very destructive as-is and will break many workflows.

@asherkin
Copy link
Member

@asherkin any update on this one? I still feel that this is very destructive as-is and will break many workflows.

I'd like to still pursue this as the current behaviour causes no end of problems - I would happily accept (fixable) breakage here in order to get there, but that still needs careful evaluation. It sounds like you know a few concrete cases where this will break, can you show any of them breaking with the specific checks added here or is it just in cases of theoretical Source badness?

@KyleSanderson KyleSanderson requested a review from asherkin March 30, 2023 04:30
@KyleSanderson
Copy link
Member

Specifically with my setup I seem to recall spawnpoints being quite odd, on CS:S storing this was fine, and then in GO I had to nest a bunch of calls to get the same result (which would change with this). Ultimately the script can change, and this coming on on a major is fine just based on the current climate as it makes things "safer".

@c0rp3n
Copy link
Contributor Author

c0rp3n commented Apr 25, 2024

Is there any consensus on wanting this? Happy to just close the issue, or make any changes.
Though I have been on a long hiatus from any SM dev work.

My original intent was to just avoid confusing behaviour.
As it was something that tripped me up for a short while.

@psychonic
Copy link
Member

As far as I could tell, you had updated with the latest requested changes. I also looked through and think this fine. Thanks!

@psychonic psychonic dismissed asherkin’s stale review April 25, 2024 23:18

This has been addressed

@psychonic psychonic merged commit f9ad35b into alliedmodders:master Apr 25, 2024
jensewe added a commit to jensewe/sourcemod that referenced this pull request Mar 2, 2025
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

Successfully merging this pull request may close these issues.

4 participants