private void listBox_SelectedIndexChanged(object sender, System.EventArgs e) { // TODO: check if player is allowed to inject // TODO: get informations about hack HackStatus iHackStatus = (HackStatus)listBox.SelectedIndex; bool bEnableInject = false; DateTime dtExpiresOn = DateTime.Now; dtExpiresOn = dtExpiresOn.AddMinutes(listBox.SelectedIndex); // TODO: lblExpiresOnValue.Text = dtExpiresOn.ToShortDateString() + ' ' + dtExpiresOn.ToShortTimeString(); lblExpiresOnValue.ForeColor = dtExpiresOn > DateTime.Now ? System.Drawing.Color.Green : System.Drawing.Color.Red; switch (iHackStatus) { case HackStatus.Unknown: lblStatusValue.Text = "Unknown"; lblStatusValue.ForeColor = System.Drawing.Color.Orange; bEnableInject = true; break; case HackStatus.Updating: lblStatusValue.Text = "Updating"; lblStatusValue.ForeColor = System.Drawing.Color.Red; bEnableInject = false; break; case HackStatus.Undetected: lblStatusValue.Text = "Undetected"; lblStatusValue.ForeColor = System.Drawing.Color.Green; bEnableInject = true; break; } btnInject.Enabled = bEnableInject; }
private async Task HandleSingleHackAsync(IEnumerable <ActorInfo> actors, HackStatus hack, JudgeStatus judge, Problem problem, Guid?testCaseId, CancellationToken token) { var sub = new SubJudgeStatus(); var isBadData = false; if (actors.Count(x => x.Name == "CompareActor") == 0) { var rangeValidateActor = actors.FirstOrDefault(x => x.Stage == "ValidateData"); var rangeRunner = rangeValidateActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(rangeValidateActor.Outputs.Single(x => x.Name == "runner.json").Id, token); var runActor = actors.FirstOrDefault(x => x.Stage == "GenerateHackeeAnswer"); var runRunner = runActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token); if (rangeRunner != null && rangeRunner.ExitCode != 0) { isBadData = true; sub.TimeUsedInMs = 0; sub.MemoryUsedInByte = 0; sub.Result = JudgeResult.Accepted; sub.Hint = string.Join(Environment.NewLine, rangeValidateActor.Exceptions) + Environment.NewLine + rangeRunner.Error; } else if (runRunner.IsTimeout) { sub.TimeUsedInMs = problem.TimeLimitationPerCaseInMs; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = JudgeResult.TimeExceeded; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error; } else if (runRunner.ExitCode == 139 || runActor.Exceptions.Any(x => x.Contains("May cause by out of memory")) || runRunner.Error.Contains("std::bad_alloc") || runRunner.PeakMemory > problem.MemoryLimitationPerCaseInByte) { sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = problem.MemoryLimitationPerCaseInByte; sub.Result = JudgeResult.MemoryExceeded; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error; } else if (runRunner.ExitCode != 0) { sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = JudgeResult.RuntimeError; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error + Environment.NewLine + $"User process exited with code { runRunner.ExitCode }"; } } else if (actors.Count(x => x.Name == "CompareActor") > 0) { var runners = actors.Where(x => x.Name == "CompareActor").Select(x => x.Outputs.Single(y => y.Name == "runner.json")); var runnerResults = runners.Select(x => _mgmt.ReadBlobAsObjectAsync <Runner>(x.Id, token).Result); var exitCodes = runnerResults.Select(x => x.ExitCode); if (exitCodes.Distinct().Count() > 1) { isBadData = true; } else { var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer"); var runRunner = await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token); var compareActor = actors.Last(x => x.Name == "CompareActor"); var runner = await _mgmt.ReadBlobAsObjectAsync <Runner>(compareActor.Outputs.Single(x => x.Name == "runner.json").Id, token); if (runner.ExitCode < 0 || runner.ExitCode > 2) { sub.TimeUsedInMs = 0; sub.MemoryUsedInByte = 0; sub.Result = JudgeResult.SystemError; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error; } else { var validatorOutput = Encoding.UTF8.GetString((await _mgmt.GetBlobAsync(compareActor.Outputs.Single(x => x.Name == "stdout.txt").Id)).Body); sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = (JudgeResult)runner.ExitCode; sub.Hint = validatorOutput + Environment.NewLine + string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error; } } } else { isBadData = true; } if (hack == null && actors.Count(x => x.Stage == "GenerateHackeeAnswer") > 0 && testCaseId.HasValue) { var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer"); var statusId = Guid.Parse(runActor.Tag); var testCase = await _db.TestCases.SingleAsync(x => x.Id == testCaseId.Value, token); var testCases = await _db.TestCases .Where(x => x.ProblemId == problem.Id) .Select(x => x.Id) .ToListAsync(token); var status = await _db.JudgeStatuses .Include(x => x.SubStatuses) .SingleAsync(x => x.Id == statusId, token); sub.StatusId = statusId; sub.TestCaseId = testCaseId.Value; sub.InputBlobId = testCase.InputBlobId; sub.OutputBlobId = testCase.OutputBlobId; sub.SubId = testCases.IndexOf(testCaseId.Value); status.SubStatuses.Add(sub); status.MemoryUsedInByte = status.SubStatuses.Max(x => x.MemoryUsedInByte); status.TimeUsedInMs = status.SubStatuses.Sum(x => x.TimeUsedInMs); status.Result = status.SubStatuses.Max(x => x.Result); _db.SaveChanges(); } if (hack != null) { _db.HackStatuses .Where(x => x.Id == hack.Id) .SetField(x => x.HackeeResult).WithValue(isBadData ? JudgeResult.Accepted : sub.Result) .SetField(x => x.TimeUsedInMs).WithValue(sub.TimeUsedInMs) .SetField(x => x.MemoryUsedInByte).WithValue(sub.MemoryUsedInByte) .SetField(x => x.Result).WithValue(isBadData ? (HackResult.BadData) : (sub.Result == JudgeResult.Accepted ? HackResult.Failed : HackResult.Succeeded)) .SetField(x => x.Hint).WithValue(sub.Hint) .Update(); } }
public override void OnShowHackResult(HackStatus status) { status.HackDataBody = null; }
public override void OnHackCompleted(HackStatus status) { if (status.Result == HackResult.Succeeded) { // 1. Set the status to be non-hackable DB.ContestProblemLastStatuses .Where(x => x.StatusId == status.JudgeStatusId && x.ContestId == ContestId) .SetField(x => x.IsHackable).WithValue(false) .SetField(x => x.IsHacked).WithValue(true) .Update(); // 2. Add the hack data to problem var input = status.HackDataBlobId.Value; var testCase = DB.TestCases.FirstOrDefault(x => x.InputBlobId == input && x.ProblemId == status.Status.ProblemId); var testCaseExisted = testCase != null; if (!testCaseExisted) { var inputLength = ManagementService.GetBlobAsync(input).Result.Body.Length; var stateMachine = ManagementService.GetStateMachineInstanceAsync(status.RelatedStateMachineIds.Last().StateMachineId).Result; var output = stateMachine.StartedActors.First(x => x.Tag == "Standard").Outputs.First(x => x.Name == "stdout.txt").Id; var outputLength = ManagementService.GetBlobAsync(output).Result.Body.Length; testCase = new TestCase { ContestId = ContestId, InputBlobId = input, InputSizeInByte = inputLength, OutputBlobId = output, OutputSizeInByte = outputLength, ProblemId = status.Status.ProblemId, Type = TestCaseType.Hack }; DB.TestCases.Add(testCase); DB.SaveChanges(); } // 3. Add the result into sub judge status if (!testCaseExisted) { var sub = new SubJudgeStatus { SubId = DB.SubJudgeStatuses.Where(x => x.StatusId == status.JudgeStatusId).Count(), Hint = status.Hint, MemoryUsedInByte = status.MemoryUsedInByte, TimeUsedInMs = status.TimeUsedInMs, Result = status.HackeeResult, InputBlobId = testCase.InputBlobId, OutputBlobId = testCase.OutputBlobId, TestCaseId = testCase.Id, StatusId = status.JudgeStatusId }; DB.SubJudgeStatuses.Add(sub); DB.SaveChanges(); } // 4. Add point for the hacker DB.ContestProblemLastStatuses .Where(x => x.ContestId == ContestId && x.ProblemId == status.Status.ProblemId && x.UserId == status.UserId) .SetField(x => x.Point2).Plus(1) .Update(); // 5. Hack all statuses if (!testCaseExisted && DB.Attendees.Any(x => x.ContestId == ContestId && x.UserId == status.UserId && !x.IsVirtual)) { var affectedStatuses = DB.ContestProblemLastStatuses .Include(x => x.Status) .Where(x => x.ProblemId == status.Status.ProblemId && x.ContestId == ContestId && x.Status.BinaryBlobId.HasValue && x.IsAccepted) .ToList(); var problem = DB.Problems.Single(x => x.Id == status.Status.ProblemId); var validatorId = problem.ValidatorBlobId.HasValue ? problem.ValidatorBlobId.Value : Guid.Parse(Configuration["JoyOI:StandardValidatorBlobId"]); var blobs = new List <BlobInfo>(affectedStatuses.Count + 10); blobs.Add(new BlobInfo { Id = ManagementService.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { UserTime = status.Status.Problem.TimeLimitationPerCaseInMs, PhysicalTime = status.Status.Problem.TimeLimitationPerCaseInMs * 4, Memory = status.Status.Problem.MemoryLimitationPerCaseInByte }))).Result, Name = "limit.json", Tag = "Problem=" + status.Status.ProblemId }); blobs.Add(new BlobInfo(validatorId, problem.ValidatorBlobId.HasValue ? "Validator" + Constants.GetBinaryExtension(problem.ValidatorLanguage) : "Validator.out")); blobs.Add(new BlobInfo(status.HackDataBlobId.Value, "data.txt", testCase.Id.ToString())); blobs.Add(new BlobInfo(testCase.OutputBlobId, "std.txt", testCase.Id.ToString())); foreach (var x in affectedStatuses) { blobs.Add(new BlobInfo(x.Status.BinaryBlobId.Value, "Hackee" + Constants.GetBinaryExtension(x.Status.Language), x.StatusId.ToString())); } ManagementService.PutStateMachineInstanceAsync("HackAllStateMachine", Configuration["ManagementService:CallBack"], blobs, 2); } } else if (status.Result == HackResult.Failed) { DB.ContestProblemLastStatuses .Where(x => x.ContestId == ContestId && x.ProblemId == status.Status.ProblemId && x.UserId == status.UserId) .SetField(x => x.Point2).Subtract(1) .SetField(x => x.Point3).Plus(1) .Update(); } }
public virtual void OnHackCompleted(HackStatus status) { throw new NotImplementedException(); }
public virtual void OnShowHackResult(HackStatus status) { }
public async Task<IActionResult> Put( [FromServices] ContestExecutorFactory cef, [FromServices] ManagementServiceClient mgmt, [FromServices] IHubContext<OnlineJudgeHub> hub, CancellationToken token) { var request = JsonConvert.DeserializeObject<HackRequest>(RequestBody); if (!User.IsSignedIn()) { return Result(403, "Please login first."); } var judge = await DB.JudgeStatuses .Include(x => x.Problem) .SingleOrDefaultAsync(x => x.Id == request.JudgeStatusId, token); if (judge == null) { return Result(404, "The judge status is not found"); } if (!judge.BinaryBlobId.HasValue) { return Result(400, "The lagency status could not be hacked."); } if (judge.UserId == User.Current.Id) { return Result(400, "You cannot hack yourself."); } if (IsGroupRequest() && !await IsGroupMemberAsync(token)) { return Result(401, "You are not a member of this group."); } if (!string.IsNullOrEmpty(request.ContestId)) { var ce = cef.Create(request.ContestId); if (!ce.IsStatusHackable(judge) || !ce.IsContestInProgress()) { return Result(400, "You cannot hack this status"); } if (await DB.HackStatuses.AnyAsync(x => x.UserId == User.Current.Id && x.JudgeStatusId == request.JudgeStatusId && x.Result == HackResult.Succeeded && x.ContestId == request.ContestId, token)) { return Result(400, "You have already hacked this status."); } } // Upload hack data to management service if (request.IsBase64) { request.Data = request.Data.Substring(request.Data.IndexOf("base64,") + "base64,".Length); } var blobId = await mgmt.PutBlobAsync("data.txt", request.IsBase64 ? Convert.FromBase64String(request.Data) : Encoding.UTF8.GetBytes(request.Data), token); var hack = new HackStatus { ContestId = request.ContestId, JudgeStatusId = judge.Id, HackDataBlobId = blobId, Result = HackResult.Pending, Time = DateTime.UtcNow, UserId = User.Current.Id, HackeeResult = JudgeResult.Pending }; DB.HackStatuses.Add(hack); await DB.SaveChangesAsync(token); var blobs = new List<BlobInfo>(10); // Put the limit.json into blob collection blobs.Add(new BlobInfo { Id = await mgmt.PutBlobAsync("limit.json", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new { UserTime = judge.Problem.TimeLimitationPerCaseInMs, PhysicalTime = judge.Problem.TimeLimitationPerCaseInMs * 4, Memory = judge.Problem.MemoryLimitationPerCaseInByte }))), Name = "limit.json", Tag = "Problem=" + judge.ProblemId }); // Put the data into blob collection blobs.Add(new BlobInfo(blobId, "data.txt")); // Put the hackee program into blob collection blobs.Add(new BlobInfo(judge.BinaryBlobId.Value, "Hackee" + Constants.GetBinaryExtension(judge.Language), judge.Id.ToString())); // Put range validator program into blob collection if (judge.Problem.RangeBlobId.HasValue && string.IsNullOrEmpty(judge.Problem.RangeError)) { blobs.Add(new BlobInfo(judge.Problem.RangeBlobId.Value, "Range" + Constants.GetBinaryExtension(judge.Problem.RangeLanguage))); } // Put standard program into blob collection if (judge.Problem.StandardBlobId.HasValue && string.IsNullOrEmpty(judge.Problem.StandardError)) { blobs.Add(new BlobInfo(judge.Problem.StandardBlobId.Value, "Standard" + Constants.GetBinaryExtension(judge.Problem.StandardLanguage))); } else { // Get 3 accepted programs instead of standard program var statuses = await DB.JudgeStatuses .Where(x => x.Result == JudgeResult.Accepted && x.ProblemId == judge.ProblemId && x.BinaryBlobId.HasValue && x.Id != judge.Id) .OrderBy(x => x.TimeUsedInMs) .ThenBy(x => x.MemoryUsedInByte) .Take(3) .ToListAsync(token); if (statuses.Count == 0) { return Result(400, "Missing standard program, this status could not be hacked"); } var standards = statuses.Select(x => new BlobInfo(x.BinaryBlobId.Value, "Standard-" + x.Id.ToString().Substring(0,8) + Constants.GetBinaryExtension(x.Language), x.Id.ToString())); blobs.AddRange(standards); } // Put validator into blob collection if (judge.Problem.ValidatorBlobId.HasValue) { blobs.Add(new BlobInfo(judge.Problem.ValidatorBlobId.Value, "Validator" + Constants.GetBinaryExtension(judge.Problem.ValidatorLanguage))); } else { blobs.Add(new BlobInfo(Guid.Parse(Configuration["JoyOI:StandardValidatorBlobId"]), "Validator.out")); } // Start hack state machine var stateMachineId = await mgmt.PutStateMachineInstanceAsync("HackStateMachine", Configuration["ManagementService:CallBack"], blobs.ToArray(), 1, token); var stateMachine = new StateMachine { CreatedTime = DateTime.Now, Name = "HackStateMachine", Id = stateMachineId }; DB.StateMachines.Add(stateMachine); hack.RelatedStateMachineIds = new List<HackStatusStateMachine>(); hack.RelatedStateMachineIds.Add(new HackStatusStateMachine { StateMachineId = stateMachine.Id, StatusId = judge.Id }); await DB.SaveChangesAsync(token); hub.Clients.All.InvokeAsync("ItemUpdated", "hack", hack.Id); return Result(hack.Id); }