Merge "Avoid infinite loop for invalid XML format" into sc-dev

This commit is contained in:
Seigo Nonaka
2021-03-04 02:31:25 +00:00
committed by Android (Google) Code Review
2 changed files with 119 additions and 4 deletions

View File

@@ -26,6 +26,8 @@ import static android.text.FontConfig.FontFamily.VARIANT_ELEGANT;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static junit.framework.Assert.fail;
import android.graphics.fonts.FontStyle;
import android.os.LocaleList;
import android.text.FontConfig;
@@ -44,6 +46,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@@ -221,9 +224,113 @@ public final class FontListParserTest {
.that(readFamily(serialized)).isEqualTo(expected);
}
@Test
public void invalidXml_unpaired_family() throws Exception {
String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<familyset>"
+ " <family name='sans-serif'>"
+ " <font index='0'>test.ttc</font>"
+ "</familyset>";
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
FontListParser.parse(is);
fail();
} catch (IOException | XmlPullParserException e) {
// pass
}
}
@Test
public void invalidXml_unpaired_font() throws Exception {
String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<familyset>"
+ " <family name='sans-serif'>"
+ " <font index='0'>test.ttc"
+ " </family>"
+ "</familyset>";
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
FontListParser.parse(is);
fail();
} catch (IOException | XmlPullParserException e) {
// pass
}
}
@Test
public void invalidXml_unpaired_axis() throws Exception {
String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<familyset>"
+ " <family name='sans-serif'>"
+ " <font index='0'>test.ttc"
+ " <axis tag=\"wght\" styleValue=\"0\" >"
+ " </font>"
+ " </family>"
+ "</familyset>";
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
FontListParser.parse(is);
fail();
} catch (IOException | XmlPullParserException e) {
// pass
}
}
@Test
public void invalidXml_unclosed_family() throws Exception {
String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<familyset>"
+ " <family name='sans-serif'"
+ " <font index='0'>test.ttc</font>"
+ " </family>"
+ "</familyset>";
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
FontListParser.parse(is);
fail();
} catch (IOException | XmlPullParserException e) {
// pass
}
}
@Test
public void invalidXml_unclosed_font() throws Exception {
String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<familyset>"
+ " <family name='sans-serif'>"
+ " <font index='0'"
+ " </family>"
+ "</familyset>";
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
FontListParser.parse(is);
fail();
} catch (IOException | XmlPullParserException e) {
// pass
}
}
@Test
public void invalidXml_unclosed_axis() throws Exception {
String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+ "<familyset>"
+ " <family name='sans-serif'>"
+ " <font index='0'>test.ttc"
+ " <axis tag=\"wght\" styleValue=\"0\""
+ " </font>"
+ " </family>"
+ "</familyset>";
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8))) {
FontListParser.parse(is);
fail();
} catch (IOException | XmlPullParserException e) {
// pass
}
}
private FontConfig.FontFamily readFamily(String xml)
throws IOException, XmlPullParserException {
StandardCharsets.UTF_8.name();
ByteArrayInputStream buffer = new ByteArrayInputStream(
xml.getBytes(StandardCharsets.UTF_8));
XmlPullParser parser = Xml.newPullParser();

View File

@@ -136,7 +136,7 @@ public class FontListParser {
customization.getAdditionalNamedFamilies();
parser.require(XmlPullParser.START_TAG, null, "familyset");
while (parser.next() != XmlPullParser.END_TAG) {
while (keepReading(parser)) {
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
String tag = parser.getName();
if (tag.equals("family")) {
@@ -158,6 +158,12 @@ public class FontListParser {
return new FontConfig(families, aliases, lastModifiedDate, configVersion);
}
private static boolean keepReading(XmlPullParser parser)
throws XmlPullParserException, IOException {
int next = parser.next();
return next != XmlPullParser.END_TAG && next != XmlPullParser.END_DOCUMENT;
}
/**
* Read family tag in fonts.xml or oem_customization.xml
*/
@@ -168,7 +174,7 @@ public class FontListParser {
final String lang = parser.getAttributeValue("", "lang");
final String variant = parser.getAttributeValue(null, "variant");
final List<FontConfig.Font> fonts = new ArrayList<>();
while (parser.next() != XmlPullParser.END_TAG) {
while (keepReading(parser)) {
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
final String tag = parser.getName();
if (tag.equals(TAG_FONT)) {
@@ -232,7 +238,7 @@ public class FontListParser {
boolean isItalic = STYLE_ITALIC.equals(parser.getAttributeValue(null, ATTR_STYLE));
String fallbackFor = parser.getAttributeValue(null, ATTR_FALLBACK_FOR);
StringBuilder filename = new StringBuilder();
while (parser.next() != XmlPullParser.END_TAG) {
while (keepReading(parser)) {
if (parser.getEventType() == XmlPullParser.TEXT) {
filename.append(parser.getText());
}
@@ -359,6 +365,8 @@ public class FontListParser {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.END_DOCUMENT:
return;
}
}
}