/// <summary> /// Populates the divergence information. /// </summary> /// <param name="example">The counter example.</param> /// <param name="error">The divergence error.</param> public void PopulateDivergenceInformation(CallCounterexample example, DivergenceError error) { CallCmd call = example.FailingCall; SourceLocationInfo source = new SourceLocationInfo(GetAttributes(call), GetSourceFileName(), call.tok); error.Location = source; }
private static Variable ExtractOffsetVar(CallCounterexample err) { var VFV = new VariableFinderVisitor( RaceInstrumentationUtil.MakeOffsetVariableName(QKeyValue.FindStringAttribute(err.FailingRequires.Attributes, "array"), GetAccessType(err))); VFV.Visit(err.FailingRequires.Condition); return(VFV.GetVariable()); }
//private readonly Dictionary<IToken, List<ErrorCode>> reportedVerificationErrors = new Dictionary<IToken, List<ErrorCode>>(); //private readonly List<string> errors = new List<string>(); public void ReportCounterexample(Counterexample ce, string message) { if (message != null) { message = " (" + message + ")"; } else { message = ""; } try { ReturnCounterexample /*?*/ rce = ce as ReturnCounterexample; if (rce != null) { IToken tok = rce.FailingReturn.tok; for (int i = rce.Trace.Length - 1; i >= 0; i--) { foreach (Cmd c in rce.Trace[i].Cmds) { AssertCmd assrt = c as AssertCmd; if (assrt != null) { NAryExpr nary = assrt.Expr as NAryExpr; if (nary != null) { FunctionCall fcall = nary.Fun as FunctionCall; if (fcall != null && fcall.FunctionName == "$position_marker") { tok = assrt.tok; } } } } } ReportOutcomePostconditionFailed(rce.FailingEnsures.tok, tok, message); } AssertCounterexample /*?*/ ace = ce as AssertCounterexample; if (ace != null) { ReportOutcomeAssertFailed(ace.FailingAssert.tok, (ace.FailingAssert is LoopInvMaintainedAssertCmd ? "Loop body invariant" : ace.FailingAssert is LoopInitAssertCmd ? "Loop entry invariant" : "Assertion"), message ); } CallCounterexample /*?*/ cce = ce as CallCounterexample; if (cce != null) { ReportOutcomePreconditionFailed(cce.FailingCall.tok, cce.FailingRequires, message); } } finally { if (commandLineOptions != null && commandLineOptions.PrintCEVModel) { ce.PrintModel(); } } }
private int ReportRequiresFailure(CallCounterexample cex) { Console.Error.WriteLine(); ErrorReporter.ErrorWriteLine(cex.FailingCall + ":", "a precondition for this call might not hold", ErrorMsgType.Error); ErrorReporter.ErrorWriteLine(cex.FailingRequires.Line + ":", "this is the precondition that might not hold", ErrorMsgType.Note); return(1); }
private string ArrayOffsetString(CallCounterexample Cex, string RaceyArraySourceName) { Variable AccessOffsetVar = ExtractOffsetVar(Cex); Variable AccessHasOccurredVar = ExtractAccessHasOccurredVar(Cex); string StateName = GetStateName(Cex); Model Model = Cex.Model; return(ArrayOffsetString(Model, StateName, AccessHasOccurredVar, AccessOffsetVar, RaceyArraySourceName)); }
private static AssumeCmd DetermineConflictingAction(CallCounterexample CallCex, string RaceyState, string AccessHasOccurred, string AccessOffset) { AssumeCmd LastLogAssume = null; string LastOffsetValue = null; foreach (var b in CallCex.Trace) { bool finished = false; foreach (var c in b.Cmds.OfType <AssumeCmd>()) { string StateName = QKeyValue.FindStringAttribute(c.Attributes, "captureState"); if (StateName == null) { continue; } Model.CapturedState state = GetStateFromModel(StateName, CallCex.Model); if (state == null || state.TryGet(AccessHasOccurred) is Model.Uninterpreted) { // Either the state was not recorded, or the state has nothing to do with the reported error, so do not // analyse it further. continue; } Model.Boolean AHO_value = state.TryGet(AccessHasOccurred) as Model.Boolean; Model.BitVector AO_value = (RaceInstrumentationUtil.RaceCheckingMethod == RaceCheckingMethod.ORIGINAL ? state.TryGet(AccessOffset) : CallCex.Model.TryGetFunc(AccessOffset).GetConstant()) as Model.BitVector; if (!AHO_value.Value) { LastLogAssume = null; LastOffsetValue = null; } else if (LastLogAssume == null || !AO_value.Numeral.Equals(LastOffsetValue)) { LastLogAssume = c; LastOffsetValue = AO_value.Numeral; } if (StateName.Equals(RaceyState)) { finished = true; } break; } if (finished) { break; } } Debug.Assert(LastLogAssume != null); return(LastLogAssume); }
private static void DetermineNatureOfRace(CallCounterexample CallCex, out string raceName, out string access1, out string access2) { if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "write_read")) { raceName = "write-read"; access1 = "Write"; access2 = "Read"; } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "read_write")) { raceName = "read-write"; access1 = "Read"; access2 = "Write"; } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "write_write")) { raceName = "write-write"; access1 = "Write"; access2 = "Write"; } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "atomic_read")) { raceName = "atomic-read"; access1 = "Atomic"; access2 = "Read"; } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "atomic_write")) { raceName = "atomic-write"; access1 = "Atomic"; access2 = "Write"; } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "read_atomic")) { raceName = "read-atomic"; access1 = "Read"; access2 = "Atomic"; } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "write_atomic")) { raceName = "write-atomic"; access1 = "Write"; access2 = "Atomic"; } else { Debug.Assert(false); raceName = null; access1 = null; access2 = null; } }
private void ReportRace(CallCounterexample CallCex) { string raceName, access1, access2; DetermineNatureOfRace(CallCex, out raceName, out access1, out access2); PopulateModelWithStatesIfNecessary(CallCex); string RaceyArrayName = GetArrayName(CallCex.FailingRequires); Debug.Assert(RaceyArrayName != null); string RaceyArraySourceName = GetArraySourceName(CallCex.FailingRequires); Debug.Assert(RaceyArraySourceName != null); IEnumerable <SourceLocationInfo> PossibleSourcesForFirstAccess = GetPossibleSourceLocationsForFirstAccessInRace(CallCex, RaceyArrayName, AccessType.Create(access1), GetStateName(CallCex)); SourceLocationInfo SourceInfoForSecondAccess = new SourceLocationInfo(GetAttributes(CallCex.FailingCall), GetSourceFileName(), CallCex.FailingCall.tok); ErrorWriteLine("\n" + SourceInfoForSecondAccess.Top().GetFile() + ":", "possible " + raceName + " race on " + ArrayOffsetString(CallCex, RaceyArraySourceName) + ":\n", ErrorMsgType.Error); Console.Error.WriteLine(access2 + " by " + ThreadDetails(CallCex.Model, 2, true) + ", " + SourceInfoForSecondAccess.Top() + ":"); SourceInfoForSecondAccess.PrintStackTrace(); Console.Error.Write(access1 + " by " + ThreadDetails(CallCex.Model, 1, true) + ", "); if (PossibleSourcesForFirstAccess.Count() == 1) { Console.Error.WriteLine(PossibleSourcesForFirstAccess.ToList()[0].Top() + ":"); PossibleSourcesForFirstAccess.ToList()[0].PrintStackTrace(); } else if (PossibleSourcesForFirstAccess.Count() == 0) { Console.Error.WriteLine("from external source location\n"); } else { Console.Error.WriteLine("possible sources are:"); List <SourceLocationInfo> LocationsAsList = PossibleSourcesForFirstAccess.ToList(); LocationsAsList.Sort(new SourceLocationInfo.SourceLocationInfoComparison()); foreach (var sli in LocationsAsList) { Console.Error.WriteLine(sli.Top() + ":"); sli.PrintStackTrace(); } Console.Error.WriteLine(); } }
public int ReportCounterexample(Counterexample error) { Contract.Requires(error != null); int errors = 0; if (error is AssertCounterexample) { AssertCounterexample cex = error as AssertCounterexample; if (QKeyValue.FindBoolAttribute(cex.FailingAssert.Attributes, "race_checking")) { errors += this.ReportRace(cex); } else { Console.WriteLine("Error: AssertCounterexample"); errors++; } } else if (error is CallCounterexample) { CallCounterexample cex = error as CallCounterexample; Console.WriteLine(cex.FailingRequires.Condition); Console.WriteLine(cex.FailingRequires.Line); Console.WriteLine("Error: CallCounterexample"); this.ReportRequiresFailure(cex); errors++; } else if (error is ReturnCounterexample) { Console.WriteLine((error as ReturnCounterexample).FailingEnsures.Condition); Console.WriteLine((error as ReturnCounterexample).FailingEnsures.Line); Console.WriteLine("Error: ReturnCounterexample"); errors++; } if (errors > 0) { this.FoundErrors = true; } return(errors); }
/// <summary> /// Retrieves the race information. /// </summary> /// <param name="example">The counter example.</param> /// <param name="error">The race error.</param> /// <returns>The race errors.</returns> public IEnumerable <RaceError> GetRaceInformation(CallCounterexample example, RaceError error) { string raceName, access1, access2; DetermineNatureOfRace(example, out raceName, out access1, out access2); PopulateModelWithStatesIfNecessary(example); string raceyArrayName = GetArrayName(example.FailingRequires); IEnumerable <SourceLocationInfo> possibleSourcesForFirstAccess = GetPossibleSourceLocationsForFirstAccessInRace( example, raceyArrayName, AccessType.Create(access1), GetStateName(example)); SourceLocationInfo sourceInfoForSecondAccess = new SourceLocationInfo( GetAttributes(example.FailingCall), GetSourceFileName(), example.FailingCall.tok); error.RaceType = raceName; error.Access1 = access1; error.Access2 = access2; List <RaceError> errors = new List <RaceError>(); foreach (SourceLocationInfo possibleSourceForFirstAccess in possibleSourcesForFirstAccess) { RaceError race = new RaceError(error.CounterExample, error.Implementation) { RaceType = raceName, Access1 = access1, Access2 = access2, Start = possibleSourceForFirstAccess, End = sourceInfoForSecondAccess }; errors.Add(race); } if (!errors.Any()) { return new List <RaceError> { error } } ; return(errors); }
private static AccessType GetAccessType(CallCounterexample err) { if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "write_write") || QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "write_read") || QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "write_atomic")) { return(AccessType.WRITE); } else if (QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "read_write") || QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "read_atomic")) { return(AccessType.READ); } else { Debug.Assert(QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "atomic_read") || QKeyValue.FindBoolAttribute(err.FailingRequires.Attributes, "atomic_write")); return(AccessType.ATOMIC); } }
/// <summary> /// Generates the errors from the counter example. /// </summary> /// <param name="example">The counter example.</param> /// <param name="implementation">The implementation.</param> /// <returns>The error.</returns> private IEnumerable <Error> GenerateErrors(Counterexample example, Implementation implementation) { List <Error> errors = new List <Error>(); if (example is CallCounterexample) { CallCounterexample callCounterexample = example as CallCounterexample; if (QKeyValue.FindBoolAttribute(callCounterexample.FailingRequires.Attributes, "barrier_divergence")) { DivergenceError divergence = new DivergenceError(example, implementation); ErrorReporter reporter = new ErrorReporter(program, implementation.Name); reporter.PopulateDivergenceInformation(callCounterexample, divergence); IdentifyVariables(divergence); errors.Add(divergence); return(errors); } else if (QKeyValue.FindBoolAttribute(callCounterexample.FailingRequires.Attributes, "race")) { RaceError template = new RaceError(example, implementation); ErrorReporter reporter = new ErrorReporter(program, implementation.Name); IEnumerable <RaceError> races = reporter.GetRaceInformation(callCounterexample, template); foreach (RaceError race in races) { IdentifyVariables(race); } errors.AddRange(races); return(errors); } } errors.Add(new Error(example, implementation)); return(errors); }
internal void ReportCounterexample(Counterexample error) { int WindowWidth; try { WindowWidth = Console.WindowWidth; } catch (IOException) { WindowWidth = 20; } for (int i = 0; i < WindowWidth; i++) { Console.Error.Write("-"); } if (error is CallCounterexample) { CallCounterexample CallCex = (CallCounterexample)error; if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "barrier_divergence")) { ReportBarrierDivergence(CallCex.FailingCall); } else if (QKeyValue.FindBoolAttribute(CallCex.FailingRequires.Attributes, "race")) { ReportRace(CallCex); } else { ReportRequiresFailure(CallCex.FailingCall, CallCex.FailingRequires); } } else if (error is ReturnCounterexample) { ReturnCounterexample ReturnCex = (ReturnCounterexample)error; ReportEnsuresFailure(ReturnCex.FailingEnsures); } else { AssertCounterexample AssertCex = (AssertCounterexample)error; if (AssertCex.FailingAssert is LoopInitAssertCmd) { ReportInvariantEntryFailure(AssertCex); } else if (AssertCex.FailingAssert is LoopInvMaintainedAssertCmd) { ReportInvariantMaintedFailure(AssertCex); } else if (QKeyValue.FindBoolAttribute(AssertCex.FailingAssert.Attributes, "barrier_invariant")) { ReportFailingBarrierInvariant(AssertCex); } else if (QKeyValue.FindBoolAttribute(AssertCex.FailingAssert.Attributes, "barrier_invariant_access_check")) { ReportFailingBarrierInvariantAccessCheck(AssertCex); } else if (QKeyValue.FindBoolAttribute(AssertCex.FailingAssert.Attributes, "constant_write")) { ReportFailingConstantWriteCheck(AssertCex); } else if (QKeyValue.FindBoolAttribute(AssertCex.FailingAssert.Attributes, "bad_pointer_access")) { ReportFailingBadPointerAccess(AssertCex); } else if (QKeyValue.FindBoolAttribute(AssertCex.FailingAssert.Attributes, "array_bounds")) { ReportFailingArrayBounds(AssertCex); } else { ReportFailingAssert(AssertCex); } } DisplayParameterValues(error); if (((GVCommandLineOptions)CommandLineOptions.Clo).DisplayLoopAbstractions) { DisplayLoopAbstractions(error); } }
private IEnumerable <SourceLocationInfo> GetPossibleSourceLocationsForFirstAccessInRace(CallCounterexample CallCex, string ArrayName, AccessType AccessType, string RaceyState) { string AccessHasOccurred = RaceInstrumentationUtil.MakeHasOccurredVariableName(ArrayName, AccessType); string AccessOffset = RaceInstrumentationUtil.MakeOffsetVariableName(ArrayName, AccessType); AssumeCmd ConflictingAction = DetermineConflictingAction(CallCex, RaceyState, AccessHasOccurred, AccessOffset); var ConflictingState = QKeyValue.FindStringAttribute(ConflictingAction.Attributes, "captureState"); if (ConflictingState.Contains("loop_head_state")) { // The state may have been renamed (for example, if k-induction has been employed), // so we need to find the original state name. This can be computed as the substring before the first // occurrence of '$'. This inversion is fragile, and would be a good candidate for making robust string ConflictingStatePrefix; if (ConflictingState.Contains('$')) { ConflictingStatePrefix = ConflictingState.Substring(0, ConflictingState.IndexOf('$')); } else { ConflictingStatePrefix = ConflictingState; } Program originalProgram = GetOriginalProgram(); var blockGraph = originalProgram.ProcessLoops(GetOriginalImplementation(originalProgram)); Block header = FindLoopHeaderWithStateName(ConflictingStatePrefix, blockGraph); Debug.Assert(header != null); HashSet <Block> LoopNodes = new HashSet <Block>( blockGraph.BackEdgeNodes(header).Select(Item => blockGraph.NaturalLoops(header, Item)).SelectMany(Item => Item) ); return(GetSourceLocationsFromBlocks("_CHECK_" + AccessType + "_" + ArrayName, LoopNodes)); } else if (ConflictingState.Contains("call_return_state")) { return(GetSourceLocationsFromCall("_CHECK_" + AccessType + "_" + ArrayName, QKeyValue.FindStringAttribute(ConflictingAction.Attributes, "procedureName"))); } else { Debug.Assert(ConflictingState.Contains("check_state")); return(new HashSet <SourceLocationInfo> { new SourceLocationInfo(ConflictingAction.Attributes, GetSourceFileName(), ConflictingAction.tok) }); } }
private static string GetStateName(CallCounterexample CallCex) { return(GetStateName(CallCex.FailingCall.Attributes, CallCex)); }