Merge "Simplify handling of steps in DecoderChainSpec"

main
Jean Chalard 2014-10-24 03:50:46 +00:00 committed by Android (Google) Code Review
commit 40c11fdbff
2 changed files with 28 additions and 14 deletions

View File

@ -45,26 +45,37 @@ public final class BinaryDictOffdeviceUtils {
private final static String PREFIX = "dicttool"; private final static String PREFIX = "dicttool";
private final static String SUFFIX = ".tmp"; private final static String SUFFIX = ".tmp";
public final static String COMPRESSION = "compressed";
public final static String ENCRYPTION = "encrypted";
private final static int MAX_DECODE_DEPTH = 8;
private final static int COPY_BUFFER_SIZE = 8192; private final static int COPY_BUFFER_SIZE = 8192;
public static class DecoderChainSpec { public static class DecoderChainSpec {
ArrayList<String> mDecoderSpec = new ArrayList<>(); public final static int COMPRESSION = 1;
public final static int ENCRYPTION = 2;
private final static int MAX_DECODE_DEPTH = 4;
ArrayList<Integer> mDecoderSpec = new ArrayList<>();
File mFile; File mFile;
public DecoderChainSpec addStep(final String stepDescription) { public DecoderChainSpec addStep(final int stepDescription) {
mDecoderSpec.add(stepDescription); mDecoderSpec.add(stepDescription);
return this; return this;
} }
private String getStepDescription(final int step) {
switch (step) {
case COMPRESSION:
return "compression";
case ENCRYPTION:
return "encryption";
default:
return "unknown";
}
}
public String describeChain() { public String describeChain() {
final StringBuilder s = new StringBuilder("raw"); final StringBuilder s = new StringBuilder("raw");
for (final String step : mDecoderSpec) { for (final int step : mDecoderSpec) {
s.append(" > "); s.append(" > ");
s.append(step); s.append(getStepDescription(step));
} }
return s.toString(); return s.toString();
} }
@ -91,11 +102,13 @@ public final class BinaryDictOffdeviceUtils {
private static DecoderChainSpec getRawDictionaryOrNullInternal( private static DecoderChainSpec getRawDictionaryOrNullInternal(
final DecoderChainSpec spec, final File src, final int depth) { final DecoderChainSpec spec, final File src, final int depth) {
// Unfortunately the decoding scheme we use can consider any data to be encrypted // Unfortunately the decoding scheme we use can consider any data to be encrypted
// and will product some output, meaning it's not possible to reliably detect encrypted // and will produce some output, meaning it's not possible to reliably detect encrypted
// data. Thus, some non-dictionary files (especially small) ones may successfully decrypt // data. Thus, some non-dictionary files (especially small) ones may successfully decrypt
// over and over, ending in a stack overflow. Hence we limit the depth at which we try // over and over, ending in a stack overflow. Hence we limit the depth at which we try
// decoding the file. // decoding the file.
if (depth > MAX_DECODE_DEPTH) return null; if (depth > DecoderChainSpec.MAX_DECODE_DEPTH) {
return null;
}
if (BinaryDictDecoderUtils.isBinaryDictionary(src) if (BinaryDictDecoderUtils.isBinaryDictionary(src)
|| CombinedInputOutput.isCombinedDictionary(src.getAbsolutePath())) { || CombinedInputOutput.isCombinedDictionary(src.getAbsolutePath())) {
spec.mFile = src; spec.mFile = src;
@ -107,7 +120,7 @@ public final class BinaryDictOffdeviceUtils {
final DecoderChainSpec newSpec = final DecoderChainSpec newSpec =
getRawDictionaryOrNullInternal(spec, uncompressedFile, depth + 1); getRawDictionaryOrNullInternal(spec, uncompressedFile, depth + 1);
if (null == newSpec) return null; if (null == newSpec) return null;
return newSpec.addStep(COMPRESSION); return newSpec.addStep(DecoderChainSpec.COMPRESSION);
} }
// It's not a compressed either - try to see if it's crypted. // It's not a compressed either - try to see if it's crypted.
final File decryptedFile = tryGetDecryptedFile(src); final File decryptedFile = tryGetDecryptedFile(src);
@ -115,7 +128,7 @@ public final class BinaryDictOffdeviceUtils {
final DecoderChainSpec newSpec = final DecoderChainSpec newSpec =
getRawDictionaryOrNullInternal(spec, decryptedFile, depth + 1); getRawDictionaryOrNullInternal(spec, decryptedFile, depth + 1);
if (null == newSpec) return null; if (null == newSpec) return null;
return newSpec.addStep(ENCRYPTION); return newSpec.addStep(DecoderChainSpec.ENCRYPTION);
} }
return null; return null;
} }

View File

@ -78,8 +78,9 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
// Test for an actually compressed dictionary and its contents // Test for an actually compressed dictionary and its contents
final BinaryDictOffdeviceUtils.DecoderChainSpec decodeSpec = final BinaryDictOffdeviceUtils.DecoderChainSpec decodeSpec =
BinaryDictOffdeviceUtils.getRawDictionaryOrNull(dst); BinaryDictOffdeviceUtils.getRawDictionaryOrNull(dst);
for (final String step : decodeSpec.mDecoderSpec) { for (final int step : decodeSpec.mDecoderSpec) {
assertEquals("Wrong decode spec", BinaryDictOffdeviceUtils.COMPRESSION, step); assertEquals("Wrong decode spec",
BinaryDictOffdeviceUtils.DecoderChainSpec.COMPRESSION, step);
} }
assertEquals("Wrong decode spec", 3, decodeSpec.mDecoderSpec.size()); assertEquals("Wrong decode spec", 3, decodeSpec.mDecoderSpec.size());
final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(decodeSpec.mFile, 0, final DictDecoder dictDecoder = BinaryDictIOUtils.getDictDecoder(decodeSpec.mFile, 0,