runtime: [Uri] System.Uri rejects otherwise valid strings with length >= 65520
The System.Uri class seems to reject URI strings greater than a strangely short length (experimentally, 65520 or higher, so probably this constant). I’m not able to find any documentation of this fact at https://docs.microsoft.com/en-us/dotnet/api/system.uri?view=netcore-3.1, nor does RFC 3986 discuss length restrictions (though I went through those two sources very quickly, so this could be my error).
Most URIs I’ve seen are short enough, but data URIs can easily be imagined to exceed this limit.
CA1056:UriPropertiesShouldNotBeStrings and related rules have been guiding me towards using this class to represent URI strings for a while now; their documentation does not list “you want to support URI strings that exceed 65519 characters in length” as good reasons to suppress warnings.
In my perfect world, I would appreciate it if the System.Uri class could represent all URI values that are legal in RFC 3986 (or at least the subset that can be represented by System.String).
I totally understand why an artificial restriction might appear as a result of engineering trade-offs, so perhaps a decent first step might be to document it better?
Repro program
The following C# program writes out the longest URI I could manage.
Incrementing the commented line causes it to throw an exception:
Unhandled exception. System.UriFormatException: Invalid URI: The Uri string is too long.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at Program.Main() in <<AIRBREATHER_REDACTED>>\Program.cs:line 10
Program.cs
using System;
using static System.Console;
static class Program
{
static void Main()
{
const int TextLength = 65489; // any higher will throw an exception
string txt = new string('a', TextLength);
WriteLine(new Uri($"data:text/plain;charset=utf-8,{txt}"));
}
}
ConsoleApp0.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
</Project>
System Information
>dotnet --info
.NET Core SDK (reflecting any global.json):
Version: 3.1.101
Commit: b377529961
Runtime Environment:
OS Name: Windows
OS Version: 10.0.18363
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\3.1.101\
Host (useful for support):
Version: 3.1.1
Commit: a1388f194c
.NET Core SDKs installed:
2.2.402 [C:\Program Files\dotnet\sdk]
3.1.100 [C:\Program Files\dotnet\sdk]
3.1.101 [C:\Program Files\dotnet\sdk]
.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 20 (13 by maintainers)
Commits related to this issue
- Allow overlong data URIs in GpxWebLink. Workaround for dotnet/runtime#1857 Resolves NetTopologySuite.IO.GPX#39 — committed to NetTopologySuite/NetTopologySuite.IO.GPX by airbreather 4 years ago
I’m really not sure you can consider that short.
In my original comment, I wrote this:
Should open an issue on dotnet/dotnet-api-docs for that “decent first step” part of it?
As of right now, the “Filing Issues” section of this repo doesn’t link over there (I only found out about it when scrolling through and noticing the cross-reference from dotnet/dotnet-api-docs#3906).
Correct
65535 is also a valid length that could be stored if the input is shorter than 65520 and has characters that would expand it to 65535.
If we were to implement it, it would most likely be done by changing the minimum amount of fields to int (we could likely keep Scheme, User, Host, PortValue and Path as ushort). That would result in a 4-8 byte size increase of Uri, which might be acceptable considering other inefficiencies in Uri.
Considering that data Uris are the only realistic scenario for Uris longer than 65k, I don’t think it is worth making such a change.
I understand that in your case you may not be interacting with the created Uri other than for validation / satisfying the object model. But otherwise the utility of Uri for data uris is practically equivalent to
It provides no utility for accesing the media type/data - those have to be manually parsed out. It also provides no validation for it except for the scheme name.
There are other downsides to removing the length restriction.
So if for some reason we decided to remove the length restriction in the future, a lot of work would have to be done to improve Uri overall first.
Given that this issue is the only ask for relaxing the length restriction that I know of and you already implemented a workaround for your use case, I don’t see a real benefit for moving forward here.
Consider as won’t-fix until then.
This is a documented length limit for Uri
See https://docs.microsoft.com/en-us/dotnet/api/system.uri.-ctor?view=netcore-3.1#System_Uri__ctor_System_String_
One of the conditions listed for throwing UriFormatException:
I agree that we can add a comment about this limit to the main Uri page as rn it is only documented on constructors.