Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy way of calling function with unknown args count via pointer

I have the following code:

typedef void * (__stdcall * call_generic)(...);
typedef void * (__stdcall * call_push2)(unsigned long,unsigned long);

void * pfunc;
// assume pfunc is a valid pointer to external function

// this is a logically correct way of calling, however this includes:
// add esp, 8
// after the call, and that breaks my stack.
((call_generic)pfunc)(1,1);

// however, if i use this call:
((call_push2)pfunc)(1,1);
// this does not happen and code works properly.

It's a pain to track all the calls and count args manually (there are lots of such calls ahead), I'd prefer a macro or something for this, but with that bug it's not possible.

Is there a solution? Is there another way of creating call_generic type to do such things?

I do not really understand why exactly it does that "cleanup" but that breaks my stack badly, causing previously defined variables to be lost.

like image 320
einclude Avatar asked Oct 11 '22 04:10

einclude


1 Answers

((call_generic)pfunc)(1,1); is only a logically correct way of calling if the function pointed to by pfunc actually has the signature you cast to, void *(...). Your code tells the compiler to make a varargs call, so it makes a varargs call. A varargs call to a function that isn't a varargs function doesn't work (in this case, there's disagreement who has to clean up the stack, and it gets done twice).

There's no way to do this for free. You must somehow cast the function pointer to the correct signature before calling it, otherwise the calling code doesn't know how to pass the parameters in a way that the callee code can use.

One option is to ensure that all the called functions that pfunc might point to have the same signature, then cast to that type. For example, you could make them all varargs functions, although I don't particularly recommend it. It would be more type safe to do what you don't want to - make sure that all the functions that might appear here take two unsigned long, and cast to call_push2.

like image 114
Steve Jessop Avatar answered Oct 18 '22 07:10

Steve Jessop