예제 #1
0
        public override object Visit(ISarifNode node)
        {
            // We override a very low level visit, one that occurs for every SARIF object instance.
            // We do this for two reasons: 1) it would be unnecessarily burdensome to override
            // every specific VisitXXX method in order to populate it, 2) this approach, even
            // if undertaken, would be quite fragile. Visit methods that disappear would break our
            // build. More worrisome, the code would miss newly introduced types on the visitor.
            //
            // We could have avoided the visitor altogether and simply performed recursive reflection
            // over a root SarifLog instance. We use this mechanism in order to minimize introducing
            // an entirely one-off construct, to glean whatever small measure of reuse is afforded
            // by the visitor, and based on an assumption that future check-ins will utilize
            // chained visitors and/or utilize more core visitor functionality.
            PopulateInstanceWithDefaultMemberValues(node);

            return(base.Visit(node));
        }
예제 #2
0
        private void PopulatePropertyWithGeneratedDefaultValue(ISarifNode node, PropertyInfo property)
        {
            // If we can't set this property, it is not of interest
            if (property.GetAccessors().Length != 2)
            {
                return;
            }

            // This special-casing is required to account for the fact that an
            // exception instance itself contains an array of exceptions
            // (exception.innerExceptions). We don't want to hydrate
            // the innerExceptions of any innerExceptions, which results
            // in re-entrancy that ends up consuming all stack space.
            //
            // Once we have populated a single exceptions.innerExceptions array,
            // we have accomplished all the testing we need in any case.
            if (node.SarifNodeKind == SarifNodeKind.ExceptionData &&
                property.Name == "InnerExceptions" &&
                _visitingExceptionData)
            {
                return;
            }

            // Similar approach applies for graph node.children
            if (node.SarifNodeKind == SarifNodeKind.Node &&
                property.Name == "Children" &&
                _visitingGraphNode)
            {
                return;
            }

            object propertyValue = null;
            Type   propertyType  = property.PropertyType;

            // isRequired flag ensures we don't end up generating a SARIF file that's missing a required property or an anyOf required property,
            // because such a file wouldn't validate.
            bool isRequired = PropertyIsRequiredBySchema(node.GetType().Name, property.Name) ||
                              PropertyIsAnyOfRequiredBySchema(node.GetType().Name, property.Name);

            if (GetPropertyFormatPattern(node.GetType().Name, property.Name) is string propertyFormatPattern)
            {
                propertyValue = GetFormattedStringValue(propertyFormatPattern);
            }
            else if (_typeToPropertyValueConstructorMap.TryGetValue(propertyType, out PrimitiveValueBuilder propertyValueBuilder))
            {
                propertyValue = propertyValueBuilder(isRequired);
            }
            else if (HasParameterlessConstructor(propertyType))
            {
                propertyValue = Activator.CreateInstance(propertyType);
            }
            else if (IsList(propertyType))
            {
                propertyValue = CreateEmptyList(propertyType);

                Type   genericTypeArgument = propertyType.GenericTypeArguments[0];
                object listElement         = null;

                // For arrays that are populated with SARIF types, we will instantiate a
                // single object instance and put it into the array. This allows the
                // default populating visitor to continue to explore the object model and
                // exercise nested types. This approach prevents comprehensive testing of
                // the arrays populated in this way (because they are non-empty
                if (genericTypeArgument.FullName.StartsWith("Microsoft.CodeAnalysis.Sarif."))
                {
                    listElement = Activator.CreateInstance(propertyType.GenericTypeArguments[0]);
                }
                else if (_typeToPropertyValueConstructorMap.TryGetValue(genericTypeArgument, out propertyValueBuilder))
                {
                    listElement = propertyValueBuilder(isRequired);
                }

                AddElementToList(propertyValue, listElement);
            }
            else if (IsDictionary(propertyType))
            {
                Type genericTypeArgument = propertyType.GenericTypeArguments[1];

                // We do not populate any propert bags directly. Instead, we will use the
                // IPropertyBagHolder API to instantiate and then empty these constructs
                if (genericTypeArgument != typeof(SerializedPropertyInfo))
                {
                    propertyValue = CreateEmptyDictionary(propertyType);

                    // For dictionaries that are populated with SARIF types, we will instantiate a
                    // single object instance and store it using an arbitrary key. This approach
                    // ensures we populate the SARIF sample with all possible object types
                    if (genericTypeArgument.FullName.StartsWith("Microsoft.CodeAnalysis.Sarif."))
                    {
                        object dictionaryValue = Activator.CreateInstance(genericTypeArgument);
                        AddElementToDictionary(propertyValue, dictionaryValue);
                    }
                }
            }
            else if ((property.PropertyType.BaseType == typeof(Enum)))
            {
                // This code sets any enum to the first non-zero value we encounter
                foreach (var enumValue in Enum.GetValues(property.PropertyType))
                {
                    if ((int)enumValue != 0)
                    {
                        propertyValue = enumValue;
                        break;
                    }
                }

                // This code ensures both that we encounter an enum value that is non-zero,
                // and that no enum definitions skips the value of one in its definition
                if ((int)propertyValue != 1)
                {
                    throw new InvalidOperationException();
                }
            }

            property.SetValue(node, propertyValue);
        }
예제 #3
0
        private void PopulateInstanceWithDefaultMemberValues(ISarifNode node)
        {
            Type nodeType = node.GetType();

            var binding = BindingFlags.Public | BindingFlags.Instance;

            foreach (PropertyInfo property in nodeType.GetProperties(binding))
            {
                // The node kind is always properly set in the OM and
                // isn't relevant to the SARIF schema itself
                if (property.Name == "SarifNodeKind")
                {
                    continue;
                }

                // Property bags and tags are populated via special methods on
                // the class rather than direct access of properties. These
                // property names extend from the PropertyBagHolder base type
                // that all properties-bearing types extend (nearly every SARIF
                // class at this point).
                if (property.Name == "PropertyNames" ||
                    property.Name == "Tags")
                {
                    continue;
                }

                if (ShouldExcludePopulationDueToOneOfCriteria(node.GetType().Name, property.Name))
                {
                    continue;
                }

                object defaultValue = null;

                MemberInfo member = nodeType.GetMember(property.Name)[0];
                foreach (CustomAttributeData attributeData in member?.GetCustomAttributesData())
                {
                    if (attributeData.AttributeType.FullName != "System.ComponentModel.DefaultValueAttribute")
                    {
                        continue;
                    }
                    defaultValue = attributeData.ConstructorArguments[0].Value;

                    // DefaultValue of -1 is to ensure an actual value of 0 will not be ignored during serialization,
                    // Hence, we will substitute them with 0.
                    if (defaultValue is int defaultIntValue && defaultIntValue == -1)
                    {
                        defaultValue = 0;
                    }
                }

                // If the member is decorated with a default value, we'll inject it. Otherwise,
                // we'll compute a default value based on the node type
                if (defaultValue != null)
                {
                    property.SetValue(node, defaultValue);
                    continue;
                }
                PopulatePropertyWithGeneratedDefaultValue(node, property);
            }

            // If we have a property bag holder (as most SARIF things are), we will
            // add and then immediately remove both a property and a tag. This has
            // the effect of leaving non-null but empty properties collection.
            var propertyBagHolder = node as PropertyBagHolder;

            if (propertyBagHolder != null)
            {
                string meaninglessValue = "ToBeRemoved";
                propertyBagHolder.SetProperty(propertyName: meaninglessValue, value: meaninglessValue);
                propertyBagHolder.RemoveProperty(propertyName: meaninglessValue);

                propertyBagHolder.Tags.Add(meaninglessValue);
                propertyBagHolder.Tags.Remove(meaninglessValue);
            }
        }
예제 #4
0
        /// <summary>
        /// Visits and rewrites a node in the Sarif object model.
        /// </summary>
        /// <param name="node">
        /// The node to rewrite.
        /// </param>
        /// <returns>
        /// A rewritten instance of the node.
        /// </returns>
        public virtual object VisitActual(ISarifNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            switch (node.SarifNodeKind)
            {
            case SarifNodeKind.Attachment:
                return(VisitAttachment((Attachment)node));

            case SarifNodeKind.CodeFlow:
                return(VisitCodeFlow((CodeFlow)node));

            case SarifNodeKind.CodeFlowLocation:
                return(VisitCodeFlowLocation((CodeFlowLocation)node));

            case SarifNodeKind.Conversion:
                return(VisitConversion((Conversion)node));

            case SarifNodeKind.Edge:
                return(VisitEdge((Edge)node));

            case SarifNodeKind.EdgeTraversal:
                return(VisitEdgeTraversal((EdgeTraversal)node));

            case SarifNodeKind.ExceptionData:
                return(VisitExceptionData((ExceptionData)node));

            case SarifNodeKind.FileChange:
                return(VisitFileChange((FileChange)node));

            case SarifNodeKind.FileContent:
                return(VisitFileContent((FileContent)node));

            case SarifNodeKind.FileData:
                return(VisitFileData((FileData)node));

            case SarifNodeKind.FileLocation:
                return(VisitFileLocation((FileLocation)node));

            case SarifNodeKind.Fix:
                return(VisitFix((Fix)node));

            case SarifNodeKind.Graph:
                return(VisitGraph((Graph)node));

            case SarifNodeKind.GraphTraversal:
                return(VisitGraphTraversal((GraphTraversal)node));

            case SarifNodeKind.Hash:
                return(VisitHash((Hash)node));

            case SarifNodeKind.Invocation:
                return(VisitInvocation((Invocation)node));

            case SarifNodeKind.Location:
                return(VisitLocation((Location)node));

            case SarifNodeKind.LogicalLocation:
                return(VisitLogicalLocation((LogicalLocation)node));

            case SarifNodeKind.Message:
                return(VisitMessage((Message)node));

            case SarifNodeKind.Node:
                return(VisitNode((Node)node));

            case SarifNodeKind.Notification:
                return(VisitNotification((Notification)node));

            case SarifNodeKind.PhysicalLocation:
                return(VisitPhysicalLocation((PhysicalLocation)node));

            case SarifNodeKind.Rectangle:
                return(VisitRectangle((Rectangle)node));

            case SarifNodeKind.Region:
                return(VisitRegion((Region)node));

            case SarifNodeKind.Replacement:
                return(VisitReplacement((Replacement)node));

            case SarifNodeKind.Resources:
                return(VisitResources((Resources)node));

            case SarifNodeKind.Result:
                return(VisitResult((Result)node));

            case SarifNodeKind.Rule:
                return(VisitRule((Rule)node));

            case SarifNodeKind.RuleConfiguration:
                return(VisitRuleConfiguration((RuleConfiguration)node));

            case SarifNodeKind.Run:
                return(VisitRun((Run)node));

            case SarifNodeKind.SarifLog:
                return(VisitSarifLog((SarifLog)node));

            case SarifNodeKind.Stack:
                return(VisitStack((Stack)node));

            case SarifNodeKind.StackFrame:
                return(VisitStackFrame((StackFrame)node));

            case SarifNodeKind.ThreadFlow:
                return(VisitThreadFlow((ThreadFlow)node));

            case SarifNodeKind.Tool:
                return(VisitTool((Tool)node));

            case SarifNodeKind.VersionControlDetails:
                return(VisitVersionControlDetails((VersionControlDetails)node));

            default:
                return(node);
            }
        }
예제 #5
0
 /// <summary>
 /// Starts a rewriting visit of a node in the Sarif object model.
 /// </summary>
 /// <param name="node">
 /// The node to rewrite.
 /// </param>
 /// <returns>
 /// A rewritten instance of the node.
 /// </returns>
 public virtual object Visit(ISarifNode node)
 {
     return(this.VisitActual(node));
 }
        /// <summary>
        /// Visits and rewrites a node in the Sarif object model.
        /// </summary>
        /// <param name="node">
        /// The node to rewrite.
        /// </param>
        /// <returns>
        /// A rewritten instance of the node.
        /// </returns>
        public virtual object VisitActual(ISarifNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            switch (node.SarifNodeKind)
            {
            case SarifNodeKind.AnnotatedCodeLocation:
                return(VisitAnnotatedCodeLocation((AnnotatedCodeLocation)node));

            case SarifNodeKind.CodeFlow:
                return(VisitCodeFlow((CodeFlow)node));

            case SarifNodeKind.FileChange:
                return(VisitFileChange((FileChange)node));

            case SarifNodeKind.FileData:
                return(VisitFileData((FileData)node));

            case SarifNodeKind.Fix:
                return(VisitFix((Fix)node));

            case SarifNodeKind.FormattedRuleMessage:
                return(VisitFormattedRuleMessage((FormattedRuleMessage)node));

            case SarifNodeKind.Hash:
                return(VisitHash((Hash)node));

            case SarifNodeKind.Invocation:
                return(VisitInvocation((Invocation)node));

            case SarifNodeKind.Location:
                return(VisitLocation((Location)node));

            case SarifNodeKind.LogicalLocationComponent:
                return(VisitLogicalLocationComponent((LogicalLocationComponent)node));

            case SarifNodeKind.PhysicalLocation:
                return(VisitPhysicalLocation((PhysicalLocation)node));

            case SarifNodeKind.Region:
                return(VisitRegion((Region)node));

            case SarifNodeKind.Replacement:
                return(VisitReplacement((Replacement)node));

            case SarifNodeKind.Result:
                return(VisitResult((Result)node));

            case SarifNodeKind.Rule:
                return(VisitRule((Rule)node));

            case SarifNodeKind.Run:
                return(VisitRun((Run)node));

            case SarifNodeKind.SarifLog:
                return(VisitSarifLog((SarifLog)node));

            case SarifNodeKind.Stack:
                return(VisitStack((Stack)node));

            case SarifNodeKind.StackFrame:
                return(VisitStackFrame((StackFrame)node));

            case SarifNodeKind.Tool:
                return(VisitTool((Tool)node));

            default:
                return(node);
            }
        }
        /// <summary>
        /// Visits and rewrites a node in the Sarif object model.
        /// </summary>
        /// <param name="node">
        /// The node to rewrite.
        /// </param>
        /// <returns>
        /// A rewritten instance of the node.
        /// </returns>
        public virtual object VisitActual(ISarifNode node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            switch (node.SarifNodeKind)
            {
            case SarifNodeKind.Artifact:
                return(VisitArtifact((Artifact)node));

            case SarifNodeKind.ArtifactChange:
                return(VisitArtifactChange((ArtifactChange)node));

            case SarifNodeKind.ArtifactContent:
                return(VisitArtifactContent((ArtifactContent)node));

            case SarifNodeKind.ArtifactLocation:
                return(VisitArtifactLocation((ArtifactLocation)node));

            case SarifNodeKind.Attachment:
                return(VisitAttachment((Attachment)node));

            case SarifNodeKind.CodeFlow:
                return(VisitCodeFlow((CodeFlow)node));

            case SarifNodeKind.Conversion:
                return(VisitConversion((Conversion)node));

            case SarifNodeKind.Edge:
                return(VisitEdge((Edge)node));

            case SarifNodeKind.EdgeTraversal:
                return(VisitEdgeTraversal((EdgeTraversal)node));

            case SarifNodeKind.ExceptionData:
                return(VisitExceptionData((ExceptionData)node));

            case SarifNodeKind.ExternalPropertyFile:
                return(VisitExternalPropertyFile((ExternalPropertyFile)node));

            case SarifNodeKind.ExternalPropertyFiles:
                return(VisitExternalPropertyFiles((ExternalPropertyFiles)node));

            case SarifNodeKind.Fix:
                return(VisitFix((Fix)node));

            case SarifNodeKind.Graph:
                return(VisitGraph((Graph)node));

            case SarifNodeKind.GraphTraversal:
                return(VisitGraphTraversal((GraphTraversal)node));

            case SarifNodeKind.Invocation:
                return(VisitInvocation((Invocation)node));

            case SarifNodeKind.Location:
                return(VisitLocation((Location)node));

            case SarifNodeKind.LogicalLocation:
                return(VisitLogicalLocation((LogicalLocation)node));

            case SarifNodeKind.Message:
                return(VisitMessage((Message)node));

            case SarifNodeKind.MultiformatMessageString:
                return(VisitMultiformatMessageString((MultiformatMessageString)node));

            case SarifNodeKind.Node:
                return(VisitNode((Node)node));

            case SarifNodeKind.Notification:
                return(VisitNotification((Notification)node));

            case SarifNodeKind.PhysicalLocation:
                return(VisitPhysicalLocation((PhysicalLocation)node));

            case SarifNodeKind.PropertyBag:
                return(VisitPropertyBag((PropertyBag)node));

            case SarifNodeKind.Rectangle:
                return(VisitRectangle((Rectangle)node));

            case SarifNodeKind.Region:
                return(VisitRegion((Region)node));

            case SarifNodeKind.Replacement:
                return(VisitReplacement((Replacement)node));

            case SarifNodeKind.ReportingConfiguration:
                return(VisitReportingConfiguration((ReportingConfiguration)node));

            case SarifNodeKind.ReportingConfigurationOverride:
                return(VisitReportingConfigurationOverride((ReportingConfigurationOverride)node));

            case SarifNodeKind.ReportingDescriptor:
                return(VisitReportingDescriptor((ReportingDescriptor)node));

            case SarifNodeKind.Result:
                return(VisitResult((Result)node));

            case SarifNodeKind.ResultProvenance:
                return(VisitResultProvenance((ResultProvenance)node));

            case SarifNodeKind.Run:
                return(VisitRun((Run)node));

            case SarifNodeKind.RunAutomationDetails:
                return(VisitRunAutomationDetails((RunAutomationDetails)node));

            case SarifNodeKind.SarifLog:
                return(VisitSarifLog((SarifLog)node));

            case SarifNodeKind.Stack:
                return(VisitStack((Stack)node));

            case SarifNodeKind.StackFrame:
                return(VisitStackFrame((StackFrame)node));

            case SarifNodeKind.ThreadFlow:
                return(VisitThreadFlow((ThreadFlow)node));

            case SarifNodeKind.ThreadFlowLocation:
                return(VisitThreadFlowLocation((ThreadFlowLocation)node));

            case SarifNodeKind.Tool:
                return(VisitTool((Tool)node));

            case SarifNodeKind.ToolComponent:
                return(VisitToolComponent((ToolComponent)node));

            case SarifNodeKind.VersionControlDetails:
                return(VisitVersionControlDetails((VersionControlDetails)node));

            default:
                return(node);
            }
        }