Pythons inspect get source returning unrelated source

47 Views Asked by At

I need to get the source of a function 'get_id' and inspect.getsource() is returning the source of the function 'update_creds' and I have no idea why

Some specifics about the environment: Its running on Splunks SOAR, which looking at the stack trace seems like it is running a wrapper program to fetch, decode, execute the script so just asking inspect to find the source doesn't seem to work unless I manually import the file into itself.

Here's the code I am debugging:

def update_creds(**kwargs):
    print("update_creds")

# Function header I cannot touch
def get_id(**kwargs):
    # inspect.stack()[0][3] gets the name of the function we are currently in
    exec(get_new_return(function=inspect.stack()[0][3]))
    return
    # Automatically generated code I cannot touch
    phantom.act("old_parameter","other_parameters_that_change")
    return

# Function header I cannot touch
def get_function_source(**kwargs):
    import inspect
    import re
    import sys

    # We have to add the git repo to the system path so we can import the file
    sys.path.insert(0, '/scm/git/')

    # Get the file name from __file__ (its formatted within angle brackets, so we get rid of them
    source=__import__(re.sub(r'(<|>)','',__file__))
    
    # use eval to specifially refer to this files function object.
    # using debug comments, the eval does indeed refer to the correct object I want the source from
    # However, the return of inspect.getsource() gives me the source of another function
    function_source=inspect.getsource(eval("source."+kwargs["function"]))
    generated_code=re.findall(r'phantom.act\((.*)\)', function_source)[-1]
    return generated_code.replace("old_parameter", "new_parameter")

get_id()

If you really want to know why I am doing this, the environment uses code blocks to generate python code, specifically function definitions and the final function call to continue execution. However, I need to add a parameter to the next function call, so I am using inspect.getsource() to get the final function call, add the parameter, call it, and do an early return.

I tried following where it loses reference to the correct function, which seems to be when inspect.getsource() is called. I am expecting the source of the 'get_id' function instead of the 'update_creds' function.

Looking into how getsource works, I thought it might have something to do with the name of the function, but the names do not have anything in common from what I can see. The only other thing I can think of would be if getsource refers to line numbers and its incorrectly using the line number from one file to another, but I would have no idea how to force inspect to make sure its referring to the same file

Edit: Added more to the code block for more context. In adding context I noticed that update_creds is the function right above get_id, so its almost as if inspect.getsource() needs to go down one more function definition, but I don't know if this is a one-off or if it will always be off by one. And if it is always off by one, how would I get getsource to give me the next function?

1

There are 1 best solutions below

1
grumBit On

In your code, get_id() is never called, so at no time will it be in the stack trace.

Aside from that, it looks like the answer is in your code's comment;

def update_creds(**kwargs):
    # inspect.stack()[0][3] gets the name of the function we are currently in
    exec(get_new_return(function=inspect.stack()[0][3]))

inspect.stack()[0][3]) will evaluate to 'update_creds', because that's the function you are in when you call it. So, when you call get_new_return(), thefunction arg will be set to 'update_creds'. As a result, get_new_return() is getting the source for update_creds()