Project

Profile

Help

Bug #5102

closed

System.ArgumentNullException from message listener (unknown location URI?)

Added by Emanuel Wlaschitz over 2 years ago. Updated about 2 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Internals
Sprint/Milestone:
-
Start date:
2021-09-22
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
10
Fix Committed on Branch:
10
Fixed in Maintenance Release:
Platforms:

Description

We're currently in the process of updating to Saxon-HE 10.6N and one of our stylesheets started to blow up for no apparent reason. Deep down we see this one:

System.ArgumentNullException
  HResult=0x80004003
  Message=Value cannot be null.
Parameter name: uriString
  Source=System
  StackTrace:
   at System.Uri..ctor(String uriString)

  This exception was originally thrown at this call stack:
    System.Uri.Uri(string)

...which is at:

 	System.dll!System.Uri.Uri(string uriString)	Unknown
 	saxon-he-api-10.6.dll!Saxon.Api.MessageListenerProxy2.message(net.sf.saxon.s9api.XdmNode xn, net.sf.saxon.s9api.QName qn, bool b, javax.xml.transform.SourceLocator sl)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.MessageListener2Proxy.write(net.sf.saxon.om.Item value)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.SequenceWriter.append(net.sf.saxon.om.Item item, net.sf.saxon.s9api.Location locationId, int copyNamespaces)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.MessageListener2Proxy.append(net.sf.saxon.om.Item value, net.sf.saxon.s9api.Location value, int value)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.SequenceWriter.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.TreeReceiver.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.ProxyReceiver.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.ComplexContentOutputter.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.expr.instruct.Message.processLeavingTail(net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContext context)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.expr.instruct.Block.processLeavingTail(net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContext context)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContext context)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.trans.Mode.applyTemplates(net.sf.saxon.expr.instruct.ParameterSet parameters, net.sf.saxon.expr.instruct.ParameterSet tunnelParameters, net.sf.saxon.om.NodeInfo separator, net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContextMajor context, net.sf.saxon.s9api.Location locationId)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.trans.XsltController.applyTemplates(net.sf.saxon.om.Sequence source, net.sf.saxon.event.Receiver out)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(javax.xml.transform.Source value, net.sf.saxon.event.Receiver value)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.XsltTransformer.transform()	Unknown
 	saxon-he-api-10.6.dll!Saxon.Api.XsltTransformer.Run(Saxon.Api.XmlDestination destination)	Unknown

...and is followed up by this when ignoring exceptions that are caught internally:

java.lang.RuntimeException
  HResult=0x80131500
  Message=Internal error evaluating template rule  in module file:///D:/_dev/SaxonMLP2NullPointer/bin/Debug/SaxonMLP2NullPointer.exe
  Source=saxon-he-10.6
  StackTrace:
   at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(Outputter output, XPathContext context)
   at net.sf.saxon.trans.Mode.applyTemplates(ParameterSet parameters, ParameterSet tunnelParameters, NodeInfo separator, Outputter output, XPathContextMajor context, Location locationId)
   at net.sf.saxon.trans.XsltController.applyTemplates(Sequence source, Receiver out)
   at net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(Source , Receiver )
   at net.sf.saxon.s9api.XsltTransformer.transform()
   at Saxon.Api.XsltTransformer.Run(XmlDestination destination)
   at SaxonMLP2NullPointer.Program.Main(String[] args) in D:\_dev\SaxonMLP2NullPointer\Program.cs:line 39

Inner Exception 1:
NullPointerException: 

It appears that in those cases, SourceLocator sl inside MessagListenerProxy2.message is net.sf.saxon.expr.parser.Loc@1029822 { columnNumber: -1, lineNumber: -1, systemId: null } and fails when attempting to set location.BaseUri = new Uri(sl.getSystemId()); due to sl.getSystemId() returning null.

I managed to create a stripped down example that still causes the issue, and it appears to be related to having both a custom MessageListener2 on the XsltTransformer, as well as writing a <xsl:message> that contains either <xsl:value-of/> or <xsl:sequence/> to produce the message itself from a non-xs:string source (that is: no select attribute, any expression that is not of type xs:string or uses any function to produce a xs:string; including a call to concat()).

Here's the (minimalistic) source:

internal class Program
{
    private static void Main(string[] args)
    {
        var xslt = XDocument.Parse(@"
        <stylesheet xmlns='http://www.w3.org/1999/XSL/Transform' version='3.0'>
            <template match='/'>
                <!-- this message causes an error when MessageListener2 is used -->
                <message><value-of select='local-name()'/></message>
                <result xmlns=''/>
            </template>
        </stylesheet>");
        var input = xslt; // does not matter for this test.
        var output = new XDocument();

        var processor = new Processor();
        using (var xsltReader = xslt.CreateReader())
        using (var inputReader = input.CreateReader())
        using (var outputWriter = output.CreateWriter())
        {
            var compiler = processor.NewXsltCompiler();
            compiler.BaseUri = new Uri(typeof(Program).Assembly.Location);
            var xsltExecutable = compiler.Compile(xsltReader);

            var transformer = xsltExecutable.Load();

            var builder = processor.NewDocumentBuilder();
            transformer.InitialContextNode = builder.Build(inputReader);
            // comment this out to prevent the issue
            transformer.MessageListener2 = new TestMessageListener();

            var destination = new TextWriterDestination(outputWriter) { CloseAfterUse = true };
            transformer.Run(destination);
        }
    }
    private sealed class TestMessageListener : IMessageListener2
    {
        public void Message(XdmNode content, QName errorCode, bool terminate, IXmlLocation location) { }
    }
}

The code will work when:

  1. transformer.MessageListener2 is not set by the code (or transformer.MessageListener if the errorCode parameter is not neede by the listener)
  2. The contents of <message> is plain text (such as <message>test</message>)
  3. The contents of <message> is a string variable (such as <variable name="message" select="'test'"/><message><value-of select="$message"/></message>)

The code will not work when:

  1. The contents of <message> is produced by a function call (such as <message><value-of select="concat('Message here: ', $message)"/></message>)
  2. The contents of <message> is not of type xs:string (such as <variable name="message" select="42"/><message><value-of select="$message"/></message>)
  3. The contents of <message> use the concatenation operator (such as <message><value-of select="Message here: " || $message"/></message> - which might be the same as the first case though)

For obvious reasons, we can't simply not add the MessageListener2 because we want to capture <xsl:message> including the errorCode. And the same thing happens if we revert back to MessageListener, except that it happens in MessageListenerProxy instead of MessageListenerProxy2 in that case.

This is using the currently most recent NuGet package with version 10.6.0 on .NET Framework 4.8

Please register to edit this issue

Also available in: Atom PDF