Skip to content

Commit 718af32

Browse files
krutonAndroid (Google) Code Review
authored andcommitted
Merge "Use long instead of int for file offsets" into jb-dev
2 parents 7d45704 + 103d530 commit 718af32

File tree

4 files changed

+63
-28
lines changed

4 files changed

+63
-28
lines changed

core/java/android/content/pm/ContainerEncryptionParams.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,16 @@ public class ContainerEncryptionParams implements Parcelable {
7070
private final byte[] mMacTag;
7171

7272
/** Offset into file where authenticated (e.g., MAC protected) data begins. */
73-
private final int mAuthenticatedDataStart;
73+
private final long mAuthenticatedDataStart;
7474

7575
/** Offset into file where encrypted data begins. */
76-
private final int mEncryptedDataStart;
76+
private final long mEncryptedDataStart;
7777

7878
/**
7979
* Offset into file for the end of encrypted data (and, by extension,
8080
* authenticated data) in file.
8181
*/
82-
private final int mDataEnd;
82+
private final long mDataEnd;
8383

8484
public ContainerEncryptionParams(String encryptionAlgorithm,
8585
AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
@@ -99,6 +99,8 @@ public ContainerEncryptionParams(String encryptionAlgorithm,
9999
* @param macAlgorithm MAC algorithm to use; format matches JCE
100100
* @param macSpec algorithm parameters specification, may be {@code null}
101101
* @param macKey key used for authentication (i.e., for the MAC tag)
102+
* @param macTag message authentication code (MAC) tag for the authenticated
103+
* data
102104
* @param authenticatedDataStart offset of start of authenticated data in
103105
* stream
104106
* @param encryptedDataStart offset of start of encrypted data in stream
@@ -109,7 +111,7 @@ public ContainerEncryptionParams(String encryptionAlgorithm,
109111
public ContainerEncryptionParams(String encryptionAlgorithm,
110112
AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
111113
AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
112-
int authenticatedDataStart, int encryptedDataStart, int dataEnd)
114+
long authenticatedDataStart, long encryptedDataStart, long dataEnd)
113115
throws InvalidAlgorithmParameterException {
114116
if (TextUtils.isEmpty(encryptionAlgorithm)) {
115117
throw new NullPointerException("algorithm == null");
@@ -172,15 +174,15 @@ public byte[] getMacTag() {
172174
return mMacTag;
173175
}
174176

175-
public int getAuthenticatedDataStart() {
177+
public long getAuthenticatedDataStart() {
176178
return mAuthenticatedDataStart;
177179
}
178180

179-
public int getEncryptedDataStart() {
181+
public long getEncryptedDataStart() {
180182
return mEncryptedDataStart;
181183
}
182184

183-
public int getDataEnd() {
185+
public long getDataEnd() {
184186
return mDataEnd;
185187
}
186188

@@ -315,9 +317,9 @@ public void writeToParcel(Parcel dest, int flags) {
315317

316318
dest.writeByteArray(mMacTag);
317319

318-
dest.writeInt(mAuthenticatedDataStart);
319-
dest.writeInt(mEncryptedDataStart);
320-
dest.writeInt(mDataEnd);
320+
dest.writeLong(mAuthenticatedDataStart);
321+
dest.writeLong(mEncryptedDataStart);
322+
dest.writeLong(mDataEnd);
321323
}
322324

323325
private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
@@ -333,9 +335,9 @@ private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParamete
333335

334336
mMacTag = source.createByteArray();
335337

336-
mAuthenticatedDataStart = source.readInt();
337-
mEncryptedDataStart = source.readInt();
338-
mDataEnd = source.readInt();
338+
mAuthenticatedDataStart = source.readLong();
339+
mEncryptedDataStart = source.readLong();
340+
mDataEnd = source.readLong();
339341

340342
switch (encParamType) {
341343
case ENC_PARAMS_IV_PARAMETERS:

core/java/android/content/pm/LimitedLengthInputStream.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.FilterInputStream;
44
import java.io.IOException;
55
import java.io.InputStream;
6+
import java.util.Arrays;
67

78
/**
89
* A class that limits the amount of data that is read from an InputStream. When
@@ -15,32 +16,36 @@ public class LimitedLengthInputStream extends FilterInputStream {
1516
/**
1617
* The end of the stream where we don't want to allow more data to be read.
1718
*/
18-
private final int mEnd;
19+
private final long mEnd;
1920

2021
/**
2122
* Current offset in the stream.
2223
*/
23-
private int mOffset;
24+
private long mOffset;
2425

2526
/**
2627
* @param in underlying stream to wrap
2728
* @param offset offset into stream where data starts
2829
* @param length length of data at offset
29-
* @throws IOException if an error occured with the underlying stream
30+
* @throws IOException if an error occurred with the underlying stream
3031
*/
31-
public LimitedLengthInputStream(InputStream in, int offset, int length) throws IOException {
32+
public LimitedLengthInputStream(InputStream in, long offset, long length) throws IOException {
3233
super(in);
3334

3435
if (in == null) {
3536
throw new IOException("in == null");
3637
}
3738

3839
if (offset < 0) {
39-
throw new IOException("offset == " + offset);
40+
throw new IOException("offset < 0");
4041
}
4142

4243
if (length < 0) {
43-
throw new IOException("length must be non-negative; is " + length);
44+
throw new IOException("length < 0");
45+
}
46+
47+
if (length > Long.MAX_VALUE - offset) {
48+
throw new IOException("offset + length > Long.MAX_VALUE");
4449
}
4550

4651
mEnd = offset + length;
@@ -65,8 +70,15 @@ public int read(byte[] buffer, int offset, int byteCount) throws IOException {
6570
return -1;
6671
}
6772

73+
final int arrayLength = buffer.length;
74+
Arrays.checkOffsetAndCount(arrayLength, offset, byteCount);
75+
76+
if (mOffset > Long.MAX_VALUE - byteCount) {
77+
throw new IOException("offset out of bounds: " + mOffset + " + " + byteCount);
78+
}
79+
6880
if (mOffset + byteCount > mEnd) {
69-
byteCount = mEnd - mOffset;
81+
byteCount = (int) (mEnd - mOffset);
7082
}
7183

7284
final int numRead = super.read(buffer, offset, byteCount);

core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,17 @@ public void testConstructor_NullInputStream_Failure() throws Exception {
6666
}
6767
}
6868

69+
@MediumTest
70+
public void testConstructor_OffsetLengthOverflow_Fail() throws Exception {
71+
try {
72+
InputStream is = new LimitedLengthInputStream(mTestStream1, Long.MAX_VALUE - 1,
73+
Long.MAX_VALUE - 1);
74+
fail("Should fail when offset + length is > Long.MAX_VALUE");
75+
} catch (IOException e) {
76+
// success
77+
}
78+
}
79+
6980
private void checkReadBytesWithOffsetAndLength_WithString1(int offset, int length)
7081
throws Exception {
7182
byte[] temp = new byte[TEST_STRING1.length];
@@ -182,5 +193,4 @@ public void testSingleByteRead_ZeroOffset_FullLength_Success() throws Exception
182193
public void testSingleByteRead_NonZeroOffset_FullLength_Success() throws Exception {
183194
checkSingleByteRead_WithString1(3, TEST_STRING1.length - 3);
184195
}
185-
186196
}

packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ private void copyFile(Uri pPackageURI, OutputStream outStream,
473473
}
474474

475475
private static class ApkContainer {
476+
private static final int MAX_AUTHENTICATED_DATA_SIZE = 16384;
477+
476478
private final InputStream mInStream;
477479

478480
private MacAuthenticatedInputStream mAuthenticatedStream;
@@ -540,26 +542,35 @@ private InputStream getDecryptedStream(InputStream inStream,
540542
throw new IOException(e);
541543
}
542544

543-
final int encStart = encryptionParams.getEncryptedDataStart();
544-
final int end = encryptionParams.getDataEnd();
545+
final long encStart = encryptionParams.getEncryptedDataStart();
546+
final long end = encryptionParams.getDataEnd();
545547
if (end < encStart) {
546548
throw new IOException("end <= encStart");
547549
}
548550

549551
final Mac mac = getMacInstance(encryptionParams);
550552
if (mac != null) {
551-
final int macStart = encryptionParams.getAuthenticatedDataStart();
553+
final long macStart = encryptionParams.getAuthenticatedDataStart();
554+
if (macStart >= Integer.MAX_VALUE) {
555+
throw new IOException("macStart >= Integer.MAX_VALUE");
556+
}
552557

553-
final int furtherOffset;
558+
final long furtherOffset;
554559
if (macStart >= 0 && encStart >= 0 && macStart < encStart) {
555560
/*
556561
* If there is authenticated data at the beginning, read
557562
* that into our MAC first.
558563
*/
559-
final int authenticatedLength = encStart - macStart;
560-
final byte[] authenticatedData = new byte[authenticatedLength];
564+
final long authenticatedLengthLong = encStart - macStart;
565+
if (authenticatedLengthLong > MAX_AUTHENTICATED_DATA_SIZE) {
566+
throw new IOException("authenticated data is too long");
567+
}
568+
final int authenticatedLength = (int) authenticatedLengthLong;
569+
570+
final byte[] authenticatedData = new byte[(int) authenticatedLength];
561571

562-
Streams.readFully(inStream, authenticatedData, macStart, authenticatedLength);
572+
Streams.readFully(inStream, authenticatedData, (int) macStart,
573+
authenticatedLength);
563574
mac.update(authenticatedData, 0, authenticatedLength);
564575

565576
furtherOffset = 0;

0 commit comments

Comments
 (0)