microsoft / PSRule

Validate infrastructure as code (IaC) and objects using PowerShell rules.
https://microsoft.github.io/PSRule/v2/
MIT License
395 stars 49 forks source link

Default TargetName binding fails with NullReferenceException when TargetName or Name property is null #202

Closed LaurentDardenne closed 5 years ago

LaurentDardenne commented 5 years ago

Description of the issue TypeOf raises a NullReferenceException if a TargetObject property contains null.

Steps to reproduce the issue:

$Path='C:\temp'

$Rule='Test.Rule.ps1'
@'
Rule 'All' {
    AllOf {
       TypeOf 'My'
       TypeOf 'System.Management.Automation.PSCustomObject'
    }
}
'@ >"$Path\$Rule"
$Result= [PSCustomObject]@{PSTypeName='My';name='Test'},(1|Select Name)|
                    Invoke-PSRule -path "$Path\$Rule" 

# La référence d'objet n'est pas définie à une instance d'un objet.
# Au caractère C:\Prive\Modules\psrule\0.7.0\PSRule.psm1:171 : 17
# +                 $pipeline.Process($InputObject);
# +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#     + CategoryInfo          : OperationStopped: (:) [], NullReferenceException
#     + FullyQualifiedErrorId : System.NullReferenceException

$e=$error[0]
$e|select *

# PSMessageDetails      :
# Exception             : System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un
#                         objet.
#                            à PSRule.Pipeline.PipelineHookActions.DefaultTargetNameBinding(PSObject targetObject)
#                            à PSRule.Pipeline.PipelineContext.SetTargetObject(PSObject targetObject)
#                            à PSRule.Pipeline.InvokeRulePipeline.ProcessTargetObject(PSObject targetObject)
#                            à PSRule.Pipeline.InvokeRulePipeline.Process(PSObject targetObject)
#                            à CallSite.Target(Closure , CallSite , Object , Object )
#                            à Invoke-PSRule<Process>(Closure , FunctionContext )
# TargetObject          :
# CategoryInfo          : OperationStopped: (:) [], NullReferenceException
# FullyQualifiedErrorId : System.NullReferenceException
# ErrorDetails          :
# InvocationInfo        : System.Management.Automation.InvocationInfo
# ScriptStackTrace      : à Invoke-PSRule<Process>, C:\Prive\Modules\psrule\0.7.0\PSRule.psm1 : ligne 171
#                         à <ScriptBlock>, <Aucun fichier> : ligne 1
# PipelineIterationInfo : {}

$e.exception|select *

# Message        : La référence d'objet n'est pas définie à une instance d'un objet.
# Data           : {}
# InnerException :
# TargetSite     : System.String DefaultTargetNameBinding(System.Management.Automation.PSObject)
# StackTrace     :    à PSRule.Pipeline.PipelineHookActions.DefaultTargetNameBinding(PSObject targetObject)
#                     à PSRule.Pipeline.PipelineContext.SetTargetObject(PSObject targetObject)
#                     à PSRule.Pipeline.InvokeRulePipeline.ProcessTargetObject(PSObject targetObject)
#                     à PSRule.Pipeline.InvokeRulePipeline.Process(PSObject targetObject)
#                     à CallSite.Target(Closure , CallSite , Object , Object )
#                     à Invoke-PSRule<Process>(Closure , FunctionContext )
# HelpLink       :
# Source         : PSRule
# HResult        : -2147467261

#Same error
$Result= [PSCustomObject]@{PSTypeName='My';name=$null}|
                   Invoke-PSRule -path "$Path\$Rule" 

#No error
$Result= [PSCustomObject]@{PSTypeName='My'}|
                Invoke-PSRule -path "$Path\$Rule" 

#Same error
@'
Rule 'All' {
       TypeOf 'My'
}
'@ >"$Path\$Rule"
$Result= (1|Select Name)|Invoke-PSRule -path "$Path\$Rule" 

Error output

Capture any error messages and or verbose messages with -Verbose.

$Result= [PSCustomObject]@{PSTypeName='My';group='test';name=$null}|
                   Invoke-PSRule -path "$Path\$Rule"  -verbose
COMMENTAIRES : [Invoke-PSRule] BEGIN::
COMMENTAIRES : [New-PSRuleOption] BEGIN::
COMMENTAIRES : Attempting to read: C:\Prive\PSRule\rules
COMMENTAIRES : [New-PSRuleOption] END::
COMMENTAIRES : [PSRule][D] -- Scanning for source files: C:\temp\Test.Rule.ps1
COMMENTAIRES : [PSRule][D] -- Discovering rules in: C:\temp\Test.Rule.ps1
COMMENTAIRES : [PSRule][D] -- Found All in C:\temp\Test.Rule.ps1
La référence d'objet n'est pas définie à une instance d'un objet.
...

Module in use and version:

Captured output from $PSVersionTable:


Name                           Value
----                           -----
PSVersion                      5.1.17134.765
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.17134.765}
BuildVersion                   10.0.17134.765
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
LaurentDardenne commented 5 years ago

Same error with Exists KeyWord:

$Path='C:\temp'

$Rule='Test.Rule.ps1'
@'
Rule 'All' {
    Exists Name
}
'@ >"$Path\$Rule"
$Result= [PSCustomObject]@{PSTypeName='My';name='Test'},(1|Select Name)|Invoke-PSRule -path "$Path\$Rule" 
# System.NullReferenceException

[edit] The keyword Match also has the same problem.

BernieWhite commented 5 years ago

@LaurentDardenne Great. Thank you for reporting the issue.

BernieWhite commented 5 years ago

@LaurentDardenne The issue a related to binding TargetName, so would affect all use cases and is not specific to keywords. Thanks again for reporting.