Răsfoiți Sursa

[corlib] Fix ASCIIEncoding with custom DecoderFallback.

Only pass one single byte to DecoderFallback.Fallback(),
throw if there's not enough space in the char array.
Martin Baulig 13 ani în urmă
părinte
comite
cd8ca2f658

+ 11 - 3
mcs/class/corlib/System.Text/ASCIIEncoding.cs

@@ -216,9 +216,17 @@ public class ASCIIEncoding : Encoding
 			else {
 			else {
 				if (buffer == null)
 				if (buffer == null)
 					buffer = DecoderFallback.CreateFallbackBuffer ();
 					buffer = DecoderFallback.CreateFallbackBuffer ();
-				buffer.Fallback (bytes, byteIndex);
-				while (buffer.Remaining > 0)
-					chars [charIndex++] = buffer.GetNextChar ();
+				var thisByte = new byte[] { bytes [byteIndex-1] };
+				buffer.Fallback (thisByte, 0);
+				while (buffer.Remaining > 0) {
+					if (charIndex < chars.Length) {
+						chars [charIndex++] = buffer.GetNextChar ();
+						continue;
+					}
+					throw new ArgumentException (
+							"The output char buffer is too small to contain the " +
+							"decoded characters.");
+				}
 			}
 			}
 		}
 		}
 		return byteCount;
 		return byteCount;

+ 95 - 2
mcs/class/corlib/Test/System.Text/ASCIIEncodingTest.cs

@@ -8,6 +8,8 @@ using System;
 using System.Text;
 using System.Text;
 
 
 using NUnit.Framework;
 using NUnit.Framework;
+using NUnit.Framework.Constraints;
+using NUnit.Framework.SyntaxHelpers;
 
 
 namespace MonoTests.System.Text
 namespace MonoTests.System.Text
 {
 {
@@ -210,7 +212,6 @@ namespace MonoTests.System.Text
 			Assert.AreEqual (string.Empty, encoding.GetString (new byte [0], 0, 0), "#2");
 			Assert.AreEqual (string.Empty, encoding.GetString (new byte [0], 0, 0), "#2");
 		}
 		}
 
 
-#if NET_2_0
 		[Test]
 		[Test]
 		[ExpectedException (typeof (DecoderFallbackException))]
 		[ExpectedException (typeof (DecoderFallbackException))]
 		public void DecoderFallback ()
 		public void DecoderFallback ()
@@ -219,6 +220,98 @@ namespace MonoTests.System.Text
 			e.DecoderFallback = new DecoderExceptionFallback ();
 			e.DecoderFallback = new DecoderExceptionFallback ();
 			e.GetChars (new byte [] {0x80});
 			e.GetChars (new byte [] {0x80});
 		}
 		}
-#endif
+
+		[Test]
+		[ExpectedException (typeof (ArgumentException))]
+		public void DecoderFallback2 ()
+		{
+			var bytes = new byte[] {
+				0x30, 0xa0, 0x31, 0xa8
+			};
+			var enc = (ASCIIEncoding)Encoding.ASCII.Clone ();
+			enc.DecoderFallback = new TestFallbackDecoder ();
+			
+			var chars = new char [7];
+			var ret = enc.GetChars (bytes, 0, bytes.Length, chars, 0);
+			Console.WriteLine (ret);
+			
+			for (int i = 0; i < chars.Length; i++) {
+				Console.Write ("{0:x2} ", (int)chars [i]);
+			}
+			Console.WriteLine ();
+		}
+		
+		[Test]
+		public void DecoderFallback3 ()
+		{
+			var bytes = new byte[] {
+				0x30, 0xa0, 0x31, 0xa8
+			};
+			var enc = (ASCIIEncoding)Encoding.ASCII.Clone ();
+			enc.DecoderFallback = new TestFallbackDecoder ();
+			
+			var chars = new char [10];
+			var ret = enc.GetChars (bytes, 0, bytes.Length, chars, 0);
+			
+			Assert.That (ret, Is.EqualTo (6), "ret");
+			Assert.That (chars [0], Is.EqualTo ((char)0x30), "chars[0]");
+			Assert.That (chars [1], Is.EqualTo ((char)0xa0), "chars[1]");
+			Assert.That (chars [2], Is.EqualTo ((char)0xa1), "chars[2]");
+			Assert.That (chars [3], Is.EqualTo ((char)0x31), "chars[3]");
+			Assert.That (chars [4], Is.EqualTo ((char)0xa8), "chars[4]");
+			Assert.That (chars [5], Is.EqualTo ((char)0xa9), "chars[5]");
+		}
+		
+		class TestFallbackDecoder : DecoderFallback {
+			const int count = 2;
+			
+			public override int MaxCharCount {
+				get { return count; }
+			}
+			
+			public override DecoderFallbackBuffer CreateFallbackBuffer ()
+			{
+				return new Buffer ();
+			}
+			
+			class Buffer : DecoderFallbackBuffer {
+				char[] queue;
+				int index;
+				
+				public override int Remaining {
+					get {
+						return queue.Length - index;
+					}
+				}
+				
+				public override char GetNextChar ()
+				{
+					return index < queue.Length ? queue [index++] : '\0';
+				}
+				
+				public override bool Fallback (byte[] bytes, int unused)
+				{
+					queue = new char[bytes.Length * count];
+					index = 0;
+					for (int i = 0; i < bytes.Length; i++) {
+						for (int j = 0; j < count; j++)
+							queue [index++] = (char)(bytes [i]+j);
+					}
+					return true;
+				}
+				
+				public override bool MovePrevious ()
+				{
+					throw new NotImplementedException ();
+				}
+				
+				public override void Reset ()
+				{
+					base.Reset ();
+				}
+			}
+		}
+		
+
 	}
 	}
 }
 }