0

I wanted to test a my idea about function pointers. I wrote a test but it doesn't work(causes a Segmentation fault). Here is my test simplified:

#include<stdlib.h>
void a(){}
void b(){}
int main(){
    size_t s=0;
    char* p1=(char*)&a;
    char* p2=(char*)&b;
    while(*p1++==*p2++) s++;
    void (*o)();
    char* c=malloc(s);
    while(s--) *(c+s)=*((char*)&a+s);
    o=(void(*)())c;
    o();
    return 0;
}

The code should copy machine code of an empty function(here if finds the intersection of data at the addresses of two empty function and copies that) and run the copy.

Thanks for reaching out.

9
  • 1
    "test a my idea". What idea? What is that code supposed to do? Commented Aug 19, 2022 at 8:11
  • 2
    Please edit the post to update it with any info like that which is critical to understanding the question. Commented Aug 19, 2022 at 8:14
  • 1
    You should at least do some plausibility checks. For example, is s > 0? And why do you think you can run arbitrary machine code allocated in data memory? Did you hear about modern protection schemes? Commented Aug 19, 2022 at 8:15
  • 1
    You want to copy code from a function into memory you've allocated on the heap. You should not expect that memory range to be executable. I would assume any recent operating system would not allow code execution from such a memory area. Commented Aug 19, 2022 at 8:23
  • 1
    If you want to play around with stuff like this, I'd recommend getting some low end, von Neumann microcontroller board to play with. These allow you to wildly copy executable code to RAM and execute it from there. But if you use a Harvard one or a mid-range MCU with MMU, that's probably not an option. Commented Aug 19, 2022 at 8:47

1 Answer 1

1

Just a few of the problems:

  • Converting between object pointers and function pointers invokes undefined behavior so you have no guarantees that correct machine code will be generated for your program.
  • You can't make any assumption of where these functions are allocated in memory.
  • Using char for raw binary is always wrong, since it has implementation-defined signedness. Use unsigned char or uint8_t.
  • Read accessing memory reserved for execution might cause a hardware exception from the MMU on most high end CPUs. And if not from the MMU then an exception from the OS. So what you are trying to do (copying a function's machine code to data RAM?) might not be possible.
  • The malloc chunk you get might not have the same alignment requirements as a function, meaning that the address might not be suitable.
  • *(c+s) = is a fairly obvious array out of bounds bug. Don't write obscure loops that iterate downwards for no good reason. In this case simply use memcpy.
  • When trying out your code on some x86_64 the functions a and b ends up as the raw binary ret instruction followed by a bunch of binary corresponding to the calling convention. More me, the functions stop having the same machine code before you reach the end of either of them. This is what the binary looks like:

enter image description here

But when I print the contents copied down to c (after fixing the other bugs mentioned in this answer) there's just 2 bytes holding C3 66, but as you can see from the pic that's in the middle of an instruction. I'm not great at decoding raw x86 asm, but the algorithm appears to be fundamentally wrong.

Sign up to request clarification or add additional context in comments.

9 Comments

I came across the idea that function addresses should be aligned but totally forgot to check it. Sorry. Also is alignement there because instructions in some architerures seem to have same size in machine code like with arm64?
@markoj That's all very CPU specific and as a C programmer I tend not to care learning about it since the linker handles all that for me.
"malloc chunk you get might not have the same alignment requirements as a function," --> interesting!
@chux-ReinstateMonica At least I wouldn't assume as much. I recall getting some very subtle function misalignment bug in a bootloader code on a Power PC and it was far from easy to track down.
@markoj So did I but apparently not... and I don't know x86 64 well enough to tell what these are there for.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.