Skip to content

Crash trying to retrieve userid from pointer? #123

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

Closed
jsza opened this issue May 8, 2016 · 10 comments
Closed

Crash trying to retrieve userid from pointer? #123

jsza opened this issue May 8, 2016 · 10 comments
Assignees

Comments

@jsza
Copy link
Contributor

jsza commented May 8, 2016

Running build 322 on TF2 (linux): http://builds.sourcepython.com/job/Source.Python/322/artifact/release/source-python-tf2-May-01-2016.zip

I've been seeing this crash rather frequently since updating my plugin to SP version 322 (I was running version 73 before)
EDIT: Just to clarify, this crash is new since updating to 322.

https://crash.limetech.org/d3j7rqvcgbyf

I tried looking through core.so in IDA Free, but I couldn't make much sense of the assembly. I did, however see a string referring to UseridFromPointer at the top of the stack.

The only place in my plugin calling that function is the following. I've tried to reproduce the crash by triggering the startTouch/endTouch callbacks as well as disconnecting while inside a trigger. Neither seems to cause it.

from core import PLATFORM
from entities.helpers import index_from_pointer
from memory import Convention, DataType
from players.helpers import userid_from_pointer

from tempus import TempusModule
from tempus.utils import createEntity, getCurrentMap



POINTER = DataType.POINTER

_startTouchCallbacks = []
_endTouchCallbacks = []



class OutputManager(TempusModule):
    def __init__(self, tempus):
        self.tempus = tempus
        if PLATFORM == 'windows':
            self.OFFSET_START_TOUCH = 98
            self.OFFSET_END_TOUCH = 100
        else:
            self.OFFSET_START_TOUCH = 99
            self.OFFSET_END_TOUCH = 101
        self.StartTouch = None
        self.EndTouch = None


    def tempusLoaded(self):
        if getCurrentMap() != '':
            self.findFunctions()


    def tempusUnloaded(self):
        if self.StartTouch is not None:
            self.StartTouch.remove_pre_hook(preStartTouch)
        if self.EndTouch is not None:
            self.EndTouch.remove_pre_hook(preEndTouch)


    def server_spawn(self, event):
        self.findFunctions()


    def registerStartTouchCallback(self, f):
        global _startTouchCallbacks
        if f not in _startTouchCallbacks:
            _startTouchCallbacks.append(f)


    def registerEndTouchCallback(self, f):
        global _endTouchCallbacks
        if f not in _endTouchCallbacks:
            _endTouchCallbacks.append(f)


    def findFunctions(self):
        entity = createEntity('trigger_multiple')
        pointer = entity.pointer
        if not pointer:
            return
        if self.StartTouch is None:
            self.StartTouch = pointer.make_virtual_function(self.OFFSET_START_TOUCH,
                Convention.THISCALL, (DataType.POINTER, DataType.POINTER),
                DataType.VOID)
            self.StartTouch.add_pre_hook(preStartTouch)
        if self.EndTouch is None:
            self.EndTouch = pointer.make_virtual_function(self.OFFSET_END_TOUCH,
                Convention.THISCALL, (DataType.POINTER, DataType.POINTER),
                DataType.VOID)
            self.EndTouch.add_pre_hook(preEndTouch)
        entity.call_input('Kill')



def preStartTouch(args):
    try:
        userid = userid_from_pointer(args[1])
    # Conversion failed - activator is not a player
    except ValueError:
        return True
    entity = index_from_pointer(args[0])
    for f in _startTouchCallbacks:
        f(userid, entity)



def preEndTouch(args):
    print(args)
    try:
        userid = userid_from_pointer(args[1])
    # Conversion failed - activator is not a player
    except ValueError:
        return True
    entity = index_from_pointer(args[0])
    for f in _endTouchCallbacks:
        f(userid, entity)
@Ayuto Ayuto self-assigned this May 8, 2016
@Ayuto
Copy link
Member

Ayuto commented May 8, 2016

The crash happens when you call the function with an invalid pointer. I will add more checks to prevent a crash.

Ayuto added a commit that referenced this issue May 8, 2016
This adds more security checks when converting from a pointer.
@Ayuto
Copy link
Member

Ayuto commented May 8, 2016

Version 327 will probably fix your issue. Please test the new version when it's ready and tell me if you are still experiencing crashes.

@jsza
Copy link
Contributor Author

jsza commented May 9, 2016

Thank you! I will test this on a single server for now, as there is a memory leak I'm trying to reproduce (I noticed around 500MB leaked in 1 hour after updating to build 322, though it may have been other factors).

I'll open another issue about the memory leak if I can prove it's somehow tied to Source.Python.

@jsza
Copy link
Contributor Author

jsza commented May 9, 2016

Just got a crash running version 327, seems to be related: https://crash.limetech.org/iwedgblu5oc5

@Ayuto
Copy link
Member

Ayuto commented May 9, 2016

To be honest that crash dump doesn't really help me, because it seems to strip off the relevant information. Can you start your server with the -debug option and post the resulting debug.log?

@jsza
Copy link
Contributor Author

jsza commented May 10, 2016

Oh wow, wish I knew about -debug before! Here's the output: http://hastebin.com/raw/orenasudoq

EDIT:
Paste expired, new link: http://pastebin.com/raw/XrsUdDsC

@Ayuto
Copy link
Member

Ayuto commented May 10, 2016

That's a really strange error. Does it perhaps occur, because of the memory leak in issue #124?

@jsza
Copy link
Contributor Author

jsza commented May 11, 2016

Could it be this line?

const char* str_value = extract<const char*>(str(from)); \

I did some digging and found that this was changed a month or two after SP version 73 was built, in commit e2e613b

Can (invalid?) pointers always be cast to char?

@Ayuto
Copy link
Member

Ayuto commented May 11, 2016

Yes, that is just the object representation. It should always work.

Ayuto added a commit that referenced this issue Jan 7, 2017
@Ayuto
Copy link
Member

Ayuto commented Feb 3, 2017

@jsza Do you still experience crashes?

@Ayuto Ayuto closed this as completed Apr 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants