-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Fix XML parameter encoding for SQL Server #38462
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
base: main
Are you sure you want to change the base?
Changes from all commits
a17073c
4601cb3
19ee474
16d73b9
97293d7
c2bfa09
96f6a7a
633a8a6
9ef8296
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,7 +2,9 @@ | |
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Data; | ||
| using System.Data.SqlTypes; | ||
| using System.Text; | ||
| using System.Xml; | ||
| using Microsoft.Data.SqlClient; | ||
| using Microsoft.EntityFrameworkCore.Storage.Json; | ||
|
|
||
|
|
@@ -19,6 +21,9 @@ public class SqlServerStringTypeMapping : StringTypeMapping | |
| private const int UnicodeMax = 4000; | ||
| private const int AnsiMax = 8000; | ||
|
|
||
| private const string Utf8XmlDeclaration = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think matching on this is not even good enough. The grammar is: So even without going into esoteric combinations, ...
Without going into full |
||
| private const string Utf16XmlDeclaration = "<?xml version=\"1.0\" encoding=\"utf-16\"?>"; | ||
|
|
||
| private static readonly CaseInsensitiveValueComparer CaseInsensitiveValueComparer = new(); | ||
|
|
||
| private readonly bool _isUtf16; | ||
|
|
@@ -110,8 +115,9 @@ protected SqlServerStringTypeMapping(RelationalTypeMappingParameters parameters, | |
| _maxSize = AnsiMax; | ||
| } | ||
|
|
||
| _isUtf16 = parameters.Unicode && parameters.StoreType.StartsWith("n", StringComparison.OrdinalIgnoreCase); | ||
| _sqlDbType = sqlDbType; | ||
| _isUtf16 = _sqlDbType == SqlDbType.Xml | ||
| || (parameters.Unicode && parameters.StoreType.StartsWith("n", StringComparison.OrdinalIgnoreCase)); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -147,6 +153,14 @@ protected override RelationalTypeMapping Clone(RelationalTypeMappingParameters p | |
| protected override void ConfigureParameter(DbParameter parameter) | ||
| { | ||
| var value = parameter.Value; | ||
|
|
||
| if (_sqlDbType == SqlDbType.Xml | ||
| && value is string stringValue | ||
| && stringValue.StartsWith(Utf8XmlDeclaration, StringComparison.Ordinal)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a valid way to check a prolog. It perhaps covers a lot of cases, but the version number can now be 1.1 as well as 1.0, and there are many encodings that are not UTF-8 or UTF-16, and the If you really want to go down the road of validating the declaration then you will definitely need an
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, sounds like just passing the XmlReader in SqlXml would be the more robust solution. |
||
| { | ||
| value = parameter.Value = string.Concat(Utf16XmlDeclaration, stringValue.AsSpan(Utf8XmlDeclaration.Length)); | ||
| } | ||
|
AndriySvyryd marked this conversation as resolved.
|
||
|
|
||
| var length = (value as string)?.Length; | ||
|
|
||
| if (_sqlDbType.HasValue | ||
|
|
@@ -211,7 +225,17 @@ protected override string GenerateNonNullSqlLiteral(object value) | |
| var concatCount = 1; | ||
| var concatStartList = new List<int>(); | ||
| var insideConcat = false; | ||
| for (i = 0; i < stringValue.Length; i++) | ||
|
|
||
| if (_sqlDbType == SqlDbType.Xml | ||
| && stringValue.StartsWith(Utf8XmlDeclaration, StringComparison.Ordinal)) | ||
| { | ||
| // The value is sent to the server as 'xml', so a UTF-8 prolog is rewritten to UTF-16. | ||
| builder.Append('N').Append('\'').Append(Utf16XmlDeclaration); | ||
| openApostrophe = true; | ||
| start = Utf8XmlDeclaration.Length; | ||
| } | ||
|
|
||
| for (i = start; i < stringValue.Length; i++) | ||
| { | ||
| var lineFeed = stringValue[i] == '\n'; | ||
| var carriageReturn = stringValue[i] == '\r'; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.