Beispiel #1
0
        public void ExtractSnippet_FileDoesNotExist_ReturnEmpty()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false);
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);

            LocationModel location = new Location
            {
                PhysicalLocation = new PhysicalLocation
                {
                    ArtifactLocation = new ArtifactLocation {
                        Uri = new Uri("file://temp.cs")
                    },
                    Region = new Region {
                        Snippet = new ArtifactContent {
                            Text = "private class Class5"
                        }
                    },
                },
            }.ToLocationModel(new Run(), 1, 1);

            string snippet = location.ExtractSnippet(regionCache, mock.Object);

            snippet.Should().BeEquivalentTo(string.Empty);
        }
        public void ToReplacementModel_RelativeUri_BinaryReplacement()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false);
            mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample);
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);

            Uri uri = new Uri(RelativeFilePath, UriKind.Relative);

            byte[] bytes = Encoding.UTF8.GetBytes(ReplacementText);

            Replacement replacement = new Replacement
            {
                DeletedRegion = new Region
                {
                    ByteOffset = 210,
                },
                InsertedContent = new ArtifactContent
                {
                    Binary = Convert.ToBase64String(bytes),
                },
            };
            ReplacementModel model = replacement.ToReplacementModel(regionCache, uri);

            model.Should().NotBeNull();
            model.InsertedString.Should().BeNull();
            model.InsertedBytes.Should().BeEquivalentTo(bytes);
            model.Region.Should().NotBeNull();
            model.Region.IsBinaryRegion.Should().BeTrue();
            model.Region.CharOffset.Should().Be(-1);
            model.Region.ByteOffset.Should().Be(210);
        }
Beispiel #3
0
        public void ExtractSnippet_FileExists_ReturnEmpty()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(true);
            mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample);
            var    regionCache     = new FileRegionsCache(fileSystem: mock.Object);
            string expectedSnippet = "internal class Class4";

            LocationModel location = new Location
            {
                PhysicalLocation = new PhysicalLocation
                {
                    ArtifactLocation = new ArtifactLocation {
                        Uri = new Uri("file://temp.cs")
                    },
                    Region = new Region
                    {
                        Snippet = new ArtifactContent {
                            Text = expectedSnippet
                        },
                        StartLine   = 7,
                        StartColumn = 5,
                        EndLine     = 7,
                        EndColumn   = 25,
                    },
                },
            }.ToLocationModel(new Run(), 1, 1);

            string snippet = location.ExtractSnippet(regionCache, mock.Object);

            snippet.Should().BeEquivalentTo(expectedSnippet);
        }
Beispiel #4
0
        public void ToFixModel_FileDoesNotExists_FixIsNotApplyable()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false);
            mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(string.Empty);
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);

            string descriptionString = "test description";
            string replacementText   = "public class";

            var fix = new Fix
            {
                Description = new Message {
                    Text = descriptionString
                },
                ArtifactChanges = new List <ArtifactChange>
                {
                    new ArtifactChange
                    {
                        ArtifactLocation = new ArtifactLocation
                        {
                            Uri = new Uri(AnotherFilePath, UriKind.Absolute),
                        },
                        Replacements = new List <Replacement>
                        {
                            new Replacement
                            {
                                DeletedRegion = new Region
                                {
                                    CharOffset = 196,
                                    CharLength = 14,
                                },
                                InsertedContent = new ArtifactContent
                                {
                                    Text = replacementText
                                },
                            },
                        },
                    },
                },
            }.ToFixModel(originalUriBaseIds: null, regionCache);

            fix.Description.Should().BeEquivalentTo(descriptionString);
            fix.ArtifactChanges.Count.Should().Be(1);
            fix.CanBeAppliedToFile(FilePath).Should().BeFalse();
            ObservableCollection <ReplacementModel> replacements = fix.ArtifactChanges.FirstOrDefault().Replacements;

            // file doesn't exist, output replacement should have be same as input region.
            replacements.Count.Should().Be(1);
            ReplacementModel replacement = replacements.FirstOrDefault();

            replacement.InsertedString.Should().BeEquivalentTo(replacementText);
            replacement.Region.CharOffset.Should().Be(196);
            replacement.Region.CharLength.Should().Be(14);
            replacement.Region.StartLine.Should().Be(0);
            replacement.Region.EndLine.Should().Be(0);
            replacement.Region.StartColumn.Should().Be(0);
            replacement.Region.EndColumn.Should().Be(0);
        }
        public void ToReplacementModel_RelativeUri_TextReplacement()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false);
            mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample);
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);

            Uri uri = new Uri(RelativeFilePath, UriKind.Relative);

            Replacement replacement = new Replacement
            {
                DeletedRegion = new Region
                {
                    CharOffset = 196,
                    CharLength = 14,
                },
                InsertedContent = new ArtifactContent
                {
                    Text = ReplacementText,
                },
            };
            ReplacementModel model = replacement.ToReplacementModel(regionCache, uri);

            model.Should().NotBeNull();
            model.InsertedBytes.Should().BeNull();
            model.InsertedString.Should().BeEquivalentTo(ReplacementText);
            model.Region.Should().NotBeNull();
            model.Region.CharLength.Should().Be(14);
            model.Region.CharOffset.Should().Be(196);
            model.Region.IsBinaryRegion.Should().BeFalse();
            model.Region.ByteOffset.Should().Be(-1);
        }
Beispiel #6
0
        public void FileRegionsCache_ProperlyCaches()
        {
            Uri uri = new Uri(@"C:\Code\Program.cs");

            StringBuilder fileContents = new StringBuilder();

            for (int i = 0; i < 1000; ++i)
            {
                fileContents.AppendLine("0123456789");
            }

            Run              run              = new Run();
            IFileSystem      mockFileSystem   = MockFactory.MakeMockFileSystem(uri.LocalPath, fileContents.ToString());
            FileRegionsCache fileRegionsCache = new FileRegionsCache(run, fileSystem: mockFileSystem);

            Region region = new Region()
            {
                StartLine   = 2,
                StartColumn = 1,
                EndLine     = 3,
                EndColumn   = 10,
            };

            Stopwatch w = Stopwatch.StartNew();

            for (int i = 0; i < 1000; ++i)
            {
                Region copy      = region.DeepClone();
                Region populated = fileRegionsCache.PopulateTextRegionProperties(copy, uri, populateSnippet: true);
            }

            // Runtime should be way under 100ms if caching, and much longer otherwise
            w.Stop();
            Assert.True(w.ElapsedMilliseconds < 100);
        }
Beispiel #7
0
        public void ToFixModel_FileExists_FixIsApplyable()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(true);
            mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample);
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);

            string descriptionString = "test description";
            string replacementText   = "public class";

            var fix = new Fix
            {
                Description = new Message {
                    Text = descriptionString
                },
                ArtifactChanges = new List <ArtifactChange>
                {
                    new ArtifactChange
                    {
                        ArtifactLocation = new ArtifactLocation
                        {
                            Uri = new Uri(FilePath, UriKind.Absolute),
                        },
                        Replacements = new List <Replacement>
                        {
                            new Replacement
                            {
                                DeletedRegion = new Region
                                {
                                    CharOffset = 196,
                                    CharLength = 14,
                                },
                                InsertedContent = new ArtifactContent
                                {
                                    Text = replacementText
                                },
                            },
                        },
                    },
                },
            }.ToFixModel(originalUriBaseIds: null, regionCache);

            fix.Description.Should().BeEquivalentTo(descriptionString);
            fix.ArtifactChanges.Count.Should().Be(1);
            fix.CanBeAppliedToFile(FilePath).Should().BeTrue();
            ObservableCollection <ReplacementModel> replacements = fix.ArtifactChanges.FirstOrDefault().Replacements;

            // input replacement is charoffset based. output replacement should have start/end line/column info.
            replacements.Count.Should().Be(1);
            ReplacementModel replacement = replacements.FirstOrDefault();

            replacement.InsertedString.Should().BeEquivalentTo(replacementText);
            replacement.Region.StartLine.Should().Be(6);
            replacement.Region.EndLine.Should().Be(6);
            replacement.Region.StartColumn.Should().Be(7);
            replacement.Region.EndColumn.Should().Be(21);
        }
Beispiel #8
0
        public override PhysicalLocation VisitPhysicalLocation(PhysicalLocation node)
        {
            if (node.Region == null || node.Region.IsBinaryRegion)
            {
                goto Exit;
            }

            bool insertRegionSnippets      = _dataToInsert.HasFlag(OptionallyEmittedData.RegionSnippets);
            bool overwriteExistingData     = _dataToInsert.HasFlag(OptionallyEmittedData.OverwriteExistingData);
            bool insertContextCodeSnippets = _dataToInsert.HasFlag(OptionallyEmittedData.ContextRegionSnippets);
            bool populateRegionProperties  = _dataToInsert.HasFlag(OptionallyEmittedData.ComprehensiveRegionProperties);

            if (insertRegionSnippets || populateRegionProperties || insertContextCodeSnippets)
            {
                Region expandedRegion;

                _fileRegionsCache = _fileRegionsCache ?? new FileRegionsCache(_run);

                // If we can resolve a file location to a newly constructed
                // absolute URI, we will prefer that
                if (!node.ArtifactLocation.TryReconstructAbsoluteUri(_run.OriginalUriBaseIds, out Uri resolvedUri))
                {
                    resolvedUri = node.ArtifactLocation.Uri;
                }

                if (!resolvedUri.IsAbsoluteUri)
                {
                    goto Exit;
                }

                expandedRegion = _fileRegionsCache.PopulateTextRegionProperties(node.Region, resolvedUri, populateSnippet: insertRegionSnippets);

                ArtifactContent originalSnippet = node.Region.Snippet;

                if (populateRegionProperties)
                {
                    node.Region = expandedRegion;
                }

                if (originalSnippet == null || overwriteExistingData)
                {
                    node.Region.Snippet = expandedRegion.Snippet;
                }
                else
                {
                    node.Region.Snippet = originalSnippet;
                }

                if (insertContextCodeSnippets && (node.ContextRegion == null || overwriteExistingData))
                {
                    node.ContextRegion = _fileRegionsCache.ConstructMultilineContextSnippet(expandedRegion, resolvedUri);
                }
            }

Exit:
            return(base.VisitPhysicalLocation(node));
        }
        private static void ExecuteTests(string fileText, ReadOnlyCollection <TestCaseData> testCases)
        {
            Uri uri = new Uri(@"c:\temp\myFile.cpp");

            var         run              = new Run();
            IFileSystem mockFileSystem   = MockFactory.MakeMockFileSystem(uri.LocalPath, fileText);
            var         fileRegionsCache = new FileRegionsCache(run, fileSystem: mockFileSystem);

            ExecuteTests(testCases, fileRegionsCache, uri);
        }
Beispiel #10
0
        // This method is called when you click an inline link, with an integer target, which
        // points to a Location object that has a region associated with it.
        internal IVsWindowFrame NavigateTo(bool usePreviewPane)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            // Before anything else, see if this is an external link we should open in the browser.
            Uri uri;

            if (Uri.TryCreate(this.FullFilePath, UriKind.Absolute, out uri))
            {
                if (!uri.IsFile)
                {
                    System.Diagnostics.Process.Start(uri.OriginalString);
                    return(null);
                }
            }

            // Fall back to the file and line number
            if (!File.Exists(this.FullFilePath))
            {
                if (!CodeAnalysisResultManager.Instance.TryRebaselineAllSarifErrors(_runId, this.UriBaseId, this.FullFilePath))
                {
                    return(null);
                }
            }

            if (File.Exists(this.FullFilePath) && Uri.TryCreate(this.FullFilePath, UriKind.Absolute, out uri))
            {
                // Fill out the region's properties
                FileRegionsCache regionsCache = CodeAnalysisResultManager.Instance.RunDataCaches[_runId].FileRegionsCache;
                Region = regionsCache.PopulateTextRegionProperties(Region, uri, true);
            }

            IVsWindowFrame windowFrame = SdkUIUtilities.OpenDocument(SarifViewerPackage.ServiceProvider, this.FullFilePath, usePreviewPane);

            if (windowFrame != null)
            {
                IVsTextView textView = GetTextViewFromFrame(windowFrame);
                if (textView == null)
                {
                    return(null);
                }

                var sourceLocation = this.GetSourceLocation();

                // Navigate the caret to the desired location. Text span uses 0-based indexes
                TextSpan ts;
                ts.iStartLine  = sourceLocation.StartLine - 1;
                ts.iEndLine    = sourceLocation.EndLine - 1;
                ts.iStartIndex = Math.Max(sourceLocation.StartColumn - 1, 0);
                ts.iEndIndex   = Math.Max(sourceLocation.EndColumn - 1, 0);

                textView.EnsureSpanVisible(ts);
                textView.SetSelection(ts.iStartLine, ts.iStartIndex, ts.iEndLine, ts.iEndIndex);
            }
            return(windowFrame);
        }
 public SearchSkimmer(IRegex engine, ValidatorsCache validators, FileRegionsCache fileRegionsCache, SearchDefinition definition, IFileSystem fileSystem = null)
     : this(
         engine,
         validators,
         fileRegionsCache,
         definition.Id,
         definition.Name,
         definition.Description,
         definition.MatchExpressions,
         fileSystem)
 {
 }
        public static string ExtractSnippet(this LocationModel location, FileRegionsCache fileRegionsCache, IFileSystem fileSystem = null)
        {
            fileSystem ??= FileSystem.Instance;
            if (fileSystem.FileExists(location.FilePath) &&
                Uri.TryCreate(location.FilePath, UriKind.Absolute, out Uri uri))
            {
                // Fill out the region's properties
                fileRegionsCache ??= new FileRegionsCache();
                Region fullyPopulatedRegion = fileRegionsCache.PopulateTextRegionProperties(location.Region, uri, populateSnippet: true);
                return(fullyPopulatedRegion?.Snippet != null ? fullyPopulatedRegion.Snippet.Text : string.Empty);
            }

            return(string.Empty);
        }
        public void ToReplacementModel_NullReplacement_ReturnNull()
        {
            var mock = new Mock <IFileSystem>();

            mock.Setup(fs => fs.FileExists(It.IsAny <string>())).Returns(false);
            mock.Setup(fs => fs.FileReadAllText(It.IsAny <string>())).Returns(CodeSample);
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);

            Uri uri = new Uri(FilePath);

            Replacement      replacement = null;
            ReplacementModel model       = replacement.ToReplacementModel(regionCache, uri);

            model.Should().BeNull();
        }
        public void FileRegionsCache_PopulatesNullRegion()
        {
            Uri uri = new Uri(@"c:\temp\myFile.cpp");

            var         run              = new Run();
            IFileSystem mockFileSystem   = MockFactory.MakeMockFileSystem(uri.LocalPath, SPEC_EXAMPLE);
            var         fileRegionsCache = new FileRegionsCache(run, fileSystem: mockFileSystem);

            Region region = fileRegionsCache.PopulateTextRegionProperties(inputRegion: null, uri: uri, populateSnippet: false);

            region.Should().BeNull();

            region = fileRegionsCache.PopulateTextRegionProperties(inputRegion: null, uri: uri, populateSnippet: true);
            region.Should().BeNull();
        }
        public void FileRegionsCache_PopulatesFromMissingFile()
        {
            var run = new Run();
            var fileRegionsCache = new FileRegionsCache(run);

            Uri uri = new Uri(@"c:\temp\DoesNotExist\" + Guid.NewGuid().ToString() + ".cpp");

            Region region = new Region()
            {
                CharOffset = 17
            };

            // Region should not be touched in any way if the file it references is missing
            fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: false).ValueEquals(region).Should().BeTrue();
            fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: true).ValueEquals(region).Should().BeTrue();
        }
        public SearchSkimmer(
            IRegex engine,
            ValidatorsCache validators,
            FileRegionsCache fileRegionsCache,
            string id,
            string name,
            string description,
            IList <MatchExpression> matchExpressions,
            IFileSystem fileSystem = null)
        {
            _id               = id;
            _name             = name;
            _engine           = engine;
            _validators       = validators;
            _fileRegionsCache = fileRegionsCache;
            _fullDescription  = new MultiformatMessageString {
                Text = description
            };
            _fileSystem = fileSystem ?? FileSystem.Instance;

            _messageStrings = new Dictionary <string, MultiformatMessageString>
            {
                { nameof(SdkResources.NotApplicable_InvalidMetadata), new MultiformatMessageString()
                  {
                      Text = SdkResources.NotApplicable_InvalidMetadata,
                  } },
            };

            foreach (MatchExpression matchExpression in matchExpressions)
            {
                string matchExpressionMessage = matchExpression.Message;
                matchExpression.ArgumentNameToIndexMap = GenerateIndicesForNamedArguments(ref matchExpressionMessage);

                string messageId = matchExpression.SubId ?? "Default";
                if (!_messageStrings.TryGetValue(messageId, out MultiformatMessageString mfString))
                {
                    _messageStrings[messageId] = new MultiformatMessageString
                    {
                        Text = matchExpressionMessage,
                    };
                }
            }

            _matchExpressions = matchExpressions;
        }
Beispiel #17
0
        public void FileRegionsCache_ValidateConcurrencyData()
        {
            Exception exception = Record.Exception(() =>
            {
                var fileRegionsCache = new FileRegionsCache();
                List <Task> taskList = new List <Task>();

                for (int i = 0; i < 1_000; i++)
                {
                    taskList.Add(Task.Factory.StartNew(() =>
                                                       fileRegionsCache.PopulateTextRegionProperties(new Region {
                    }, new Uri($"file:///c:/{Guid.NewGuid()}.txt"), true)));
                }

                Task.WaitAll(taskList.ToArray());
            });

            Assert.Null(exception);
        }
        public static string ExtractSnippet(this Location location, Run run, FileRegionsCache fileRegionsCache)
        {
            PhysicalLocation physicalLocation = location.PhysicalLocation;
            ArtifactLocation artifactLocation = location.PhysicalLocation?.ArtifactLocation;
            Region           region           = location.PhysicalLocation?.Region;
            Uri uri = location.PhysicalLocation?.ArtifactLocation?.Uri;

            if (uri == null || region == null || region.IsBinaryRegion || physicalLocation == null)
            {
                return(string.Empty);
            }

            if (region.Snippet != null)
            {
                return(region.Snippet.Text);
            }

            if (artifactLocation.Uri == null && artifactLocation.Index >= 0)
            {
                // Uri is not stored at result level, but we have an index to go look in run.Artifacts
                // we must pick the ArtifactLocation details from run.artifacts array
                Artifact artifactFromRun = run.Artifacts[artifactLocation.Index];
                artifactLocation = artifactFromRun.Location;
            }

            // If we can resolve a file location to a newly constructed
            // absolute URI, we will prefer that
            if (!artifactLocation.TryReconstructAbsoluteUri(run.OriginalUriBaseIds, out Uri resolvedUri))
            {
                resolvedUri = artifactLocation.Uri;
            }

            if (!resolvedUri.IsAbsoluteUri)
            {
                return(string.Empty);
            }

            fileRegionsCache ??= new FileRegionsCache();
            Region expandedRegion = fileRegionsCache.PopulateTextRegionProperties(region, resolvedUri, populateSnippet: true);

            return(expandedRegion.Snippet != null ? expandedRegion.Snippet.Text : string.Empty);
        }
        private SearchSkimmer CreateSkimmer(
            SearchDefinition definition,
            IRegex engine = null,
            ValidatorsCache validators        = null,
            FileRegionsCache fileRegionsCache = null,
            IFileSystem fileSystem            = null)
        {
            var definitions = new SearchDefinitions
            {
                Definitions = new List <SearchDefinition>(new[] { definition }),
            };

            definitions = AnalyzeCommand.PushInheritedData(definitions, sharedStrings: null);

            return(new SearchSkimmer(
                       engine: engine ?? RE2Regex.Instance,
                       validators: validators,
                       fileRegionsCache: fileRegionsCache ?? new FileRegionsCache(),
                       definition: definitions.Definitions[0],
                       fileSystem: fileSystem));
        }
        public void FileRegionsCache_PopulatesUsingProvidedText()
        {
            var run = new Run();
            var fileRegionsCache = new FileRegionsCache();

            Uri uri = new Uri(@"c:\temp\DoesNotExist\" + Guid.NewGuid().ToString() + ".cpp");

            string fileText   = "12345\n56790\n";
            int    charOffset = 6;
            int    charLength = 1;

            // Region should grab the second line of text in 'fileText'.
            Region region = new Region()
            {
                CharOffset = charOffset, CharLength = charLength
            };

            Region expected = new Region()
            {
                CharOffset  = charOffset,
                CharLength  = charLength,
                StartLine   = 2,
                EndLine     = 2,
                StartColumn = 1,
                EndColumn   = 2
            };

            Region actual;

            // Region should not be touched in any way if the file it references is missing
            actual = fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: false, fileText: fileText);
            actual.ValueEquals(expected).Should().BeTrue();
            actual.Snippet.Should().BeNull();

            actual = fileRegionsCache.PopulateTextRegionProperties(region, uri, populateSnippet: true, fileText: fileText);
            actual.Snippet.Text.Should().Be(fileText.Substring(charOffset, charLength));

            actual.Snippet = null;
            actual.ValueEquals(expected).Should().BeTrue();
        }
        public void ToReplacementModel_WhenUriIsRelativeAndReplacementRegionIsCharOffsetLength_ProducesExpectedModel()
        {
            const string FilePath = "test.txt";
            var          fileUri  = new Uri(FilePath, UriKind.Relative);

            const int    DeletedCharOffset = 12;
            const int    DeletedCharLength = 2;
            const string ReplacementString = "FortyTwo";

            var replacement = new Replacement
            {
                InsertedContent = new ArtifactContent
                {
                    Text = ReplacementString,
                },
                DeletedRegion = new Region
                {
                    CharOffset = DeletedCharOffset,
                    CharLength = DeletedCharLength,
                },
            };

            var run = new Run();

            var mockFileSystem = new Mock <IFileSystem>();

            var fileRegionsCache = new FileRegionsCache(FileRegionsCacheCapacity, mockFileSystem.Object);

            var actualModel = replacement.ToReplacementModel(fileRegionsCache, fileUri);

            actualModel.Region.CharOffset.Should().Be(DeletedCharOffset);
            actualModel.Region.CharLength.Should().Be(DeletedCharLength);
            actualModel.IsTextReplacement.Should().BeTrue();
            actualModel.IsBinaryReplacement.Should().BeFalse();
            actualModel.InsertedString.Should().Be(ReplacementString);

            // The run does not contain any path information, so when the FileRegionsCache is
            // constructed, it does not consult the file system.
            mockFileSystem.VerifyNoOtherCalls();
        }
Beispiel #22
0
        internal void RemapFilePath(string originalPath, string remappedPath)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            DetachFromDocument(_documentCookie);

            var uri = new Uri(remappedPath, UriKind.Absolute);
            FileRegionsCache regionsCache = CodeAnalysisResultManager.Instance.RunDataCaches[_runId].FileRegionsCache;

            if (FileName.Equals(originalPath, StringComparison.OrdinalIgnoreCase))
            {
                FileName = remappedPath;
            }

            foreach (LocationModel location in Locations)
            {
                if (location.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase))
                {
                    location.FilePath = remappedPath;
                    location.Region   = regionsCache.PopulateTextRegionProperties(location.Region, uri, true);
                }
            }

            foreach (LocationModel location in RelatedLocations)
            {
                if (location.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase))
                {
                    location.FilePath = remappedPath;
                    location.Region   = regionsCache.PopulateTextRegionProperties(location.Region, uri, true);
                }
            }

            foreach (CallTree callTree in CallTrees)
            {
                Stack <CallTreeNode> nodesToProcess = new Stack <CallTreeNode>();

                foreach (CallTreeNode topLevelNode in callTree.TopLevelNodes)
                {
                    nodesToProcess.Push(topLevelNode);
                }

                while (nodesToProcess.Count > 0)
                {
                    CallTreeNode current = nodesToProcess.Pop();
                    try
                    {
                        if (current.FilePath != null &&
                            current.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase))
                        {
                            current.FilePath = remappedPath;
                            current.Region   = regionsCache.PopulateTextRegionProperties(current.Region, uri, true);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // An argument exception is thrown if the node does not have a region.
                        // Since there's no region, there's no document to attach to.
                        // Just move on with processing the child nodes.
                    }

                    foreach (CallTreeNode childNode in current.Children)
                    {
                        nodesToProcess.Push(childNode);
                    }
                }
            }

            foreach (StackCollection stackCollection in Stacks)
            {
                foreach (StackFrameModel stackFrame in stackCollection)
                {
                    if (stackFrame.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase))
                    {
                        stackFrame.FilePath = remappedPath;
                        stackFrame.Region   = regionsCache.PopulateTextRegionProperties(stackFrame.Region, uri, true);
                    }
                }
            }

            foreach (FixModel fixModel in Fixes)
            {
                foreach (ArtifactChangeModel fileChangeModel in fixModel.ArtifactChanges)
                {
                    if (fileChangeModel.FilePath.Equals(originalPath, StringComparison.OrdinalIgnoreCase))
                    {
                        fileChangeModel.FilePath = remappedPath;
                    }
                }
            }

            AttachToDocument();
        }
        private static void ExecuteTests(ReadOnlyCollection <TestCaseData> testCases, FileRegionsCache fileRegionsCache, Uri uri)
        {
            foreach (TestCaseData testCase in testCases)
            {
                Region          inputRegion    = testCase.InputRegion;
                Region          expectedRegion = testCase.OutputRegion.DeepClone();
                ArtifactContent snippet        = expectedRegion.Snippet;

                expectedRegion.Snippet = null;
                Region actualRegion = fileRegionsCache.PopulateTextRegionProperties(inputRegion, uri, populateSnippet: false);

                actualRegion.ValueEquals(expectedRegion).Should().BeTrue();
                actualRegion.Snippet.Should().BeNull();

                expectedRegion.Snippet = snippet;
                actualRegion           = fileRegionsCache.PopulateTextRegionProperties(inputRegion, uri, populateSnippet: true);

                actualRegion.ValueEquals(expectedRegion).Should().BeTrue();

                if (snippet == null)
                {
                    actualRegion.Snippet.Should().BeNull();
                }
                else
                {
                    actualRegion.Snippet.Text.Should().Be(snippet.Text);
                }
            }
        }
Beispiel #24
0
        public static ArtifactChangeModel ToArtifactChangeModel(this ArtifactChange fileChange, IDictionary <string, Uri> originalUriBaseIds, FileRegionsCache fileRegionsCache)
        {
            if (fileChange == null)
            {
                return(null);
            }

            Dictionary <string, ArtifactLocation> uriToArtifactLocationMap = null;

            if (originalUriBaseIds != null)
            {
                // convert IDictionary<string, Uri> to IDictionary<string, ArtifactLocation> which
                // is needed by Sarif.SDK extension method ArtifactLocation.TryReconstructAbsoluteUri()
                uriToArtifactLocationMap = new Dictionary <string, ArtifactLocation>(originalUriBaseIds.Count);
                foreach (KeyValuePair <string, Uri> entry in originalUriBaseIds)
                {
                    uriToArtifactLocationMap.Add(entry.Key, new ArtifactLocation {
                        Uri = entry.Value
                    });
                }
            }

            return(fileChange.ToArtifactChangeModel(uriToArtifactLocationMap, fileRegionsCache));
        }
Beispiel #25
0
        public static FixModel ToFixModel(this Fix fix, IDictionary <string, ArtifactLocation> originalUriBaseIds, FileRegionsCache fileRegionsCache)
        {
            fix = fix ?? throw new ArgumentNullException(nameof(fix));

            var model = new FixModel(fix.Description?.Text);

            if (fix.ArtifactChanges != null)
            {
                foreach (ArtifactChange change in fix.ArtifactChanges)
                {
                    model.ArtifactChanges.Add(change.ToArtifactChangeModel(originalUriBaseIds, fileRegionsCache));
                }
            }

            return(model);
        }
Beispiel #26
0
        public void ExtractSnippet_ReturnsExpectedValue()
        {
            var mock        = new Mock <IFileSystem>();
            var regionCache = new FileRegionsCache(fileSystem: mock.Object);
            var testCases   = new[]
            {
                new
                {
                    location = new Location {
                        PhysicalLocation = null
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = string.Empty,
                },
                new
                {
                    location = new Location {
                        PhysicalLocation = new PhysicalLocation {
                            ArtifactLocation = null
                        }
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = string.Empty,
                },
                new
                {
                    location = new Location {
                        PhysicalLocation = new PhysicalLocation {
                            ArtifactLocation = new ArtifactLocation {
                                Uri = null
                            }
                        }
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = string.Empty,
                },
                new
                {
                    location = new Location {
                        PhysicalLocation = new PhysicalLocation {
                            ArtifactLocation = new ArtifactLocation {
                                Uri = new Uri("file://temp.cs")
                            }
                        }
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = string.Empty,
                },
                new
                {
                    location = new Location
                    {
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Uri = new Uri("file://temp.cs")
                            },
                            Region = new Region(),
                        },
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = string.Empty,
                },
                new
                {
                    location = new Location
                    {
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Uri = new Uri("file://temp.cs")
                            },
                            Region = new Region {
                                ByteOffset = 0
                            },
                        },
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = string.Empty,
                },
                new
                {
                    location = new Location
                    {
                        PhysicalLocation = new PhysicalLocation
                        {
                            ArtifactLocation = new ArtifactLocation {
                                Uri = new Uri("file://temp.cs")
                            },
                            Region = new Region {
                                Snippet = new ArtifactContent {
                                    Text = "private class Class5"
                                }
                            },
                        },
                    },
                    run            = new Run(),
                    regionCache    = regionCache,
                    expectedResult = "private class Class5",
                },
            };

            int failedCases = 0;

            foreach (var testcase in testCases)
            {
                string snippet = testcase.location.ExtractSnippet(testcase.run, testcase.regionCache);
                if (snippet != testcase.expectedResult)
                {
                    failedCases++;
                }
            }

            failedCases.Should().Be(0, "failed test cases: " + failedCases.ToString());
        }
Beispiel #27
0
        public static ISet <Skimmer <AnalyzeContext> > CreateSkimmersFromDefinitionsFiles(
            IFileSystem fileSystem,
            IEnumerable <string> searchDefinitionsPaths,
            IRegex engine = null)
        {
            engine ??= RE2Regex.Instance;

            var validators = new ValidatorsCache();
            FileRegionsCache fileRegionsCache = FileRegionsCache.Instance;

            var skimmers = new HashSet <Skimmer <AnalyzeContext> >();

            // TODO exception handling for bad search definitions files
            foreach (string searchDefinitionsPath in searchDefinitionsPaths)
            {
                string searchDefinitionsText =
                    fileSystem.FileReadAllText(searchDefinitionsPath);

                SearchDefinitions definitions =
                    JsonConvert.DeserializeObject <SearchDefinitions>(searchDefinitionsText);

                // This would skip files that does not look like rules.
                if (definitions == null || definitions.Definitions == null)
                {
                    continue;
                }

                string validatorPath        = null;
                string definitionsDirectory = Path.GetDirectoryName(searchDefinitionsPath);

                if (!string.IsNullOrEmpty(definitions.ValidatorsAssemblyName))
                {
                    // TODO File.Exists check? Logging if not locatable?
                    validatorPath = Path.Combine(definitionsDirectory, definitions.ValidatorsAssemblyName);
                    validators.ValidatorPaths.Add(validatorPath);
                }
                else
                {
                    // If no explicit name of a validator binary was provided,
                    // we look for one that lives alongside the definitions file.
                    validatorPath = Path.GetFileNameWithoutExtension(searchDefinitionsPath) + ".dll";
                    validatorPath = Path.Combine(definitionsDirectory, validatorPath);

                    if (File.Exists(validatorPath))
                    {
                        validators.ValidatorPaths.Add(validatorPath);
                    }
                }

                Dictionary <string, string> sharedStrings = null;
                if (!string.IsNullOrEmpty(definitions.SharedStringsFileName))
                {
                    string sharedStringsFullPath = Path.Combine(definitionsDirectory, definitions.SharedStringsFileName);
                    sharedStrings = LoadSharedStrings(sharedStringsFullPath, fileSystem);
                }

                definitions = PushInheritedData(definitions, sharedStrings);

                foreach (SearchDefinition definition in definitions.Definitions)
                {
                    Skimmer <AnalyzeContext> skimmer = skimmers.FirstOrDefault(skimmer => skimmer.Id == definition.Id);

                    if (skimmer != null)
                    {
                        skimmers.Remove(skimmer);
                    }

                    skimmers.Add(
                        new SearchSkimmer(
                            engine: engine,
                            validators: validators,
                            fileRegionsCache: fileRegionsCache,
                            definition));

                    const string singleSpace = " ";

                    // Send no-op match operations through engine in order to drive caching of all regexes.
                    if (definition.FileNameAllowRegex != null)
                    {
                        engine.Match(singleSpace, definition.FileNameAllowRegex, RegexDefaults.DefaultOptionsCaseSensitive);
                    }

                    foreach (MatchExpression matchExpression in definition.MatchExpressions)
                    {
                        if (!string.IsNullOrEmpty(matchExpression.FileNameAllowRegex))
                        {
                            engine.Match(singleSpace, matchExpression.FileNameAllowRegex, RegexDefaults.DefaultOptionsCaseSensitive);
                        }

                        if (!string.IsNullOrEmpty(matchExpression.ContentsRegex))
                        {
                            engine.Match(singleSpace, matchExpression.ContentsRegex, RegexDefaults.DefaultOptionsCaseSensitive);
                        }
                    }
                }
            }

            return(skimmers);
        }
Beispiel #28
0
        public static ReplacementModel ToReplacementModel(this Replacement replacement, FileRegionsCache fileRegionsCache, Uri uri)
        {
            if (replacement == null)
            {
                return(null);
            }

            var model = new ReplacementModel
            {
                Region = uri.IsAbsoluteUri
                    ? fileRegionsCache.PopulateTextRegionProperties(replacement.DeletedRegion, uri, populateSnippet: false)
                    : replacement.DeletedRegion,
            };

            if (model.Region.CharOffset >= 0)
            {
                // This is a text replacement.
                model.InsertedString = replacement.InsertedContent?.Text;
            }
            else
            {
                // This is a binary replacement, but don't try to convert the replacement
                // content to a string if there isn't any.
                if (replacement.InsertedContent?.Binary != null)
                {
                    model.InsertedBytes = Convert.FromBase64String(replacement.InsertedContent.Binary);
                }
            }

            return(model);
        }
Beispiel #29
0
        public override PhysicalLocation VisitPhysicalLocation(PhysicalLocation node)
        {
            if (node.Region == null || node.Region.IsBinaryRegion)
            {
                goto Exit;
            }

            bool insertRegionSnippets      = _dataToInsert.HasFlag(OptionallyEmittedData.RegionSnippets);
            bool overwriteExistingData     = _dataToInsert.HasFlag(OptionallyEmittedData.OverwriteExistingData);
            bool insertContextCodeSnippets = _dataToInsert.HasFlag(OptionallyEmittedData.ContextRegionSnippets);
            bool populateRegionProperties  = _dataToInsert.HasFlag(OptionallyEmittedData.ComprehensiveRegionProperties);

            if (insertRegionSnippets || populateRegionProperties || insertContextCodeSnippets)
            {
                Region           expandedRegion;
                ArtifactLocation artifactLocation = node.ArtifactLocation;

                _fileRegionsCache = _fileRegionsCache ?? new FileRegionsCache(_run);

                if (artifactLocation.Uri == null && artifactLocation.Index >= 0)
                {
                    // Uri is not stored at result level, but we have an index to go look in run.Artifacts
                    // we must pick the ArtifactLocation details from run.artifacts array
                    Artifact artifactFromRun = _run.Artifacts[artifactLocation.Index];
                    artifactLocation = artifactFromRun.Location;
                }

                // If we can resolve a file location to a newly constructed
                // absolute URI, we will prefer that
                if (!artifactLocation.TryReconstructAbsoluteUri(_run.OriginalUriBaseIds, out Uri resolvedUri))
                {
                    resolvedUri = artifactLocation.Uri;
                }

                if (!resolvedUri.IsAbsoluteUri)
                {
                    goto Exit;
                }

                expandedRegion = _fileRegionsCache.PopulateTextRegionProperties(node.Region, resolvedUri, populateSnippet: insertRegionSnippets);

                ArtifactContent originalSnippet = node.Region.Snippet;

                if (populateRegionProperties)
                {
                    node.Region = expandedRegion;
                }

                if (originalSnippet == null || overwriteExistingData)
                {
                    node.Region.Snippet = expandedRegion.Snippet;
                }
                else
                {
                    node.Region.Snippet = originalSnippet;
                }

                if (insertContextCodeSnippets && (node.ContextRegion == null || overwriteExistingData))
                {
                    node.ContextRegion = _fileRegionsCache.ConstructMultilineContextSnippet(expandedRegion, resolvedUri);
                }
            }

Exit:
            return(base.VisitPhysicalLocation(node));
        }
Beispiel #30
0
 public RunDataCache(Run run)
 {
     FileRegionsCache = new FileRegionsCache(run);
 }