Skip to content

Commit ad4ff2a

Browse files
committed
New static field STRICT_MODE added which allows to only log minor data
format violations instead of aborting with a RuntimeException (see #716)
1 parent 47c2872 commit ad4ff2a

File tree

1 file changed

+72
-24
lines changed

1 file changed

+72
-24
lines changed

soot-infoflow-android/src/soot/jimple/infoflow/android/resources/ARSCFileParser.java

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.io.IOException;
1515
import java.io.InputStream;
1616
import java.math.BigInteger;
17+
import java.nio.charset.StandardCharsets;
1718
import java.util.ArrayList;
1819
import java.util.Arrays;
1920
import java.util.Collection;
@@ -38,6 +39,15 @@
3839
*/
3940
public class ARSCFileParser extends AbstractResourceParser {
4041

42+
/**
43+
* If <code>true</code> any encountered resource format violation like reserved
44+
* fields which should be zero but have a value will raise an
45+
* {@link RuntimeException}.
46+
*
47+
* If <code>false</code> format violations will only be logged as errors.
48+
*/
49+
public static boolean STRICT_MODE = true;
50+
4151
protected final Logger logger = LoggerFactory.getLogger(getClass());
4252

4353
protected final static int RES_STRING_POOL_TYPE = 0x0001;
@@ -1438,13 +1448,13 @@ protected static class ResTable_TypeSpec {
14381448
*/
14391449
int id; // uint8
14401450
/**
1441-
* Must be 0 (solid) or 1 (sparse).
1451+
* Must be 0
14421452
*/
1443-
int flags; // uint8
1453+
int res0; // uint8
14441454
/**
14451455
* Must be 1.
14461456
*/
1447-
int reserved; // uint16
1457+
int res1; // uint16
14481458
/**
14491459
* Number of uint32_t entry configuration masks that follow.
14501460
*/
@@ -1457,8 +1467,8 @@ public int hashCode() {
14571467
result = prime * result + entryCount;
14581468
result = prime * result + ((header == null) ? 0 : header.hashCode());
14591469
result = prime * result + id;
1460-
result = prime * result + flags;
1461-
result = prime * result + reserved;
1470+
result = prime * result + res0;
1471+
result = prime * result + res1;
14621472
return result;
14631473
}
14641474

@@ -1480,9 +1490,9 @@ public boolean equals(Object obj) {
14801490
return false;
14811491
if (id != other.id)
14821492
return false;
1483-
if (flags != other.flags)
1493+
if (res0 != other.res0)
14841494
return false;
1485-
if (reserved != other.reserved)
1495+
if (res1 != other.res1)
14861496
return false;
14871497
return true;
14881498
}
@@ -2137,8 +2147,7 @@ private void readResourceHeader(InputStream stream) throws IOException {
21372147
packageTable.header = nextChunkHeader;
21382148
offset = parsePackageTable(packageTable, remainingData, offset);
21392149

2140-
logger.debug(
2141-
String.format("\tPackage %s id=%d name=%s", packageCtr, packageTable.id, packageTable.name));
2150+
logger.debug("\tPackage {} id={} name={}", packageCtr, packageTable.id, packageTable.name);
21422151

21432152
// Record the end of the object to know then to stop looking for
21442153
// internal records
@@ -2272,7 +2281,7 @@ private void readResourceHeader(InputStream stream) throws IOException {
22722281
ResTable_Map map = new ResTable_Map();
22732282
entryOffset = readComplexValue(map, remainingData, entryOffset);
22742283

2275-
final String mapName = map.name + "";
2284+
final String mapName = Integer.toString(map.name);
22762285
AbstractResource value = parseValue(map.value);
22772286

22782287
// If we are dealing with an array, we put it into a special array container
@@ -2438,8 +2447,9 @@ private int readValue(Res_Value val, byte[] remainingData, int offset) throws IO
24382447
return 0;
24392448

24402449
val.res0 = readUInt8(remainingData, offset);
2441-
if (val.res0 != 0)
2442-
throw new RuntimeException("File format error, res0 was not zero");
2450+
if (val.res0 != 0) {
2451+
raiseFormatViolationIssue("File format violation: res0 is not zero", offset);
2452+
}
24432453
offset += 1;
24442454

24452455
val.dataType = readUInt8(remainingData, offset);
@@ -2484,18 +2494,35 @@ else if (size == 0x10)
24842494
return entry;
24852495
}
24862496

2497+
/**
2498+
* Parse data struct <code>ResTable_type</code> as defined in AOSP
2499+
* https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/include/androidfw/ResourceTypes.h
2500+
*
2501+
* Also parses subsequent config table.
2502+
*
2503+
* @param typeTable
2504+
* @param data
2505+
* @param offset
2506+
* @return
2507+
* @throws IOException
2508+
*/
24872509
private int readTypeTable(ResTable_Type typeTable, byte[] data, int offset) throws IOException {
24882510
typeTable.id = readUInt8(data, offset);
2511+
if (typeTable.id == 0) {
2512+
raiseFormatViolationIssue("File format violation in type table: id is zero", offset);
2513+
}
24892514
offset += 1;
24902515

24912516
typeTable.flags = readUInt8(data, offset);
2492-
if (typeTable.flags != 0 && typeTable.flags != 1)
2493-
throw new RuntimeException("File format error, flags is not zero or one");
2517+
if (typeTable.flags != 0 && typeTable.flags != 1) {
2518+
raiseFormatViolationIssue("File format violation in type table: flags is not zero or one", offset);
2519+
}
24942520
offset += 1;
24952521

24962522
typeTable.reserved = readUInt16(data, offset);
2497-
if (typeTable.reserved != 0)
2498-
throw new RuntimeException("File format error, reserved was not zero");
2523+
if (typeTable.reserved != 0) {
2524+
raiseFormatViolationIssue("File format violation in type table: reserved is not zero", offset);
2525+
}
24992526
offset += 2;
25002527

25012528
typeTable.entryCount = readUInt32(data, offset);
@@ -2600,19 +2627,34 @@ private int readConfigTable(ResTable_Config config, byte[] data, int offset) thr
26002627
return offset;
26012628
}
26022629

2630+
/**
2631+
* Parse data struct <code>ResTable_typeSpec</code> as defined in AOSP
2632+
* https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/include/androidfw/ResourceTypes.h
2633+
*
2634+
* @param typeSpecTable
2635+
* @param data
2636+
* @param offset
2637+
* @return
2638+
* @throws IOException
2639+
*/
26032640
private int readTypeSpecTable(ResTable_TypeSpec typeSpecTable, byte[] data, int offset) throws IOException {
26042641
typeSpecTable.id = readUInt8(data, offset);
2642+
if (typeSpecTable.id == 0) {
2643+
raiseFormatViolationIssue("File format violation in type spec table: id is zero", offset);
2644+
}
26052645
offset += 1;
26062646

2607-
typeSpecTable.flags = readUInt8(data, offset);
2647+
typeSpecTable.res0 = readUInt8(data, offset);
2648+
if (typeSpecTable.res0 != 0) {
2649+
raiseFormatViolationIssue("File format violation in type spec table: res0 is not zero", offset);
2650+
}
26082651
offset += 1;
2609-
if (typeSpecTable.flags != 0)
2610-
throw new RuntimeException("File format violation, res0 was not zero");
26112652

2612-
typeSpecTable.reserved = readUInt16(data, offset);
2653+
typeSpecTable.res1 = readUInt16(data, offset);
2654+
if (typeSpecTable.res1 != 0) {
2655+
raiseFormatViolationIssue("File format violation in type spec table: res1 is not zero", offset);
2656+
}
26132657
offset += 2;
2614-
if (typeSpecTable.reserved != 0)
2615-
throw new RuntimeException("File format violation, res1 was not zero");
26162658

26172659
typeSpecTable.entryCount = readUInt32(data, offset);
26182660
offset += 4;
@@ -2674,7 +2716,7 @@ private String readString(byte[] remainingData, int stringIdx) throws IOExceptio
26742716
stringIdx += 2;
26752717
byte[] str = new byte[strLen * 2];
26762718
System.arraycopy(remainingData, stringIdx, str, 0, strLen * 2);
2677-
return new String(remainingData, stringIdx, strLen * 2, "UTF-16LE");
2719+
return new String(remainingData, stringIdx, strLen * 2, StandardCharsets.UTF_16LE);
26782720
}
26792721

26802722
private String readStringUTF8(byte[] remainingData, int stringIdx) throws IOException {
@@ -2683,7 +2725,7 @@ private String readStringUTF8(byte[] remainingData, int stringIdx) throws IOExce
26832725
// the length here is somehow weird
26842726
int strLen = readUInt8(remainingData, stringIdx + 1);
26852727
stringIdx += 2;
2686-
String str = new String(remainingData, stringIdx, strLen, "UTF-8");
2728+
String str = new String(remainingData, stringIdx, strLen, StandardCharsets.UTF_8);
26872729
return str;
26882730
}
26892731

@@ -2944,4 +2986,10 @@ public void addAll(ARSCFileParser otherParser) {
29442986
stringTable.putAll(otherParser.stringTable);
29452987
}
29462988

2989+
protected void raiseFormatViolationIssue(String message, int offset) {
2990+
if (STRICT_MODE) {
2991+
throw new RuntimeException(String.format("%s offset=0x%x", message, offset));
2992+
}
2993+
logger.error("{} offset=0x{}", message, Integer.toHexString(offset));
2994+
}
29472995
}

0 commit comments

Comments
 (0)