Cleanup after dicttool
Arrange for temporary files to be deleted. Also, add a security on stack overflows. Change-Id: I9da2ebefb06409a71b235243ea835ce10d6a9b81main
parent
ee0b5488b5
commit
a8058d169d
|
@ -50,6 +50,8 @@ public final class BinaryDictOffdeviceUtils {
|
||||||
public final static String COMPRESSION = "compressed";
|
public final static String COMPRESSION = "compressed";
|
||||||
public final static String ENCRYPTION = "encrypted";
|
public final static String ENCRYPTION = "encrypted";
|
||||||
|
|
||||||
|
private final static int MAX_DECODE_DEPTH = 8;
|
||||||
|
|
||||||
public static class DecoderChainSpec {
|
public static class DecoderChainSpec {
|
||||||
ArrayList<String> mDecoderSpec = new ArrayList<String>();
|
ArrayList<String> mDecoderSpec = new ArrayList<String>();
|
||||||
File mFile;
|
File mFile;
|
||||||
|
@ -85,12 +87,17 @@ public final class BinaryDictOffdeviceUtils {
|
||||||
* If this is not a binary dictionary, the method returns null.
|
* If this is not a binary dictionary, the method returns null.
|
||||||
*/
|
*/
|
||||||
public static DecoderChainSpec getRawBinaryDictionaryOrNull(final File src) {
|
public static DecoderChainSpec getRawBinaryDictionaryOrNull(final File src) {
|
||||||
return getRawBinaryDictionaryOrNullInternal(new DecoderChainSpec(), src);
|
return getRawBinaryDictionaryOrNullInternal(new DecoderChainSpec(), src, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DecoderChainSpec getRawBinaryDictionaryOrNullInternal(
|
private static DecoderChainSpec getRawBinaryDictionaryOrNullInternal(
|
||||||
final DecoderChainSpec spec, final File src) {
|
final DecoderChainSpec spec, final File src, final int depth) {
|
||||||
// TODO: arrange for the intermediary files to be deleted
|
// 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
|
||||||
|
// 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
|
||||||
|
// decoding the file.
|
||||||
|
if (depth > MAX_DECODE_DEPTH) return null;
|
||||||
if (BinaryDictInputOutput.isBinaryDictionary(src)) {
|
if (BinaryDictInputOutput.isBinaryDictionary(src)) {
|
||||||
spec.mFile = src;
|
spec.mFile = src;
|
||||||
return spec;
|
return spec;
|
||||||
|
@ -99,7 +106,7 @@ public final class BinaryDictOffdeviceUtils {
|
||||||
final File uncompressedFile = tryGetUncompressedFile(src);
|
final File uncompressedFile = tryGetUncompressedFile(src);
|
||||||
if (null != uncompressedFile) {
|
if (null != uncompressedFile) {
|
||||||
final DecoderChainSpec newSpec =
|
final DecoderChainSpec newSpec =
|
||||||
getRawBinaryDictionaryOrNullInternal(spec, uncompressedFile);
|
getRawBinaryDictionaryOrNullInternal(spec, uncompressedFile, depth + 1);
|
||||||
if (null == newSpec) return null;
|
if (null == newSpec) return null;
|
||||||
return newSpec.addStep(COMPRESSION);
|
return newSpec.addStep(COMPRESSION);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +114,7 @@ public final class BinaryDictOffdeviceUtils {
|
||||||
final File decryptedFile = tryGetDecryptedFile(src);
|
final File decryptedFile = tryGetDecryptedFile(src);
|
||||||
if (null != decryptedFile) {
|
if (null != decryptedFile) {
|
||||||
final DecoderChainSpec newSpec =
|
final DecoderChainSpec newSpec =
|
||||||
getRawBinaryDictionaryOrNullInternal(spec, decryptedFile);
|
getRawBinaryDictionaryOrNullInternal(spec, decryptedFile, depth + 1);
|
||||||
if (null == newSpec) return null;
|
if (null == newSpec) return null;
|
||||||
return newSpec.addStep(ENCRYPTION);
|
return newSpec.addStep(ENCRYPTION);
|
||||||
}
|
}
|
||||||
|
@ -122,6 +129,7 @@ public final class BinaryDictOffdeviceUtils {
|
||||||
private static File tryGetUncompressedFile(final File src) {
|
private static File tryGetUncompressedFile(final File src) {
|
||||||
try {
|
try {
|
||||||
final File dst = File.createTempFile(PREFIX, SUFFIX);
|
final File dst = File.createTempFile(PREFIX, SUFFIX);
|
||||||
|
dst.deleteOnExit();
|
||||||
final FileOutputStream dstStream = new FileOutputStream(dst);
|
final FileOutputStream dstStream = new FileOutputStream(dst);
|
||||||
copy(Compress.getUncompressedStream(new BufferedInputStream(new FileInputStream(src))),
|
copy(Compress.getUncompressedStream(new BufferedInputStream(new FileInputStream(src))),
|
||||||
new BufferedOutputStream(dstStream)); // #copy() closes the streams
|
new BufferedOutputStream(dstStream)); // #copy() closes the streams
|
||||||
|
@ -140,12 +148,13 @@ public final class BinaryDictOffdeviceUtils {
|
||||||
private static File tryGetDecryptedFile(final File src) {
|
private static File tryGetDecryptedFile(final File src) {
|
||||||
try {
|
try {
|
||||||
final File dst = File.createTempFile(PREFIX, SUFFIX);
|
final File dst = File.createTempFile(PREFIX, SUFFIX);
|
||||||
|
dst.deleteOnExit();
|
||||||
final FileOutputStream dstStream = new FileOutputStream(dst);
|
final FileOutputStream dstStream = new FileOutputStream(dst);
|
||||||
copy(Crypt.getDecryptedStream(new BufferedInputStream(new FileInputStream(src))),
|
copy(Crypt.getDecryptedStream(new BufferedInputStream(new FileInputStream(src))),
|
||||||
dstStream); // #copy() closes the streams
|
dstStream); // #copy() closes the streams
|
||||||
return dst;
|
return dst;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Could not uncompress the file: presumably the file is simply not a compressed file
|
// Could not decrypt the file: presumably the file is simply not a crypted file
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class Info extends Dicttool.Command {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getHelp() {
|
public String getHelp() {
|
||||||
return COMMAND + "<filename>: prints various information about a dictionary file";
|
return COMMAND + " <filename>: prints various information about a dictionary file";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void showInfo(final FusionDictionary dict) {
|
private static void showInfo(final FusionDictionary dict) {
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
|
||||||
dict.add("fool", 1, null, false /* isNotAWord */);
|
dict.add("fool", 1, null, false /* isNotAWord */);
|
||||||
|
|
||||||
final File dst = File.createTempFile("testGetRawDict", ".tmp");
|
final File dst = File.createTempFile("testGetRawDict", ".tmp");
|
||||||
|
dst.deleteOnExit();
|
||||||
final OutputStream out = Compress.getCompressedStream(
|
final OutputStream out = Compress.getCompressedStream(
|
||||||
Compress.getCompressedStream(
|
Compress.getCompressedStream(
|
||||||
Compress.getCompressedStream(
|
Compress.getCompressedStream(
|
||||||
|
@ -81,6 +82,7 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
|
||||||
public void testGetRawDictFails() throws IOException {
|
public void testGetRawDictFails() throws IOException {
|
||||||
// Randomly create some 4k file containing garbage
|
// Randomly create some 4k file containing garbage
|
||||||
final File dst = File.createTempFile("testGetRawDict", ".tmp");
|
final File dst = File.createTempFile("testGetRawDict", ".tmp");
|
||||||
|
dst.deleteOnExit();
|
||||||
final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst));
|
final OutputStream out = new BufferedOutputStream(new FileOutputStream(dst));
|
||||||
for (int i = 0; i < 1024; ++i) {
|
for (int i = 0; i < 1024; ++i) {
|
||||||
out.write(0x12345678);
|
out.write(0x12345678);
|
||||||
|
@ -92,6 +94,7 @@ public class BinaryDictOffdeviceUtilsTests extends TestCase {
|
||||||
BinaryDictOffdeviceUtils.getRawBinaryDictionaryOrNull(dst));
|
BinaryDictOffdeviceUtils.getRawBinaryDictionaryOrNull(dst));
|
||||||
|
|
||||||
final File gzDst = File.createTempFile("testGetRawDict", ".tmp");
|
final File gzDst = File.createTempFile("testGetRawDict", ".tmp");
|
||||||
|
gzDst.deleteOnExit();
|
||||||
final OutputStream gzOut =
|
final OutputStream gzOut =
|
||||||
Compress.getCompressedStream(new BufferedOutputStream(new FileOutputStream(gzDst)));
|
Compress.getCompressedStream(new BufferedOutputStream(new FileOutputStream(gzDst)));
|
||||||
for (int i = 0; i < 1024; ++i) {
|
for (int i = 0; i < 1024; ++i) {
|
||||||
|
|
Loading…
Reference in New Issue