private static string MakeDisplayString(CallTreeNode node)
        {
            // Use the following preferences for the CallTreeNode text.
            // 1. CodeFlowLocation.Location.Message.Text
            // 2. CodeFlowLocation.Location.PhysicalLocation.Region.Snippet.Text
            // 3. "Continuing"
            string text = string.Empty;

            CodeFlowLocation codeFlowLocation = node.Location;

            if (codeFlowLocation != null)
            {
                if (!String.IsNullOrWhiteSpace(codeFlowLocation.Location?.Message?.Text))
                {
                    text = codeFlowLocation.Location.Message.Text;
                }
                else if (!String.IsNullOrWhiteSpace(codeFlowLocation.Location?.PhysicalLocation?.Region?.Snippet?.Text))
                {
                    text = codeFlowLocation.Location.PhysicalLocation.Region.Snippet.Text.Trim();
                }
                else
                {
                    text = Resources.ContinuingCallTreeNodeMessage;
                }
            }

            return(text);
        }
        internal CodeFlowLocation CreateCodeFlowLocation(AnnotatedCodeLocationVersionOne v1AnnotatedCodeLocation)
        {
            CodeFlowLocation codeFlowLocation = null;

            if (v1AnnotatedCodeLocation != null)
            {
                codeFlowLocation = new CodeFlowLocation
                {
                    Importance   = Utilities.CreateCodeFlowLocationImportance(v1AnnotatedCodeLocation.Importance),
                    Location     = CreateLocation(v1AnnotatedCodeLocation),
                    Module       = v1AnnotatedCodeLocation.Module,
                    NestingLevel = _codeFlowLocationNestingLevel,
                    Properties   = v1AnnotatedCodeLocation.Properties,
                    State        = v1AnnotatedCodeLocation.State,
                    Step         = v1AnnotatedCodeLocation.Step + _codeFlowLocationStepAdjustment
                };

                if (v1AnnotatedCodeLocation.Kind == AnnotatedCodeLocationKindVersionOne.Call)
                {
                    _codeFlowLocationNestingLevel++;
                }
                else if (v1AnnotatedCodeLocation.Kind == AnnotatedCodeLocationKindVersionOne.CallReturn)
                {
                    _codeFlowLocationNestingLevel--;
                }
            }

            return(codeFlowLocation);
        }
Пример #3
0
        public static CodeFlowLocationModel ToCodeFlowLocationModel(this CodeFlowLocation codeFlowLocation)
        {
            var model = codeFlowLocation.Location != null
                ? codeFlowLocation.Location.ToCodeFlowLocationModel()
                : new CodeFlowLocationModel();

            model.IsEssential = codeFlowLocation.Importance == CodeFlowLocationImportance.Essential;

            return(model);
        }
Пример #4
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 <CodeFlowLocation>();
            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 codeFlowLocation = new CodeFlowLocation
                {
                    Location = new Location
                    {
                        PhysicalLocation = fileLocation
                    },
                    Step = ++step
                };

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

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

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

                locations.Add(codeFlowLocation);
            }

            result.CodeFlows = new List <CodeFlow>()
            {
                SarifUtilities.CreateSingleThreadedCodeFlow(locations)
            };
        }
        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 codeFlowLocation = new CodeFlowLocation
                {
                    Step       = step + 1,
                    Importance = CodeFlowLocationImportance.Unimportant,
                    Location   = new Location
                    {
                        Message = new Message()
                    }
                };

                if (uri != null)
                {
                    codeFlowLocation.Location.PhysicalLocation = new PhysicalLocation
                    {
                        FileLocation = new FileLocation
                        {
                            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))
                    {
                        codeFlowLocation.Location.FullyQualifiedLogicalName = caller;
                        codeFlowLocation.Location.Message.Text = callee;
                        codeFlowLocation.SetProperty("target", callee);
                        _callers.Push(caller);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    codeFlowLocation.NestingLevel = nestingLevel++;

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

                    codeFlowLocation.NestingLevel = nestingLevel--;
                    codeFlowLocation.Location.FullyQualifiedLogicalName = _callers.Pop();
                }
                else
                {
                    codeFlowLocation.NestingLevel          = nestingLevel;
                    codeFlowLocation.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)
                    {
                        codeFlowLocation.SetProperty("currentDataValues", stateTokens[0]);
                        codeFlowLocation.SetProperty("permanentDataValues", stateTokens[1]);
                    }
                    else
                    {
                        Debug.Assert(stateTokens.Length == 1);
                        if (stateTokens[0].StartsWith(separatorText))
                        {
                            codeFlowLocation.SetProperty("permanentDataValues", stateTokens[0]);
                        }
                        else
                        {
                            codeFlowLocation.SetProperty("currentDataValues", stateTokens[0]);
                        }
                    }
                }

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

                string levelText = tokens[LEVEL];

                result.Level = ConvertToResultLevel(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 = ResultLevel.Pass;
                }

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

                IList <CodeFlowLocation> 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;
                    }
                }
            }
        }
Пример #6
0
        private void ParseLocationFromAnalysisInfo(Result result)
        {
            CodeFlow codeFlow = result.CodeFlows.First();
            int      step     = 0;

            _reader.Read();
            string lastSnippetId = null;

            while (!AtEndOf(_strings.AnalysisInfo))
            {
                // Note: SourceLocation is an empty element (it has only attributes),
                // so we can't call AtStartOfNonEmpty here.
                if (AtStartOf(_strings.SourceLocation))
                {
                    string           snippetId = _reader.GetAttribute(_strings.SnippetAttribute);
                    PhysicalLocation physLoc   = ParsePhysicalLocationFromSourceInfo();

                    var cfl = new CodeFlowLocation
                    {
                        Step     = ++step,
                        Location = new Location
                        {
                            PhysicalLocation = physLoc
                        }
                    };

                    // 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))
                    {
                        _cflToSnippetIdDictionary.Add(cfl, snippetId);
                    }

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

                    // 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.
                    lastSnippetId = snippetId;

                    // Step past the empty element.
                    _reader.Read();
                }
                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
                });

                if (!String.IsNullOrEmpty(lastSnippetId))
                {
                    _resultToSnippetIdDictionary.Add(result, lastSnippetId);
                }
            }
        }