Created
February 22, 2021 23:19
-
-
Save qookei/ab108385a79ec3e66f686076e1ea0bba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <vector> | |
| #include <string> | |
| #include <algorithm> | |
| #include <sys/types.h> | |
| #include <sys/wait.h> | |
| #include <sys/mman.h> | |
| #include <unistd.h> | |
| #include <fcntl.h> | |
| #include <dlfcn.h> | |
| #include <readline/readline.h> | |
| #include <readline/history.h> | |
| #include <cstdlib> | |
| // returns stdout and stderr combined | |
| std::string run(std::string exe, std::vector<std::string> args, std::string stdin_s, int &ec) { | |
| int stdin_pipe[2]; | |
| int stdout_pipe[2]; | |
| pipe(stdin_pipe); | |
| pipe(stdout_pipe); | |
| pid_t child = fork(); | |
| std::string stdout_s; | |
| if (!child) { | |
| dup2(stdin_pipe[0], STDIN_FILENO); | |
| dup2(stdout_pipe[1], STDOUT_FILENO); | |
| dup2(stdout_pipe[1], STDERR_FILENO); | |
| std::vector<char *> arg_ptrs; | |
| std::transform(args.begin(), args.end(), std::back_inserter(arg_ptrs), [] (auto &v) { return v.data(); }); | |
| arg_ptrs.push_back(nullptr); | |
| close(stdin_pipe[0]); | |
| close(stdin_pipe[1]); | |
| close(stdout_pipe[0]); | |
| close(stdout_pipe[1]); | |
| execv(exe.data(), arg_ptrs.data()); | |
| } else { | |
| close(stdout_pipe[1]); | |
| close(stdin_pipe[0]); | |
| write(stdin_pipe[1], stdin_s.data(), stdin_s.size()); | |
| close(stdin_pipe[1]); | |
| int wstatus; | |
| wait(&wstatus); | |
| ec = WIFEXITED(wstatus) ? WEXITSTATUS(wstatus) : -1; | |
| ssize_t n; | |
| char buf[4096]; | |
| while ((n = read(stdout_pipe[0], buf, 4096)) > 0) { | |
| stdout_s += std::string_view{buf, size_t(n)}; | |
| } | |
| close(stdout_pipe[0]); | |
| } | |
| return stdout_s; | |
| } | |
| int main() { | |
| using_history(); | |
| while (true) { | |
| auto input = readline(">>> "); | |
| if (!input) // EOF | |
| break; | |
| add_history(input); | |
| std::string line{input}; | |
| std::free(input); | |
| std::string code = "#include <bits/stdc++.h>\n" | |
| + ("[[gnu::constructor]] void dont_mind_me_great_code_here___() {" | |
| + line + "}"); | |
| int ec; | |
| auto out = run("/usr/bin/clang++", | |
| {"clang++", "-std=c++20", "-shared", | |
| "-fuse-ld=lld", "-x", "c++", "-", | |
| "-o", "/dev/stdout"}, code, ec); | |
| if (ec != 0) { | |
| std::cout << out << std::flush; | |
| } else { | |
| int fd = memfd_create("so", MFD_CLOEXEC); | |
| write(fd, out.data(), out.size()); | |
| char buf[512]; | |
| snprintf(buf, 512, "/proc/self/fd/%d", fd); | |
| void *dl = dlopen(buf, RTLD_NOW); | |
| dlclose(dl); | |
| close(fd); | |
| std::cout << std::endl; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment