예제 #1
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 <AnnotatedCodeLocation>();
            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(uri: uri, uriBaseId: null, region: region);
                var annotatedCodeLocation = new AnnotatedCodeLocation
                {
                    PhysicalLocation = fileLocation,
                    Step             = ++step
                };

                if (pathUsesKeyEvents)
                {
                    if (string.IsNullOrWhiteSpace(sfa.KeyEvent?.Id))
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Unimportant;
                    }
                    else
                    {
                        annotatedCodeLocation.SetProperty("keyEventId", sfa.KeyEvent.Id);
                        if (Enum.TryParse(sfa.KeyEvent.Kind, true, out AnnotatedCodeLocationKind kind))
                        {
                            annotatedCodeLocation.Kind = kind;
                        }

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

                        if (!string.IsNullOrWhiteSpace(sfa.KeyEvent.Message))
                        {
                            annotatedCodeLocation.Message = sfa.KeyEvent.Message;
                        }
                    }
                }

                locations.Add(annotatedCodeLocation);
            }

            result.CodeFlows = new List <CodeFlow>()
            {
                new CodeFlow
                {
                    Locations = locations
                }
            };
        }
        private void ProcessLine(string logFileLine, 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];
                }

                AnnotatedCodeLocationKind kind = ConvertToAnnotatedCodeLocationKind(sdvKind.Trim());

                var annotatedCodeLocation = new AnnotatedCodeLocation
                {
                    Kind = kind,
                    Step = step,
                    Importance = AnnotatedCodeLocationImportance.Unimportant,
                    PhysicalLocation = (uri != null) ? new PhysicalLocation
                    {
                        Uri = uri,
                        Region = new Region
                        {
                            StartLine = line
                        }
                    } : null,
                };

                if (kind == AnnotatedCodeLocationKind.Call)
                {
                    string extraMsg = tokens[KIND1] + " " + tokens[CALLER] + " " + tokens[CALLEE];

                    string caller, callee;

                    if (ExtractCallerAndCallee(extraMsg.Trim(), out caller, out callee))
                    {
                        annotatedCodeLocation.FullyQualifiedLogicalName = caller;
                        annotatedCodeLocation.Target = callee;
                        _callers.Push(caller);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    if (uri == null)
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Unimportant;
                    }
                    else if (IsHarnessOrRulesFiles(uriText))
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Important;
                    }
                    else
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Essential;
                    }

                }

                if (kind == AnnotatedCodeLocationKind.CallReturn)
                {
                    Debug.Assert(_callers.Count > 0);
                    annotatedCodeLocation.FullyQualifiedLogicalName = _callers.Pop();
                }

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

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

                codeFlow.Locations.Add(annotatedCodeLocation);
            }
            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 = 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.Contains("is satisfied"))
                {
                    result.Level = ResultLevel.Pass;
                }

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

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

                for (int i = locations.Count - 1; i >= 0; --i)
                {
                    if (locations[i].PhysicalLocation != null)
                    {
                        result.Locations.Add(new Location
                        {
                            ResultFile = locations[i].PhysicalLocation
                        });
                        break;
                    }
                }
            }
        }
예제 #3
0
        private void ProcessLine(string logFileLine, 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];
                }

                AnnotatedCodeLocationKind kind = ConvertToAnnotatedCodeLocationKind(sdvKind.Trim());

                var annotatedCodeLocation = new AnnotatedCodeLocation
                {
                    Kind             = kind,
                    Step             = step,
                    Importance       = AnnotatedCodeLocationImportance.Unimportant,
                    PhysicalLocation = (uri != null) ? new PhysicalLocation
                    {
                        Uri    = uri,
                        Region = new Region
                        {
                            StartLine = line
                        }
                    } : null,
                };

                if (kind == AnnotatedCodeLocationKind.Call)
                {
                    string extraMsg = tokens[KIND1] + " " + tokens[CALLER] + " " + tokens[CALLEE];

                    string caller, callee;

                    if (ExtractCallerAndCallee(extraMsg.Trim(), out caller, out callee))
                    {
                        annotatedCodeLocation.FullyQualifiedLogicalName = caller;
                        annotatedCodeLocation.Target = callee;
                        _callers.Push(caller);
                    }
                    else
                    {
                        Debug.Assert(false);
                    }

                    if (uri == null)
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Unimportant;
                    }
                    else if (IsHarnessOrRulesFiles(uriText))
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Important;
                    }
                    else
                    {
                        annotatedCodeLocation.Importance = AnnotatedCodeLocationImportance.Essential;
                    }
                }

                if (kind == AnnotatedCodeLocationKind.CallReturn)
                {
                    Debug.Assert(_callers.Count > 0);
                    annotatedCodeLocation.FullyQualifiedLogicalName = _callers.Pop();
                }

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

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

                codeFlow.Locations.Add(annotatedCodeLocation);
            }
            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 = 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.Contains("is satisfied"))
                {
                    result.Level = ResultLevel.Pass;
                }

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

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

                for (int i = locations.Count - 1; i >= 0; --i)
                {
                    if (locations[i].PhysicalLocation != null)
                    {
                        result.Locations.Add(new Location
                        {
                            ResultFile = locations[i].PhysicalLocation
                        });
                        break;
                    }
                }
            }
        }