fix abused lengths (strings over 32768) for UTF-16 strings

This commit is contained in:
Connor Tumbleson 2014-02-09 18:48:40 -06:00
parent b1d1a0863d
commit ca314b9aae

View File

@ -21,6 +21,7 @@ import brut.util.ExtDataInput;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.*; import java.nio.charset.*;
import java.util.Arrays;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -52,9 +53,8 @@ public class StringBlock {
block.m_isUTF8 = (flags & UTF8_FLAG) != 0; block.m_isUTF8 = (flags & UTF8_FLAG) != 0;
block.m_stringOffsets = reader.readIntArray(stringCount); block.m_stringOffsets = reader.readIntArray(stringCount);
block.m_stringOwns = new int[stringCount]; block.m_stringOwns = new int[stringCount];
for (int i = 0; i < stringCount; i++) { Arrays.fill(block.m_stringOwns, -1);
block.m_stringOwns[i] = -1;
}
if (styleOffsetCount != 0) { if (styleOffsetCount != 0) {
block.m_styleOffsets = reader.readIntArray(styleOffsetCount); block.m_styleOffsets = reader.readIntArray(styleOffsetCount);
} }
@ -91,33 +91,20 @@ public class StringBlock {
* Returns raw string (without any styling information) at specified index. * Returns raw string (without any styling information) at specified index.
*/ */
public String getString(int index) { public String getString(int index) {
if (index < 0 || m_stringOffsets == null if (index < 0 || m_stringOffsets == null || index >= m_stringOffsets.length) {
|| index >= m_stringOffsets.length) {
return null; return null;
} }
int offset = m_stringOffsets[index]; int offset = m_stringOffsets[index];
int length; int length;
if (!m_isUTF8) { if (m_isUTF8) {
length = getShort(m_strings, offset) * 2; int[] val = getUtf8(m_strings, offset);
offset += 2; offset = val[0];
length = val[1];
} else { } else {
int val = m_strings[offset]; int[] val = getUtf16(m_strings, offset);
if ((val & 0x80) != 0) { offset += val[0];
offset += 2; length = val[1];
} else {
offset += 1;
}
val = m_strings[offset];
if ((val & 0x80) != 0) {
offset += 2;
} else {
offset += 1;
}
length = 0;
while (m_strings[offset + length] != 0) {
length++;
}
} }
return decodeString(offset, length); return decodeString(offset, length);
} }
@ -309,18 +296,39 @@ public class StringBlock {
} }
} }
private static final int[] getVarint(byte[] array, int offset) { private static final int[] getUtf8(byte[] array, int offset) {
int val = array[offset]; int val = array[offset];
boolean more = (val & 0x80) != 0; int length;
val &= 0x7f;
if (!more) { if ((val & 0x80) != 0) {
return new int[] { val, 1 }; offset += 2;
} else { } else {
return new int[] { val << 8 | array[offset + 1] & 0xff, 2 }; offset += 1;
} }
val = array[offset];
if ((val & 0x80) != 0) {
offset += 2;
} else {
offset += 1;
}
length = 0;
while (array[offset + length] != 0) {
length++;
}
return new int[] { offset, length};
} }
private static final int[] getUtf16(byte[] array, int offset) {
int val = ((array[offset + 1] & 0xFF) << 8 | array[offset] & 0xFF);
if (val == 0x8000) {
int high = (array[offset + 3] & 0xFF) << 8;
int low = (array[offset + 2] & 0xFF);
return new int[] {4, (high + low) * 2};
}
return new int[] {2, val * 2};
}
private int[] m_stringOffsets; private int[] m_stringOffsets;
private byte[] m_strings; private byte[] m_strings;
private int[] m_styleOffsets; private int[] m_styleOffsets;
@ -333,6 +341,8 @@ public class StringBlock {
.newDecoder(); .newDecoder();
private static final Logger LOGGER = Logger.getLogger(StringBlock.class private static final Logger LOGGER = Logger.getLogger(StringBlock.class
.getName()); .getName());
// ResChunk_header = header.type (0x0001) + header.headerSize (0x001C)
private static final int CHUNK_TYPE = 0x001C0001; private static final int CHUNK_TYPE = 0x001C0001;
private static final int UTF8_FLAG = 0x00000100; private static final int UTF8_FLAG = 0x00000100;
} }