├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── bindings ├── Lua │ ├── LICENSE │ ├── Makefile │ └── judger.c ├── NodeJS │ ├── binding.gyp │ ├── judger.cc │ ├── package.json │ └── readme.md └── Python │ ├── .gitignore │ ├── _judger │ └── __init__.py │ ├── pyproject.toml │ └── setup.cfg ├── demo ├── 1.in ├── demo.py └── main.c ├── src ├── argtable3.c ├── argtable3.h ├── child.c ├── child.h ├── killer.c ├── killer.h ├── logger.c ├── logger.h ├── main.c ├── rules │ ├── c_cpp.c │ ├── c_cpp_file_io.c │ ├── general.c │ ├── golang.c │ ├── node.c │ └── seccomp_rules.h ├── runner.c └── runner.h └── tests ├── Dockerfile-16.04 ├── Dockerfile-18.04 ├── Nodejs_and_core ├── base.js └── test_integration.js ├── Python_and_core ├── __init__.py ├── test.py └── testcase │ ├── __init__.py │ ├── base.py │ ├── integration │ ├── __init__.py │ └── test.py │ └── seccomp │ ├── __init__.py │ └── test.py ├── runtest.sh └── test_src ├── integration ├── args.c ├── child_proc_cpu_time_limit.c ├── child_proc_real_time_limit.c ├── cpp_meta.cpp ├── env.c ├── gcc_random.c ├── math.c ├── memory1.c ├── memory2.c ├── memory3.c ├── normal.c ├── output_size.c ├── re1.c ├── re2.c ├── sleep.c ├── stack.c ├── stdout_stderr.c ├── time.c ├── uid_gid.c ├── while1.c └── writev.cpp └── seccomp ├── execve.c ├── execveat.c ├── fork.c ├── sysinfo.c ├── write_file_open.c └── write_file_openat.c /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | build/ 3 | .DS_Store 4 | *.log 5 | *.swp 6 | *.so 7 | __pycache__ 8 | *.pyc 9 | cmake-build-debug/ 10 | .ycm_extra_conf.py 11 | node_modules/ 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | script: 7 | - docker build -t judger-test -f tests/Dockerfile-16.04 . 8 | - docker run -it --rm -v $PWD:/src judger-test /bin/bash -c "chmod +x tests/runtest.sh && ./tests/runtest.sh" 9 | 10 | - docker build -t judger-test -f tests/Dockerfile-18.04 . 11 | - docker run -it --rm -v $PWD:/src judger-test /bin/bash -c "chmod +x tests/runtest.sh && ./tests/runtest.sh" 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.5) 2 | project(judger C) 3 | 4 | #set(CMAKE_VERBOSE_MAKEFILE ON) 5 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output) 6 | 7 | set(CMAKE_C_FLAGS "-g -Wall -Werror -O3 -std=c99 -pie -fPIC") 8 | 9 | # make judger lib 10 | file(GLOB SOURCE "src/*.c" "src/rules/*.c") 11 | add_executable(libjudger.so ${SOURCE}) 12 | target_link_libraries(libjudger.so pthread seccomp) 13 | 14 | 15 | install(FILES output/libjudger.so 16 | PERMISSIONS OWNER_EXECUTE OWNER_READ 17 | DESTINATION /usr/lib/judger) 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Star And Thank Author License (SATA) 2 | 3 | Copyright (c) 4 | 5 | Project Url: https://github.com/QingdaoU/OnlineJudge 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | And wait, the most important, you shall star/+1/like the project(s) in project url 18 | section above first, and then thank the author(s) in Copyright section. 19 | 20 | Here are some suggested ways: 21 | 22 | - Email the authors a thank-you letter, and make friends with him/her/them. 23 | - Report bugs or issues. 24 | - Tell friends what a wonderful project this is. 25 | - And, sure, you can just express thanks in your mind without telling the world. 26 | 27 | Contributors of this project by forking have the option to add his/her name and 28 | forked project url at copyright and project url sections, but shall not delete 29 | or modify anything else in these two sections. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 37 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Judger 2 | 3 | [![Build Status](https://travis-ci.org/QingdaoU/Judger.svg?branch=newnew)](https://travis-ci.org/QingdaoU/Judger) 4 | 5 | Judger for OnlineJudge 6 | 7 | [Document](https://opensource.qduoj.com#/judger/api) 8 | 9 | [JudgeServer](https://github.com/QingdaoU/JudgeServer) 10 | 11 | [OnlineJudge](https://github.com/QingdaoU/OnlineJudge) 12 | -------------------------------------------------------------------------------- /bindings/Lua/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yanghe Sun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bindings/Lua/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Judger's lua binding 2 | 3 | CC = gcc 4 | LDFLAGS ?= -pthread -lseccomp -fPIC -shared 5 | LUAVER ?= 5.3 6 | LUAVERPURE ?= $(subst .,,${LUAVER}) 7 | CFLAGS ?= -Wall -Werror -O3 -std=c99 -fPIC -I/usr/include/lua${LUAVER} -DLUA${LUAVERPURE} 8 | 9 | JUDGER_OBJECTS = child.o killer.o logger.o runner.o rules/c_cpp.o rules/general.o 10 | OBJECTS = $(addprefix ../../src/,${JUDGER_OBJECTS}) judger.o 11 | 12 | .PHONY: all test install clean 13 | 14 | all: judger.so 15 | 16 | judger.so: ${OBJECTS} 17 | ${CC} ${OBJECTS} ${LDFLAGS} -o judger.so 18 | 19 | install: all 20 | @mkdir -p /usr/local/lib/lua/${LUAVER}/ 21 | @cp -f judger.so /usr/local/lib/lua/${LUAVER}/ 22 | 23 | clean: 24 | @rm -f ${OBJECTS} judger.so 25 | 26 | %.o: %c 27 | ${CC} ${CFLAGS} -o $@ -c $< 28 | 29 | -------------------------------------------------------------------------------- /bindings/Lua/judger.c: -------------------------------------------------------------------------------- 1 | /* 2 | Lua Binding: 3 | The MIT License (MIT) 4 | Copyright (c) <2016> 5 | 6 | Judger: 7 | The Star And Thank Author License (SATA) 8 | Copyright (c) 9 | */ 10 | 11 | /* 12 | Usage: 13 | In Lua: require "judger" 14 | In C: luaL_requiref(L, "judger", luaopen_judger, 1) 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include "../../src/runner.h" 24 | 25 | typedef struct ConfItem { 26 | const char* name; 27 | int value; 28 | } ConfItem; 29 | static ConfItem conf_item[] = { 30 | {"_VERSION", VERSION}, 31 | {"_UNLIMITED", UNLIMITED}, 32 | {"_RESULT_WRONG_ANSWER", WRONG_ANSWER}, 33 | {"_RESULT_SUCCESS", SUCCESS}, 34 | {"_RESULT_CPU_TIME_LIMIT_EXCEEDED", CPU_TIME_LIMIT_EXCEEDED}, 35 | {"_RESULT_REAL_TIME_LIMIT_EXCEEDED", REAL_TIME_LIMIT_EXCEEDED}, 36 | {"_RESULT_MEMORY_LIMIT_EXCEEDED", MEMORY_LIMIT_EXCEEDED}, 37 | {"_RESULT_RUNTIME_ERROR", RUNTIME_ERROR}, 38 | {"_RESULT_SYSTEM_ERROR", SYSTEM_ERROR}, 39 | {"_ERROR_INVALID_CONFIG", INVALID_CONFIG}, 40 | {"_ERROR_FORK_FAILED", FORK_FAILED}, 41 | 42 | {"_ERROR_PTHREAD_FAILED", PTHREAD_FAILED}, 43 | {"_ERROR_WAIT_FAILED", WAIT_FAILED}, 44 | {"_ERROR_ROOT_REQUIRED", ROOT_REQUIRED}, 45 | {"_ERROR_LOAD_SECCOMP_FAILED", LOAD_SECCOMP_FAILED}, 46 | {"_ERROR_SETRLIMIT_FAILED", SETRLIMIT_FAILED}, 47 | {"_ERROR_DUP2_FAILED", DUP2_FAILED}, 48 | {"_ERROR_SETUID_FAILED", SETUID_FAILED}, 49 | {"_ERROR_EXECVE_FAILED", EXECVE_FAILED}, 50 | {"_ERROR_SPJ_ERROR", SPJ_ERROR} 51 | }; 52 | static const int conf_item_size = sizeof(conf_item) / sizeof(ConfItem); 53 | 54 | typedef struct ArgMask { 55 | const char* name; 56 | int t; //Should be lua_type 57 | int nil_accept; 58 | } ArgMask; 59 | static ArgMask arg_mask[] = { 60 | {"max_cpu_time", LUA_TNUMBER, 0}, 61 | {"max_real_time", LUA_TNUMBER, 0}, 62 | {"max_memory", LUA_TNUMBER, 0}, 63 | {"max_process_number", LUA_TNUMBER, 0}, 64 | {"max_output_size", LUA_TNUMBER, 0}, 65 | {"exe_path", LUA_TSTRING, 0}, 66 | {"input_path", LUA_TSTRING, 0}, 67 | {"output_path", LUA_TSTRING, 0}, 68 | {"error_path", LUA_TSTRING, 0}, 69 | {"log_path", LUA_TSTRING, 0}, 70 | {"seccomp_rule_name", LUA_TSTRING, 1}, 71 | {"args", LUA_TTABLE, 0}, 72 | {"env", LUA_TTABLE, 0}, 73 | {"uid", LUA_TNUMBER, 0}, 74 | {"gid", LUA_TNUMBER, 0} 75 | }; 76 | static const int arg_mask_size = sizeof(arg_mask) / sizeof(ArgMask); 77 | 78 | static int global_judge(lua_State* L); 79 | 80 | static const struct luaL_Reg judger[] = { 81 | {"run", global_judge}, 82 | {NULL, NULL} 83 | }; 84 | 85 | static char* _strdup(const char* s) { 86 | char* t = NULL; 87 | if (s && (t = (char*)malloc(strlen(s) + 1))) 88 | strcpy(t, s); 89 | return t; 90 | } 91 | 92 | static void destory_config(struct config* config) { 93 | int i = 0; 94 | 95 | free(config->exe_path); 96 | free(config->input_path); 97 | free(config->output_path); 98 | free(config->error_path); 99 | free(config->log_path); 100 | free(config->seccomp_rule_name); 101 | 102 | for (; i < 256; ++i) { 103 | free(config->args[i]); 104 | free(config->env[i]); 105 | } 106 | } 107 | 108 | static int lua_checkstringtable(lua_State* L, char** dst, int max_size, int* dst_size) { 109 | int table_index = lua_gettop(L); 110 | int table_size = 0; 111 | 112 | lua_pushnil(L); 113 | while (0 != lua_next(L, table_index)) { 114 | if (lua_type(L, -1) != LUA_TSTRING) 115 | return 0; 116 | if (lua_type(L, -2) != LUA_TNUMBER) 117 | return 0; 118 | 119 | if (table_size == max_size) 120 | return 0; 121 | 122 | dst[table_size] = _strdup(lua_tostring(L, -1)); 123 | table_size++; 124 | 125 | lua_pop(L, 1); 126 | } 127 | 128 | if (dst_size != NULL) 129 | *dst_size = table_size; 130 | 131 | return 1; 132 | } 133 | 134 | static int global_judge(lua_State* L) { 135 | int i = 0, table_size = 0; 136 | struct config config; 137 | struct result result; 138 | void* arg_refs[arg_mask_size]; 139 | 140 | arg_refs[0] = &config.max_cpu_time; 141 | arg_refs[1] = &config.max_real_time; 142 | arg_refs[2] = &config.max_memory; 143 | arg_refs[3] = &config.max_process_number; 144 | arg_refs[4] = &config.max_output_size; 145 | arg_refs[5] = &config.exe_path; 146 | arg_refs[6] = &config.input_path; 147 | arg_refs[7] = &config.output_path; 148 | arg_refs[8] = &config.error_path; 149 | arg_refs[9] = &config.log_path; 150 | arg_refs[10] = &config.seccomp_rule_name; 151 | arg_refs[11] = &config.args; 152 | arg_refs[12] = &config.env; 153 | arg_refs[13] = &config.uid; 154 | arg_refs[14] = &config.gid; 155 | memset(&config, 0, sizeof(config)); 156 | 157 | luaL_checktype(L, 1, LUA_TTABLE); 158 | for (; i < arg_mask_size; ++i) { 159 | lua_pushstring(L, arg_mask[i].name); 160 | lua_gettable(L, -2); 161 | if (lua_type(L, -1) != arg_mask[i].t && !(arg_mask[i].nil_accept && lua_type(L, -1) == LUA_TNIL)) 162 | return destory_config(&config), luaL_error(L, "bad argument %s", arg_mask[i].name); 163 | 164 | 165 | switch (lua_type(L, -1)) { 166 | case LUA_TNUMBER: 167 | *(int*)arg_refs[i] = lua_tointeger(L, -1); 168 | break; 169 | case LUA_TSTRING: 170 | *(char**)arg_refs[i] = _strdup(lua_tostring(L, -1)); 171 | break; 172 | case LUA_TTABLE: 173 | if (lua_checkstringtable(L, (char**)arg_refs[i], 256 - 1, &table_size) == 0) { 174 | destory_config(&config); 175 | return luaL_error(L, "bad argument %s (item must be a string)", arg_mask[i].name); 176 | } 177 | *((char**)arg_refs[i] + table_size) = NULL; 178 | break; 179 | case LUA_TNIL: 180 | *(char**)arg_refs[i] = NULL; 181 | break; 182 | } 183 | 184 | lua_pop(L, 1); 185 | } 186 | 187 | run(&config, &result); 188 | 189 | lua_newtable(L); 190 | lua_pushstring(L, "cpu_time"); lua_pushnumber(L, result.cpu_time); lua_rawset(L, -3); 191 | lua_pushstring(L, "real_time"); lua_pushnumber(L, result.real_time); lua_rawset(L, -3); 192 | lua_pushstring(L, "memory"); lua_pushnumber(L, result.memory); lua_rawset(L, -3); 193 | lua_pushstring(L, "signal"); lua_pushnumber(L, result.signal); lua_rawset(L, -3); 194 | lua_pushstring(L, "exit_code"); lua_pushnumber(L, result.exit_code); lua_rawset(L, -3); 195 | lua_pushstring(L, "error"); lua_pushnumber(L, result.error); lua_rawset(L, -3); 196 | lua_pushstring(L, "result"); lua_pushnumber(L, result.result); lua_rawset(L, -3); 197 | assert(lua_gettop(L) == 2); 198 | 199 | destory_config(&config); 200 | return 1; 201 | } 202 | 203 | 204 | int luaopen_judger(lua_State* L) { 205 | int i = 0; 206 | 207 | #ifdef LUA51 208 | luaL_register(L, "judger", judger); 209 | #else 210 | luaL_newlib(L, judger); 211 | #endif 212 | 213 | for (; i < conf_item_size; ++i) { 214 | lua_pushstring(L, conf_item[i].name); 215 | lua_pushnumber(L, conf_item[i].value); 216 | lua_rawset(L, -3); 217 | } 218 | 219 | return 1; 220 | } 221 | -------------------------------------------------------------------------------- /bindings/NodeJS/binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "judger", 5 | 'cflags_cc!': [ '-std=c++11','-O2' ], 6 | "sources": [ "judger.cc"], 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /bindings/NodeJS/judger.cc: -------------------------------------------------------------------------------- 1 | #include "node.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | namespace demo { 11 | 12 | using v8::FunctionCallbackInfo; 13 | using v8::Isolate; 14 | using v8::JSON; 15 | using v8::Local; 16 | using v8::Int32; 17 | using v8::Array; 18 | using v8::Integer; 19 | using v8::Uint32; 20 | using v8::Number; 21 | using v8::Object; 22 | using v8::String; 23 | using v8::Value; 24 | using v8::MaybeLocal; 25 | using v8::Exception; 26 | using v8::Context; 27 | 28 | /* 转成数字 */ 29 | bool ToNumber(Isolate * isolate,Local &args,char * key,std::string &str){ 30 | Local context= isolate->GetCurrentContext(); 31 | Local val = args->ToObject()->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked(); 32 | if(val->IsNullOrUndefined()) 33 | return true; 34 | else if( val->IsNumber()){ 35 | Local num = val->ToInteger(context).ToLocalChecked(); 36 | str+=" --"; 37 | str+=std::string(key); 38 | str+="="; 39 | str+=std::to_string(num->Value()); 40 | return true; 41 | } 42 | else { 43 | isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument must be Object!"))); 44 | return false; 45 | } 46 | } 47 | 48 | char * _ToCharPTR(Local &val,Local &context,char * str_content){ 49 | String::Utf8Value str_val( val->ToString(context).ToLocalChecked()); 50 | strcpy(str_content,*str_val); 51 | return str_content; 52 | } 53 | 54 | /* 转成字符串 */ 55 | bool ToCStr(Isolate * isolate,Local &args,char * key,std::string &str){ 56 | 57 | char str_content[255]={0}; 58 | Local context= isolate->GetCurrentContext(); 59 | Local val; 60 | if(args->IsObject()) 61 | val = args->ToObject()->Get(context,String::NewFromUtf8(isolate,key)).ToLocalChecked(); 62 | else 63 | val = args; 64 | if(val->IsNullOrUndefined()) 65 | return true; 66 | else if(val->IsString()){ 67 | _ToCharPTR(val,context,str_content); 68 | str+=" --"; 69 | str+=std::string(key); 70 | str+="="; 71 | str+=std::string(str_content); 72 | return true; 73 | } 74 | else { 75 | char ret[100]; 76 | sprintf(ret,"typeof %s must be String!",key); 77 | isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,ret))); 78 | return false; 79 | } 80 | } 81 | 82 | 83 | /** 84 | * 参数: 85 | * { 86 | * max_cpu_time 87 | * max_real_time 88 | * max_memory 89 | * memory_limit_check_only ?? 90 | * max_stack 91 | * max_process 92 | * max_output_size 93 | * exe_path 94 | * input_path 95 | * output_path 96 | * error_path 97 | * args:[] 98 | * env:[] 99 | * } 100 | * 返回值 101 | * { 102 | * cpu_time 103 | * real_time 104 | * memory 105 | * signal 106 | * exit_code 107 | * result 108 | * error: 109 | * } 110 | */ 111 | 112 | void Method(const FunctionCallbackInfo& args) 113 | { 114 | Isolate* isolate = args.GetIsolate(); 115 | Local context= isolate->GetCurrentContext(); 116 | 117 | std::string _args = "/usr/lib/judger/libjudger.so"; 118 | 119 | if( !args[0]->IsObject()){ 120 | isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"typeof argument must be Object!"))); 121 | } 122 | 123 | Local argument = args[0]; 124 | 125 | std::string int_vars[] = { "max_cpu_time","max_real_time","max_memory","memory_limit_check_only","max_stack","max_process_number","max_output_size","uid","gid"}; 126 | std::string str_vars[] = { "input_path","output_path","error_path","exe_path","log_path","seccomp_rule_name"}; 127 | 128 | for( auto var :int_vars){ 129 | if( ! ToNumber(isolate,argument,(char *)var.c_str(),_args)) 130 | return; 131 | } 132 | 133 | for( auto var : str_vars){ 134 | if( !ToCStr(isolate,argument,(char *)var.c_str(),_args)) 135 | return; 136 | } 137 | 138 | /* args */ 139 | Local margs= argument->ToObject()->Get(context,String::NewFromUtf8(isolate,"args")).ToLocalChecked(); 140 | if( margs->IsNullOrUndefined()){ 141 | ; 142 | } 143 | else if( margs->IsArray()){ 144 | Local args = margs.As(); 145 | int len = args->Length(); 146 | int i; 147 | for(i=0;i in = args->Get(i); 149 | if( !ToCStr(isolate,in,(char *)"args",_args)) 150 | return; 151 | } 152 | } 153 | else { //not array 154 | isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"args must be a list"))); 155 | return; 156 | } 157 | 158 | Local menv= argument->ToObject()->Get(context,String::NewFromUtf8(isolate,"env")).ToLocalChecked(); 159 | if( menv->IsNullOrUndefined()){ 160 | ; 161 | } 162 | else if( margs->IsArray()){ 163 | Local env = menv.As(); 164 | int len = env->Length(); 165 | int i; 166 | for(i=0;i in = env->Get(i); 168 | if(!ToCStr(isolate,in,(char *)"env",_args)) 169 | return; 170 | 171 | } 172 | } 173 | else { //not array 174 | isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"env must be a list"))); 175 | return; 176 | } 177 | 178 | 179 | 180 | char buf[255]; 181 | FILE *_result_f; 182 | std::string result; 183 | if(( _result_f = popen(_args.c_str(),"r"))==NULL) 184 | isolate->ThrowException(Exception::Error(String::NewFromUtf8(isolate,"run /usr/lib/judger/libjudger.so failed!"))); 185 | while(fgets(buf,sizeof(buf),_result_f)){ 186 | result += std::string(buf); 187 | } 188 | pclose(_result_f); 189 | 190 | const char *pr = result.c_str(); 191 | int len = strlen(pr); 192 | for(len--;len>=0;len--){ 193 | if( pr[len] == '{') 194 | break; 195 | } 196 | 197 | if(len) 198 | printf("%*.*s",len,len,pr); //输出 程序的输出 199 | 200 | MaybeLocal mres = JSON::Parse(isolate,String::NewFromUtf8(isolate,pr+len)); 201 | args.GetReturnValue().Set(mres.ToLocalChecked()); 202 | } 203 | 204 | void init(Local exports) 205 | { 206 | v8::Isolate* isolate = v8::Isolate::GetCurrent(); 207 | NODE_SET_METHOD(exports, "run", Method); 208 | exports->Set( String::NewFromUtf8(isolate,"UNLIMITED"),Integer::New(isolate, -1)); 209 | exports->Set(String::NewFromUtf8(isolate,"VERSION"),Integer::New(isolate, 0x020101)); 210 | 211 | exports->Set(String::NewFromUtf8(isolate,"RESULT_SUCCESS"),Integer::New(isolate, 0)); 212 | exports->Set(String::NewFromUtf8(isolate,"RESULT_WRONG_ANSWER"),Integer::New(isolate, -1)); 213 | exports->Set(String::NewFromUtf8(isolate,"RESULT_CPU_TIME_LIMIT_EXCEEDED"),Integer::New(isolate, 1)); 214 | exports->Set(String::NewFromUtf8(isolate,"RESULT_REAL_TIME_LIMIT_EXCEEDED"),Integer::New(isolate, 2)); 215 | exports->Set(String::NewFromUtf8(isolate,"RESULT_MEMORY_LIMIT_EXCEEDED"),Integer::New(isolate, 3)); 216 | exports->Set(String::NewFromUtf8(isolate,"RESULT_RUNTIME_ERROR"),Integer::New(isolate, 4)); 217 | exports->Set(String::NewFromUtf8(isolate,"RESULT_SYSTEM_ERROR"),Integer::New(isolate, 5)); 218 | 219 | exports->Set(String::NewFromUtf8(isolate,"ERROR_INVALID_CONFIG"),Integer::New(isolate, -1)); 220 | exports->Set(String::NewFromUtf8(isolate,"ERROR_FORK_FAILED"),Integer::New(isolate, -2)); 221 | exports->Set(String::NewFromUtf8(isolate,"ERROR_PTHREAD_FAILED"),Integer::New(isolate, -3)); 222 | exports->Set(String::NewFromUtf8(isolate,"ERROR_WAIT_FAILED"),Integer::New(isolate, -4)); 223 | exports->Set(String::NewFromUtf8(isolate,"ERROR_ROOT_REQUIRED"),Integer::New(isolate, -5)); 224 | exports->Set(String::NewFromUtf8(isolate,"ERROR_LOAD_SECCOMP_FAILED"),Integer::New(isolate, -6)); 225 | exports->Set(String::NewFromUtf8(isolate,"ERROR_SETRLIMIT_FAILED"),Integer::New(isolate, -7)); 226 | exports->Set(String::NewFromUtf8(isolate,"ERROR_DUP2_FAILED"),Integer::New(isolate, -8)); 227 | exports->Set(String::NewFromUtf8(isolate,"ERROR_SETUID_FAILED"),Integer::New(isolate, -9)); 228 | exports->Set(String::NewFromUtf8(isolate,"ERROR_EXECVE_FAILED"),Integer::New(isolate, -10)); 229 | exports->Set(String::NewFromUtf8(isolate,"ERROR_SPJ_ERROR"),Integer::New(isolate, -11)); 230 | } 231 | 232 | NODE_MODULE(addon, init) 233 | 234 | } 235 | -------------------------------------------------------------------------------- /bindings/NodeJS/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "judger", 3 | "version": "1.0.0", 4 | "description": "judger for online system", 5 | "main": "./build/Release/judger.node", 6 | "scripts": { 7 | "build": "node-gyp rebuild", 8 | "test": "sudo ./node_modules/.bin/mocha -t 5000 ../../tests/Nodejs_and_core" 9 | }, 10 | "author": "virusdefender,rainboy", 11 | "license": "GPL", 12 | "devDependencies": { 13 | "mocha": "^6.1.4", 14 | "node-gyp": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /bindings/NodeJS/readme.md: -------------------------------------------------------------------------------- 1 | ## 安装 2 | 3 | 先安装`judger`,然后 4 | 5 | ``` 6 | npm install 7 | npm run build 8 | npm run test 9 | ``` 10 | 11 | ## 已知bug 12 | 13 | #### bug_1 14 | 15 | `freopen("data.out","w",stdout)`,不能产生"data.out",这个应该是judger代码的锅,:cry: 16 | -------------------------------------------------------------------------------- /bindings/Python/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | build/ 3 | *.egg-info/ 4 | -------------------------------------------------------------------------------- /bindings/Python/_judger/__init__.py: -------------------------------------------------------------------------------- 1 | import json 2 | import subprocess 3 | 4 | UNLIMITED = -1 5 | VERSION = 0x020101 6 | 7 | RESULT_SUCCESS = 0 8 | RESULT_WRONG_ANSWER = -1 9 | RESULT_CPU_TIME_LIMIT_EXCEEDED = 1 10 | RESULT_REAL_TIME_LIMIT_EXCEEDED = 2 11 | RESULT_MEMORY_LIMIT_EXCEEDED = 3 12 | RESULT_RUNTIME_ERROR = 4 13 | RESULT_SYSTEM_ERROR = 5 14 | 15 | ERROR_INVALID_CONFIG = -1 16 | ERROR_FORK_FAILED = -2 17 | ERROR_PTHREAD_FAILED = -3 18 | ERROR_WAIT_FAILED = -4 19 | ERROR_ROOT_REQUIRED = -5 20 | ERROR_LOAD_SECCOMP_FAILED = -6 21 | ERROR_SETRLIMIT_FAILED = -7 22 | ERROR_DUP2_FAILED = -8 23 | ERROR_SETUID_FAILED = -9 24 | ERROR_EXECVE_FAILED = -10 25 | ERROR_SPJ_ERROR = -11 26 | 27 | 28 | def run(max_cpu_time, 29 | max_real_time, 30 | max_memory, 31 | max_stack, 32 | max_output_size, 33 | max_process_number, 34 | exe_path, 35 | input_path, 36 | output_path, 37 | error_path, 38 | args, 39 | env, 40 | log_path, 41 | seccomp_rule_name, 42 | uid, 43 | gid, 44 | memory_limit_check_only=0): 45 | str_list_vars = ["args", "env"] 46 | int_vars = ["max_cpu_time", "max_real_time", 47 | "max_memory", "max_stack", "max_output_size", 48 | "max_process_number", "uid", "gid", "memory_limit_check_only"] 49 | str_vars = ["exe_path", "input_path", "output_path", "error_path", "log_path"] 50 | 51 | proc_args = ["/usr/lib/judger/libjudger.so"] 52 | 53 | for var in str_list_vars: 54 | value = vars()[var] 55 | if not isinstance(value, list): 56 | raise ValueError("{} must be a list".format(var)) 57 | for item in value: 58 | if not isinstance(item, str): 59 | raise ValueError("{} item must be a string".format(var)) 60 | proc_args.append("--{}={}".format(var, item)) 61 | 62 | for var in int_vars: 63 | value = vars()[var] 64 | if not isinstance(value, int): 65 | raise ValueError("{} must be a int".format(var)) 66 | if value != UNLIMITED: 67 | proc_args.append("--{}={}".format(var, value)) 68 | 69 | for var in str_vars: 70 | value = vars()[var] 71 | if not isinstance(value, str): 72 | raise ValueError("{} must be a string".format(var)) 73 | proc_args.append("--{}={}".format(var, value)) 74 | 75 | if not isinstance(seccomp_rule_name, str) and seccomp_rule_name is not None: 76 | raise ValueError("seccomp_rule_name must be a string or None") 77 | if seccomp_rule_name: 78 | proc_args.append("--seccomp_rule={}".format(seccomp_rule_name)) 79 | 80 | proc = subprocess.Popen(proc_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 81 | out, err = proc.communicate() 82 | if err: 83 | raise ValueError("Error occurred while calling judger: {}".format(err)) 84 | return json.loads(out.decode("utf-8")) 85 | -------------------------------------------------------------------------------- /bindings/Python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools"] 3 | build-backend = "setuptools.build_meta" 4 | -------------------------------------------------------------------------------- /bindings/Python/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = judger 3 | version = 2.2.0 4 | description = python wrapper of libjudger 5 | 6 | [options] 7 | packages = find: 8 | -------------------------------------------------------------------------------- /demo/1.in: -------------------------------------------------------------------------------- 1 | World 2 | -------------------------------------------------------------------------------- /demo/demo.py: -------------------------------------------------------------------------------- 1 | import _judger 2 | import os 3 | 4 | if os.system("gcc main.c -o main"): 5 | print("compile error") 6 | exit(1) 7 | 8 | ret = _judger.run(max_cpu_time=1000, 9 | max_real_time=2000, 10 | max_memory=128 * 1024 * 1024, 11 | max_process_number=200, 12 | max_output_size=10000, 13 | max_stack=32 * 1024 * 1024, 14 | # five args above can be _judger.UNLIMITED 15 | exe_path="main", 16 | input_path="1.in", 17 | output_path="1.out", 18 | error_path="1.out", 19 | args=[], 20 | # can be empty list 21 | env=[], 22 | log_path="judger.log", 23 | # can be None 24 | seccomp_rule_name="c_cpp", 25 | uid=0, 26 | gid=0) 27 | print(ret) 28 | -------------------------------------------------------------------------------- /demo/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | char input[1000]; 5 | scanf("%s", input); 6 | printf("Hello %s\n", input); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /src/argtable3.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * argtable3: Declares the main interfaces of the library 3 | * 4 | * This file is part of the argtable3 library. 5 | * 6 | * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann 7 | * 8 | * All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions are met: 12 | * * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * * Neither the name of STEWART HEITMANN nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, 25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | ******************************************************************************/ 32 | 33 | #ifndef ARGTABLE3 34 | #define ARGTABLE3 35 | 36 | #include /* FILE */ 37 | #include /* struct tm */ 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | #define ARG_REX_ICASE 1 44 | #define ARG_DSTR_SIZE 200 45 | #define ARG_CMD_NAME_LEN 100 46 | #define ARG_CMD_DESCRIPTION_LEN 256 47 | 48 | #ifndef ARG_REPLACE_GETOPT 49 | #define ARG_REPLACE_GETOPT 1 /* use the embedded getopt as the system getopt(3) */ 50 | #endif /* ARG_REPLACE_GETOPT */ 51 | 52 | /* bit masks for arg_hdr.flag */ 53 | enum { ARG_TERMINATOR = 0x1, ARG_HASVALUE = 0x2, ARG_HASOPTVALUE = 0x4 }; 54 | 55 | #if defined(_WIN32) 56 | #if defined(argtable3_EXPORTS) 57 | #define ARG_EXTERN __declspec(dllexport) 58 | #elif defined(argtable3_IMPORTS) 59 | #define ARG_EXTERN __declspec(dllimport) 60 | #else 61 | #define ARG_EXTERN 62 | #endif 63 | #else 64 | #define ARG_EXTERN 65 | #endif 66 | 67 | typedef struct _internal_arg_dstr* arg_dstr_t; 68 | typedef void* arg_cmd_itr_t; 69 | 70 | typedef void(arg_resetfn)(void* parent); 71 | typedef int(arg_scanfn)(void* parent, const char* argval); 72 | typedef int(arg_checkfn)(void* parent); 73 | typedef void(arg_errorfn)(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname); 74 | typedef void(arg_dstr_freefn)(char* buf); 75 | typedef int(arg_cmdfn)(int argc, char* argv[], arg_dstr_t res); 76 | typedef int(arg_comparefn)(const void* k1, const void* k2); 77 | 78 | /* 79 | * The arg_hdr struct defines properties that are common to all arg_xxx structs. 80 | * The argtable library requires each arg_xxx struct to have an arg_hdr 81 | * struct as its first data member. 82 | * The argtable library functions then use this data to identify the 83 | * properties of the command line option, such as its option tags, 84 | * datatype string, and glossary strings, and so on. 85 | * Moreover, the arg_hdr struct contains pointers to custom functions that 86 | * are provided by each arg_xxx struct which perform the tasks of parsing 87 | * that particular arg_xxx arguments, performing post-parse checks, and 88 | * reporting errors. 89 | * These functions are private to the individual arg_xxx source code 90 | * and are the pointer to them are initiliased by that arg_xxx struct's 91 | * constructor function. The user could alter them after construction 92 | * if desired, but the original intention is for them to be set by the 93 | * constructor and left unaltered. 94 | */ 95 | typedef struct arg_hdr { 96 | char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */ 97 | const char* shortopts; /* String defining the short options */ 98 | const char* longopts; /* String defiing the long options */ 99 | const char* datatype; /* Description of the argument data type */ 100 | const char* glossary; /* Description of the option as shown by arg_print_glossary function */ 101 | int mincount; /* Minimum number of occurences of this option accepted */ 102 | int maxcount; /* Maximum number of occurences if this option accepted */ 103 | void* parent; /* Pointer to parent arg_xxx struct */ 104 | arg_resetfn* resetfn; /* Pointer to parent arg_xxx reset function */ 105 | arg_scanfn* scanfn; /* Pointer to parent arg_xxx scan function */ 106 | arg_checkfn* checkfn; /* Pointer to parent arg_xxx check function */ 107 | arg_errorfn* errorfn; /* Pointer to parent arg_xxx error function */ 108 | void* priv; /* Pointer to private header data for use by arg_xxx functions */ 109 | } arg_hdr_t; 110 | 111 | typedef struct arg_rem { 112 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 113 | } arg_rem_t; 114 | 115 | typedef struct arg_lit { 116 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 117 | int count; /* Number of matching command line args */ 118 | } arg_lit_t; 119 | 120 | typedef struct arg_int { 121 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 122 | int count; /* Number of matching command line args */ 123 | int* ival; /* Array of parsed argument values */ 124 | } arg_int_t; 125 | 126 | typedef struct arg_dbl { 127 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 128 | int count; /* Number of matching command line args */ 129 | double* dval; /* Array of parsed argument values */ 130 | } arg_dbl_t; 131 | 132 | typedef struct arg_str { 133 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 134 | int count; /* Number of matching command line args */ 135 | const char** sval; /* Array of parsed argument values */ 136 | } arg_str_t; 137 | 138 | typedef struct arg_rex { 139 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 140 | int count; /* Number of matching command line args */ 141 | const char** sval; /* Array of parsed argument values */ 142 | } arg_rex_t; 143 | 144 | typedef struct arg_file { 145 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 146 | int count; /* Number of matching command line args*/ 147 | const char** filename; /* Array of parsed filenames (eg: /home/foo.bar) */ 148 | const char** basename; /* Array of parsed basenames (eg: foo.bar) */ 149 | const char** extension; /* Array of parsed extensions (eg: .bar) */ 150 | } arg_file_t; 151 | 152 | typedef struct arg_date { 153 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 154 | const char* format; /* strptime format string used to parse the date */ 155 | int count; /* Number of matching command line args */ 156 | struct tm* tmval; /* Array of parsed time values */ 157 | } arg_date_t; 158 | 159 | enum { ARG_ELIMIT = 1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG }; 160 | typedef struct arg_end { 161 | struct arg_hdr hdr; /* The mandatory argtable header struct */ 162 | int count; /* Number of errors encountered */ 163 | int* error; /* Array of error codes */ 164 | void** parent; /* Array of pointers to offending arg_xxx struct */ 165 | const char** argval; /* Array of pointers to offending argv[] string */ 166 | } arg_end_t; 167 | 168 | typedef struct arg_cmd_info { 169 | char name[ARG_CMD_NAME_LEN]; 170 | char description[ARG_CMD_DESCRIPTION_LEN]; 171 | arg_cmdfn* proc; 172 | } arg_cmd_info_t; 173 | 174 | /**** arg_xxx constructor functions *********************************/ 175 | 176 | ARG_EXTERN struct arg_rem* arg_rem(const char* datatype, const char* glossary); 177 | 178 | ARG_EXTERN struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary); 179 | ARG_EXTERN struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary); 180 | ARG_EXTERN struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary); 181 | 182 | ARG_EXTERN struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 183 | ARG_EXTERN struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 184 | ARG_EXTERN struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); 185 | 186 | ARG_EXTERN struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 187 | ARG_EXTERN struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 188 | ARG_EXTERN struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); 189 | 190 | ARG_EXTERN struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 191 | ARG_EXTERN struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 192 | ARG_EXTERN struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); 193 | 194 | ARG_EXTERN struct arg_rex* arg_rex0(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary); 195 | ARG_EXTERN struct arg_rex* arg_rex1(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary); 196 | ARG_EXTERN struct arg_rex* arg_rexn(const char* shortopts, 197 | const char* longopts, 198 | const char* pattern, 199 | const char* datatype, 200 | int mincount, 201 | int maxcount, 202 | int flags, 203 | const char* glossary); 204 | 205 | ARG_EXTERN struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 206 | ARG_EXTERN struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); 207 | ARG_EXTERN struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); 208 | 209 | ARG_EXTERN struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary); 210 | ARG_EXTERN struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary); 211 | ARG_EXTERN struct arg_date* arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary); 212 | 213 | ARG_EXTERN struct arg_end* arg_end(int maxcount); 214 | 215 | #define ARG_DSTR_STATIC ((arg_dstr_freefn*)0) 216 | #define ARG_DSTR_VOLATILE ((arg_dstr_freefn*)1) 217 | #define ARG_DSTR_DYNAMIC ((arg_dstr_freefn*)3) 218 | 219 | /**** other functions *******************************************/ 220 | ARG_EXTERN int arg_nullcheck(void** argtable); 221 | ARG_EXTERN int arg_parse(int argc, char** argv, void** argtable); 222 | ARG_EXTERN void arg_print_option(FILE* fp, const char* shortopts, const char* longopts, const char* datatype, const char* suffix); 223 | ARG_EXTERN void arg_print_syntax(FILE* fp, void** argtable, const char* suffix); 224 | ARG_EXTERN void arg_print_syntaxv(FILE* fp, void** argtable, const char* suffix); 225 | ARG_EXTERN void arg_print_glossary(FILE* fp, void** argtable, const char* format); 226 | ARG_EXTERN void arg_print_glossary_gnu(FILE* fp, void** argtable); 227 | ARG_EXTERN void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname); 228 | ARG_EXTERN void arg_print_option_ds(arg_dstr_t ds, const char* shortopts, const char* longopts, const char* datatype, const char* suffix); 229 | ARG_EXTERN void arg_print_syntax_ds(arg_dstr_t ds, void** argtable, const char* suffix); 230 | ARG_EXTERN void arg_print_syntaxv_ds(arg_dstr_t ds, void** argtable, const char* suffix); 231 | ARG_EXTERN void arg_print_glossary_ds(arg_dstr_t ds, void** argtable, const char* format); 232 | ARG_EXTERN void arg_print_glossary_gnu_ds(arg_dstr_t ds, void** argtable); 233 | ARG_EXTERN void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname); 234 | ARG_EXTERN void arg_freetable(void** argtable, size_t n); 235 | 236 | ARG_EXTERN arg_dstr_t arg_dstr_create(void); 237 | ARG_EXTERN void arg_dstr_destroy(arg_dstr_t ds); 238 | ARG_EXTERN void arg_dstr_reset(arg_dstr_t ds); 239 | ARG_EXTERN void arg_dstr_free(arg_dstr_t ds); 240 | ARG_EXTERN void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc); 241 | ARG_EXTERN void arg_dstr_cat(arg_dstr_t ds, const char* str); 242 | ARG_EXTERN void arg_dstr_catc(arg_dstr_t ds, char c); 243 | ARG_EXTERN void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...); 244 | ARG_EXTERN char* arg_dstr_cstr(arg_dstr_t ds); 245 | 246 | ARG_EXTERN void arg_cmd_init(void); 247 | ARG_EXTERN void arg_cmd_uninit(void); 248 | ARG_EXTERN void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description); 249 | ARG_EXTERN void arg_cmd_unregister(const char* name); 250 | ARG_EXTERN int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res); 251 | ARG_EXTERN unsigned int arg_cmd_count(void); 252 | ARG_EXTERN arg_cmd_info_t* arg_cmd_info(const char* name); 253 | ARG_EXTERN arg_cmd_itr_t arg_cmd_itr_create(void); 254 | ARG_EXTERN void arg_cmd_itr_destroy(arg_cmd_itr_t itr); 255 | ARG_EXTERN int arg_cmd_itr_advance(arg_cmd_itr_t itr); 256 | ARG_EXTERN char* arg_cmd_itr_key(arg_cmd_itr_t itr); 257 | ARG_EXTERN arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr); 258 | ARG_EXTERN int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k); 259 | ARG_EXTERN void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn); 260 | ARG_EXTERN void arg_make_get_help_msg(arg_dstr_t res); 261 | ARG_EXTERN void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable); 262 | ARG_EXTERN void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end); 263 | ARG_EXTERN int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode); 264 | ARG_EXTERN void arg_set_module_name(const char* name); 265 | ARG_EXTERN void arg_set_module_version(int major, int minor, int patch, const char* tag); 266 | 267 | /**** deprecated functions, for back-compatibility only ********/ 268 | ARG_EXTERN void arg_free(void** argtable); 269 | 270 | #ifdef __cplusplus 271 | } 272 | #endif 273 | #endif 274 | -------------------------------------------------------------------------------- /src/child.c: -------------------------------------------------------------------------------- 1 | #define _DEFAULT_SOURCE 2 | #define _POSIX_SOURCE 3 | #define _GNU_SOURCE 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "runner.h" 20 | #include "child.h" 21 | #include "logger.h" 22 | #include "rules/seccomp_rules.h" 23 | 24 | #include "killer.h" 25 | 26 | 27 | void close_file(FILE *fp) { 28 | if (fp != NULL) { 29 | fclose(fp); 30 | } 31 | } 32 | 33 | 34 | void child_process(FILE *log_fp, struct config *_config) { 35 | FILE *input_file = NULL, *output_file = NULL, *error_file = NULL; 36 | 37 | if (_config->max_stack != UNLIMITED) { 38 | struct rlimit max_stack; 39 | max_stack.rlim_cur = max_stack.rlim_max = (rlim_t) (_config->max_stack); 40 | if (setrlimit(RLIMIT_STACK, &max_stack) != 0) { 41 | CHILD_ERROR_EXIT(SETRLIMIT_FAILED); 42 | } 43 | } 44 | 45 | // set memory limit 46 | // if memory_limit_check_only == 0, we only check memory usage number, because setrlimit(maxrss) will cause some crash issues 47 | if (_config->memory_limit_check_only == 0) { 48 | if (_config->max_memory != UNLIMITED) { 49 | struct rlimit max_memory; 50 | max_memory.rlim_cur = max_memory.rlim_max = (rlim_t) (_config->max_memory) * 2; 51 | if (setrlimit(RLIMIT_AS, &max_memory) != 0) { 52 | CHILD_ERROR_EXIT(SETRLIMIT_FAILED); 53 | } 54 | } 55 | } 56 | 57 | // set cpu time limit (in seconds) 58 | if (_config->max_cpu_time != UNLIMITED) { 59 | struct rlimit max_cpu_time; 60 | max_cpu_time.rlim_cur = max_cpu_time.rlim_max = (rlim_t) ((_config->max_cpu_time + 1000) / 1000); 61 | if (setrlimit(RLIMIT_CPU, &max_cpu_time) != 0) { 62 | CHILD_ERROR_EXIT(SETRLIMIT_FAILED); 63 | } 64 | } 65 | 66 | // set max process number limit 67 | if (_config->max_process_number != UNLIMITED) { 68 | struct rlimit max_process_number; 69 | max_process_number.rlim_cur = max_process_number.rlim_max = (rlim_t) _config->max_process_number; 70 | if (setrlimit(RLIMIT_NPROC, &max_process_number) != 0) { 71 | CHILD_ERROR_EXIT(SETRLIMIT_FAILED); 72 | } 73 | } 74 | 75 | // set max output size limit 76 | if (_config->max_output_size != UNLIMITED) { 77 | struct rlimit max_output_size; 78 | max_output_size.rlim_cur = max_output_size.rlim_max = (rlim_t ) _config->max_output_size; 79 | if (setrlimit(RLIMIT_FSIZE, &max_output_size) != 0) { 80 | CHILD_ERROR_EXIT(SETRLIMIT_FAILED); 81 | } 82 | } 83 | 84 | if (_config->input_path != NULL) { 85 | input_file = fopen(_config->input_path, "r"); 86 | if (input_file == NULL) { 87 | CHILD_ERROR_EXIT(DUP2_FAILED); 88 | } 89 | // redirect file -> stdin 90 | // On success, these system calls return the new descriptor. 91 | // On error, -1 is returned, and errno is set appropriately. 92 | if (dup2(fileno(input_file), fileno(stdin)) == -1) { 93 | // todo log 94 | CHILD_ERROR_EXIT(DUP2_FAILED); 95 | } 96 | } 97 | 98 | if (_config->output_path != NULL) { 99 | output_file = fopen(_config->output_path, "w"); 100 | if (output_file == NULL) { 101 | CHILD_ERROR_EXIT(DUP2_FAILED); 102 | } 103 | // redirect stdout -> file 104 | if (dup2(fileno(output_file), fileno(stdout)) == -1) { 105 | CHILD_ERROR_EXIT(DUP2_FAILED); 106 | } 107 | } 108 | 109 | if (_config->error_path != NULL) { 110 | // if outfile and error_file is the same path, we use the same file pointer 111 | if (_config->output_path != NULL && strcmp(_config->output_path, _config->error_path) == 0) { 112 | error_file = output_file; 113 | } 114 | else { 115 | error_file = fopen(_config->error_path, "w"); 116 | if (error_file == NULL) { 117 | // todo log 118 | CHILD_ERROR_EXIT(DUP2_FAILED); 119 | } 120 | } 121 | // redirect stderr -> file 122 | if (dup2(fileno(error_file), fileno(stderr)) == -1) { 123 | // todo log 124 | CHILD_ERROR_EXIT(DUP2_FAILED); 125 | } 126 | } 127 | 128 | // set gid 129 | gid_t group_list[] = {_config->gid}; 130 | if (_config->gid != -1 && (setgid(_config->gid) == -1 || setgroups(sizeof(group_list) / sizeof(gid_t), group_list) == -1)) { 131 | CHILD_ERROR_EXIT(SETUID_FAILED); 132 | } 133 | 134 | // set uid 135 | if (_config->uid != -1 && setuid(_config->uid) == -1) { 136 | CHILD_ERROR_EXIT(SETUID_FAILED); 137 | } 138 | 139 | // load seccomp 140 | if (_config->seccomp_rule_name != NULL) { 141 | if (strcmp("c_cpp", _config->seccomp_rule_name) == 0) { 142 | if (c_cpp_seccomp_rules(_config) != SUCCESS) { 143 | CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED); 144 | } 145 | } 146 | else if (strcmp("c_cpp_file_io", _config->seccomp_rule_name) == 0) { 147 | if (c_cpp_file_io_seccomp_rules(_config) != SUCCESS) { 148 | CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED); 149 | } 150 | } 151 | else if (strcmp("general", _config->seccomp_rule_name) == 0) { 152 | if (general_seccomp_rules(_config) != SUCCESS ) { 153 | CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED); 154 | } 155 | } 156 | else if (strcmp("golang", _config->seccomp_rule_name) == 0) { 157 | if (golang_seccomp_rules(_config) != SUCCESS ) { 158 | CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED); 159 | } 160 | } 161 | else if (strcmp("node", _config->seccomp_rule_name) == 0) { 162 | if (node_seccomp_rules(_config) != SUCCESS ) { 163 | CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED); 164 | } 165 | } 166 | // other rules 167 | else { 168 | // rule does not exist 169 | CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED); 170 | } 171 | } 172 | 173 | execve(_config->exe_path, _config->args, _config->env); 174 | CHILD_ERROR_EXIT(EXECVE_FAILED); 175 | } 176 | -------------------------------------------------------------------------------- /src/child.h: -------------------------------------------------------------------------------- 1 | #ifndef JUDGER_CHILD_H 2 | #define JUDGER_CHILD_H 3 | 4 | #include 5 | #include "runner.h" 6 | 7 | #define CHILD_ERROR_EXIT(error_code)\ 8 | {\ 9 | LOG_FATAL(log_fp, "Error: System errno: %s; Internal errno: "#error_code, strerror(errno)); \ 10 | close_file(input_file); \ 11 | if (output_file == error_file) { \ 12 | close_file(output_file); \ 13 | } else { \ 14 | close_file(output_file); \ 15 | close_file(error_file); \ 16 | } \ 17 | raise(SIGUSR1); \ 18 | exit(EXIT_FAILURE); \ 19 | } 20 | 21 | 22 | void child_process(FILE *log_fp, struct config *_config); 23 | 24 | #endif //JUDGER_CHILD_H 25 | -------------------------------------------------------------------------------- /src/killer.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | #include "killer.h" 7 | 8 | 9 | int kill_pid(pid_t pid) { 10 | return kill(pid, SIGKILL); 11 | } 12 | 13 | 14 | void *timeout_killer(void *timeout_killer_args) { 15 | // this is a new thread, kill the process if timeout 16 | pid_t pid = ((struct timeout_killer_args *)timeout_killer_args)->pid; 17 | int timeout = ((struct timeout_killer_args *)timeout_killer_args)->timeout; 18 | // On success, pthread_detach() returns 0; on error, it returns an error number. 19 | if (pthread_detach(pthread_self()) != 0) { 20 | kill_pid(pid); 21 | return NULL; 22 | } 23 | // usleep can't be used, for time args must < 1000ms 24 | // this may sleep longer that expected, but we will have a check at the end 25 | if (sleep((unsigned int)((timeout + 1000) / 1000)) != 0) { 26 | kill_pid(pid); 27 | return NULL; 28 | } 29 | if (kill_pid(pid) != 0) { 30 | return NULL; 31 | } 32 | return NULL; 33 | } -------------------------------------------------------------------------------- /src/killer.h: -------------------------------------------------------------------------------- 1 | #ifndef JUDGER_KILLER_H 2 | #define JUDGER_KILLER_H 3 | 4 | struct timeout_killer_args { 5 | int pid; 6 | int timeout; 7 | }; 8 | 9 | int kill_pid(pid_t pid); 10 | 11 | void *timeout_killer(void *timeout_killer_args); 12 | 13 | #endif //JUDGER_KILLER_H 14 | -------------------------------------------------------------------------------- /src/logger.c: -------------------------------------------------------------------------------- 1 | #define _POSIX_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "logger.h" 10 | 11 | #define log_buffer_size 8192 12 | 13 | 14 | FILE *log_open(const char *filename) { 15 | FILE *log_fp = fopen(filename, "a"); 16 | if (log_fp == NULL) { 17 | fprintf(stderr, "can not open log file %s", filename); 18 | } 19 | return log_fp; 20 | } 21 | 22 | 23 | void log_close(FILE *log_fp) { 24 | if (log_fp != NULL) { 25 | fclose(log_fp); 26 | } 27 | } 28 | 29 | 30 | void log_write(int level, const char *source_filename, const int line, const FILE *log_fp, const char *fmt, ...) { 31 | char LOG_LEVEL_NOTE[][10] = {"FATAL", "WARNING", "INFO", "DEBUG"}; 32 | if (log_fp == NULL) { 33 | fprintf(stderr, "can not open log file"); 34 | return; 35 | } 36 | static char buffer[log_buffer_size]; 37 | static char log_buffer[log_buffer_size]; 38 | static char datetime[100]; 39 | static char line_str[20]; 40 | static time_t now; 41 | now = time(NULL); 42 | 43 | strftime(datetime, 99, "%Y-%m-%d %H:%M:%S", localtime(&now)); 44 | snprintf(line_str, 19, "%d", line); 45 | va_list ap; 46 | va_start(ap, fmt); 47 | vsnprintf(log_buffer, log_buffer_size, fmt, ap); 48 | va_end(ap); 49 | 50 | int count = snprintf(buffer, log_buffer_size, 51 | "%s [%s] [%s:%s]%s\n", 52 | LOG_LEVEL_NOTE[level], datetime, source_filename, line_str, log_buffer); 53 | // fprintf(stderr, "%s", buffer); 54 | int log_fd = fileno((FILE *) log_fp); 55 | if (flock(log_fd, LOCK_EX) == 0) { 56 | if (write(log_fd, buffer, (size_t) count) < 0) { 57 | fprintf(stderr, "write error"); 58 | return; 59 | } 60 | flock(log_fd, LOCK_UN); 61 | } 62 | else { 63 | fprintf(stderr, "flock error"); 64 | return; 65 | } 66 | } -------------------------------------------------------------------------------- /src/logger.h: -------------------------------------------------------------------------------- 1 | #ifndef JUDGER_LOGGER_H 2 | #define JUDGER_LOGGER_H 3 | 4 | #define LOG_LEVEL_FATAL 0 5 | #define LOG_LEVEL_WARNING 1 6 | #define LOG_LEVEL_INFO 2 7 | #define LOG_LEVEL_DEBUG 3 8 | 9 | 10 | FILE *log_open(const char *); 11 | 12 | void log_close(FILE *); 13 | 14 | void log_write(int level, const char *source_filename, const int line_number, const FILE *log_fp, const char *, ...); 15 | 16 | #ifdef JUDGER_DEBUG 17 | #define LOG_DEBUG(log_fp, x...) log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, log_fp, ##x) 18 | #else 19 | #define LOG_DEBUG(log_fp, x...) 20 | #endif 21 | 22 | #define LOG_INFO(log_fp, x...) log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, log_fp, ##x) 23 | #define LOG_WARNING(log_fp, x...) log_write(LOG_LEVEL_WARNING, __FILE__, __LINE__, log_fp, ##x) 24 | #define LOG_FATAL(log_fp, x...) log_write(LOG_LEVEL_FATAL, __FILE__, __LINE__, log_fp, ##x) 25 | 26 | #endif //JUDGER_LOGGER_H 27 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include "argtable3.h" 2 | #include "runner.h" 3 | 4 | #define INT_PLACE_HOLDER "" 5 | #define STR_PLACE_HOLDER "" 6 | 7 | struct arg_lit *verb, *help, *version; 8 | struct arg_int *max_cpu_time, *max_real_time, *max_memory, *max_stack, *memory_limit_check_only, 9 | *max_process_number, *max_output_size, *uid, *gid; 10 | struct arg_str *exe_path, *input_path, *output_path, *error_path, *args, *env, *log_path, *seccomp_rule_name; 11 | struct arg_end *end; 12 | 13 | int main(int argc, char *argv[]) { 14 | void *arg_table[] = { 15 | help = arg_litn(NULL, "help", 0, 1, "Display This Help And Exit"), 16 | version = arg_litn(NULL, "version", 0, 1, "Display Version Info And Exit"), 17 | max_cpu_time = arg_intn(NULL, "max_cpu_time", INT_PLACE_HOLDER, 0, 1, "Max CPU Time (ms)"), 18 | max_real_time = arg_intn(NULL, "max_real_time", INT_PLACE_HOLDER, 0, 1, "Max Real Time (ms)"), 19 | max_memory = arg_intn(NULL, "max_memory", INT_PLACE_HOLDER, 0, 1, "Max Memory (byte)"), 20 | memory_limit_check_only = arg_intn(NULL, "memory_limit_check_only", INT_PLACE_HOLDER, 0, 1, "only check memory usage, do not setrlimit (default False)"), 21 | max_stack = arg_intn(NULL, "max_stack", INT_PLACE_HOLDER, 0, 1, "Max Stack (byte, default 16M)"), 22 | max_process_number = arg_intn(NULL, "max_process_number", INT_PLACE_HOLDER, 0, 1, "Max Process Number"), 23 | max_output_size = arg_intn(NULL, "max_output_size", INT_PLACE_HOLDER, 0, 1, "Max Output Size (byte)"), 24 | 25 | exe_path = arg_str1(NULL, "exe_path", STR_PLACE_HOLDER, "Exe Path"), 26 | input_path = arg_strn(NULL, "input_path", STR_PLACE_HOLDER, 0, 1, "Input Path"), 27 | output_path = arg_strn(NULL, "output_path", STR_PLACE_HOLDER, 0, 1, "Output Path"), 28 | error_path = arg_strn(NULL, "error_path", STR_PLACE_HOLDER, 0, 1, "Error Path"), 29 | 30 | args = arg_strn(NULL, "args", STR_PLACE_HOLDER, 0, 255, "Arg"), 31 | env = arg_strn(NULL, "env", STR_PLACE_HOLDER, 0, 255, "Env"), 32 | 33 | log_path = arg_strn(NULL, "log_path", STR_PLACE_HOLDER, 0, 1, "Log Path"), 34 | seccomp_rule_name = arg_strn(NULL, "seccomp_rule_name", STR_PLACE_HOLDER, 0, 1, "Seccomp Rule Name"), 35 | 36 | uid = arg_intn(NULL, "uid", INT_PLACE_HOLDER, 0, 1, "UID (default 65534)"), 37 | gid = arg_intn(NULL, "gid", INT_PLACE_HOLDER, 0, 1, "GID (default 65534)"), 38 | 39 | end = arg_end(10), 40 | }; 41 | 42 | int exitcode = 0; 43 | char name[] = "libjudger.so"; 44 | 45 | int nerrors = arg_parse(argc, argv, arg_table); 46 | 47 | if (help->count > 0) { 48 | printf("Usage: %s", name); 49 | arg_print_syntax(stdout, arg_table, "\n\n"); 50 | arg_print_glossary(stdout, arg_table, " %-25s %s\n"); 51 | goto exit; 52 | } 53 | 54 | if (version->count > 0) { 55 | printf("Version: %d.%d.%d\n", (VERSION >> 16) & 0xff, (VERSION >> 8) & 0xff, VERSION & 0xff); 56 | goto exit; 57 | } 58 | 59 | if (nerrors > 0) { 60 | arg_print_errors(stdout, end, name); 61 | printf("Try '%s --help' for more information.\n", name); 62 | exitcode = 1; 63 | goto exit; 64 | } 65 | 66 | struct config _config; 67 | struct result _result = {0, 0, 0, 0, 0, 0, 0}; 68 | 69 | if (max_cpu_time->count > 0) { 70 | _config.max_cpu_time = *max_cpu_time->ival; 71 | } else { 72 | _config.max_cpu_time = UNLIMITED; 73 | } 74 | 75 | if (max_real_time->count > 0) { 76 | _config.max_real_time = *max_real_time->ival; 77 | } else { 78 | _config.max_real_time = UNLIMITED; 79 | } 80 | 81 | if (max_memory->count > 0) { 82 | _config.max_memory = (long) *max_memory->ival; 83 | } else { 84 | _config.max_memory = UNLIMITED; 85 | } 86 | 87 | if (memory_limit_check_only->count > 0) { 88 | _config.memory_limit_check_only = *memory_limit_check_only->ival == 0 ? 0 : 1; 89 | } else { 90 | _config.memory_limit_check_only = 0; 91 | } 92 | 93 | if (max_stack->count > 0) { 94 | _config.max_stack = (long) *max_stack->ival; 95 | } else { 96 | _config.max_stack = 16 * 1024 * 1024; 97 | } 98 | 99 | if (max_process_number->count > 0) { 100 | _config.max_process_number = *max_process_number->ival; 101 | } else { 102 | _config.max_process_number = UNLIMITED; 103 | } 104 | 105 | if (max_output_size->count > 0) { 106 | _config.max_output_size = (long) *max_output_size->ival; 107 | } else { 108 | _config.max_output_size = UNLIMITED; 109 | } 110 | 111 | _config.exe_path = (char *)*exe_path->sval; 112 | 113 | if (input_path->count > 0) { 114 | _config.input_path = (char *)input_path->sval[0]; 115 | } else { 116 | _config.input_path = "/dev/stdin"; 117 | } 118 | if (output_path->count > 0) { 119 | _config.output_path = (char *)output_path->sval[0]; 120 | } else { 121 | _config.output_path = "/dev/stdout"; 122 | } 123 | if (error_path->count > 0) { 124 | _config.error_path = (char *)error_path->sval[0]; 125 | } else { 126 | _config.error_path = "/dev/stderr"; 127 | } 128 | 129 | _config.args[0] = _config.exe_path; 130 | int i = 1; 131 | if (args->count > 0) { 132 | for (; i < args->count + 1; i++) { 133 | _config.args[i] = (char *)args->sval[i - 1]; 134 | } 135 | } 136 | _config.args[i] = NULL; 137 | 138 | i = 0; 139 | if (env->count > 0) { 140 | for (; i < env->count; i++) { 141 | _config.env[i] = (char *)env->sval[i]; 142 | } 143 | } 144 | _config.env[i] = NULL; 145 | 146 | if (log_path->count > 0) { 147 | _config.log_path = (char *)log_path->sval[0]; 148 | } else { 149 | _config.log_path = "judger.log"; 150 | } 151 | if (seccomp_rule_name->count > 0) { 152 | _config.seccomp_rule_name = (char *)seccomp_rule_name->sval[0]; 153 | } else { 154 | _config.seccomp_rule_name = NULL; 155 | } 156 | 157 | if (uid->count > 0) { 158 | _config.uid = (uid_t)*(uid->ival); 159 | } 160 | else { 161 | _config.uid = 65534; 162 | } 163 | if(gid->count > 0) { 164 | _config.gid = (gid_t)*(gid->ival); 165 | } 166 | else { 167 | _config.gid = 65534; 168 | } 169 | 170 | run(&_config, &_result); 171 | 172 | printf("{\n" 173 | " \"cpu_time\": %d,\n" 174 | " \"real_time\": %d,\n" 175 | " \"memory\": %ld,\n" 176 | " \"signal\": %d,\n" 177 | " \"exit_code\": %d,\n" 178 | " \"error\": %d,\n" 179 | " \"result\": %d\n" 180 | "}", 181 | _result.cpu_time, 182 | _result.real_time, 183 | _result.memory, 184 | _result.signal, 185 | _result.exit_code, 186 | _result.error, 187 | _result.result); 188 | 189 | exit: 190 | arg_freetable(arg_table, sizeof(arg_table) / sizeof(arg_table[0])); 191 | return exitcode; 192 | } 193 | -------------------------------------------------------------------------------- /src/rules/c_cpp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../runner.h" 9 | 10 | 11 | int _c_cpp_seccomp_rules(struct config *_config, bool allow_write_file) { 12 | int syscalls_whitelist[] = { 13 | SCMP_SYS(access), 14 | SCMP_SYS(arch_prctl), 15 | SCMP_SYS(brk), 16 | SCMP_SYS(clock_gettime), 17 | SCMP_SYS(close), 18 | SCMP_SYS(exit_group), 19 | SCMP_SYS(faccessat), 20 | SCMP_SYS(fstat), 21 | SCMP_SYS(futex), 22 | SCMP_SYS(getrandom), 23 | SCMP_SYS(lseek), 24 | SCMP_SYS(mmap), 25 | SCMP_SYS(mprotect), 26 | SCMP_SYS(munmap), 27 | SCMP_SYS(newfstatat), 28 | SCMP_SYS(pread64), 29 | SCMP_SYS(prlimit64), 30 | SCMP_SYS(read), 31 | SCMP_SYS(readlink), 32 | SCMP_SYS(readv), 33 | SCMP_SYS(rseq), 34 | SCMP_SYS(set_robust_list), 35 | SCMP_SYS(set_tid_address), 36 | SCMP_SYS(write), 37 | SCMP_SYS(writev) 38 | }; 39 | 40 | int syscalls_whitelist_length = sizeof(syscalls_whitelist) / sizeof(int); 41 | scmp_filter_ctx ctx = NULL; 42 | 43 | // load seccomp rules 44 | ctx = seccomp_init(SCMP_ACT_KILL); 45 | if (!ctx) { 46 | return LOAD_SECCOMP_FAILED; 47 | } 48 | 49 | for (int i = 0; i < syscalls_whitelist_length; i++) { 50 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls_whitelist[i], 0) != 0) { 51 | return LOAD_SECCOMP_FAILED; 52 | } 53 | } 54 | 55 | // extra rule for execve 56 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)(_config->exe_path))) != 0) { 57 | return LOAD_SECCOMP_FAILED; 58 | } 59 | 60 | if (allow_write_file) { 61 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0) != 0) { 62 | return LOAD_SECCOMP_FAILED; 63 | } 64 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0) != 0) { 65 | return LOAD_SECCOMP_FAILED; 66 | } 67 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup), 0) != 0) { 68 | return LOAD_SECCOMP_FAILED; 69 | } 70 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0) != 0) { 71 | return LOAD_SECCOMP_FAILED; 72 | } 73 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 0) != 0) { 74 | return LOAD_SECCOMP_FAILED; 75 | } 76 | } else { 77 | // do not allow "w" and "rw" 78 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) != 0) { 79 | return LOAD_SECCOMP_FAILED; 80 | } 81 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) != 0) { 82 | return LOAD_SECCOMP_FAILED; 83 | } 84 | } 85 | 86 | if (seccomp_load(ctx) != 0) { 87 | return LOAD_SECCOMP_FAILED; 88 | } 89 | seccomp_release(ctx); 90 | return 0; 91 | } 92 | 93 | int c_cpp_seccomp_rules(struct config *_config, bool allow_write_file) { 94 | return _c_cpp_seccomp_rules(_config, false); 95 | } 96 | -------------------------------------------------------------------------------- /src/rules/c_cpp_file_io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "seccomp_rules.h" 3 | 4 | 5 | int c_cpp_file_io_seccomp_rules(struct config *_config) { 6 | return _c_cpp_seccomp_rules(_config, true); 7 | } 8 | -------------------------------------------------------------------------------- /src/rules/general.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../runner.h" 9 | 10 | 11 | int general_seccomp_rules(struct config *_config) { 12 | int syscalls_blacklist[] = {SCMP_SYS(clone), 13 | SCMP_SYS(fork), SCMP_SYS(vfork), 14 | SCMP_SYS(kill), 15 | #ifdef __NR_execveat 16 | SCMP_SYS(execveat) 17 | #endif 18 | }; 19 | int syscalls_blacklist_length = sizeof(syscalls_blacklist) / sizeof(int); 20 | scmp_filter_ctx ctx = NULL; 21 | // load seccomp rules 22 | ctx = seccomp_init(SCMP_ACT_ALLOW); 23 | if (!ctx) { 24 | return LOAD_SECCOMP_FAILED; 25 | } 26 | for (int i = 0; i < syscalls_blacklist_length; i++) { 27 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, syscalls_blacklist[i], 0) != 0) { 28 | return LOAD_SECCOMP_FAILED; 29 | } 30 | } 31 | // use SCMP_ACT_KILL for socket, python will be killed immediately 32 | if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 0) != 0) { 33 | return LOAD_SECCOMP_FAILED; 34 | } 35 | // add extra rule for execve 36 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_NE, (scmp_datum_t)(_config->exe_path))) != 0) { 37 | return LOAD_SECCOMP_FAILED; 38 | } 39 | // do not allow "w" and "rw" using open 40 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) { 41 | return LOAD_SECCOMP_FAILED; 42 | } 43 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) { 44 | return LOAD_SECCOMP_FAILED; 45 | } 46 | // do not allow "w" and "rw" using openat 47 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) { 48 | return LOAD_SECCOMP_FAILED; 49 | } 50 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) { 51 | return LOAD_SECCOMP_FAILED; 52 | } 53 | 54 | if (seccomp_load(ctx) != 0) { 55 | return LOAD_SECCOMP_FAILED; 56 | } 57 | seccomp_release(ctx); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /src/rules/golang.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../runner.h" 9 | 10 | 11 | int golang_seccomp_rules(struct config *_config) { 12 | int syscalls_blacklist[] = {SCMP_SYS(socket), 13 | SCMP_SYS(fork), SCMP_SYS(vfork), 14 | SCMP_SYS(kill), 15 | #ifdef __NR_execveat 16 | SCMP_SYS(execveat) 17 | #endif 18 | }; 19 | int syscalls_blacklist_length = sizeof(syscalls_blacklist) / sizeof(int); 20 | scmp_filter_ctx ctx = NULL; 21 | // load seccomp rules 22 | ctx = seccomp_init(SCMP_ACT_ALLOW); 23 | if (!ctx) { 24 | return LOAD_SECCOMP_FAILED; 25 | } 26 | for (int i = 0; i < syscalls_blacklist_length; i++) { 27 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, syscalls_blacklist[i], 0) != 0) { 28 | return LOAD_SECCOMP_FAILED; 29 | } 30 | } 31 | // do not allow "w" and "rw" using open 32 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) { 33 | return LOAD_SECCOMP_FAILED; 34 | } 35 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) { 36 | return LOAD_SECCOMP_FAILED; 37 | } 38 | // do not allow "w" and "rw" using openat 39 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) { 40 | return LOAD_SECCOMP_FAILED; 41 | } 42 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) { 43 | return LOAD_SECCOMP_FAILED; 44 | } 45 | 46 | if (seccomp_load(ctx) != 0) { 47 | return LOAD_SECCOMP_FAILED; 48 | } 49 | seccomp_release(ctx); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /src/rules/node.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../runner.h" 9 | 10 | 11 | int node_seccomp_rules(struct config *_config) { 12 | int syscalls_blacklist[] = {SCMP_SYS(socket), 13 | SCMP_SYS(fork), SCMP_SYS(vfork), 14 | SCMP_SYS(kill), 15 | #ifdef __NR_execveat 16 | SCMP_SYS(execveat) 17 | #endif 18 | }; 19 | int syscalls_blacklist_length = sizeof(syscalls_blacklist) / sizeof(int); 20 | scmp_filter_ctx ctx = NULL; 21 | // load seccomp rules 22 | ctx = seccomp_init(SCMP_ACT_ALLOW); 23 | if (!ctx) { 24 | return LOAD_SECCOMP_FAILED; 25 | } 26 | for (int i = 0; i < syscalls_blacklist_length; i++) { 27 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, syscalls_blacklist[i], 0) != 0) { 28 | return LOAD_SECCOMP_FAILED; 29 | } 30 | } 31 | if (seccomp_load(ctx) != 0) { 32 | return LOAD_SECCOMP_FAILED; 33 | } 34 | seccomp_release(ctx); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/rules/seccomp_rules.h: -------------------------------------------------------------------------------- 1 | #ifndef JUDGER_SECCOMP_RULES_H 2 | #define JUDGER_SECCOMP_RULES_H 3 | #include 4 | #include "../runner.h" 5 | 6 | int _c_cpp_seccomp_rules(struct config *_config, bool allow_write_file); 7 | int c_cpp_seccomp_rules(struct config *_config); 8 | int general_seccomp_rules(struct config *_config); 9 | int c_cpp_file_io_seccomp_rules(struct config *_config); 10 | int golang_seccomp_rules(struct config *_config); 11 | int node_seccomp_rules(struct config *_config); 12 | 13 | #endif //JUDGER_SECCOMP_RULES_H 14 | -------------------------------------------------------------------------------- /src/runner.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #define _POSIX_SOURCE 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "runner.h" 18 | #include "killer.h" 19 | #include "child.h" 20 | #include "logger.h" 21 | 22 | void init_result(struct result *_result) { 23 | _result->result = _result->error = SUCCESS; 24 | _result->cpu_time = _result->real_time = _result->signal = _result->exit_code = 0; 25 | _result->memory = 0; 26 | } 27 | 28 | 29 | void run(struct config *_config, struct result *_result) { 30 | // init log fp 31 | FILE *log_fp = log_open(_config->log_path); 32 | 33 | // init result 34 | init_result(_result); 35 | 36 | // check whether current user is root 37 | uid_t uid = getuid(); 38 | if (uid != 0) { 39 | ERROR_EXIT(ROOT_REQUIRED); 40 | } 41 | 42 | // check args 43 | if ((_config->max_cpu_time < 1 && _config->max_cpu_time != UNLIMITED) || 44 | (_config->max_real_time < 1 && _config->max_real_time != UNLIMITED) || 45 | (_config->max_stack < 1) || 46 | (_config->max_memory < 1 && _config->max_memory != UNLIMITED) || 47 | (_config->max_process_number < 1 && _config->max_process_number != UNLIMITED) || 48 | (_config->max_output_size < 1 && _config->max_output_size != UNLIMITED)) { 49 | ERROR_EXIT(INVALID_CONFIG); 50 | } 51 | 52 | // record current time 53 | struct timeval start, end; 54 | gettimeofday(&start, NULL); 55 | 56 | pid_t child_pid = fork(); 57 | 58 | // pid < 0 shows clone failed 59 | if (child_pid < 0) { 60 | ERROR_EXIT(FORK_FAILED); 61 | } 62 | else if (child_pid == 0) { 63 | child_process(log_fp, _config); 64 | } 65 | else if (child_pid > 0){ 66 | // create new thread to monitor process running time 67 | pthread_t tid = 0; 68 | if (_config->max_real_time != UNLIMITED) { 69 | struct timeout_killer_args killer_args; 70 | 71 | killer_args.timeout = _config->max_real_time; 72 | killer_args.pid = child_pid; 73 | if (pthread_create(&tid, NULL, timeout_killer, (void *) (&killer_args)) != 0) { 74 | kill_pid(child_pid); 75 | ERROR_EXIT(PTHREAD_FAILED); 76 | } 77 | } 78 | 79 | int status; 80 | struct rusage resource_usage; 81 | 82 | // wait for child process to terminate 83 | // on success, returns the process ID of the child whose state has changed; 84 | // On error, -1 is returned. 85 | if (wait4(child_pid, &status, WSTOPPED, &resource_usage) == -1) { 86 | kill_pid(child_pid); 87 | ERROR_EXIT(WAIT_FAILED); 88 | } 89 | // get end time 90 | gettimeofday(&end, NULL); 91 | _result->real_time = (int) (end.tv_sec * 1000 + end.tv_usec / 1000 - start.tv_sec * 1000 - start.tv_usec / 1000); 92 | 93 | // process exited, we may need to cancel timeout killer thread 94 | if (_config->max_real_time != UNLIMITED) { 95 | if (pthread_cancel(tid) != 0) { 96 | // todo logging 97 | }; 98 | } 99 | 100 | if (WIFSIGNALED(status) != 0) { 101 | _result->signal = WTERMSIG(status); 102 | } 103 | 104 | if(_result->signal == SIGUSR1) { 105 | _result->result = SYSTEM_ERROR; 106 | } 107 | else { 108 | _result->exit_code = WEXITSTATUS(status); 109 | _result->cpu_time = (int) (resource_usage.ru_utime.tv_sec * 1000 + 110 | resource_usage.ru_utime.tv_usec / 1000); 111 | _result->memory = resource_usage.ru_maxrss * 1024; 112 | 113 | if (_result->exit_code != 0) { 114 | _result->result = RUNTIME_ERROR; 115 | } 116 | 117 | if (_result->signal == SIGSEGV) { 118 | if (_config->max_memory != UNLIMITED && _result->memory > _config->max_memory) { 119 | _result->result = MEMORY_LIMIT_EXCEEDED; 120 | } 121 | else { 122 | _result->result = RUNTIME_ERROR; 123 | } 124 | } 125 | else { 126 | if (_result->signal != 0) { 127 | _result->result = RUNTIME_ERROR; 128 | } 129 | if (_config->max_memory != UNLIMITED && _result->memory > _config->max_memory) { 130 | _result->result = MEMORY_LIMIT_EXCEEDED; 131 | } 132 | if (_config->max_real_time != UNLIMITED && _result->real_time > _config->max_real_time) { 133 | _result->result = REAL_TIME_LIMIT_EXCEEDED; 134 | } 135 | if (_config->max_cpu_time != UNLIMITED && _result->cpu_time > _config->max_cpu_time) { 136 | _result->result = CPU_TIME_LIMIT_EXCEEDED; 137 | } 138 | } 139 | } 140 | 141 | log_close(log_fp); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/runner.h: -------------------------------------------------------------------------------- 1 | #ifndef JUDGER_RUNNER_H 2 | #define JUDGER_RUNNER_H 3 | 4 | #include 5 | #include 6 | 7 | // (ver >> 16) & 0xff, (ver >> 8) & 0xff, ver & 0xff -> real version 8 | #define VERSION 0x020101 9 | 10 | #define UNLIMITED -1 11 | 12 | #define LOG_ERROR(error_code) LOG_FATAL(log_fp, "Error: "#error_code); 13 | 14 | #define ERROR_EXIT(error_code)\ 15 | {\ 16 | LOG_ERROR(error_code); \ 17 | _result->error = error_code; \ 18 | log_close(log_fp); \ 19 | return; \ 20 | } 21 | 22 | #define ARGS_MAX_NUMBER 256 23 | #define ENV_MAX_NUMBER 256 24 | 25 | 26 | enum { 27 | SUCCESS = 0, 28 | INVALID_CONFIG = -1, 29 | FORK_FAILED = -2, 30 | PTHREAD_FAILED = -3, 31 | WAIT_FAILED = -4, 32 | ROOT_REQUIRED = -5, 33 | LOAD_SECCOMP_FAILED = -6, 34 | SETRLIMIT_FAILED = -7, 35 | DUP2_FAILED = -8, 36 | SETUID_FAILED = -9, 37 | EXECVE_FAILED = -10, 38 | SPJ_ERROR = -11 39 | }; 40 | 41 | 42 | struct config { 43 | int max_cpu_time; 44 | int max_real_time; 45 | long max_memory; 46 | long max_stack; 47 | int max_process_number; 48 | long max_output_size; 49 | int memory_limit_check_only; 50 | char *exe_path; 51 | char *input_path; 52 | char *output_path; 53 | char *error_path; 54 | char *args[ARGS_MAX_NUMBER]; 55 | char *env[ENV_MAX_NUMBER]; 56 | char *log_path; 57 | char *seccomp_rule_name; 58 | uid_t uid; 59 | gid_t gid; 60 | }; 61 | 62 | 63 | enum { 64 | WRONG_ANSWER = -1, 65 | CPU_TIME_LIMIT_EXCEEDED = 1, 66 | REAL_TIME_LIMIT_EXCEEDED = 2, 67 | MEMORY_LIMIT_EXCEEDED = 3, 68 | RUNTIME_ERROR = 4, 69 | SYSTEM_ERROR = 5 70 | }; 71 | 72 | 73 | struct result { 74 | int cpu_time; 75 | int real_time; 76 | long memory; 77 | int signal; 78 | int exit_code; 79 | int error; 80 | int result; 81 | }; 82 | 83 | 84 | void run(struct config *, struct result *); 85 | #endif //JUDGER_RUNNER_H 86 | -------------------------------------------------------------------------------- /tests/Dockerfile-16.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | RUN apt-get update && apt-get install -y cmake python python3 libseccomp-dev gcc g++ 3 | WORKDIR /src 4 | -------------------------------------------------------------------------------- /tests/Dockerfile-18.04: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | RUN apt-get update && apt-get install -y cmake python python3 python3-pip libseccomp-dev gcc g++ strace && pip3 install setuptools --upgrade 3 | WORKDIR /src -------------------------------------------------------------------------------- /tests/Nodejs_and_core/base.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs") 2 | const path = require("path") 3 | const execSync = require("child_process").execSync 4 | 5 | var out_base_path = '/tmp/judge' 6 | var compile_base_path = "" 7 | var compile_c = function(name){ 8 | out_path =path.join(out_base_path,'main') 9 | execSync(`gcc -o ${out_path} ${path.join(this.compile_base_path,name)}`) 10 | return out_path 11 | } 12 | 13 | var compile_cpp = function(name){ 14 | out_path =path.join(out_base_path,'main') 15 | execSync(`g++ -o ${out_path} ${path.join(this.compile_base_path,name)}`) 16 | return out_path 17 | } 18 | 19 | var make_input = content =>{ 20 | fs.writeFileSync('/tmp/judge/input',content,{'encoding':'utf-8'}) 21 | return '/tmp/judge/input' 22 | } 23 | 24 | var read_input = read_path => { 25 | return fs.readFileSync(read_path,{'encoding':'utf-8'}) 26 | } 27 | 28 | var output_path = ()=>{ 29 | return '/tmp/judge/output' 30 | } 31 | 32 | var error_path = ()=>{ 33 | return '/tmp/judge/error' 34 | } 35 | 36 | var mkdir = _path => { 37 | execSync(`mkdir -p ${_path}`) 38 | } 39 | 40 | var rmdir = _path => { 41 | execSync(`rm -r ${_path}`) 42 | } 43 | 44 | var baseconfig = ()=>{ 45 | return { 46 | max_cpu_time:1000, 47 | max_real_time:8000, 48 | max_memory:128*1024*1024, 49 | max_stack:128*1024*1024, 50 | max_process_number:8, 51 | max_output_size:128*1024*1024, 52 | exe_path:"/dev/null", 53 | input_path:"/dev/null", 54 | output_path:"/dev/null", 55 | error_path:"/dev/null", 56 | args:[], 57 | env:[], 58 | log_path:"/dev/null", 59 | seccomp_rule_name:null, 60 | gid:0, 61 | uid:0, 62 | info:false, 63 | debug:false, 64 | } 65 | } 66 | 67 | module.exports = { 68 | compile_c,compile_cpp,make_input,read_input,mkdir,rmdir,baseconfig,compile_base_path, 69 | output_path, 70 | error_path 71 | } 72 | -------------------------------------------------------------------------------- /tests/Nodejs_and_core/test_integration.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert") 2 | const path = require("path") 3 | var judger = require("../../bindings/NodeJS") 4 | var base = require('./base.js') 5 | var signal = require("os").constants.signals 6 | 7 | 8 | var compile_base_path = base.compile_base_path = path.join(__dirname,"../test_src","integration") 9 | 10 | 11 | 12 | describe('#常用测试',function(){ 13 | 14 | 15 | before( ()=>{ 16 | //mkdir /tmp/judge 17 | base.mkdir('/tmp/judge') 18 | }) 19 | after( ()=>{ 20 | base.rmdir('/tmp/judge') 21 | }) 22 | 23 | it('args must be a list 1',()=>{ 24 | assert.throws(()=>judger.run({args:{},output_path:"/dev/null"}),/args must be a list$/) 25 | }) 26 | 27 | it('args must be a list 2',()=>{ 28 | assert.throws(()=>judger.run({args:"1234",output_path:"/dev/null"}),/args must be a list$/) 29 | }) 30 | 31 | it('test_env_must_be_list',()=>{ 32 | assert.throws(()=>judger.run({env:"1234",output_path:"/dev/null"}),/env must be a list$/) 33 | }) 34 | it('test_seccomp_rule_can_be_none',()=>{ 35 | let ret = judger.run({ output_path:"/dev/null",exe_path:"/bin/ls",args:["/"],env:["a=b"] }) 36 | assert.strictEqual(ret.result,0) 37 | }) 38 | 39 | it('test normal.c',()=>{ 40 | let config = base.baseconfig() 41 | config["exe_path"] = base.compile_c("normal.c") 42 | config["input_path"] = base.make_input("judger_test") 43 | config["output_path"] = config["error_path"] = base.output_path() 44 | let ret = judger.run(config) 45 | let output = "judger_test\nHello world" 46 | let content = base.read_input( base.output_path()) 47 | assert.strictEqual(content,output) 48 | }) 49 | 50 | it('test math.c' ,()=>{ 51 | let config = base.baseconfig() 52 | config["exe_path"] = base.compile_c("math.c") 53 | config["output_path"] = config["error_path"] = base.output_path() 54 | let ret = judger.run(config) 55 | assert.strictEqual(ret.result,judger.RESULT_SUCCESS) 56 | let content = base.read_input( base.output_path()) 57 | assert.strictEqual(content,"abs 1024") 58 | }) 59 | 60 | it('test_args',()=>{ 61 | let config = base.baseconfig() 62 | config["exe_path"] = base.compile_c("args.c") 63 | config["args"] = ["test", "hehe", "000"] 64 | config["output_path"] = config["error_path"] = base.output_path() 65 | 66 | let result = judger.run(config) 67 | let output = "argv[0]: /tmp/judge/main\nargv[1]: test\nargv[2]: hehe\nargv[3]: 000\n" 68 | assert.strictEqual(result.result, judger.RESULT_SUCCESS) 69 | assert.strictEqual(output, base.read_input(config["output_path"])) 70 | 71 | }) 72 | 73 | it('test env',()=>{ 74 | let config = base.baseconfig() 75 | config["exe_path"] = base.compile_c("env.c") 76 | config["output_path"] = config["error_path"] = base.output_path() 77 | config["env"] = ["env=judger_test","test=judger"] 78 | let result = judger.run(config) 79 | let output = "judger_test\njudger\n" 80 | assert.strictEqual(result["result"], judger.RESULT_SUCCESS) 81 | assert.strictEqual(output, base.read_input(config["output_path"])) 82 | 83 | }) 84 | 85 | it('test real time',()=>{ 86 | let config = base.baseconfig() 87 | config["exe_path"] = base.compile_c("sleep.c") 88 | config["max_real_time"] = 3 89 | let result = judger.run(config) 90 | //assert.strictEqual(result["result"], judger.RESULT_REAL_TIME_LIMIT_EXCEEDED) 91 | assert.strictEqual(result["signal"], signal.SIGKILL) 92 | assert.ok(result["real_time"] >= config["max_real_time"]) 93 | 94 | }) 95 | 96 | it('test cpu time',()=>{ 97 | let config = base.baseconfig() 98 | config["exe_path"] = base.compile_c("while1.c") 99 | let result= judger.run(config) 100 | 101 | assert.strictEqual(result["result"], judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) 102 | assert.strictEqual(result["signal"], signal.SIGKILL) 103 | assert.ok(result["cpu_time"] >= config["max_cpu_time"]) 104 | 105 | }) 106 | 107 | it('test memory1',()=>{ 108 | let config = base.baseconfig() 109 | config["max_memory"] = 64 * 1024 * 1024 110 | config["exe_path"] = base.compile_c("memory1.c") 111 | let result= judger.run(config) 112 | //# malloc succeeded 113 | assert.ok(result["memory"] > 80 * 1024 * 1024) 114 | assert.strictEqual(result["result"], judger.RESULT_MEMORY_LIMIT_EXCEEDED) 115 | }) 116 | 117 | it('test memory2',()=>{ 118 | let config = base.baseconfig() 119 | config["max_memory"] = 64 * 1024 * 1024 120 | config["exe_path"] = base.compile_c("memory2.c") 121 | let result= judger.run(config) 122 | //# malloc failed, return 1 123 | assert.strictEqual(result["exit_code"], 1) 124 | //# malloc failed, so it should use a little memory 125 | assert.ok(result["memory"] < 12 * 1024 * 1024) 126 | assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR) 127 | }) 128 | 129 | it('test memory3',()=>{ 130 | let config = base.baseconfig() 131 | config["max_memory"] = 512 * 1024 * 1024 132 | config["exe_path"] = base.compile_c("memory3.c") 133 | let result= judger.run(config) 134 | assert.strictEqual(result["result"], judger.RESULT_SUCCESS) 135 | assert.ok(result["memory"] >= 102400000 * 4) 136 | }) 137 | it('test re1',()=>{ 138 | let config = base.baseconfig() 139 | config["exe_path"] = base.compile_c("re1.c") 140 | let result= judger.run(config) 141 | //# re1.c return 25 142 | assert.strictEqual(result["exit_code"], 25) 143 | 144 | }) 145 | it('test re2',()=>{ 146 | let config = base.baseconfig() 147 | config["exe_path"] = base.compile_c("re2.c") 148 | let result= judger.run(config) 149 | assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR) 150 | assert.strictEqual(result["signal"], signal.SIGSEGV) 151 | }) 152 | it('test child proc cpu time limit',()=>{ 153 | let config = base.baseconfig() 154 | 155 | config["exe_path"] = base.compile_c("child_proc_cpu_time_limit.c") 156 | let result= judger.run(config) 157 | assert.strictEqual(result["result"], judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) 158 | 159 | }) 160 | it('test child proc real time limit',()=>{ 161 | let config = base.baseconfig() 162 | config["exe_path"] = base.compile_c("child_proc_real_time_limit.c") 163 | config["max_real_time"] = 3 164 | let result= judger.run(config) 165 | assert.strictEqual(result["result"], judger.RESULT_REAL_TIME_LIMIT_EXCEEDED) 166 | assert.strictEqual(result["signal"], signal.SIGKILL) 167 | }) 168 | it('test stdout and stderr',()=>{ 169 | let config = base.baseconfig() 170 | config["exe_path"] = base.compile_c("stdout_stderr.c") 171 | config["output_path"] = config["error_path"] = base.output_path() 172 | let result= judger.run(config) 173 | assert.strictEqual(result["result"], judger.RESULT_SUCCESS) 174 | let output = "stderr\n+++++++++++++++\n--------------\nstdout\n" 175 | assert.strictEqual(output, base.read_input(config["output_path"])) 176 | }) 177 | it('test uid and gid',()=>{ 178 | let config = base.baseconfig() 179 | config["exe_path"] = base.compile_c("uid_gid.c") 180 | config["output_path"] = config["error_path"] = base.output_path() 181 | config["uid"] = 65534 182 | config["gid"] = 65534 183 | let result= judger.run(config) 184 | assert.strictEqual(result["result"], judger.RESULT_SUCCESS) 185 | output = "uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)\nuid 65534\ngid 65534\n" 186 | assert.strictEqual(output, base.read_input(config["output_path"])) 187 | 188 | }) 189 | it('test gcc random',()=>{ 190 | let config = base.baseconfig() 191 | config["max_memory"] = judger.UNLIMITED 192 | config["exe_path"] = "/usr/bin/gcc" 193 | config["args"] = [path.join(compile_base_path,'gcc_random.c'), 194 | "-o", '/tmp/judge/gcc_random'] 195 | let result= judger.run(config) 196 | assert.ok(result["real_time"] >= 2000) 197 | 198 | }) 199 | it('test cpp meta',()=>{ 200 | let config = base.baseconfig() 201 | config["exe_path"] = "/usr/bin/g++" 202 | config["max_memory"] = 1024 * 1024 * 1024 203 | config["args"] = [path.join(compile_base_path,'cpp_meta.cpp'), 204 | "-o",'/tmp/judge/cpp_meta'] 205 | let result= judger.run(config) 206 | assert.strictEqual(result["result"], judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) 207 | assert.ok(result["cpu_time"] > 1500) 208 | assert.ok(result["real_time"] >= 2000) 209 | }) 210 | it('test output size',()=>{ 211 | let config = base.baseconfig() 212 | config["exe_path"] = base.compile_c("output_size.c") 213 | config["output_path"] = base.output_path() 214 | config["max_output_size"] = 1000 * 10 215 | let result= judger.run(config) 216 | assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR) 217 | assert.ok(base.read_input("/tmp/judge/fsize_test").length <= 1000*10) 218 | }) 219 | it('test stack size',()=>{ 220 | let config = base.baseconfig() 221 | config["max_memory"] = 256 * 1024 * 1024 222 | config["exe_path"] = base.compile_c("stack.c") 223 | config["max_stack"] = 16 * 1024 * 1024 224 | config["output_path"] = config["error_path"] = base.output_path() 225 | 226 | let result= judger.run(config) 227 | assert.strictEqual(result["result"], judger.RESULT_RUNTIME_ERROR) 228 | 229 | config["max_stack"] = 128 * 1024 * 1024 230 | result= judger.run(config).result 231 | assert.strictEqual(result["result"], judger.RESULT_SUCCESS) 232 | assert.strictEqual("big stack", base.read_input(config["output_path"])) 233 | 234 | }) 235 | it('test writev',()=>{ 236 | let config = base.baseconfig() 237 | config["exe_path"] = base.compile_cpp("writev.cpp") 238 | config["seccomp_rule_name"] = "c_cpp" 239 | config["input_path"] = base.make_input("111" * 10000 + "\n") 240 | config["output_path"] = config["error_path"] = base.output_path() 241 | 242 | let result= judger.run(config) 243 | assert.strictEqual(result["result"], judger.RESULT_SUCCESS) 244 | }) 245 | }) 246 | -------------------------------------------------------------------------------- /tests/Python_and_core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QingdaoU/Judger/d19a6dc192ebd7f41fed44ae6e091575ef22906a/tests/Python_and_core/__init__.py -------------------------------------------------------------------------------- /tests/Python_and_core/test.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | from __future__ import print_function 3 | import sys 4 | import _judger 5 | from unittest import TestCase, main 6 | 7 | from testcase.integration.test import IntegrationTest 8 | from testcase.seccomp.test import SeccompTest 9 | 10 | ver = _judger.VERSION 11 | print("Judger version %d.%d.%d" % ((ver >> 16) & 0xff, (ver >> 8) & 0xff, ver & 0xff)) 12 | print(sys.version) 13 | main() 14 | -------------------------------------------------------------------------------- /tests/Python_and_core/testcase/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QingdaoU/Judger/d19a6dc192ebd7f41fed44ae6e091575ef22906a/tests/Python_and_core/testcase/__init__.py -------------------------------------------------------------------------------- /tests/Python_and_core/testcase/base.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | from __future__ import print_function 3 | import os 4 | import random 5 | import shutil 6 | import copy 7 | from unittest import TestCase 8 | 9 | 10 | class RunResult(object): 11 | cpu_time_limited = 1 12 | real_time_limit_exceeded = 2 13 | memory_limit_exceeded = 3 14 | runtime_error = 4 15 | system_error = 5 16 | 17 | 18 | class BaseTestCase(TestCase): 19 | BAD_SYSTEM_CALL = 31 20 | 21 | def init_workspace(self, language): 22 | base_workspace = "/tmp" 23 | workspace = os.path.join(base_workspace, language) 24 | shutil.rmtree(workspace, ignore_errors=True) 25 | os.makedirs(workspace) 26 | return workspace 27 | 28 | def tearDown(self): 29 | shutil.rmtree(self.workspace, ignore_errors=True) 30 | 31 | def rand_str(self): 32 | return "".join([random.choice("123456789abcdef") for _ in range(12)]) 33 | 34 | def _compile_c(self, src_name, extra_flags=None): 35 | path = os.path.dirname(os.path.abspath(__file__)) 36 | exe_path = os.path.join(self.workspace, src_name.split("/")[-1].split(".")[0]) 37 | flags = " " 38 | if extra_flags: 39 | flags += " ".join(extra_flags) 40 | cmd = ("gcc {0} -g -O0 -static -o {1}" + flags).format(os.path.join(path, src_name), exe_path) 41 | if os.system(cmd): 42 | raise AssertionError("compile error, cmd: {0}".format(cmd)) 43 | return exe_path 44 | 45 | def _compile_cpp(self, src_name): 46 | path = os.path.dirname(os.path.abspath(__file__)) 47 | exe_path = os.path.join(self.workspace, src_name.split("/")[-1].split(".")[0]) 48 | cmd = "g++ {0} -g -O0 -o {1}".format(os.path.join(path, src_name), exe_path) 49 | if os.system(cmd): 50 | raise AssertionError("compile error, cmd: {0}".format(cmd)) 51 | return exe_path 52 | 53 | def make_input(self, content): 54 | path = os.path.join(self.workspace, self.rand_str()) 55 | with open(path, "w") as f: 56 | f.write(content) 57 | return path 58 | 59 | def output_path(self): 60 | return os.path.join(self.workspace, self.rand_str()) 61 | 62 | def output_content(self, path): 63 | with open(path, "r") as f: 64 | return f.read() 65 | 66 | @property 67 | def base_config(self): 68 | config = {"max_cpu_time": 1000, 69 | "max_real_time": 3000, 70 | "max_memory": 128 * 1024 * 1024, 71 | "max_stack": 32 * 1024 * 1024, 72 | "max_process_number": 10, 73 | "max_output_size": 1024 * 1024, 74 | "exe_path": "/bin/ls", 75 | "input_path": "/dev/null", 76 | "output_path": "/dev/null", 77 | "error_path": "/dev/null", 78 | "args": [], 79 | "env": ["env=judger_test", "test=judger"], 80 | "log_path": "judger_test.log", 81 | "seccomp_rule_name": None, 82 | "uid": 0, 83 | "gid": 0} 84 | return config 85 | -------------------------------------------------------------------------------- /tests/Python_and_core/testcase/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QingdaoU/Judger/d19a6dc192ebd7f41fed44ae6e091575ef22906a/tests/Python_and_core/testcase/integration/__init__.py -------------------------------------------------------------------------------- /tests/Python_and_core/testcase/integration/test.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | from __future__ import print_function 3 | import sys 4 | import signal 5 | import os 6 | import resource 7 | import _judger 8 | 9 | from .. import base 10 | 11 | 12 | class IntegrationTest(base.BaseTestCase): 13 | def setUp(self): 14 | print("Running", self._testMethodName) 15 | self.workspace = self.init_workspace("integration") 16 | 17 | def _compile_c(self, src_name, extra_flags=None): 18 | return super(IntegrationTest, self)._compile_c("../../test_src/integration/" + src_name, extra_flags) 19 | 20 | def _compile_cpp(self, src_name): 21 | return super(IntegrationTest, self)._compile_cpp("../../test_src/integration/" + src_name) 22 | 23 | def test_args_must_be_list(self): 24 | with self.assertRaisesRegexp(ValueError, "args must be a list"): 25 | _judger.run(max_cpu_time=1000, max_real_time=2000, 26 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 27 | max_process_number=200, max_output_size=10000, exe_path="1.out", 28 | input_path="1.in", output_path="1.out", error_path="1.out", 29 | args="12344", env=["a=b"], log_path="1.log", 30 | seccomp_rule_name="1.so", uid=0, gid=0) 31 | 32 | with self.assertRaisesRegexp(ValueError, "args must be a list"): 33 | _judger.run(max_cpu_time=1000, max_real_time=2000, 34 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 35 | max_process_number=200, max_output_size=10000, exe_path="1.out", 36 | input_path="1.in", output_path="1.out", error_path="1.out", 37 | args={"k": "v"}, env=["a=b"], log_path="1.log", 38 | seccomp_rule_name="1.so", uid=0, gid=0) 39 | 40 | def test_args_item_must_be_string(self): 41 | with self.assertRaisesRegexp(ValueError, "args item must be a string"): 42 | _judger.run(max_cpu_time=1000, max_real_time=2000, 43 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 44 | max_process_number=200, max_output_size=10000, exe_path="1.out", 45 | input_path="1.in", output_path="1.out", error_path="1.out", 46 | args=["1234", 1234], env=["a=b"], log_path="1.log", 47 | seccomp_rule_name="1.so", uid=0, gid=0) 48 | 49 | with self.assertRaisesRegexp(ValueError, "args item must be a string"): 50 | _judger.run(max_cpu_time=1000, max_real_time=2000, 51 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 52 | max_process_number=200, max_output_size=10000, exe_path="1.out", 53 | input_path="1.in", output_path="1.out", error_path="1.out", 54 | args=["1234", None], env=["a=b"], log_path="1.log", 55 | seccomp_rule_name="1.so", uid=0, gid=0) 56 | 57 | if sys.version_info >= (3, 5): 58 | args = ["哈哈哈".encode("utf-8")] 59 | else: 60 | args = [u"哈哈哈"] 61 | with self.assertRaisesRegexp(ValueError, "args item must be a string"): 62 | _judger.run(max_cpu_time=1000, max_real_time=2000, 63 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 64 | max_process_number=200, max_output_size=10000, exe_path="1.out", 65 | input_path="1.in", output_path="1.out", error_path="1.out", 66 | args=args, env=["a="], log_path="1.log", 67 | seccomp_rule_name="1.so", uid=0, gid=0) 68 | 69 | def test_env_must_be_list(self): 70 | with self.assertRaisesRegexp(ValueError, "env must be a list"): 71 | _judger.run(max_cpu_time=1000, max_real_time=2000, 72 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 73 | max_process_number=200, max_output_size=10000, exe_path="1.out", 74 | input_path="1.in", output_path="1.out", error_path="1.out", 75 | args=["1234"], env="1234", log_path="1.log", 76 | seccomp_rule_name="1.so", uid=0, gid=0) 77 | 78 | with self.assertRaisesRegexp(ValueError, "env must be a list"): 79 | _judger.run(max_cpu_time=1000, max_real_time=2000, 80 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 81 | max_process_number=200, max_output_size=10000, exe_path="1.out", 82 | input_path="1.in", output_path="1.out", error_path="1.out", 83 | args=["1234"], env={"k": "v"}, log_path="1.log", 84 | seccomp_rule_name="1.so", uid=0, gid=0) 85 | 86 | def test_env_item_must_be_string(self): 87 | with self.assertRaisesRegexp(ValueError, "env item must be a string"): 88 | _judger.run(max_cpu_time=1000, max_real_time=2000, 89 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 90 | max_process_number=200, max_output_size=10000, exe_path="1.out", 91 | input_path="1.in", output_path="1.out", error_path="1.out", 92 | args=["1234"], env=["1234", 1234], log_path="1.log", 93 | seccomp_rule_name="1.so", uid=0, gid=0) 94 | 95 | with self.assertRaisesRegexp(ValueError, "env item must be a string"): 96 | _judger.run(max_cpu_time=1000, max_real_time=2000, 97 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 98 | max_process_number=200, max_output_size=10000, exe_path="1.out", 99 | input_path="1.in", output_path="1.out", error_path="1.out", 100 | args=["1234"], env=["a=b", None], log_path="1.log", 101 | seccomp_rule_name="1.so", uid=0, gid=0) 102 | 103 | if sys.version_info >= (3, 5): 104 | env = ["哈哈哈".encode("utf-8")] 105 | else: 106 | env = [u"哈哈哈"] 107 | with self.assertRaisesRegexp(ValueError, "env item must be a string"): 108 | _judger.run(max_cpu_time=1000, max_real_time=2000, 109 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 110 | max_process_number=200, max_output_size=10000, exe_path="1.out", 111 | input_path="1.in", output_path="1.out", error_path="1.out", 112 | args=["1234"], env=env, log_path="1.log", 113 | seccomp_rule_name="1.so", uid=0, gid=0) 114 | 115 | def test_seccomp_rule_can_be_none(self): 116 | _judger.run(max_cpu_time=1000, max_real_time=2000, 117 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 118 | max_process_number=200, max_output_size=10000, exe_path="/bin/ls", 119 | input_path="/dev/null", output_path="/dev/null", error_path="/dev/null", 120 | args=["12344"], env=["a=b"], log_path="/dev/null", 121 | seccomp_rule_name="c_cpp", uid=0, gid=0) 122 | 123 | _judger.run(max_cpu_time=1000, max_real_time=2000, 124 | max_memory=1024 * 1024 * 128, max_stack=32 * 1024 * 1024, 125 | max_process_number=200, max_output_size=10000, exe_path="/bin/ls", 126 | input_path="/dev/null", output_path="/dev/null", error_path="/dev/null", 127 | args=["12344"], env=["a=b"], log_path="/dev/null", 128 | seccomp_rule_name=None, uid=0, gid=0) 129 | 130 | def test_normal(self): 131 | config = self.base_config 132 | config["exe_path"] = self._compile_c("normal.c") 133 | config["input_path"] = self.make_input("judger_test") 134 | config["output_path"] = config["error_path"] = self.output_path() 135 | result = _judger.run(**config) 136 | output = "judger_test\nHello world" 137 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 138 | self.assertEqual(output, self.output_content(config["output_path"])) 139 | 140 | config["exe_path"] = self._compile_c("math.c") 141 | config["input_path"] = "/dev/null" 142 | config["output_path"] = config["error_path"] = self.output_path() 143 | result = _judger.run(**config) 144 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 145 | self.assertEqual("abs 1024", self.output_content(config["output_path"])) 146 | 147 | def test_args(self): 148 | config = self.base_config 149 | config["exe_path"] = self._compile_c("args.c") 150 | config["args"] = ["test", "hehe", "000"] 151 | config["output_path"] = config["error_path"] = self.output_path() 152 | result = _judger.run(**config) 153 | output = "argv[0]: /tmp/integration/args\nargv[1]: test\nargv[2]: hehe\nargv[3]: 000\n" 154 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 155 | self.assertEqual(output, self.output_content(config["output_path"])) 156 | 157 | def test_env(self): 158 | config = self.base_config 159 | config["exe_path"] = self._compile_c("env.c") 160 | config["output_path"] = config["error_path"] = self.output_path() 161 | result = _judger.run(**config) 162 | output = "judger_test\njudger\n" 163 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 164 | self.assertEqual(output, self.output_content(config["output_path"])) 165 | 166 | def test_real_time(self): 167 | config = self.base_config 168 | config["exe_path"] = self._compile_c("sleep.c") 169 | result = _judger.run(**config) 170 | self.assertEqual(result["result"], _judger.RESULT_REAL_TIME_LIMIT_EXCEEDED) 171 | self.assertEqual(result["signal"], signal.SIGKILL) 172 | self.assertTrue(result["real_time"] >= config["max_real_time"]) 173 | 174 | def test_cpu_time(self): 175 | config = self.base_config 176 | config["exe_path"] = self._compile_c("while1.c") 177 | result = _judger.run(**config) 178 | self.assertEqual(result["result"], _judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) 179 | self.assertEqual(result["signal"], signal.SIGKILL) 180 | self.assertTrue(result["cpu_time"] >= config["max_cpu_time"]) 181 | 182 | def test_memory1(self): 183 | config = self.base_config 184 | config["max_memory"] = 64 * 1024 * 1024 185 | config["exe_path"] = self._compile_c("memory1.c") 186 | result = _judger.run(**config) 187 | # malloc succeeded 188 | self.assertTrue(result["memory"] > 80 * 1024 * 1024) 189 | self.assertEqual(result["result"], _judger.RESULT_MEMORY_LIMIT_EXCEEDED) 190 | 191 | def test_memory2(self): 192 | config = self.base_config 193 | config["max_memory"] = 64 * 1024 * 1024 194 | config["exe_path"] = self._compile_c("memory2.c") 195 | result = _judger.run(**config) 196 | # malloc failed, return 1 197 | self.assertEqual(result["exit_code"], 1) 198 | # malloc failed, so it should use a little memory 199 | self.assertTrue(result["memory"] < 12 * 1024 * 1024) 200 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 201 | 202 | def test_memory3(self): 203 | config = self.base_config 204 | config["max_memory"] = 512 * 1024 * 1024 205 | config["exe_path"] = self._compile_c("memory3.c") 206 | result = _judger.run(**config) 207 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 208 | self.assertTrue(result["memory"] >= 102400000 * 4) 209 | 210 | def test_memory4(self): 211 | """parent process memory should not affect child process""" 212 | a = ["test" for i in range(2000000)] 213 | # get self maxrss 214 | max_rss = resource.getrusage(resource.RUSAGE_SELF)[2] 215 | self.assertTrue(max_rss > 28000) 216 | result = _judger.run(**self.base_config) 217 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 218 | self.assertTrue(result["memory"] < 3000000) 219 | del a 220 | 221 | def test_memory_limit_check_only(self): 222 | config = self.base_config 223 | config["memory_limit_check_only"] = 1 224 | config["max_memory"] = 64 * 1024 * 1024 225 | config["exe_path"] = self._compile_c("memory2.c") 226 | result = _judger.run(**config) 227 | self.assertEqual(result["exit_code"], 0) 228 | self.assertTrue(result["memory"] > 256 * 1024 * 1024) 229 | self.assertEqual(result["result"], _judger.RESULT_MEMORY_LIMIT_EXCEEDED) 230 | 231 | def test_re1(self): 232 | config = self.base_config 233 | config["exe_path"] = self._compile_c("re1.c") 234 | result = _judger.run(**config) 235 | # re1.c return 25 236 | self.assertEqual(result["exit_code"], 25) 237 | 238 | def test_re2(self): 239 | config = self.base_config 240 | config["exe_path"] = self._compile_c("re2.c") 241 | result = _judger.run(**config) 242 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 243 | self.assertEqual(result["signal"], signal.SIGSEGV) 244 | 245 | def test_child_proc_cpu_time_limit(self): 246 | config = self.base_config 247 | config["exe_path"] = self._compile_c("child_proc_cpu_time_limit.c") 248 | result = _judger.run(**config) 249 | self.assertEqual(result["result"], _judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) 250 | 251 | def test_child_proc_real_time_limit(self): 252 | config = self.base_config 253 | config["exe_path"] = self._compile_c("child_proc_real_time_limit.c") 254 | result = _judger.run(**config) 255 | self.assertEqual(result["result"], _judger.RESULT_REAL_TIME_LIMIT_EXCEEDED) 256 | self.assertEqual(result["signal"], signal.SIGKILL) 257 | 258 | def test_stdout_and_stderr(self): 259 | config = self.base_config 260 | config["exe_path"] = self._compile_c("stdout_stderr.c") 261 | config["output_path"] = config["error_path"] = self.output_path() 262 | result = _judger.run(**config) 263 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 264 | output = "stderr\n+++++++++++++++\n--------------\nstdout\n" 265 | self.assertEqual(output, self.output_content(config["output_path"])) 266 | 267 | def test_uid_and_gid(self): 268 | config = self.base_config 269 | config["exe_path"] = self._compile_c("uid_gid.c") 270 | config["output_path"] = config["error_path"] = self.output_path() 271 | config["uid"] = 65534 272 | config["gid"] = 65534 273 | result = _judger.run(**config) 274 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 275 | output = "uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)\nuid 65534\ngid 65534\n" 276 | self.assertEqual(output, self.output_content(config["output_path"])) 277 | 278 | def test_gcc_random(self): 279 | config = self.base_config 280 | config["max_memory"] = _judger.UNLIMITED 281 | config["exe_path"] = "/usr/bin/gcc" 282 | config["args"] = ["../test_src/integration/gcc_random.c", 283 | "-o", os.path.join(self.workspace, "gcc_random")] 284 | result = _judger.run(**config) 285 | self.assertTrue(result["real_time"] >= 2000) 286 | 287 | def test_cpp_meta(self): 288 | config = self.base_config 289 | config["exe_path"] = "/usr/bin/g++" 290 | config["max_memory"] = 1024 * 1024 * 1024 291 | config["args"] = ["../test_src/integration/cpp_meta.cpp", 292 | "-o", os.path.join(self.workspace, "cpp_meta")] 293 | result = _judger.run(**config) 294 | self.assertEqual(result["result"], _judger.RESULT_CPU_TIME_LIMIT_EXCEEDED) 295 | self.assertTrue(result["cpu_time"] > 1500) 296 | self.assertTrue(result["real_time"] >= 2000) 297 | 298 | def test_output_size(self): 299 | config = self.base_config 300 | config["exe_path"] = self._compile_c("output_size.c") 301 | config["max_output_size"] = 1000 * 10 302 | result = _judger.run(**config) 303 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 304 | with open("/tmp/fsize_test", "r") as f: 305 | self.assertEqual(len(f.read()), 10000) 306 | 307 | def test_stack_size(self): 308 | config = self.base_config 309 | config["max_memory"] = 256 * 1024 * 1024 310 | config["exe_path"] = self._compile_c("stack.c") 311 | config["output_path"] = config["error_path"] = self.output_path() 312 | 313 | result = _judger.run(**config) 314 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 315 | 316 | config["max_stack"] = 128 * 1024 * 1024 317 | result = _judger.run(**config) 318 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 319 | self.assertEqual("big stack", self.output_content(config["output_path"])) 320 | 321 | def test_writev(self): 322 | config = self.base_config 323 | config["exe_path"] = self._compile_cpp("writev.cpp") 324 | config["seccomp_rule_name"] = "c_cpp" 325 | config["input_path"] = self.make_input("111" * 10000 + "\n") 326 | config["output_path"] = config["error_path"] = self.output_path() 327 | 328 | result = _judger.run(**config) 329 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 330 | 331 | def test_get_time(self): 332 | config = self.base_config 333 | config["exe_path"] = self._compile_c("time.c") 334 | config["seccomp_rule_name"] = "c_cpp" 335 | 336 | result = _judger.run(**config) 337 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 338 | -------------------------------------------------------------------------------- /tests/Python_and_core/testcase/seccomp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QingdaoU/Judger/d19a6dc192ebd7f41fed44ae6e091575ef22906a/tests/Python_and_core/testcase/seccomp/__init__.py -------------------------------------------------------------------------------- /tests/Python_and_core/testcase/seccomp/test.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | from __future__ import print_function 3 | import _judger 4 | import signal 5 | import shutil 6 | import os 7 | 8 | from .. import base 9 | 10 | 11 | class SeccompTest(base.BaseTestCase): 12 | def setUp(self): 13 | print("Running", self._testMethodName) 14 | self.workspace = self.init_workspace("integration") 15 | 16 | def _compile_c(self, src_name, extra_flags=None): 17 | return super(SeccompTest, self)._compile_c("../../test_src/seccomp/" + src_name, extra_flags) 18 | 19 | def test_fork(self): 20 | config = self.base_config 21 | config["exe_path"] = self._compile_c("fork.c") 22 | config["output_path"] = config["error_path"] = self.output_path() 23 | result = _judger.run(**config) 24 | 25 | # without seccomp 26 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 27 | 28 | # with general seccomp 29 | config["seccomp_rule_name"] = "general" 30 | result = _judger.run(**config) 31 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 32 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 33 | 34 | # with c_cpp seccomp 35 | config["seccomp_rule_name"] = "c_cpp" 36 | result = _judger.run(**config) 37 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 38 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 39 | 40 | def test_execve(self): 41 | config = self.base_config 42 | config["exe_path"] = self._compile_c("execve.c") 43 | config["output_path"] = config["error_path"] = self.output_path() 44 | result = _judger.run(**config) 45 | # without seccomp 46 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 47 | self.assertEqual("Helloworld\n", self.output_content(config["output_path"])) 48 | 49 | # with general seccomp 50 | config["seccomp_rule_name"] = "general" 51 | result = _judger.run(**config) 52 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 53 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 54 | 55 | # with c_cpp seccomp 56 | config["seccomp_rule_name"] = "c_cpp" 57 | result = _judger.run(**config) 58 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 59 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 60 | 61 | def test_write_file_using_open(self): 62 | config = self.base_config 63 | config["exe_path"] = self._compile_c("write_file_open.c") 64 | config["output_path"] = config["error_path"] = self.output_path() 65 | path = os.path.join(self.workspace, "file1.txt") 66 | config["args"] = [path, "w"] 67 | result = _judger.run(**config) 68 | # without seccomp 69 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 70 | self.assertEqual("", self.output_content(path)) 71 | 72 | # with general seccomp 73 | config["seccomp_rule_name"] = "general" 74 | result = _judger.run(**config) 75 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 76 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 77 | 78 | # with c_cpp seccomp 79 | config["seccomp_rule_name"] = "c_cpp" 80 | result = _judger.run(**config) 81 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 82 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 83 | 84 | def test_read_write_file_using_open(self): 85 | config = self.base_config 86 | config["exe_path"] = self._compile_c("write_file_open.c") 87 | config["output_path"] = config["error_path"] = self.output_path() 88 | path = os.path.join(self.workspace, "file2.txt") 89 | config["args"] = [path, "w+"] 90 | result = _judger.run(**config) 91 | # without seccomp 92 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 93 | self.assertEqual("", self.output_content(path)) 94 | 95 | # with general seccomp 96 | config["seccomp_rule_name"] = "general" 97 | result = _judger.run(**config) 98 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 99 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 100 | 101 | # with c_cpp seccomp 102 | config["seccomp_rule_name"] = "c_cpp" 103 | result = _judger.run(**config) 104 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 105 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 106 | 107 | def test_write_file_using_openat(self): 108 | config = self.base_config 109 | config["exe_path"] = self._compile_c("write_file_openat.c") 110 | config["output_path"] = config["error_path"] = self.output_path() 111 | path = os.path.join(self.workspace, "file3.txt") 112 | config["args"] = [path, "w"] 113 | result = _judger.run(**config) 114 | # without seccomp 115 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 116 | self.assertEqual("", self.output_content(path)) 117 | 118 | # with general seccomp 119 | config["seccomp_rule_name"] = "general" 120 | result = _judger.run(**config) 121 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 122 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 123 | 124 | # with c_cpp seccomp 125 | config["seccomp_rule_name"] = "c_cpp" 126 | result = _judger.run(**config) 127 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 128 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 129 | 130 | def test_read_write_file_using_openat(self): 131 | config = self.base_config 132 | config["exe_path"] = self._compile_c("write_file_openat.c") 133 | config["output_path"] = config["error_path"] = self.output_path() 134 | path = os.path.join(self.workspace, "file4.txt") 135 | config["args"] = [path, "w+"] 136 | result = _judger.run(**config) 137 | # without seccomp 138 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 139 | self.assertEqual("", self.output_content(path)) 140 | 141 | # with general seccomp 142 | config["seccomp_rule_name"] = "general" 143 | result = _judger.run(**config) 144 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 145 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 146 | 147 | # with c_cpp seccomp 148 | config["seccomp_rule_name"] = "c_cpp" 149 | result = _judger.run(**config) 150 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 151 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 152 | 153 | def test_sysinfo(self): 154 | config = self.base_config 155 | config["exe_path"] = self._compile_c("sysinfo.c") 156 | result = _judger.run(**config) 157 | 158 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 159 | 160 | def test_exceveat(self): 161 | config = self.base_config 162 | config["exe_path"] = self._compile_c("execveat.c") 163 | config["output_path"] = config["error_path"] = self.output_path() 164 | result = _judger.run(**config) 165 | if "syscall not found" in self.output_content(config["output_path"]): 166 | print("execveat syscall not found, test ignored") 167 | return 168 | self.assertEqual(result["result"], _judger.RESULT_SUCCESS) 169 | 170 | # with general seccomp 171 | config["seccomp_rule_name"] = "general" 172 | result = _judger.run(**config) 173 | self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) 174 | self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) 175 | -------------------------------------------------------------------------------- /tests/runtest.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | set -ex 3 | dir=$PWD 4 | python -V 5 | gcc -v 6 | g++ -v 7 | 8 | for py in python2 python3; do 9 | cd $dir 10 | rm -rf build && mkdir build && cd build && cmake .. 11 | make 12 | make install 13 | cd ../bindings/Python && rm -rf build 14 | $py setup.py install 15 | cd ../../tests/Python_and_core && $py test.py 16 | done 17 | -------------------------------------------------------------------------------- /tests/test_src/integration/args.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | int j; 5 | for (j = 0; j < argc; j++) 6 | printf("argv[%d]: %s\n", j, argv[j]); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /tests/test_src/integration/child_proc_cpu_time_limit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int status; 11 | int pid; 12 | 13 | if ((pid = fork()) < 0) { 14 | perror("fork error"); 15 | return 0; 16 | } 17 | 18 | if (pid == 0) { 19 | while (1) {}; 20 | } 21 | else { 22 | struct rusage resource_usage; 23 | if (wait4(pid, &status, 0, &resource_usage) == -1) { 24 | perror("wait4 error!"); 25 | } 26 | } 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /tests/test_src/integration/child_proc_real_time_limit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int status; 11 | int pid; 12 | 13 | if ((pid = fork()) < 0) { 14 | perror("fork error"); 15 | return 0; 16 | } 17 | 18 | if (pid == 0) { 19 | sleep(10); 20 | } 21 | else { 22 | struct rusage resource_usage; 23 | if (wait4(pid, &status, 0, &resource_usage) == -1) { 24 | perror("wait4 error!"); 25 | } 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/test_src/integration/cpp_meta.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | std::vector Primes; 9 | 10 | template // factor should be odd 11 | class IsPrime 12 | { 13 | public: 14 | enum { 15 | result = ( toTest == 2 ) 16 | || toTest % factor 17 | && IsPrime < toTest , factor - 2 >::result 18 | }; 19 | }; 20 | 21 | template 22 | class IsPrime 23 | { 24 | public: 25 | enum {result = ( toTest == 2 ) || ( toTest & 1 ) }; 26 | }; 27 | 28 | template // upperBound should be odd or 2 29 | class PrimePick : public PrimePick < upperBound - 2 > 30 | { 31 | public: 32 | enum { 33 | isPrime = IsPrime < upperBound, ( upperBound >> 1 ) | 1 >::result 34 | }; 35 | PrimePick() { 36 | if ( isPrime ) 37 | Primes.push_back ( upperBound ); 38 | } 39 | }; 40 | 41 | template<> 42 | class PrimePick<2> 43 | { 44 | public: 45 | PrimePick<2>() { 46 | Primes.push_back ( 2 ); 47 | } 48 | }; 49 | 50 | template<> 51 | class PrimePick<1> : public PrimePick<2> {}; 52 | 53 | template // upperBound should be odd or 2 54 | class Primxx : public Primxx < upperBound - 2 > 55 | { 56 | public: 57 | enum { 58 | isPrime = IsPrime < upperBound, ( upperBound >> 1 ) | 1 >::result 59 | }; 60 | Primxx() { 61 | if ( isPrime ) 62 | Primes.push_back ( upperBound ); 63 | } 64 | }; 65 | 66 | template<> 67 | class Primxx<2> 68 | { 69 | public: 70 | Primxx<2>() { 71 | Primes.push_back ( 2 ); 72 | } 73 | }; 74 | 75 | template<> 76 | class Primxx<1> : public Primxx<2> {}; 77 | 78 | template // upperBound should be odd or 2 79 | class Primxa : public Primxa < upperBound - 2 > 80 | { 81 | public: 82 | enum { 83 | isPrime = IsPrime < upperBound, ( upperBound >> 1 ) | 1 >::result 84 | }; 85 | Primxa() { 86 | if ( isPrime ) 87 | Primes.push_back ( upperBound ); 88 | } 89 | }; 90 | 91 | template<> 92 | class Primxa<2> 93 | { 94 | public: 95 | Primxa<2>() { 96 | Primes.push_back ( 2 ); 97 | } 98 | }; 99 | 100 | template<> 101 | class Primxa<1> : public Primxa<2> {}; 102 | 103 | template // upperBound should be odd or 2 104 | class Primxb : public Primxb < upperBound - 2 > 105 | { 106 | public: 107 | enum { 108 | isPrime = IsPrime < upperBound, ( upperBound >> 1 ) | 1 >::result 109 | }; 110 | Primxb() { 111 | if ( isPrime ) 112 | Primes.push_back ( upperBound ); 113 | } 114 | }; 115 | 116 | template<> 117 | class Primxb<2> 118 | { 119 | public: 120 | Primxb<2>() { 121 | Primes.push_back ( 2 ); 122 | } 123 | }; 124 | 125 | template<> 126 | class Primxb<1> : public Primxb<2> {}; 127 | 128 | int main() 129 | { 130 | PrimePick<1601> PrimeInitializer; 131 | Primxx<1601> test1; 132 | Primxa<1601> test2; 133 | Primxb<1601> test3; 134 | int a, b; 135 | cin >> a >> b; 136 | cout << a + b; 137 | return 0; 138 | } -------------------------------------------------------------------------------- /tests/test_src/integration/env.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | printf("%s\n%s\n", getenv("env"), getenv("test")); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /tests/test_src/integration/gcc_random.c: -------------------------------------------------------------------------------- 1 | #include -------------------------------------------------------------------------------- /tests/test_src/integration/math.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | printf("abs %d", abs(-1024)); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /tests/test_src/integration/memory1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int size = 80 * 1024 * 1024; 8 | int *a = NULL; 9 | a = (int *)malloc(size); 10 | memset(a, 1, size); 11 | free(a); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /tests/test_src/integration/memory2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int size = 256 * 1024 * 1024; 8 | int *a = NULL; 9 | a = (int *)malloc(size); 10 | if (a == NULL) { 11 | return 1; 12 | } 13 | else { 14 | memset(a, 1, size); 15 | free(a); 16 | return 0; 17 | } 18 | } -------------------------------------------------------------------------------- /tests/test_src/integration/memory3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int arr[102400000]; 6 | 7 | 8 | int main() 9 | { 10 | memset(arr, 1, sizeof(arr)); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /tests/test_src/integration/normal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | char input[100]; 7 | scanf("%s", input); 8 | printf("%s\n", input); 9 | printf("Hello world"); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /tests/test_src/integration/output_size.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | FILE *f = fopen("/tmp/fsize_test", "w"); 4 | if(f == NULL) { 5 | return 1; 6 | } 7 | int i; 8 | for(i = 0;i < 10000; i++) { 9 | if (fprintf(f, "%s", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") <= 0) { 10 | return 2; 11 | } 12 | } 13 | fclose(f); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /tests/test_src/integration/re1.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | return 25; 4 | } -------------------------------------------------------------------------------- /tests/test_src/integration/re2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | raise(SIGSEGV); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /tests/test_src/integration/sleep.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | sleep(4000); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /tests/test_src/integration/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int big_stack[1024 * 1024 * 20] = {0}; 5 | printf("big stack"); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /tests/test_src/integration/stdout_stderr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | fprintf(stderr, "stderr\n"); 7 | fprintf(stdout, "--------------\n"); 8 | fprintf(stdout, "stdout\n"); 9 | fprintf(stderr, "+++++++++++++++\n"); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /tests/test_src/integration/time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main () { 5 | clock(); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /tests/test_src/integration/uid_gid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | printf("uid %d\ngid %d\n", getuid(), getgid()); 8 | system("/usr/bin/id"); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /tests/test_src/integration/while1.c: -------------------------------------------------------------------------------- 1 | int main() 2 | { 3 | while(1){}; 4 | return 0; 5 | } -------------------------------------------------------------------------------- /tests/test_src/integration/writev.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | ios::sync_with_stdio(false); 10 | string s; 11 | cin >> s; 12 | cout << s; 13 | return 0; 14 | } -------------------------------------------------------------------------------- /tests/test_src/seccomp/execve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | char *argv[] = {"/bin/echo", "Helloworld", NULL}; 8 | char *env[] = {NULL}; 9 | 10 | execve("/bin/echo", argv, env); 11 | perror("execve"); 12 | exit(EXIT_FAILURE); 13 | } -------------------------------------------------------------------------------- /tests/test_src/seccomp/execveat.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | int execveat_(int fd, const char *path, char **argv, char **envp, int flags) 9 | { 10 | #ifdef __NR_execveat 11 | return syscall(__NR_execveat, fd, path, argv, envp, flags); 12 | #endif 13 | } 14 | 15 | int main() { 16 | #ifndef __NR_execveat 17 | printf("syscall not found"); 18 | return 0; 19 | #else 20 | char *envp[] = {"test=1", NULL}; 21 | char *argv[] = {"hello", NULL}; 22 | 23 | execveat_(1, "/bin/true", argv, envp, 0); 24 | printf("failed %d", errno); 25 | return 1; 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /tests/test_src/seccomp/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | pid_t pid = fork(); 7 | if (pid > 0) { 8 | printf("i'm parent"); 9 | } 10 | else if (pid == 0) { 11 | printf("i'm children"); 12 | } 13 | else { 14 | printf("fork failed"); 15 | } 16 | return 0; 17 | } -------------------------------------------------------------------------------- /tests/test_src/seccomp/sysinfo.c: -------------------------------------------------------------------------------- 1 | // maybe used in qsort function 2 | #include 3 | #include 4 | 5 | int main() { 6 | printf("%ld", sysconf(_SC_PAGE_SIZE)); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /tests/test_src/seccomp/write_file_open.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(int argc, char *argv[]) 4 | { 5 | FILE *f = fopen(argv[1], argv[2]); 6 | if (f == NULL) { 7 | return errno; 8 | } 9 | return 0; 10 | } -------------------------------------------------------------------------------- /tests/test_src/seccomp/write_file_openat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) { 7 | int flags; 8 | if (!strcmp(argv[2], "w")) { 9 | flags = O_WRONLY | O_CREAT; 10 | } 11 | else { 12 | flags = O_RDWR | O_CREAT; 13 | } 14 | int fd = openat(0, argv[1], flags, 0755); 15 | if (fd < 0) { 16 | return errno; 17 | } 18 | close(fd); 19 | return 0; 20 | } 21 | --------------------------------------------------------------------------------