Ejemplo n.º 1
1
judge_result testcase_impl::run(env &env, compiler::result &cr)
{
	judge_result result = {0};
	shared_ptr<temp_dir> dir = _prepare_dir(env.pool(), cr);
	env.grant_access(dir->path());

	path_a executable_path;
	if (cr.compiler->target_executable_path().empty()) {
		executable_path = dir->path();
		executable_path.push(cr.compiler->target_filename().c_str());
	} else {
		executable_path = cr.compiler->target_executable_path();
	}

	shared_ptr<testcase_impl::context> context(new testcase_impl::context(*this));
	judge::bunny bunny(env, false, executable_path.c_str(), cr.compiler->target_command_line(), dir->path(),
		context->stdin_pipe.read_handle(), context->stdout_pipe.write_handle(), context->stderr_pipe.write_handle(), limit_);
	context->stdin_pipe.close_read();
	context->stdout_pipe.close_write();
	context->stderr_pipe.close_write();

	// stdin thread
	env.pool().thread_pool().queue([context]()->void {
		try {
			istream in(&context->stdin_buf);
			os_filebuf out_buf(context->stdin_pipe.write_handle(), false);
			ostream out(&out_buf);
			const size_t buffer_size = 4096;
			util::stream_copy<buffer_size>(in, out);
		} catch (...) {
		}
		context->stdin_pipe.close_write();
		context->stdin_event.set();
	});

	// stderr thread
	env.pool().thread_pool().queue([context]()->void {
		try {
			os_filebuf in_buf(context->stderr_pipe.read_handle(), false);
			istream in(&in_buf);
			const size_t buffer_size = 4096;
			util::stream_copy_n<buffer_size>(in, context->stderr_stream, context->stderr_output_limit);
		} catch (...) {
		}
		context->stderr_pipe.close_read();
		context->stderr_event.set();
	});

	bunny.start();

	// judge
	{
		istream model_in(&context->stdout_buf);
		os_filebuf user_buf(context->stdout_pipe.read_handle(), false);
		istream user_in(&user_buf);
		pair<bool, string> compare_result = compare_stream(model_in, user_in);
		if (compare_result.first) {
			result.flag = max(result.flag, JUDGE_ACCEPTED);
		} else {
			result.flag = max(result.flag, JUDGE_WRONG_ANSWER);
		}
		judge_output_ = move(compare_result.second);

		// read all user output
		const size_t buffer_size = 4096;
		util::stream_copy<buffer_size>(user_in, onullstream());
	}

	bunny::result bunny_result = bunny.wait();
	DWORD wait_result = winstl::wait_for_multiple_objects(context->stdin_event, context->stderr_event, true, INFINITE);
	if (wait_result == WAIT_FAILED) {
		throw win32_exception(::GetLastError());
	}

	result.flag = max(result.flag, bunny_result.flag);
	result.time_usage_ms = bunny_result.time_usage_ms;
	result.memory_usage_kb = bunny_result.memory_usage_kb;
	result.runtime_error = bunny_result.runtime_error;
	result.judge_output = judge_output_.c_str();
	user_output_ = context->stderr_stream.str();
	result.user_output = user_output_.c_str();
	return result;
}
Ejemplo n.º 2
0
void restricted_env::grant_access(const winstl::path_a &path)
{
	LPSTR username = const_cast<LPSTR>(username_.c_str());
	DWORD result;
	HANDLE file = ::CreateFileA(path.c_str(), READ_CONTROL | WRITE_DAC,
		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
		FILE_FLAG_BACKUP_SEMANTICS, NULL);
	if (file == INVALID_HANDLE_VALUE) {
		throw win32_exception(::GetLastError());
	}

	PACL old_dacl, new_dacl;
	PSECURITY_DESCRIPTOR sd;
	EXPLICIT_ACCESSA ea = {0};

	result = ::GetSecurityInfo(file, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
		NULL, NULL, &old_dacl, NULL, &sd);
	if (result != ERROR_SUCCESS) {
		::CloseHandle(file);
		throw win32_exception(result);
	}

	ea.grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE;
	ea.grfAccessMode = GRANT_ACCESS;
	ea.grfInheritance = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
	ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
	ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
	ea.Trustee.ptstrName = username;
	result = ::SetEntriesInAclA(1, &ea, old_dacl, &new_dacl);
	if (result != ERROR_SUCCESS) {
		::LocalFree(sd);
		::CloseHandle(file);
		throw win32_exception(result);
	}

	result = ::SetSecurityInfo(file, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
		NULL, NULL, new_dacl, NULL);
	if (result != ERROR_SUCCESS) {
		::LocalFree(new_dacl);
		::LocalFree(sd);
		::CloseHandle(file);
		throw win32_exception(result);
	}

	::LocalFree(new_dacl);
	::LocalFree(sd);
	::CloseHandle(file);
}
Ejemplo n.º 3
0
void job_object::terminate(int32_t exit_code)
{
	BOOL result = ::TerminateJobObject(handle(), static_cast<UINT>(exit_code));
	if (!result) {
		throw win32_exception(::GetLastError());
	}
}
Ejemplo n.º 4
0
void job_object::assign(HANDLE process_handle)
{
	BOOL result = ::AssignProcessToJobObject(handle(), process_handle);
	if (!result) {
		throw win32_exception(::GetLastError());
	}
}
Ejemplo n.º 5
0
HANDLE job_object::_create()
{
	HANDLE result = ::CreateJobObject(NULL, NULL);
	if (!result) {
		throw win32_exception(::GetLastError());
	}
	return result;
}
Ejemplo n.º 6
0
HANDLE window_station::_process_window_station()
{
	HANDLE result = ::GetProcessWindowStation();
	if (!result) {
		throw win32_exception(::GetLastError());
	}
	return result;
}
Ejemplo n.º 7
0
void RegValue::CheckError(LPCSTR szMessage)
{
	if (m_stResult != ERROR_SUCCESS)
	{
		LPCSTR szMessageTmp = szMessage != NULL? szMessage: "Error while operating with register";
		throw win32_exception(szMessageTmp, m_stResult);
	}
}
Ejemplo n.º 8
0
HANDLE desktop::_create_desktop(const std::string &name)
{
	HANDLE result = ::CreateDesktopA(name.c_str(), NULL, NULL, 0,
		DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_WRITEOBJECTS |
		READ_CONTROL | WRITE_DAC | DESKTOP_SWITCHDESKTOP, 0);
	if (!result) {
		throw win32_exception(::GetLastError());
	}
	return result;
}
Ejemplo n.º 9
0
void job_object::limits_info::commit()
{
	BOOL result = ::SetInformationJobObject(
		job_.handle(),
		::JobObjectExtendedLimitInformation,
		static_cast<::JOBOBJECT_EXTENDED_LIMIT_INFORMATION *>(this),
		sizeof(::JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
	if (!result) {
		throw win32_exception(::GetLastError());
	}
}
Ejemplo n.º 10
0
void job_object::ui_restrictions_info::commit()
{
	BOOL result = ::SetInformationJobObject(
		job_.handle(),
		::JobObjectBasicUIRestrictions,
		static_cast<::JOBOBJECT_BASIC_UI_RESTRICTIONS *>(this),
		sizeof(::JOBOBJECT_BASIC_UI_RESTRICTIONS));
	if (!result) {
		throw win32_exception(::GetLastError());
	}
}
Ejemplo n.º 11
0
void win32_exception::translate(unsigned code, EXCEPTION_POINTERS* info)
{
  switch (code) 
  {
    case EXCEPTION_ACCESS_VIOLATION:
      throw access_violation(info);
      break;
    default:
      throw win32_exception(info);
  }
}
Ejemplo n.º 12
0
void __cdecl  win32_exception::translate(unsigned code, EXCEPTION_POINTERS* info)
{
    // Windows guarantees that *(info->ExceptionRecord) is valid
    switch (code) {
    case EXCEPTION_ACCESS_VIOLATION:
        throw access_violation(*(info->ExceptionRecord));
        break;
    default:
        throw win32_exception(*(info->ExceptionRecord));
    }
}
Ejemplo n.º 13
0
void win32_exception::Handler(unsigned int errorCode, EXCEPTION_POINTERS* pInfo) {
	switch(errorCode)
	{
	case EXCEPTION_ACCESS_VIOLATION:
		throw win32_access_violation(*(pInfo->ExceptionRecord));
		break;

	default:
		throw win32_exception(*(pInfo->ExceptionRecord));
	}
}
Ejemplo n.º 14
0
pair<shared_ptr<process>, shared_ptr<thread_suspension> > restricted_env::create_process(
	const string &executable_path, const string &command_line, const path_a &current_dir,
	HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle)
{
	string desktop_name = window_station_.name() + "\\" + desktop_.name();
	PROCESS_INFORMATION process_info;
	BOOL result;

	if (!proc_thread_attribute_list::is_supported()) {
		STARTUPINFOA startup_info = {0};
		startup_info.cb = sizeof(startup_info);
		startup_info.lpDesktop = const_cast<LPSTR>(desktop_name.c_str());
		startup_info.dwFlags = STARTF_FORCEOFFFEEDBACK | STARTF_USESTDHANDLES;

		uintptr_t handle_value = 0;
		duplicate_handle stdin_h(stdin_handle, handle_value);
		duplicate_handle stdout_h(stdout_handle, handle_value);
		duplicate_handle stderr_h(stderr_handle, handle_value);
		startup_info.hStdInput = stdin_h.target();
		startup_info.hStdOutput = stdout_h.target();
		startup_info.hStdError = stderr_h.target();

		result = ::CreateProcessAsUserA(session_.handle(), executable_path.empty() ? NULL : executable_path.c_str(),
			const_cast<LPSTR>(command_line.c_str()), NULL, NULL, FALSE,
			CREATE_BREAKAWAY_FROM_JOB | CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW | CREATE_SUSPENDED,
			NULL, current_dir.c_str(), &startup_info, &process_info);

		if (result) {
			try {
				stdin_h(process_info.hProcess);
				stdout_h(process_info.hProcess);
				stderr_h(process_info.hProcess);
			} catch (...) {
				::TerminateProcess(process_info.hProcess, 1);
				::CloseHandle(process_info.hProcess);
				::CloseHandle(process_info.hThread);
				throw;
			}
		}

	} else {
		inherit_handle stdin_h(stdin_handle);
		inherit_handle stdout_h(stdout_handle);
		inherit_handle stderr_h(stderr_handle);

		proc_thread_attribute_list attr_list(1);
		vector<HANDLE> handle_list;
		if (stdin_handle) handle_list.push_back(stdin_handle);
		if (stdout_handle) handle_list.push_back(stdout_handle);
		if (stderr_handle) handle_list.push_back(stderr_handle);
		sort(handle_list.begin(), handle_list.end());
		handle_list.erase(unique(handle_list.begin(), handle_list.end()), handle_list.end());
		attr_list.update(PROC_THREAD_ATTRIBUTE_HANDLE_LIST, handle_list.data(), handle_list.size() * sizeof(HANDLE));

		STARTUPINFOEXA info = {0};
		info.StartupInfo.cb = sizeof(info);
		info.StartupInfo.lpDesktop = const_cast<LPSTR>(desktop_name.c_str());
		info.StartupInfo.dwFlags = STARTF_FORCEOFFFEEDBACK | STARTF_USESTDHANDLES;
		info.StartupInfo.hStdInput = stdin_handle;
		info.StartupInfo.hStdOutput = stdout_handle;
		info.StartupInfo.hStdError = stderr_handle;
		info.lpAttributeList = attr_list.pointer();

		result = ::CreateProcessAsUserA(session_.handle(), executable_path.empty() ? NULL : executable_path.c_str(),
			const_cast<LPSTR>(command_line.c_str()), NULL, NULL, TRUE,
			CREATE_BREAKAWAY_FROM_JOB | CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW | CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT,
			NULL, current_dir.c_str(), &info.StartupInfo, &process_info);
	}

	if (!result) {
		throw win32_exception(::GetLastError());
	}

	shared_ptr<process> p;
	try {
		p.reset(new process(process_info.hProcess));
	} catch (...) {
		::TerminateProcess(process_info.hProcess, 1);
		::CloseHandle(process_info.hProcess);
		::CloseHandle(process_info.hThread);
		throw;
	}

	shared_ptr<thread_suspension> t;
	try {
		t.reset(new thread_suspension(process_info.hThread));
	} catch (...) {
		::TerminateProcess(process_info.hProcess, 1);
		::CloseHandle(process_info.hThread);
		throw;
	}

	return make_pair(move(p), move(t));
}