Is calling a function pointer to generated code undefined behavior?

Viewed 238

Is there a way, in purely standard C++, to somehow call a function generated within a buffer?

Let's assume:

  1. We've used implementation-specific knowledge (and obv. architecture-specific) to generate the byte sequence implementing some function in an array of char.
  2. This implementation correctly matches the implementation's calling convention, and other relevant parts of the ABI, so that it will actually function correctly if called as C++ function
  3. The buffer is correctly marked as executable

I.e., all the architecture / ABI hurdles have been overcome, all we need to do is actually call this block of code. The question is: is there a standards-compliant way to create a function pointer to this and call said function pointer without hitting undefined behavior?

As I understand it, it is implementation-defined if we can cast a pointer to an object type to a function pointer type. I also believe that it is implementation-defined if said pointer will point to the same logical address as the original pointer. The obstacle is the call: from the perspective of the implementation, all I've done is try and cast a pointer to an array of chars into a function pointer and then call it. If said ptr was one to an object type, I know this would be violating strict aliasing rules, and would be undefined behavior. But is it undefined behavior or merely implementation-defined what will occur if I attempt to call this function pointer?

2 Answers

It is implementation-defined what the conversion means, so the implementation can choose to interpret it as a pointer to some function “defined by the implementation” (as if its standard library contained all possible functions). I’m not sure that implementations actually document support for this technique (as required for implementation-defined behavior), but it’s only reasonable to interpret that as a bug in their documentation.

As I understand your question, you ask about code such as:

char buffer[200] = "some valid operations";
void (*func)() = reinterpret_cast<void(*)()>(buffer);
func();

I see in the standard in C++ expr.call 7.6.1.3 Function call:

  1. A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of initializer-clauses which constitute the arguments to the function.
    [...]
    The postfix expression shall have function type or function pointer type. For a call to a non-member function or to a static member function, the postfix expression shall either be an lvalue that refers to a function [...], or have function pointer type.

The func in the above code is an lvalue that refers to a char array and not to a function. The following points in the standard describe other cases of function call expression, such as virtual function call or call to a destructor of some object. These points also do not apply here. To summarize, the standard does not define what will happen when the function call expression is applied to a lvalue that refers to a object that is a char array. Because it's not defined, hence it's undefined behavior.

is there a standards-compliant way to create a function pointer to this

Just cast it, via reinterpret_cast. The resulting value is implementation-defined.

and call said function pointer without hitting undefined behavior?

No.

Is calling a function pointer to generated code undefined behavior?

Yes.

Is there a way, in purely standard C++, to somehow call a function generated within a buffer?

No.

But is it undefined behavior or merely implementation-defined what will occur if I attempt to call this function pointer?

Undefined behavior.

Related