Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UnixDomainSocketBinding ignoring set ReaderQuotas #5660

Open
Arzbergerr opened this issue Oct 9, 2024 · 5 comments
Open

UnixDomainSocketBinding ignoring set ReaderQuotas #5660

Arzbergerr opened this issue Oct 9, 2024 · 5 comments
Labels

Comments

@Arzbergerr
Copy link

Describe the bug
When using the UnixDomainSocketBinding for the WCF Client the set ReaderQuotas are ignored which may lead to an exception:
"[...] The maximum array length quota (16384) has been exceeded while reading XML data. This quota may be increased by changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader."

I have set the mentioned MaxArrayLength to a higher value which works well on NetNamedPipeBinding but not on UnixDomainSocketBinding.

To Reproduce
If needed i can try to create a small sample project the next days but i add informations after my investigations in Additional context below.

Expected behavior
The set ReaderQuotas of the UnixDomainSocketBinding to be considered like in other Bindings like NetNamedPipeBinding

Additional context
After some investigation of this behavior i found that the NetNamedPipeBinding add's the created BinaryMessageEncodingBindingElement of the _encoding field when CreateBindingElements is called.

public override BindingElementCollection CreateBindingElements()
        {   // return collection of BindingElements
            BindingElementCollection bindingElements = new BindingElementCollection();
            // order of BindingElements is important
            // add encoding
            bindingElements.Add(_encoding);
            // add transport security
            WindowsStreamSecurityBindingElement transportSecurity = CreateTransportSecurity();
            if (transportSecurity != null)
            {
                bindingElements.Add(transportSecurity);
            }
            // add transport (named pipes)
            bindingElements.Add(_namedPipe);

            return bindingElements.Clone();
        }

While the UnixDomainSocketBinding does not add the BinaryMessageEncodingBindingElement of the _encoding field:

public override BindingElementCollection CreateBindingElements()
        {
            // return collection of BindingElements
            BindingElementCollection bindingElements = new BindingElementCollection();
            BindingElement transportSecurity = CreateTransportSecurity();
            if (transportSecurity != null)
            {
                bindingElements.Add(transportSecurity);
            }
            _transport.ExtendedProtectionPolicy = _security.Transport.ExtendedProtectionPolicy;
            bindingElements.Add(_transport);

            return bindingElements.Clone();
        }

As workaround i created my own binding which derives form UnixDomainSocketBinding and overrides the CreateBindingElements.
In my override i get the value of _encoding via reflection and add it at first position of the BindingElementCollection (like also done at NetNamedPipeBinding). With that binding the ReaderQuotas are considered and the Data get read correctly.

@mconnew
Copy link
Member

mconnew commented Oct 9, 2024

You could also create a CustomBinding from the binding and add a BinaryMessageEncodingBindingElement copying the reader quotas across. That way you don't need to use reflection or create your own class.

@Arzbergerr
Copy link
Author

Thanks for your info, i also had the CustomBinding as an option in mind but did not try it out yesterday at the moment i wrote the issue.
Now i also tried that version with using the CustomBinding instead of the own class with reflection 'hack'.

This also works but it is important to not only add the element because that would result in another exception because the UnixDomainSocketTransportBindingElement is expected to be the last element in the BindingElementCollection.

So if the BinaryMessageEncodingBindingElement is not added but inserted this also works fine (e.g. below):

CustomBinding binding = new CustomBinding(udsBinding);
BinaryMessageEncodingBindingElement messageEncodingElement = new BinaryMessageEncodingBindingElement();
udsBinding.ReaderQuotas.CopyTo(messageEncodingElement.ReaderQuotas);

binding.Elements.Insert(0, messageEncodingElement);

The udsBinding as the already finished setup bindig of UnixDomainSocketBinding and using later this created CustomBinding works as well.

@mconnew
Copy link
Member

mconnew commented Oct 10, 2024

I would do this in anticipation of a fix:

CustomBinding binding = new CustomBinding(udsBinding);
if (binding.Elements.Find<BinaryMessageEncodingBindingElement>() == null)
{
    BinaryMessageEncodingBindingElement messageEncodingElement = new BinaryMessageEncodingBindingElement();
    udsBinding.ReaderQuotas.CopyTo(messageEncodingElement.ReaderQuotas);
    binding.Elements.Insert(0, messageEncodingElement);
}

@mconnew
Copy link
Member

mconnew commented Oct 10, 2024

@birojnayak, can you take a look. We should have a test which validates the reader quotas get applied. I think the easiest way to test that is to have an api where you send and receive a string. The MaxStringContentLength reader quota limits how long the string can be, the default is 8192.

@Arzbergerr
Copy link
Author

I would do this in anticipation of a fix:

CustomBinding binding = new CustomBinding(udsBinding);
if (binding.Elements.Find() == null)
{
BinaryMessageEncodingBindingElement messageEncodingElement = new BinaryMessageEncodingBindingElement();
udsBinding.ReaderQuotas.CopyTo(messageEncodingElement.ReaderQuotas);
binding.Elements.Insert(0, messageEncodingElement);
}

Yes, this way it would be also safe when the BinaryMessageEncodingBindingElement will be also considered by the UnixDomainSocketBinding. In my case i decided to get an exception if it is fixed so i can reconsider it and remove the workaround to make the binding preparation of UnixDomainSocketBinding more like other bindings which also may be used depending on the mode/configuration we use.
This is sure the better way to stick with this solution, thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants