MemoryExtensions ToUpper / ToLower throws for overlapping buffer (#25327)
authorMarco Rossignoli <marco.rossignoli@gmail.com>
Sun, 23 Jun 2019 15:30:58 +0000 (17:30 +0200)
committerJan Kotas <jkotas@microsoft.com>
Sun, 23 Jun 2019 15:30:58 +0000 (08:30 -0700)
src/System.Private.CoreLib/Resources/Strings.resx
src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
tests/CoreFX/CoreFX.issues.rsp

index 3bd8d5a..653c1d3 100644 (file)
   <data name="NotSupported_GlobalMethodSerialization" xml:space="preserve">
     <value>Serialization of global methods (including implicit serialization via the use of asynchronous delegates) is not supported.</value>
   </data>
+    <data name="InvalidOperation_SpanOverlappedOperation" xml:space="preserve">
+    <value>This operation is invalid on overlapping buffers.</value>
+  </data>
   <data name="NotSupported_IDispInvokeDefaultMemberWithNamedArgs" xml:space="preserve">
     <value>Invoking default method with named arguments is not supported.</value>
   </data>
   <data name="InvalidOperation_MultipleComUnRegFunctions" xml:space="preserve">
     <value>Type '{0}' has more than one COM unregistration function.</value>
   </data>
-</root>
\ No newline at end of file
+</root>
index 33617b4..801c87f 100644 (file)
@@ -219,11 +219,14 @@ namespace System
         /// <param name="source">The source span.</param>
         /// <param name="destination">The destination span which contains the transformed characters.</param>
         /// <param name="culture">An object that supplies culture-specific casing rules.</param>
-        /// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
-        /// a temporary location before the destination is overwritten. If <paramref name="culture"/> is null, <see cref="System.Globalization.CultureInfo.CurrentCulture"/> will be used.</remarks>
+        /// <remarks>If <paramref name="culture"/> is null, <see cref="System.Globalization.CultureInfo.CurrentCulture"/> will be used.</remarks>
         /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
+        /// <exception cref="InvalidOperationException">The source and destination buffers overlap.</exception>
         public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture)
         {
+            if (source.Overlaps(destination))
+                throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
+
             if (culture == null)
                 culture = CultureInfo.CurrentCulture;
 
@@ -244,11 +247,13 @@ namespace System
         /// </summary>
         /// <param name="source">The source span.</param>
         /// <param name="destination">The destination span which contains the transformed characters.</param>
-        /// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
-        /// a temporary location before the destination is overwritten.</remarks>
         /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
+        /// <exception cref="InvalidOperationException">The source and destination buffers overlap.</exception>
         public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination)
         {
+            if (source.Overlaps(destination))
+                throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
+
             // Assuming that changing case does not affect length
             if (destination.Length < source.Length)
                 return -1;
@@ -267,11 +272,14 @@ namespace System
         /// <param name="source">The source span.</param>
         /// <param name="destination">The destination span which contains the transformed characters.</param>
         /// <param name="culture">An object that supplies culture-specific casing rules.</param>
-        /// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
-        /// a temporary location before the destination is overwritten. If <paramref name="culture"/> is null, <see cref="System.Globalization.CultureInfo.CurrentCulture"/> will be used.</remarks>
+        /// <remarks>If <paramref name="culture"/> is null, <see cref="System.Globalization.CultureInfo.CurrentCulture"/> will be used.</remarks>
         /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
+        /// <exception cref="InvalidOperationException">The source and destination buffers overlap.</exception>
         public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture)
         {
+            if (source.Overlaps(destination))
+                throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
+
             if (culture == null)
                 culture = CultureInfo.CurrentCulture;
 
@@ -292,11 +300,13 @@ namespace System
         /// </summary>
         /// <param name="source">The source span.</param>
         /// <param name="destination">The destination span which contains the transformed characters.</param>
-        /// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
-        /// a temporary location before the destination is overwritten.</remarks>
         /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
+        /// <exception cref="InvalidOperationException">The source and destination buffers overlap.</exception>
         public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination)
         {
+            if (source.Overlaps(destination))
+                throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
+
             // Assuming that changing case does not affect length
             if (destination.Length < source.Length)
                 return -1;
index e34bcd0..d39d214 100644 (file)
 -nomethod System.Diagnostics.Tests.StackTraceTests.Ctor_Exception_LargeSkipFrames_FNeedFileInfo
 -nomethod System.Diagnostics.Tests.StackTraceTests.Ctor_LargeSkipFrames_GetFramesReturnsNull
 -nomethod System.Diagnostics.Tests.StackTraceTests.Ctor_LargeSkipFramesFNeedFileInfo_GetFramesReturnsNull
+
+# requires corefx test updates
+-nomethod System.Tests.StringTests.SameSpanToLower
+-nomethod System.Tests.StringTests.ToLowerOverlapping
+-nomethod System.Tests.StringTests.SameSpanToUpper
+-nomethod System.Tests.StringTests.ToUpperOverlapping