Try to create Typeface before writing to config file

This is additional guard for preventing unusable font files for update.

Bug: 187542525
Test: atest FontFamilyUpdateRequestTest
Test: atest FontListParserTest
Test: atest FontManagerTest
Test: atest NativeSystemFontTest
Test: atest PersistentSystemFontConfigTest
Test: atest SystemFontsTest
Test: atest SystemFontsUniqueNameTest
Test: atest UpdatableFontDirTest
Test: atest UpdatableSystemFontTest
Change-Id: I61060e19e0e8c9b1ee992ab85eb93562ea823e5e
This commit is contained in:
Seigo Nonaka
2021-05-10 11:06:47 -07:00
parent 048fc0ae1a
commit 4f136b5c2d
3 changed files with 72 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontFileUtil;
import android.graphics.fonts.FontManager;
@@ -194,6 +195,13 @@ public final class FontManagerService extends IFontManager.Stub {
}
}
@Override
public void tryToCreateTypeface(File file) throws IOException {
Font font = new Font.Builder(file).build();
FontFamily family = new FontFamily.Builder(font).build();
new Typeface.CustomFallbackBuilder(family).build();
}
private static ByteBuffer mmap(File file) throws IOException {
try (FileInputStream in = new FileInputStream(file)) {
FileChannel fileChannel = in.getChannel();

View File

@@ -68,6 +68,8 @@ final class UpdatableFontDir {
String buildFontFileName(File file) throws IOException;
long getRevision(File file) throws IOException;
void tryToCreateTypeface(File file) throws IOException;
}
/** Interface to mock fs-verity in tests. */
@@ -372,6 +374,16 @@ final class UpdatableFontDir {
"Failed to change mode to 711", e);
}
FontFileInfo fontFileInfo = validateFontFile(newFontFile);
// Try to create Typeface and treat as failure something goes wrong.
try {
mParser.tryToCreateTypeface(fontFileInfo.getFile());
} catch (IOException e) {
throw new SystemFontException(
FontManager.RESULT_ERROR_INVALID_FONT_FILE,
"Failed to create Typeface from file", e);
}
FontConfig fontConfig = getSystemFontConfig();
if (!addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, false)) {
throw new SystemFontException(

View File

@@ -90,6 +90,10 @@ public final class UpdatableFontDirTest {
String content = FileUtils.readTextFile(file, 100, "");
return Long.parseLong(content.split(",")[1]);
}
@Override
public void tryToCreateTypeface(File file) throws IOException {
}
}
// FakeFsverityUtil will successfully set up fake fs-verity if the signature is GOOD_SIGNATURE.
@@ -717,6 +721,10 @@ public final class UpdatableFontDirTest {
public long getRevision(File file) throws IOException {
return 0;
}
@Override
public void tryToCreateTypeface(File file) throws IOException {
}
}, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
@@ -751,6 +759,50 @@ public final class UpdatableFontDirTest {
public long getRevision(File file) throws IOException {
return 0;
}
@Override
public void tryToCreateTypeface(File file) throws IOException {
}
}, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();
try {
dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1,foo",
GOOD_SIGNATURE)));
fail("Expect SystemFontException");
} catch (FontManagerService.SystemFontException e) {
assertThat(e.getErrorCode())
.isEqualTo(FontManager.RESULT_ERROR_INVALID_FONT_FILE);
}
assertThat(dir.getPostScriptMap()).isEmpty();
}
@Test
public void installFontFile_failedToCreateTypeface() throws Exception {
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
FakeFontFileParser parser = new FakeFontFileParser();
UpdatableFontDir dir = new UpdatableFontDir(
mUpdatableFontFilesDir,
new UpdatableFontDir.FontFileParser() {
@Override
public String getPostScriptName(File file) throws IOException {
return parser.getPostScriptName(file);
}
@Override
public String buildFontFileName(File file) throws IOException {
return parser.buildFontFileName(file);
}
@Override
public long getRevision(File file) throws IOException {
return parser.getRevision(file);
}
@Override
public void tryToCreateTypeface(File file) throws IOException {
throw new IOException();
}
}, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
dir.loadFontFileMap();