function pointers, casting, call stack overwriting 
Author Message
 function pointers, casting, call stack overwriting

Quote:

>    funcPtr lookupFuncs[] = {
>         (funcPtr)funcA,  /* should be ok */
>         (funcPtr)funcB,       /* ?? */
>         (funcPtr)funcC        /* ?? */
>     /*is there a possibility of overwriting the call
>       stack or something when performing the last 2 casts ?
>       is this a compiler dependent issue ? */
>     };

There is no problem *at the cast*, but certainly if you end up
invoking a function via a pointer to a type incompatible with
the function that actually resides at that address, all sorts
of bad things can happen during the linkage.  Generally, such
a table works best if all the pointed-to functions have
compatible types.  Or, they could all use a variadic [stdarg]
interface with identical anchor argument.
--



Thu, 18 Mar 2004 02:38:24 GMT  
 function pointers, casting, call stack overwriting

Quote:

> Im trying to determine the effects / potential problems on the stack
> when casting function pointers to functions with varying parameter
> sizes,
> to a typedef'd function pointer taking parameter of a
> specific (maximum) size (btw, i am aware of data truncation.)

The only legal thing you can do with casting function pointers is to
cast it to a different function pointer (not data pointer) type and cast
it back.  You can't do anything else with it.

Quote:
>    /* function lookup table */
>    funcPtr lookupFuncs[] = {
>         (funcPtr)funcA,  /* should be ok */
>         (funcPtr)funcB,       /* ?? */
>         (funcPtr)funcC        /* ?? */
>     /*is there a possibility of overwriting the call
>       stack or something when performing the last 2 casts ?
>       is this a compiler dependent issue ? */

Namely, this is fine.

Quote:
>     lookupFuncs[0](value);
>     lookupFuncs[1](value);
>     lookupFuncs[2](value);

However, this is undefined behavior.  You're trying to call functions by
dereferencing function pointers that have the wrong type.

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ It's just a day that brings it all about
\__/ Sade
    Alcyone Systems' CatCam / http://www.catcam.com/
 What do your pets do all day while you're at work?  Find out.
--



Thu, 18 Mar 2004 02:38:27 GMT  
 function pointers, casting, call stack overwriting

[This is a C answer and may not be true of C++]

Quote:
>Hi,

>Im trying to determine the effects / potential problems on the stack
>when casting function pointers to functions with varying parameter sizes,
>to a typedef'd function pointer taking parameter of a
>specific (maximum) size (btw, i am aware of data truncation.)

>ie: would doing so affect the call stack in any way ?

You can convert a function pointer to a function pointer of a
different type and back again.  Here's the relevant text of C99:

6.3.2.3(8) (partial)

<quote>
A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare
equal to the original pointer...
</quote>

Quote:

>typedef u32 (*funcPtr)(u32);    /* my generic function pointer */

>u32  funcA(u32){/*dosomething()*/ return 0xFEFEFEFE;}
>void funcB(u16){/*dosomething()*/ }
>u16 funcC(u8){/*dosomething()*/return 0xFE;}
>bool funcD(u64){/*data truncation would occur*/ return 1;}

>/* would there be particular
>   problems with performing the following: */

>int main (void)
>{

>   u32 value = 99;

>   /* function lookup table */
>   funcPtr lookupFuncs[] = {
>        (funcPtr)funcA,  /* should be ok */

Right, but you don't need the cast since funcA is the same type as
funcPtr.

Quote:
>        (funcPtr)funcB,       /* ?? */
>        (funcPtr)funcC        /* ?? */
>    /*is there a possibility of overwriting the call
>      stack or something when performing the last 2 casts ?
>      is this a compiler dependent issue ? */
>    };

So far you're ok as the conversions you've performed are in keeping in
the 6.3.2.3(8).

Quote:

>             :

>    lookupFuncs[0](value);

This is ok as funcA matches the type of funcPtr.

Quote:
>    lookupFuncs[1](value);
>    lookupFuncs[2](value);

Now you've run into trouble.  Here's the last part of 6.3.2.3(8) that
was omitted above:

<quote>
...If a converted pointer is used to call a function whose type is not
compatible with the pointed-to type, the behavior is undefined.
</quote>

Which is exactly what you're doing in these last 2 function calls.
Since undefined behavior means anything can occur, I suppose the call
stack *could* be corrupted (if such a call stack exists ;-).

Russ    
--



Thu, 18 Mar 2004 02:38:45 GMT  
 function pointers, casting, call stack overwriting

Quote:

> Hi,

> Im trying to determine the effects / potential problems on the stack
> when casting function pointers to functions with varying parameter sizes,
> to a typedef'd function pointer taking parameter of a
> specific (maximum) size (btw, i am aware of data truncation.)

> ie: would doing so affect the call stack in any way ?

> typedef u32 (*funcPtr)(u32);    /* my generic function pointer */

> u32  funcA(u32){/*dosomething()*/ return 0xFEFEFEFE;}
> void funcB(u16){/*dosomething()*/ }
> u16 funcC(u8){/*dosomething()*/return 0xFE;}
> bool funcD(u64){/*data truncation would occur*/ return 1;}

> /* would there be particular
>    problems with performing the following: */

> int main (void)
> {

>    u32 value = 99;

>    /* function lookup table */
>    funcPtr lookupFuncs[] = {
>         (funcPtr)funcA,  /* should be ok */
>         (funcPtr)funcB,       /* ?? */
>         (funcPtr)funcC        /* ?? */

Don't typecast. Do anything to avoid it. The above typecasts produce
undefined behavior (whether you get them to appear to work or not).

Quote:
> The motivation is to use generated code via a lookup table.

Then populate this lookup table with pointers to polymorphic interfaces.

--
Phlip

http://www.greencheese.org/SonseOne
--



Thu, 18 Mar 2004 02:38:46 GMT  
 function pointers, casting, call stack overwriting

Quote:

>     /*is there a possibility of overwriting the call
>       stack or something when performing the last 2 casts ?

Not when you cast the function pointer, but when you call it.

Quote:
>       is this a compiler dependent issue ? */

Yes.  If you want portable code, don't do it.

If you want to know whether it would work on your compiler, first
read its documentation about "calling conventions" and then trace
your test program at the machine code level until you understand
clearly how it passes the arguments to the function and the
returned value back.  Try floating-point values and structures
too, as they may be passed in different ways.  Check that the
correct number of bytes is freed from the stack.  Just running
the program may look like it works but corrupt memory somewhere.

[followups set]
--



Thu, 18 Mar 2004 02:38:54 GMT  
 function pointers, casting, call stack overwriting

Quote:
> Hi,

> Im trying to determine the effects / potential problems on the stack
> when casting function pointers to functions with varying parameter sizes,
> to a typedef'd function pointer taking parameter of a
> specific (maximum) size (btw, i am aware of data truncation.)

> ie: would doing so affect the call stack in any way ?

C doesn't define a "call stack", so that cannot be answered.  However, see
below for the answer you're looking for...

Quote:

> typedef u32 (*funcPtr)(u32);    /* my generic function pointer */

What's a u32?  Or a u16, u8 or u64?  I'll assume that they're different
flavors of int.  Unless they're the same, exactly what they are doesn't
change the answer...

Quote:

> u32  funcA(u32){/*dosomething()*/ return 0xFEFEFEFE;}
> void funcB(u16){/*dosomething()*/ }
> u16 funcC(u8){/*dosomething()*/return 0xFE;}
> bool funcD(u64){/*data truncation would occur*/ return 1;}

> /* would there be particular
>    problems with performing the following: */

> int main (void)
> {

>    u32 value = 99;

>    /* function lookup table */
>    funcPtr lookupFuncs[] = {
>         (funcPtr)funcA,  /* should be ok */

Fine.

Quote:
>         (funcPtr)funcB,       /* ?? */

Fine, up to now.

Quote:
>         (funcPtr)funcC        /* ?? */
>     /*is there a possibility of overwriting the call
>       stack or something when performing the last 2 casts ?
>       is this a compiler dependent issue ? */
>     };

>              :

>     lookupFuncs[0](value);
>     lookupFuncs[1](value);

Blamo!  This caused Undefined Behavior.  The program expects lookupFuncs[1]
to point to a function that takes as a single parameter a u32, and returns a
u32, and that's not the type of function it actually has.  You just lied to
the compiler, and in return, it gets to do anything it wants (at least, as
far as the C Standard is concerned) -- it may affect the call stack
(whatever that is), it may crash the program, it may appear to operate (and
later crash when you give the Big Demo), only the compiler writer can say.

However, if you modify the program to be:

   ((void (*)(u16))lookupFuncs[1])( value );

(I think I got the parens right)  that is, you explicitly cast the pointer
back to the type of function it actually points to, that works fine.
However, this assumes you knew what type of function lookupFuncs[1] was, and
if you did, you're not that far from knowing what function it actually was,
and in which case, why did you need to function pointer in the first place?

Quote:
>     lookupFuncs[2](value);

Ditto, of course...

Quote:

>     return 0;

> }

> The motivation is to use generated code via a lookup table.

Why can't you make all the functions use the same signature (take the same
types of values, and return the same type of value)?  Oh, and get rid of
those ugly casts -- C is designed to catch these types of errors -- putting
in the casts is only promising the compiler that "I know what I'm doing",
and unless you actually do, that's a dangerous promise to make.

--
poncho
--



Thu, 18 Mar 2004 02:38:52 GMT  
 function pointers, casting, call stack overwriting

Quote:
> Im trying to determine the effects / potential problems on the stack

What the hell is a stack? There is no stack in C. Your C *implementation*
(aka compiler etc.) could use a stack to implement functions calls passing
parameters and automatic data, but it has nothing to do with the C-language
itself.

Quote:
> when casting function pointers to functions with varying parameter sizes,

varying? Do you mean variadic:

type_t f (type_t, ...);

or unspecified:

type_t f ();

Quote:
> to a typedef'd function pointer taking parameter of a
> specific (maximum) size (btw, i am aware of data truncation.)

This is highly non portable. The behaviour is undefined. In other words,
don't do that.

Quote:
> ie: would doing so affect the call stack in any way ?

> typedef u32 (*funcPtr)(u32);    /* my generic function pointer */

It's not generic. It has one parameter of type u32 (BTW what the heck is
that u32?).

Quote:
> u32  funcA(u32){/*dosomething()*/ return 0xFEFEFEFE;}
> void funcB(u16){/*dosomething()*/ }
> u16 funcC(u8){/*dosomething()*/return 0xFE;}
> bool funcD(u64){/*data truncation would occur*/ return 1;}

Ah, in fact, you mean a function with with variable width parameter? Don't
to that at all, or if you have to, declare your generic function with the
biggest possible unsigned integer type :

C90 : unsigned long
C99 : unsigned long long

It would accept any kind of unsigned parameter without loss of data.

Quote:
> /* would there be particular
>    problems with performing the following: */

> int main (void)
> {

>    u32 value = 99;

u32 is undefined. do you mean

typedef unsigned short u32; ?

Quote:

>    /* function lookup table */
>    funcPtr lookupFuncs[] = {
>         (funcPtr)funcA,  /* should be ok */
>         (funcPtr)funcB,       /* ?? */
>         (funcPtr)funcC        /* ?? */
>     /*is there a possibility of overwriting the call
>       stack or something when performing the last 2 casts ?
>       is this a compiler dependent issue ? */
>     };

A array of pointers to functions only stores the functions references. It
has nothing to do with the parameters. A parameter consistency could be
performed by your compiler, but the cast simply avoid it.

Quote:
>              :

>     lookupFuncs[0](value);        
>     lookupFuncs[1](value);
>     lookupFuncs[2](value);

>     return 0;

> }

> The motivation is to use generated code via a lookup table.

I see. You should learn more about variadic functions.

--
-hs- emdel at noos.fr "support Afghans against Talebans"
"Car les bandits qui sont cause des guerres
 N'en meurent jamais, on n'tue qu'les innocents."
Gaston Monthus -- La Butte Rouge
--



Thu, 18 Mar 2004 02:39:00 GMT  
 function pointers, casting, call stack overwriting

Quote:

> Don't typecast. Do anything to avoid it. The above typecasts produce
> undefined behavior (whether you get them to appear to work or not).

No, they don't.  The typecasts are perfectly legal.  It's the
invocations of the functions with different signatures that causes
undefined behavior.

Casting a function pointer to a different (function pointer) type and
back is perfectly legal.

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ Procrastination is the thief of time.
\__/ Edward Young
    Rules for Buh / http://www.alcyone.com/max/projects/cards/buh.html
 The official rules to the betting card game, Buh.



Thu, 18 Mar 2004 03:18:16 GMT  
 function pointers, casting, call stack overwriting

writes

Quote:
>> Im trying to determine the effects / potential problems on the stack

>What the hell is a stack? There is no stack in C. Your C *implementation*
>(aka compiler etc.) could use a stack to implement functions calls passing
>parameters and automatic data, but it has nothing to do with the C-language
>itself.

Was it necessary to be so discourteous. I would expect you to know that
it is common to refer to memory as 'the stack' and 'the heap' to
distinguish between that allocated dynamically via malloc and friends
from that allocated at entry to a block. This nesgroup is not
'comp.std.c' and so I would expect a greater latitude for common
parlance.

Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.
--



Fri, 19 Mar 2004 23:02:01 GMT  
 function pointers, casting, call stack overwriting

Quote:

> >     /*is there a possibility of overwriting the call
> >       stack or something when performing the last 2 casts ?

> Not when you cast the function pointer, but when you call it.

Yep, thats what i meant, sorry.
btw, most of the other replies didnt seem to understand what i meant
by 'call stack', did I get the terminolgy wrong - what i (think i)
meant was 'executing machine code' or the 'push / pop' stuff in
assembler terms - not an area i know alot about.

Quote:

> >       is this a compiler dependent issue ? */

> Yes.  If you want portable code, don't do it.

portability would be 'preferable'.

Quote:
> If you want to know whether it would work on your compiler, first
> read its documentation about "calling conventions" and then trace
> your test program at the machine code level until you understand
> clearly how it passes the arguments to the function and the
> returned value back.  Try floating-point values and structures
> too, as they may be passed in different ways.  Check that the
> correct number of bytes is freed from the stack.  Just running
> the program may look like it works but corrupt memory somewhere.

as above 'not an area i really know a lot about'.

Quote:
>From the replies recieved i guess i'll avoid the approach i described.

For reference, what i was trying to do was along the lines of :

#include "3rdPartyCode.h"    /* funcXXX - code generated from an IDL */

ioctl( .. )
{
  switch(FUNC_ID)              /*trying to avoid this */
    case FUNC001:              
      func001(arg);
        ..
    case FUNC220:
      func220(arg);

Quote:
}

or

ioctl( .. )
{
  ...
  lookupTable[FUNC_ID](arg);  /* would have prefered this */

Quote:
}

the first seemed inneficiant: lots of cascading through the switch,
hand coding etc.

If anybody has any other suggestions i'd be interested.

Thanks all, for the replies.

Quote:
> [followups set]

--



Fri, 19 Mar 2004 23:02:41 GMT  
 function pointers, casting, call stack overwriting

Quote:

> #include "3rdPartyCode.h"    /* funcXXX - code generated from an IDL */

> ioctl( .. )
> {
>   switch(FUNC_ID)              /*trying to avoid this */
>     case FUNC001:              
>       func001(arg);
>         ..
>     case FUNC220:
>       func220(arg);
> }

Perhaps you could find a way to generate the switch from the IDL too.
With 220 cases, the probability of copy-and-paste errors runs high.
--



Sat, 20 Mar 2004 01:41:04 GMT  
 function pointers, casting, call stack overwriting

Quote:
> >> Im trying to determine the effects / potential problems on the stack

> writes
> >What the hell is a stack? There is no stack in C. Your C *implementation*
> >(aka compiler etc.) could use a stack to implement functions calls passing
> >parameters and automatic data, but it has nothing to do with the C-language
> >itself.

> Was it necessary to be so discourteous. I would expect you to know that
> it is common to refer to memory as 'the stack' and 'the heap' to
> distinguish between that allocated dynamically via malloc and friends
> from that allocated at entry to a block. ...

Especially since, even though the call frames may be
implemented as linked segments, they have to implement
a stack discipline (except for longjmp, which is a
special kludge).  So calling them a "stack" is correct.
--



Sat, 20 Mar 2004 01:41:07 GMT  
 function pointers, casting, call stack overwriting

Quote:

> For reference, what i was trying to do was along the lines of :
        ...
> the first seemed inneficiant: lots of cascading through the switch,
> hand coding etc.

> If anybody has any other suggestions i'd be interested.

If the functions have different signatures (even if the arguments differ
only by variables that are convertible into one another), then
attempting to store them all in the same function pointer type will not
work.  You'll either have to do a switch...case structure and use the
appropriate argument types, or wrap each of the differing functions in a
function wrapper that you've written which normalizes all the interfaces
to the same function signature and does the conversions back and forth.

--

 __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
/  \ I want to know God's thought; the rest are details.
\__/ Albert Einstein
    Alcyone Systems / http://www.alcyone.com/
 Alcyone Systems, San Jose, California.
--



Sat, 20 Mar 2004 03:00:54 GMT  
 function pointers, casting, call stack overwriting


Quote:

> > >     /*is there a possibility of overwriting the call
> > >       stack or something when performing the last 2 casts ?

> > Not when you cast the function pointer, but when you call it.

> Yep, thats what i meant, sorry.
> btw, most of the other replies didnt seem to understand what i meant
> by 'call stack', did I get the terminolgy wrong - what i (think i)
> meant was 'executing machine code' or the 'push / pop' stuff in
> assembler terms - not an area i know alot about.

Actually, the other repliers understood exactly what you meant.  It's just
that there are implementations that either do not have a call stack, or have
one which is significantly different than what you are thinking about (e.g.
not being used to pass parameters), that thinking about a call stack doesn't
help a whole lot at a C level.  That's a large reason why people have
suggested you look at it from what the C Standard says, because what it says
is guarranteed -- how an implement meets those requirements is not.

Quote:

> > >       is this a compiler dependent issue ? */

> > Yes.  If you want portable code, don't do it.

> portability would be 'preferable'.

> > If you want to know whether it would work on your compiler, first
> > read its documentation about "calling conventions" and then trace
> > your test program at the machine code level until you understand
> > clearly how it passes the arguments to the function and the
> > returned value back.  Try floating-point values and structures
> > too, as they may be passed in different ways.  Check that the
> > correct number of bytes is freed from the stack.  Just running
> > the program may look like it works but corrupt memory somewhere.

> as above 'not an area i really know a lot about'.

> >From the replies recieved i guess i'll avoid the approach i described.
> For reference, what i was trying to do was along the lines of :

> #include "3rdPartyCode.h"    /* funcXXX - code generated from an IDL */

> ioctl( .. )
> {
>   switch(FUNC_ID)              /*trying to avoid this */
>     case FUNC001:
>       func001(arg);

Don't forget a break here!

Quote:
>         ..
>     case FUNC220:
>       func220(arg);
> }

> or

> ioctl( .. )
> {
>   ...
>   lookupTable[FUNC_ID](arg);  /* would have prefered this */
> }

> the first seemed inneficiant: lots of cascading through the switch,
> hand coding etc.

Actually, I wouldn't expect the switch approach to be significantly less
efficient than the function table approach.  You can legimately balk at the
coding.

Another approach is to take glue logic:

/* This particular function takes two parameters, and returns a value */
static unsigned do_func001( unsigned long arg1, unsigned long arg2 ) {
   return func001(arg1, arg2);

Quote:
}

/* ... */

/* This particular function takes only one parameter, and doesn't return a
value */
static unsigned do_func220( unsigned long arg1, unsigned long arg2 ) {
   func220(arg1);    /* Second parameter is ignored */
   return 0;

Quote:
}

unsigned ((*lookupTable)(unsigned long, unsigned long))[] = {
   do_func001,
/* ... */
   do_func220,

Quote:
};

Now, whether that is significantly cleaner than the switch approach is
debatable.  However, it would also work...

Quote:

> If anybody has any other suggestions i'd be interested.

> Thanks all, for the replies.

> > [followups set]
> --


--



Sat, 20 Mar 2004 13:13:01 GMT  
 function pointers, casting, call stack overwriting


Quote:
>> >> Im trying to determine the effects / potential problems on the stack

>> writes
>> >What the hell is a stack? There is no stack in C. Your C *implementation*
>> >(aka compiler etc.) could use a stack to implement functions calls passing
>> >parameters and automatic data, but it has nothing to do with the C-language
>> >itself.

>> Was it necessary to be so discourteous. I would expect you to know that
>> it is common to refer to memory as 'the stack' and 'the heap' to
>> distinguish between that allocated dynamically via malloc and friends
>> from that allocated at entry to a block. ...

>Especially since, even though the call frames may be
>implemented as linked segments, they have to implement
>a stack discipline (except for longjmp, which is a
>special kludge).  So calling them a "stack" is correct.

Even if the hardware has multitudinous register files, and
function arguments and return values are passed to and fro in or
via registers, which may contain or point to anything?

Thanks. Take care, Brian Inglis         Calgary, Alberta, Canada
--

    fake address                use address above to reply

                                                spam traps
--



Wed, 31 Mar 2004 23:26:48 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. function pointers, casting, call stack overwriting

2. DLL function call stack pointer adjust.

3. destructor is called before copy-constructor on temporary class (allocated on stack during function call)

4. Casting function pointer to void pointer

5. casting void pointer to be a pointer to a function

6. casting void pointer to be a pointer to a function

7. Casting a method pointer to a function pointer.

8. Debugger shows function calls overwriting other variables data!

9. How to use (pointer to function), and function and pointer to (pointer to function)

10. Debugging stack overwrites and SIGSEGV

11. Running app in the debugger causes stack overwrite

12. Stack overwritten error

 

 
Powered by phpBB® Forum Software