19932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda/* 29932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * Copyright (C) 2009 The Android Open Source Project 39932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * 49932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * Licensed under the Apache License, Version 2.0 (the "License"); 59932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * you may not use this file except in compliance with the License. 69932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * You may obtain a copy of the License at 79932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * 89932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * http://www.apache.org/licenses/LICENSE-2.0 99932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * 109932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * Unless required by applicable law or agreed to in writing, software 119932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * distributed under the License is distributed on an "AS IS" BASIS, 129932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * See the License for the specific language governing permissions and 149932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * limitations under the License. 159932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda */ 169932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1754f969b83377b1540efc0180962966df0732a479Jesse Wilsonpackage libcore.java.nio.charset; 189932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1954f969b83377b1540efc0180962966df0732a479Jesse Wilsonimport java.nio.ByteBuffer; 2054f969b83377b1540efc0180962966df0732a479Jesse Wilsonimport java.nio.CharBuffer; 219932735d0306721523082f77b0a9ba4aa4db8cdbMihai Predaimport java.nio.charset.Charset; 229932735d0306721523082f77b0a9ba4aa4db8cdbMihai Predaimport java.nio.charset.CharsetDecoder; 239932735d0306721523082f77b0a9ba4aa4db8cdbMihai Predaimport java.nio.charset.CharsetEncoder; 2454f969b83377b1540efc0180962966df0732a479Jesse Wilsonimport junit.framework.TestCase; 259932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 269932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 27c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes/* See bug http://b/1844104. 289932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * Checks for ICU encoder/decoder buffer corruption. 299932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda */ 3054f969b83377b1540efc0180962966df0732a479Jesse Wilsonpublic class OldCharsetEncoderDecoderBufferTest extends TestCase { 319932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 329932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda /* Checks for a buffer corruption that happens in ICU 339932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * (CharsetDecoderICU) when a decode operation 349932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * is done first with an out-buffer with hasArray()==true, and next with an out-buffer with 359932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * hasArray()==false. In that situation ICU may overwrite the first out-buffer. 369932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda */ 379932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda public void testDecoderOutputBuffer() { 389932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder(); 399932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 409932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda char[] cBuf = new char[10]; 419932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharBuffer out = CharBuffer.wrap(cBuf); 429932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertTrue(out.hasArray()); 439932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda decoder.decode(ByteBuffer.wrap(new byte[]{(byte)'a', (byte)'b', (byte)'c', (byte)'d'}), 449932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda out, false); 459932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 469932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals("abcd", new String(cBuf, 0, 4)); 479932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, cBuf[4]); 489932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, cBuf[5]); 499932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 509932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda byte[] bBuf = new byte[10]; 519932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda out = ByteBuffer.wrap(bBuf).asCharBuffer(); 529932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertFalse(out.hasArray()); 539932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda decoder.decode(ByteBuffer.wrap(new byte[]{(byte)'x'}), out, true); 549932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 559932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('x', bBuf[1]); 569932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, bBuf[3]); 579932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 589932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda // check if the first buffer was corrupted by the second decode 599932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals("abcd", new String(cBuf, 0, 4)); 609932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, cBuf[4]); 619932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, cBuf[5]); 629932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda } 639932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 649932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda /* Checks for a buffer corruption that happens in ICU 659932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * (CharsetDecoderICU) when a decode operation 669932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * is done first with an in-buffer with hasArray()==true, and next with an in-buffer with 679932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * hasArray()==false. In that situation ICU may overwrite the array of the first in-buffer. 689932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda */ 699932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda public void testDecoderInputBuffer() { 709932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder(); 719932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharBuffer out = CharBuffer.wrap(new char[10]); 729932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 739932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda byte[] inArray = {(byte)'a', (byte)'b'}; 749932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda ByteBuffer inWithArray = ByteBuffer.wrap(inArray); 759932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertTrue(inWithArray.hasArray()); 769932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda decoder.decode(inWithArray, out, false); 779932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('a', inArray[0]); 789932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('b', inArray[1]); 799932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 80c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes // A read-only ByteBuffer must not expose its array. 81c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes ByteBuffer inWithoutArray = ByteBuffer.wrap(new byte[] { (byte) 'x' }).asReadOnlyBuffer(); 829932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertFalse(inWithoutArray.hasArray()); 839932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda decoder.decode(inWithoutArray, out, true); 849932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 859932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda // check whether the first buffer was corrupted by the second decode 869932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('a', inArray[0]); 879932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('b', inArray[1]); 889932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda } 899932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 909932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda /* Checks for a buffer corruption that happens in ICU 919932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * (CharsetEncoderICU) when an encode operation 929932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * is done first with an out-buffer with hasArray()==true, and next with an out-buffer with 939932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * hasArray()==false. In that situation ICU may overwrite the first out-buffer. 949932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda */ 959932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda public void testEncoderOutputBuffer() { 969932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); 979932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 989932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda byte[] buffer = new byte[10]; 999932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda ByteBuffer out = ByteBuffer.wrap(buffer); 1009932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1019932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertTrue(out.hasArray()); 1029932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda encoder.encode(CharBuffer.wrap("ab"), out, false); 1039932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1049932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('a', buffer[0]); 1059932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('b', buffer[1]); 1069932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, buffer[2]); 1079932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1089932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda out = ByteBuffer.allocateDirect(10); 109c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes // It's no longer possible to get a byte buffer without a backing byte[] on Android. 110c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes // This test is useless on Android, unless that changes again. (You can't even 111c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes // subclass ByteBuffer because -- although it's non-final -- both the RI and Android 112c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes // have [different] package-private abstract methods you'd need to implement but can't.) 113c6210a287dad8ae2447387ec840696b0e366046fElliott Hughes //assertFalse(out.hasArray()); 1149932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda encoder.encode(CharBuffer.wrap("x"), out, true); 1159932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1169932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda // check whether the second decode corrupted the first buffer 1179932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('a', buffer[0]); 1189932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('b', buffer[1]); 1199932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals(0, buffer[2]); 1209932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda } 1219932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1229932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda /* Checks for a buffer corruption that happens in ICU 1239932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * (CharsetEncoderICU) when an encode operation 1249932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * is done first with an in-buffer with hasArray()==true, and next with an in-buffer with 1259932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda * hasArray()==false. In that situation ICU may overwrite the array of the first in-buffer. 1269932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda */ 1279932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda public void testEncoderInputBuffer() { 1289932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); 1299932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda ByteBuffer out = ByteBuffer.wrap(new byte[10]); 1309932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1319932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda char[] inArray = {'a', 'b'}; 1329932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharBuffer inWithArray = CharBuffer.wrap(inArray); 1339932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertTrue(inWithArray.hasArray()); 1349932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda encoder.encode(inWithArray, out, false); 1359932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1369932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('a', inArray[0]); 1379932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('b', inArray[1]); 1389932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1399932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda CharBuffer inWithoutArray = CharBuffer.wrap("x"); 1409932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertFalse(inWithoutArray.hasArray()); 1419932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda encoder.encode(inWithoutArray, out, true); 1429932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda 1439932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda // check whether the second decode corrupted the first buffer 1449932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('a', inArray[0]); 1459932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda assertEquals('b', inArray[1]); 1469932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda } 1479932735d0306721523082f77b0a9ba4aa4db8cdbMihai Preda} 148