@@ -221,4 +221,42 @@ public void Read_VeryLarge()
221221 }
222222 while ( charsRead > 0 ) ;
223223 }
224+
225+ [ Theory ]
226+ [ CombinatorialData ]
227+ public void SurrogatePairsAtBufferBoundary ( bool surrogatePairsStartOnOddIndex )
228+ {
229+ // Fill a buffer large enough that it surely exceeds the internal char[] size inside the SequenceTextReader.
230+ var surrogateCharsBuffer = new char [ 5 * 1024 ] ;
231+
232+ // Now initialize it with surrogate character pairs.
233+ // Each pair will align at the even or odd indexes (based on test method argument) to ensure that
234+ // if there's a vulnerability in SequenceTextReader, we'll find it.
235+ int i = surrogatePairsStartOnOddIndex ? 1 : 0 ;
236+ for ( ; i < surrogateCharsBuffer . Length - 1 ; i += 2 )
237+ {
238+ // Compose a treble clef (𝄞).
239+ surrogateCharsBuffer [ i ] = '\uD834 ' ;
240+ surrogateCharsBuffer [ i + 1 ] = '\uDD1E ' ;
241+ }
242+
243+ byte [ ] bytes = DefaultEncoding . GetBytes ( surrogateCharsBuffer ) ;
244+
245+ this . sequenceTextReader . Initialize ( new ReadOnlySequence < byte > ( bytes ) , DefaultEncoding ) ;
246+ char [ ] actualBlock = new char [ 49 ] ;
247+ int totalCharsRead = 0 ;
248+ int charsRead ;
249+ do
250+ {
251+ charsRead = this . sequenceTextReader . Read ( actualBlock , 0 , actualBlock . Length ) ;
252+ for ( int j = 0 ; j < charsRead ; j ++ )
253+ {
254+ Assert . Equal ( surrogateCharsBuffer [ totalCharsRead + j ] , actualBlock [ j ] ) ;
255+ }
256+
257+ totalCharsRead += charsRead ;
258+ }
259+ while ( charsRead > 0 ) ;
260+ Assert . Equal ( surrogateCharsBuffer . Length , totalCharsRead ) ;
261+ }
224262}
0 commit comments