blob: 6465d9e5a8535d9a92cd3a0941daf1a77e7ac8b4 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package libcore.java.nio.charset;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import junit.framework.TestCase;
/* See bug http://b/1844104.
* Checks for ICU encoder/decoder buffer corruption.
*/
public class OldCharsetEncoderDecoderBufferTest extends TestCase {
/* Checks for a buffer corruption that happens in ICU
* (CharsetDecoderICU) when a decode operation
* is done first with an out-buffer with hasArray()==true, and next with an out-buffer with
* hasArray()==false. In that situation ICU may overwrite the first out-buffer.
*/
public void testDecoderOutputBuffer() {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
char[] cBuf = new char[10];
CharBuffer out = CharBuffer.wrap(cBuf);
assertTrue(out.hasArray());
decoder.decode(ByteBuffer.wrap(new byte[]{(byte)'a', (byte)'b', (byte)'c', (byte)'d'}),
out, false);
assertEquals("abcd", new String(cBuf, 0, 4));
assertEquals(0, cBuf[4]);
assertEquals(0, cBuf[5]);
byte[] bBuf = new byte[10];
out = ByteBuffer.wrap(bBuf).asCharBuffer();
assertFalse(out.hasArray());
decoder.decode(ByteBuffer.wrap(new byte[]{(byte)'x'}), out, true);
assertEquals('x', bBuf[1]);
assertEquals(0, bBuf[3]);
// check if the first buffer was corrupted by the second decode
assertEquals("abcd", new String(cBuf, 0, 4));
assertEquals(0, cBuf[4]);
assertEquals(0, cBuf[5]);
}
/* Checks for a buffer corruption that happens in ICU
* (CharsetDecoderICU) when a decode operation
* is done first with an in-buffer with hasArray()==true, and next with an in-buffer with
* hasArray()==false. In that situation ICU may overwrite the array of the first in-buffer.
*/
public void testDecoderInputBuffer() {
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
CharBuffer out = CharBuffer.wrap(new char[10]);
byte[] inArray = {(byte)'a', (byte)'b'};
ByteBuffer inWithArray = ByteBuffer.wrap(inArray);
assertTrue(inWithArray.hasArray());
decoder.decode(inWithArray, out, false);
assertEquals('a', inArray[0]);
assertEquals('b', inArray[1]);
// A read-only ByteBuffer must not expose its array.
ByteBuffer inWithoutArray = ByteBuffer.wrap(new byte[] { (byte) 'x' }).asReadOnlyBuffer();
assertFalse(inWithoutArray.hasArray());
decoder.decode(inWithoutArray, out, true);
// check whether the first buffer was corrupted by the second decode
assertEquals('a', inArray[0]);
assertEquals('b', inArray[1]);
}
/* Checks for a buffer corruption that happens in ICU
* (CharsetEncoderICU) when an encode operation
* is done first with an out-buffer with hasArray()==true, and next with an out-buffer with
* hasArray()==false. In that situation ICU may overwrite the first out-buffer.
*/
public void testEncoderOutputBuffer() {
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
byte[] buffer = new byte[10];
ByteBuffer out = ByteBuffer.wrap(buffer);
assertTrue(out.hasArray());
encoder.encode(CharBuffer.wrap("ab"), out, false);
assertEquals('a', buffer[0]);
assertEquals('b', buffer[1]);
assertEquals(0, buffer[2]);
out = ByteBuffer.allocateDirect(10);
// It's no longer possible to get a byte buffer without a backing byte[] on Android.
// This test is useless on Android, unless that changes again. (You can't even
// subclass ByteBuffer because -- although it's non-final -- both the RI and Android
// have [different] package-private abstract methods you'd need to implement but can't.)
//assertFalse(out.hasArray());
encoder.encode(CharBuffer.wrap("x"), out, true);
// check whether the second decode corrupted the first buffer
assertEquals('a', buffer[0]);
assertEquals('b', buffer[1]);
assertEquals(0, buffer[2]);
}
/* Checks for a buffer corruption that happens in ICU
* (CharsetEncoderICU) when an encode operation
* is done first with an in-buffer with hasArray()==true, and next with an in-buffer with
* hasArray()==false. In that situation ICU may overwrite the array of the first in-buffer.
*/
public void testEncoderInputBuffer() {
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
ByteBuffer out = ByteBuffer.wrap(new byte[10]);
char[] inArray = {'a', 'b'};
CharBuffer inWithArray = CharBuffer.wrap(inArray);
assertTrue(inWithArray.hasArray());
encoder.encode(inWithArray, out, false);
assertEquals('a', inArray[0]);
assertEquals('b', inArray[1]);
CharBuffer inWithoutArray = CharBuffer.wrap("x");
assertFalse(inWithoutArray.hasArray());
encoder.encode(inWithoutArray, out, true);
// check whether the second decode corrupted the first buffer
assertEquals('a', inArray[0]);
assertEquals('b', inArray[1]);
}
}