Пример #1
0
        private void Visit(ThreadFlowLocation threadFlowLocation, string threadFlowLocationPointer)
        {
            Analyze(threadFlowLocation, threadFlowLocationPointer);

            if (threadFlowLocation.Location != null)
            {
                Visit(threadFlowLocation.Location, threadFlowLocationPointer.AtProperty(SarifPropertyName.Location));
            }

            if (threadFlowLocation.Taxa != null)
            {
                string taxaPointer = threadFlowLocationPointer.AtProperty(SarifPropertyName.Taxa);

                Context.CurrentReportingDescriptorKind = SarifValidationContext.ReportingDescriptorKind.Taxon;
                try
                {
                    for (int i = 0; i < threadFlowLocation.Taxa.Count; ++i)
                    {
                        Visit(threadFlowLocation.Taxa[i], taxaPointer.AtIndex(i));
                    }
                }
                finally
                {
                    Context.CurrentReportingDescriptorKind = SarifValidationContext.ReportingDescriptorKind.None;
                }
            }

            if (threadFlowLocation.WebRequest != null)
            {
                Visit(threadFlowLocation.WebRequest, threadFlowLocationPointer.AtProperty(SarifPropertyName.WebRequest));
            }

            if (threadFlowLocation.WebResponse != null)
            {
                Visit(threadFlowLocation.WebResponse, threadFlowLocationPointer.AtProperty(SarifPropertyName.WebResponse));
            }
        }
Пример #2
0
        private void ParseLocationsFromTraces(Result result)
        {
            CodeFlow codeFlow   = null;
            string   nodeLabel  = null;
            string   lastNodeId = null;
            bool?    isDefault  = null;

            while (!AtEndOf(_strings.Unified))
            {
                if (AtStartOf(_strings.Trace))
                {
                    codeFlow = SarifUtilities.CreateSingleThreadedCodeFlow();
                    result.CodeFlows.Add(codeFlow);

                    while (!AtEndOf(_strings.Trace))
                    {
                        if (AtStartOf(_strings.NodeRef))
                        {
                            string nodeId = _reader.GetAttribute(_strings.IdAttribute);

                            if (!string.IsNullOrWhiteSpace(nodeId))
                            {
                                var tfl = new ThreadFlowLocation();
                                _tflToNodeIdDictionary.Add(tfl, nodeId);
                                codeFlow.ThreadFlows[0].Locations.Add(tfl);
                            }

                            _reader.Read();
                        }
                        else if (AtStartOf(_strings.Node))
                        {
                            if (isDefault == null)
                            {
                                // We haven't found the default node yet, so check this one.
                                string isDefaultValue = _reader.GetAttribute(_strings.IsDefaultAttribute);

                                if (!string.IsNullOrWhiteSpace(isDefaultValue) &&
                                    bool.TryParse(isDefaultValue, out bool val) &&
                                    val == true)
                                {
                                    // This is the default, set the flag so we know to add a result location
                                    isDefault = val;
                                }
                            }

                            nodeLabel = _reader.GetAttribute(_strings.LabelAttribute);
                            _reader.Read();
                        }
                        else if (AtStartOf(_strings.SourceLocation))
                        {
                            // Note: SourceLocation is an empty element (it has only attributes),
                            // so we can't call AtStartOfNonEmpty here.

                            string           snippetId        = _reader.GetAttribute(_strings.SnippetAttribute);
                            PhysicalLocation physicalLocation = ParsePhysicalLocationFromSourceInfo();

                            // Step past the empty SourceLocation element.
                            _reader.Read();

                            string actionType = null;
                            if (AtStartOf(_strings.Action))
                            {
                                actionType = _reader.GetAttribute(_strings.TypeAttribute);
                                actionType = actionType ?? string.Empty; // We use empty string to indicates there is an
                                                                         // Action element without a type attribute.

                                // If we don't have a label, get the <Action> value
                                if (string.IsNullOrWhiteSpace(nodeLabel))
                                {
                                    nodeLabel = _reader.ReadElementContentAsString();
                                }
                            }

                            if (actionType == string.Empty)
                            {
                                if (codeFlow.ThreadFlows[0].Locations.Count > 0)
                                {
                                    // If there is no type attribute on the Action element, we treat
                                    // it as a note about the prior node.
                                    ThreadFlowLocation tfl = codeFlow.ThreadFlows[0].Locations.Last();

                                    // Annotate the location with the Action text.
                                    if (tfl?.Location != null)
                                    {
                                        tfl.Location.Annotations = new List <Region>();
                                        Region region = physicalLocation.Region;
                                        region.Message = new Message
                                        {
                                            Text = nodeLabel
                                        };
                                        tfl.Location.Annotations.Add(region);
                                    }
                                }
                            }
                            else
                            {
                                var location = new Location
                                {
                                    PhysicalLocation = physicalLocation
                                };

                                if (isDefault == true)
                                {
                                    result.Locations = new List <Location>();
                                    result.Locations.Add(location.DeepClone());
                                    result.RelatedLocations.Add(location.DeepClone());

                                    // Keep track of the snippet associated with the default location.
                                    // That's the snippet that we'll associate with the result.
                                    lastNodeId = snippetId;

                                    isDefault = false; // This indicates we have already found the default node.
                                }

                                var tfl = new ThreadFlowLocation
                                {
                                    Kinds = new List <string> {
                                        actionType
                                    },
                                    Location = location
                                };

                                if (!string.IsNullOrWhiteSpace(nodeLabel))
                                {
                                    tfl.Location.Message = new Message
                                    {
                                        Text = nodeLabel
                                    };
                                }

                                // Remember the id of the snippet associated with this location.
                                // We'll use it to fill the snippet text when we read the Snippets element later on.
                                if (!string.IsNullOrEmpty(snippetId))
                                {
                                    _tflToSnippetIdDictionary.Add(tfl, snippetId);
                                }

                                codeFlow.ThreadFlows[0].Locations.Add(tfl);
                            }
                        }
                        else
                        {
                            _reader.Read();
                        }
                    }
                }
                else
                {
                    _reader.Read();
                }
            }

            if (result.RelatedLocations.Any())
            {
                Location relatedLocation = result.RelatedLocations.Last();

                if (relatedLocation != null)
                {
                    relatedLocation.PhysicalLocation.Id = 1;
                }
            }

            if (!string.IsNullOrEmpty(lastNodeId))
            {
                _resultToSnippetIdDictionary.Add(result, lastNodeId);
            }
        }
        internal AnnotatedCodeLocationVersionOne CreateAnnotatedCodeLocationVersionOne(ThreadFlowLocation v2ThreadFlowLocation)
        {
            AnnotatedCodeLocationVersionOne annotatedCodeLocation = null;

            if (v2ThreadFlowLocation != null)
            {
                annotatedCodeLocation = CreateAnnotatedCodeLocationVersionOne(v2ThreadFlowLocation.Location);
                annotatedCodeLocation = annotatedCodeLocation ?? new AnnotatedCodeLocationVersionOne();

                annotatedCodeLocation.Importance = Utilities.CreateAnnotatedCodeLocationImportance(v2ThreadFlowLocation.Importance);
                annotatedCodeLocation.Module     = v2ThreadFlowLocation.Module;
                annotatedCodeLocation.Properties = v2ThreadFlowLocation.Properties;
                annotatedCodeLocation.State      = v2ThreadFlowLocation.State;
                annotatedCodeLocation.Step       = v2ThreadFlowLocation.ExecutionOrder;
            }

            return(annotatedCodeLocation);
        }
Пример #4
0
        private void ProcessLine(string logFileLine, ref int nestingLevel, Result result)
        {
            var codeFlow = result.CodeFlows[0];

            const int STEP = 0;
            const int URI  = 1;
            const int LINE = 2;
            // const int IMPORTANCE  = 3; This value not persisted to SARIF
            const int STATE = 4;
            const int KIND1 = 5;

            // When KIND1 == "Atomic" the 6th slot is the
            // the remainder of the kind id, e.g., Atomic Assigment
            const int KIND2 = 6;

            // When KIND1 == "Call" the 6th and 7th slots are:
            const int CALLER = 6;
            const int CALLEE = 7;

            int step;

            string[] tokens = logFileLine.Split(' ');

            if (int.TryParse(tokens[STEP], out step))
            {
                // If we find a numeric value as the first token,
                // this is a general step.

                Uri    uri     = null;
                string uriText = tokens[URI].Trim('"');

                if (!uriText.Equals("?", StringComparison.Ordinal))
                {
                    if (File.Exists(uriText))
                    {
                        uriText = Path.GetFullPath(uriText);
                    }
                    uri = new Uri(uriText, UriKind.RelativeOrAbsolute);
                }

                // We assume a valid line here. This code will throw if not.
                int line = int.Parse(tokens[LINE]);

                string sdvKind = tokens[KIND1];

                if (sdvKind.Equals("Atomic", StringComparison.Ordinal))
                {
                    // For multipart SDV kinds 'Atomic XXX', we
                    // map using the second value only, e.g,
                    // 'Assignment' or 'Conditional'
                    sdvKind = tokens[KIND2];
                }

                sdvKind = sdvKind.Trim();

                var threadFlowLocation = new ThreadFlowLocation
                {
                    Importance = ThreadFlowLocationImportance.Unimportant,
                    Location   = new Location
                    {
                        Message = new Message()
                    }
                };

                if (uri != null)
                {
                    threadFlowLocation.Location.PhysicalLocation = new PhysicalLocation
                    {
                        ArtifactLocation = new ArtifactLocation
                        {
                            Uri = uri
                        },
                        Region = new Region
                        {
                            StartLine = line
                        }
                    };
                }

                if (sdvKind == "Call")
                {
                    string extraMsg = $"{tokens[KIND1]} {tokens[CALLER]} {tokens[CALLEE]}";

                    string caller, callee;

                    if (ExtractCallerAndCallee(extraMsg.Trim(), out caller, out callee))
                    {
                        threadFlowLocation.Location.FullyQualifiedLogicalName = caller;
                        threadFlowLocation.Location.Message.Text = callee;
                        threadFlowLocation.SetProperty("target", callee);
                        _callers.Push(caller);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    threadFlowLocation.NestingLevel = nestingLevel++;

                    if (uri == null)
                    {
                        threadFlowLocation.Importance = ThreadFlowLocationImportance.Unimportant;
                    }
                    else if (IsHarnessOrRulesFiles(uriText))
                    {
                        threadFlowLocation.Importance = ThreadFlowLocationImportance.Important;
                    }
                    else
                    {
                        threadFlowLocation.Importance = ThreadFlowLocationImportance.Essential;
                    }
                }
                else if (sdvKind == "Return")
                {
                    Debug.Assert(_callers.Count > 0);

                    threadFlowLocation.NestingLevel = nestingLevel--;
                    threadFlowLocation.Location.FullyQualifiedLogicalName = _callers.Pop();
                }
                else
                {
                    threadFlowLocation.NestingLevel          = nestingLevel;
                    threadFlowLocation.Location.Message.Text = sdvKind;
                }

                string   separatorText = "^====Auto=====";
                string   state         = tokens[STATE];
                string[] stateTokens   = state.Split(new string[] { separatorText }, StringSplitOptions.RemoveEmptyEntries);

                if (stateTokens.Length > 0)
                {
                    if (stateTokens.Length == 2)
                    {
                        threadFlowLocation.SetProperty("currentDataValues", stateTokens[0]);
                        threadFlowLocation.SetProperty("permanentDataValues", stateTokens[1]);
                    }
                    else
                    {
                        Debug.Assert(stateTokens.Length == 1);
                        if (stateTokens[0].StartsWith(separatorText))
                        {
                            threadFlowLocation.SetProperty("permanentDataValues", stateTokens[0]);
                        }
                        else
                        {
                            threadFlowLocation.SetProperty("currentDataValues", stateTokens[0]);
                        }
                    }
                }

                codeFlow.ThreadFlows[0].Locations.Add(threadFlowLocation);
            }
            else
            {
                // This is the defect message.
                const int LEVEL = 0;

                string levelText = tokens[LEVEL];

                result.Level = ConvertToFailureLevel(levelText);

                // Everything on the line following defect level comprises the message
                result.Message = new Message {
                    Text = logFileLine.Substring(levelText.Length).Trim()
                };

                // SDV currently produces 'pass' notifications when
                // the final line is prefixed with 'Error'. We'll examine
                // the message text to detect this condition
                if (result.Message.Text.Contains("is satisfied"))
                {
                    result.Level = FailureLevel.None;
                    result.Kind  = ResultKind.Pass;
                }

                // Finally, populate this result location with the
                // last observed location in the code flow.

                IList <ThreadFlowLocation> locations = result.CodeFlows[0].ThreadFlows[0].Locations;

                for (int i = locations.Count - 1; i >= 0; --i)
                {
                    if (locations[i].Location?.PhysicalLocation != null)
                    {
                        result.Locations.Add(new Location
                        {
                            PhysicalLocation = locations[i].Location.PhysicalLocation
                        });
                        break;
                    }
                }
            }
        }
Пример #5
0
        private void GenerateCodeFlows(Defect defect, Result result)
        {
            List <SFA> sfas = defect?.Path?.SFAs;

            if (sfas == null || sfas.Count == 0)
            {
                return;
            }

            int  step              = 0;
            var  locations         = new List <ThreadFlowLocation>();
            bool pathUsesKeyEvents = defect.Path.SFAs.Any(x => !string.IsNullOrWhiteSpace(x?.KeyEvent?.Id));

            foreach (var sfa in defect.Path.SFAs)
            {
                var region = new Region()
                {
                    StartColumn = sfa.Column + 1,
                    StartLine   = sfa.Line
                };

                var uri                = new Uri($"{sfa.FilePath}{sfa.FileName}", UriKind.Relative);
                var fileLocation       = new PhysicalLocation(id: 0, fileLocation: new FileLocation(uri: uri, uriBaseId: null), region: region, contextRegion: null);
                var threadFlowLocation = new ThreadFlowLocation
                {
                    Location = new Location
                    {
                        PhysicalLocation = fileLocation
                    },
                    Step = ++step
                };

                if (pathUsesKeyEvents)
                {
                    if (string.IsNullOrWhiteSpace(sfa.KeyEvent?.Id))
                    {
                        threadFlowLocation.Importance = ThreadFlowLocationImportance.Unimportant;
                    }
                    else
                    {
                        threadFlowLocation.SetProperty("keyEventId", sfa.KeyEvent.Id);

                        if (Enum.TryParse(sfa.KeyEvent.Importance, true, out ThreadFlowLocationImportance importance))
                        {
                            threadFlowLocation.Importance = importance;
                        }

                        if (!string.IsNullOrWhiteSpace(sfa.KeyEvent.Message) &&
                            threadFlowLocation.Location?.Message != null)
                        {
                            threadFlowLocation.Location.Message.Text = sfa.KeyEvent.Message;
                        }
                    }
                }

                locations.Add(threadFlowLocation);
            }

            result.CodeFlows = new List <CodeFlow>()
            {
                SarifUtilities.CreateSingleThreadedCodeFlow(locations)
            };
        }
Пример #6
0
 protected virtual void Analyze(ThreadFlowLocation threadFlowLocation, string threadFlowLocationPointer)
 {
 }
Пример #7
0
        private void ParseLocationFromTrace(Result result)
        {
            CodeFlow codeFlow   = result.CodeFlows.First();
            int      step       = 0;
            string   nodeLabel  = null;
            string   lastNodeId = null;

            _reader.Read();

            while (!AtEndOf(_strings.Trace))
            {
                if (AtStartOf(_strings.NodeRef))
                {
                    string nodeId = _reader.GetAttribute(_strings.IdAttribute);

                    if (!string.IsNullOrWhiteSpace(nodeId))
                    {
                        var tfl = new ThreadFlowLocation
                        {
                            Step = ++step
                        };

                        _tflToNodeIdDictionary.Add(tfl, nodeId);
                        codeFlow.ThreadFlows[0].Locations.Add(tfl);
                    }

                    _reader.Read();
                }
                else if (AtStartOf(_strings.Node))
                {
                    nodeLabel = _reader.GetAttribute(_strings.LabelAttribute);
                    _reader.Read();
                }
                else if (AtStartOf(_strings.SourceLocation))
                {
                    // Note: SourceLocation is an empty element (it has only attributes),
                    // so we can't call AtStartOfNonEmpty here.

                    string           snippetId        = _reader.GetAttribute(_strings.SnippetAttribute);
                    PhysicalLocation physicalLocation = ParsePhysicalLocationFromSourceInfo();

                    // Step past the empty SourceLocation element.
                    _reader.Read();

                    // If we don't have a label, get the <Action> value
                    if (string.IsNullOrWhiteSpace(nodeLabel))
                    {
                        nodeLabel = _reader.ReadElementContentAsString();
                    }

                    var tfl = new ThreadFlowLocation
                    {
                        Step     = ++step,
                        Location = new Location
                        {
                            Message = new Message
                            {
                                Text = nodeLabel
                            },
                            PhysicalLocation = physicalLocation
                        }
                    };

                    // Remember the id of the snippet associated with this location.
                    // We'll use it to fill the snippet text when we read the Snippets element later on.
                    if (!string.IsNullOrEmpty(snippetId))
                    {
                        _tflToSnippetIdDictionary.Add(tfl, snippetId);
                    }

                    codeFlow.ThreadFlows[0].Locations.Add(tfl);

                    // Keep track of the snippet associated with the last location in the
                    // CodeFlow; that's the snippet that we'll associate with the Result
                    // as a whole.
                    lastNodeId = snippetId;
                }
                else
                {
                    _reader.Read();
                }
            }

            if (codeFlow.ThreadFlows[0].Locations.Any())
            {
                result.Locations.Add(new Location
                {
                    // TODO: Confirm that the traces are ordered chronologically
                    // (so that we really do want to use the last one as the
                    // overall result location).
                    PhysicalLocation = codeFlow.ThreadFlows[0].Locations.Last().Location?.PhysicalLocation.DeepClone()
                });
                result.RelatedLocations.Add(new Location
                {
                    // Links embedded in the result message refer to related physicalLocation.id
                    PhysicalLocation = codeFlow.ThreadFlows[0].Locations.Last().Location?.PhysicalLocation.DeepClone()
                });

                result.RelatedLocations.Last().PhysicalLocation.Id = 1;

                if (!string.IsNullOrEmpty(lastNodeId))
                {
                    _resultToSnippetIdDictionary.Add(result, lastNodeId);
                }
            }
        }
Пример #8
0
 public Node(ThreadFlowLocation tfl, string snippetId)
 {
     this.ThreadFlowLocation = tfl;
     this.SnippetId          = snippetId;
 }