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