|
|
| version 1.74, 2009/07/06 08:47:10 | version 1.85, 2015/10/26 01:21:58 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: program executing for different OS-es. | Parser: program executing for different OS-es. |
| Copyright(c) 2000-2009 ArtLebedev Group(http://www.artlebedev.com) | Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| @todo setrlimit | @todo setrlimit |
| */ | */ |
| static const char * const IDENT_EXEC_C="$Date$"; | |
| #include "pa_config_includes.h" | #include "pa_config_includes.h" |
| #include "pa_exec.h" | #include "pa_exec.h" |
| #include "pa_exception.h" | #include "pa_exception.h" |
| #include "pa_common.h" | #include "pa_common.h" |
| #ifdef WIN32 | volatile const char * IDENT_PA_EXEC_C="$Id$" IDENT_PA_EXEC_H; |
| # include <windows.h> | |
| #else | |
| # include <signal.h> | |
| # include <sys/types.h> | |
| # include <sys/wait.h> | |
| #endif | |
| #ifdef WIN32 | #ifdef _MSC_VER |
| #include <windows.h> | |
| /// this func from http://www.ccas.ru/~posp/popov/spawn.htm | /// this func from http://www.ccas.ru/~posp/popov/spawn.htm |
| static DWORD CreateHiddenConsoleProcess(LPCTSTR szCmdLine, | static DWORD CreateHiddenConsoleProcess(LPCTSTR szCmdLine, |
| Line 113 error: | Line 107 error: |
| static void read_pipe(String& result, HANDLE hOutRead, String::Language lang){ | static void read_pipe(String& result, HANDLE hOutRead, String::Language lang){ |
| while(true) { | while(true) { |
| char *buf=new(PointerFreeGC) char[MAX_STRING]; | char *buf=new(PointerFreeGC) char[MAX_STRING+1]; |
| unsigned long size; | DWORD size=0; |
| if(!ReadFile(hOutRead, buf, MAX_STRING-1, &size, NULL) || !size) | if(!ReadFile(hOutRead, buf, MAX_STRING, &size, NULL) || !size) |
| break; | break; |
| buf[size]=0; | buf[size]=0; |
| result.append_know_length(buf, size, lang); | result.append_know_length(buf, size, lang); |
| Line 124 static void read_pipe(String& result, HA | Line 118 static void read_pipe(String& result, HA |
| static void read_pipe(File_read_result& result, HANDLE hOutRead){ | static void read_pipe(File_read_result& result, HANDLE hOutRead){ |
| char *buf=new(PointerFreeGC) char[MAX_STRING]; | char *buf=(char*)pa_malloc(MAX_STRING+1); |
| DWORD bufsize = MAX_STRING; | |
| unsigned long size = 0; | |
| unsigned long bufsize = 0; | |
| unsigned long newsize = 0; | |
| result.headers = 0; | result.headers = 0; |
| result.length = 0; | result.length = 0; |
| Line 136 static void read_pipe(File_read_result& | Line 127 static void read_pipe(File_read_result& |
| result.success = false; | result.success = false; |
| while(true) { | while(true) { |
| if(!ReadFile(hOutRead, buf, MAX_STRING-1, &size, NULL) || !size) | DWORD size=0; |
| if(!ReadFile(hOutRead, buf + result.length, bufsize - result.length, &size, NULL) || !size) | |
| break; | break; |
| newsize = (size + result.length); | result.length += size; |
| if(newsize > bufsize){ | if(result.length >= bufsize){ |
| bufsize = (size==MAX_STRING-1)?newsize*2:newsize; | bufsize *= 2; |
| char *tmp = new(PointerFreeGC) char[bufsize]; | buf=(char*)pa_realloc(buf, bufsize+1); |
| if(result.str) | |
| memcpy(tmp, result.str, result.length); | |
| memcpy(tmp+result.length, buf, size); | |
| result.str = tmp; | |
| }else{ | |
| memcpy(result.str+result.length, buf, size); | |
| } | } |
| result.length = newsize; | result.str=buf; |
| } | } |
| } | } |
| Line 312 static int get_exit_status(int pid) { | Line 298 static int get_exit_status(int pid) { |
| static void read_pipe(String& result, int file, String::Language lang){ | static void read_pipe(String& result, int file, String::Language lang){ |
| while(true) { | while(true) { |
| char *buf=new(PointerFreeGC) char[MAX_STRING]; | char *buf=new(PointerFreeGC) char[MAX_STRING+1]; |
| ssize_t length=read(file, buf, MAX_STRING-1); | ssize_t length=read(file, buf, MAX_STRING); |
| if(length<=0) | if(length<=0) |
| break; | break; |
| buf[length]=0; | buf[length]=0; |
| Line 322 static void read_pipe(String& result, in | Line 308 static void read_pipe(String& result, in |
| } | } |
| static void read_pipe(File_read_result& result, int file){ | static void read_pipe(File_read_result& result, int file){ |
| char *buf=new(PointerFreeGC) char[MAX_STRING]; | char *buf=(char*)pa_malloc(MAX_STRING+1); |
| ssize_t bufsize = MAX_STRING; | |
| unsigned long bufsize = 0; | |
| unsigned long newsize = 0; | |
| result.headers = 0; | result.headers = 0; |
| result.length = 0; | result.length = 0; |
| Line 333 static void read_pipe(File_read_result& | Line 317 static void read_pipe(File_read_result& |
| result.success = false; | result.success = false; |
| while(true) { | while(true) { |
| ssize_t size=read(file, buf, MAX_STRING-1); | ssize_t size=read(file, buf + result.length, bufsize - result.length); |
| if(size <= 0) | if(size <= 0) |
| break; | break; |
| newsize = (size + result.length); | result.length += size; |
| if(newsize > bufsize){ | if(result.length >= bufsize){ |
| bufsize = (size==MAX_STRING-1)?newsize*2:newsize; | bufsize *= 2; |
| char *tmp = new(PointerFreeGC) char[bufsize]; | buf=(char*)pa_realloc(buf, bufsize+1); |
| if(result.str) | |
| memcpy(tmp, result.str, result.length); | |
| memcpy(tmp+result.length, buf, size); | |
| result.str = tmp; | |
| }else{ | |
| memcpy(result.str+result.length, buf, size); | |
| } | } |
| result.length = newsize; | result.str=buf; |
| } | } |
| } | } |
| Line 355 static void read_pipe(File_read_result& | Line 333 static void read_pipe(File_read_result& |
| #ifndef DOXYGEN | #ifndef DOXYGEN |
| struct Append_env_pair_info { | struct Append_env_pair_info { |
| #ifdef WIN32 | #ifdef _MSC_VER |
| String::Body& body; | String::Body& body; |
| Append_env_pair_info(String::Body& abody): body(abody) {} | Append_env_pair_info(String::Body& abody): body(abody) {} |
| #else | #else |
| Line 363 struct Append_env_pair_info { | Line 341 struct Append_env_pair_info { |
| #endif | #endif |
| }; | }; |
| #endif | #endif |
| ///@test maybe here and at argv construction --- cstr(String::L_UNSPECIFIED | |
| ///@test maybe here and at argv construction --- untaint_cstr(String::L_AS_IS | |
| static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value, | static void append_env_pair(HashStringString::key_type key, HashStringString::value_type value, |
| Append_env_pair_info *info) { | Append_env_pair_info *info) { |
| #ifdef WIN32 | #ifdef _MSC_VER |
| info->body << key << "=" << value; | info->body << key << "=" << value; |
| info->body.append_know_length("\1", 1); // placeholder for of zero byte | info->body.append_know_length("\1", 1); // placeholder for of zero byte |
| #else | #else |
| Line 378 static void append_env_pair(HashStringSt | Line 357 static void append_env_pair(HashStringSt |
| } | } |
| PA_exec_result pa_exec( | PA_exec_result pa_exec( |
| bool | bool forced_allow, |
| #if defined(NO_PA_EXEC) || defined(PA_SAFE_MODE) | |
| forced_allow | |
| #endif | |
| , | |
| const String& file_spec, | const String& file_spec, |
| const HashStringString* env, | const HashStringString* env, |
| const ArrayString& argv, | const ArrayString& argv, |
| Line 396 PA_exec_result pa_exec( | Line 371 PA_exec_result pa_exec( |
| "parser execs are disabled [recompile parser without --disable-execs configure option]"); | "parser execs are disabled [recompile parser without --disable-execs configure option]"); |
| #endif | #endif |
| #ifdef WIN32 | #ifdef _MSC_VER |
| PROCESS_INFORMATION pi; | PROCESS_INFORMATION pi; |
| HANDLE hInWrite, hOutRead, hErrRead; | HANDLE hInWrite, hOutRead, hErrRead; |
| const char* script_spec_cstr=file_spec.cstr_taint(String::L_FILE_SPEC); | const char* script_spec_cstr=file_spec.taint_cstr(String::L_FILE_SPEC); |
| const char* cmd=buildCommand(script_spec_cstr, argv); | const char* cmd=buildCommand(script_spec_cstr, argv); |
| char* env_cstr=0; | char* env_cstr=0; |
| if(env) { | if(env) { |
| Line 437 PA_exec_result pa_exec( | Line 412 PA_exec_result pa_exec( |
| CloseHandle(hInWrite); | CloseHandle(hInWrite); |
| read_pipe(result.out, hOutRead); | read_pipe(result.out, hOutRead); |
| CloseHandle(hOutRead); | CloseHandle(hOutRead); |
| read_pipe(result.err, hErrRead, String::L_TAINTED); | read_pipe(result.err, hErrRead, String::L_TAINTED); |
| CloseHandle(hErrRead); | CloseHandle(hErrRead); |
| /* | // We must close the handles to the new process and its main thread |
| from http://www.apache.org/websrc/cvsweb.cgi/apache-1.3/src/main/util_script.c?rev=1.151&content-type=text/vnd.viewcvs-markup | // to prevent handle and memory leaks. |
| * We must close the handles to the new process and its main thread | |
| * to prevent handle and memory leaks. | |
| */ | |
| CloseHandle(pi.hProcess); | CloseHandle(pi.hProcess); |
| CloseHandle(pi.hThread); | CloseHandle(pi.hThread); |
| } | } |
| Line 452 from http://www.apache.org/websrc/cvsweb | Line 423 from http://www.apache.org/websrc/cvsweb |
| #else | #else |
| // execve needs non const | // execve needs non const |
| char* file_spec_cstr=file_spec.cstrm(String::L_FILE_SPEC); | char* file_spec_cstr=file_spec.taint_cstrm(String::L_FILE_SPEC); |
| int pipe_write, pipe_read, pipe_err; | int pipe_write, pipe_read, pipe_err; |
| #ifdef PA_SAFE_MODE | |
| if(!forced_allow) { | if(!forced_allow) { |
| struct stat finfo; | struct stat finfo; |
| if(stat(file_spec_cstr, &finfo)!=0) | if(stat(file_spec_cstr, &finfo)!=0) |
| Line 467 from http://www.apache.org/websrc/cvsweb | Line 437 from http://www.apache.org/websrc/cvsweb |
| check_safe_mode(finfo, file_spec, file_spec_cstr); | check_safe_mode(finfo, file_spec, file_spec_cstr); |
| } | } |
| #endif | |
| char* argv_cstrs[1+50+1]={file_spec_cstr, 0}; | char* argv_cstrs[1+100+1]={file_spec_cstr, 0}; |
| const int argv_size=argv.count(); | const int argv_size=argv.count(); |
| const int argv_max=sizeof(argv_cstrs)/sizeof(argv_cstrs[0])-1-1; | const int argv_max=sizeof(argv_cstrs)/sizeof(argv_cstrs[0])-1-1; |
| if(argv_size>argv_max) | if(argv_size>argv_max) |