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

TF2 run_command hook gives bad pointer as second argument when the player in question is a bot #140

Closed
quartata opened this issue Jul 14, 2016 · 16 comments
Labels

Comments

@quartata
Copy link

quartata commented Jul 14, 2016

Original thread: http://forums.sourcepython.com/viewtopic.php?f=20&t=1257

Title says it all. Not certain what pointer is getting passed, but it's not pointing to an instance of CUserCmd nor to an instance of CBotCmd. To reproduce, make a new plugin with this code:

from entities.hooks import EntityCondition, EntityPreHook
from memory import make_object
from players import UserCmd

@EntityPreHook(EntityCondition.is_player, "run_command")
def hook(stack):
  print(make_object(UserCmd, stack[1]).buttons)

and add a bot with sv_cheats 1; bot. Currently only been reproduced on TF2 with Linux, other games/platforms may be affected. NextBots (added with tf_bot_add) do not seem to have any problems.

@quartata quartata changed the title TF2 run_command hook gives bad pointer as second argument when the player in question is a puppet bot TF2 run_command hook gives bad pointer as second argument when the player in question is a bot Jul 14, 2016
@Ayuto
Copy link
Member

Ayuto commented Jul 14, 2016

What gets printed to the console when you execute the following?

stack[1].type_info.dump()

@quartata
Copy link
Author

Segfault. Here's the debug.log: http://pastebin.com/pn9eY8re

@quartata
Copy link
Author

I'll try to see if I can reproduce this on DoD:S a little later.

@Ayuto
Copy link
Member

Ayuto commented Jul 14, 2016

Well, the debug.log still mentions MakeObject. Just use this and not more:

from entities.hooks import EntityCondition, EntityPreHook

@EntityPreHook(EntityCondition.is_player, "run_command")
def hook(stack):
    stack[1].type_info.dump()

@quartata
Copy link
Author

quartata commented Jul 14, 2016

This was all I had:

from entities.hooks import EntityCondition, EntityPreHook

@EntityPreHook(EntityCondition.is_player, "run_command")
def hook(stack):
    print(stack[1].type_info.dump())

@Ayuto
Copy link
Member

Ayuto commented Jul 14, 2016

The log says something different:
#10 0xebc1c7ab in MakeObject(boost::python::api::object, boost::python::api::object) () from /home/quartata/sourcepythonds/tf/addons/source-python/bin/core.so

@quartata
Copy link
Author

I've done it three times now (each time I've removed the pycache, guaranteed that no other plugins were loaded, etc.) and that's what the stacktrace looks like. Maybe dump() calls it?

@Ayuto
Copy link
Member

Ayuto commented Jul 14, 2016

No, it doesn't call it. In the log file there is also this line:

#2  0xebd8eb67 in boost::python::objects::caller_py_function_impl<boost::python::detail::caller<CUserCmd* (*)(CPointer*), boost::python::return_value_policy<boost::python::reference_existing_object, boost::python::default_call_policies>, boost::mpl::vector2<CUserCmd*, CPointer*> > >::operator()(_object*, _object*) () from /home/quartata/sourcepythonds/tf/addons/source-python/bin/core.so

Did you notice the CUserCmd occurence? You definitely run the old plugin.

@quartata
Copy link
Author

quartata commented Jul 14, 2016

I added a print statement before the dump() and it showed up in the output right before the segfault. It's not the old plugin.

@Ayuto
Copy link
Member

Ayuto commented Jul 14, 2016

Then please upload the new debug.log. It's impossible to get this output with the snippet I gave you.

@jordanbriere
Copy link
Contributor

CRASH: Thu Jul 14 11:15:12 PDT 2016
Current PDT time: 13:03:49

→ That debug.log is about 2 hours old. Delete the file, and try again.

@quartata
Copy link
Author

quartata commented Jul 14, 2016

That 2 hour old log was the first log I got when I ran the snippet plugin. All the other logs I got had identical stacktraces, but for some reason when I deleted the __pycache__ again just now the stack trace changed to something that makes a little more sense: http://pastebin.com/SpVVv9Js

@Ayuto
Copy link
Member

Ayuto commented Jul 14, 2016

L'In20Cible and I came to the conclusion that the passed pointer doesn't has RTTI data. This snippet will work around that issue.

ucmd_size = memory.get_size(UserCmd)

@EntityPreHook(EntityCondition.is_player, "run_command")
def hook(stack):
    ucmd = UserCmd()
    ucmd_ptr = memory.get_object_pointer(ucmd)

    orig_ucmd_ptr = stack[1]
    orig_ucmd_ptr.copy(ucmd_ptr, ucmd_size)

    # You have now read-only access to the user command. Writing any attribute
    # has no effect as it doesn't modify the original user command.
    print(ucmd.buttons)

    # If you want to modify the user command, you need to copy back your work
    ucmd_ptr.copy(orig_ucmd_ptr, ucmd_size)

@Ayuto
Copy link
Member

Ayuto commented Jul 19, 2016

Does this workaround work for you, @quartata?

@quartata
Copy link
Author

Yes, it works fine. Thanks.

@jordanbriere
Copy link
Contributor

Thanks for confirming! I guess we can close this issue now, since it is not directly related to Source.Python.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants