Loading tools/apksigner/core/src/com/android/apksigner/core/internal/util/ByteBufferDataSource.java +53 −21 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ import java.nio.ByteBuffer; public class ByteBufferDataSource implements DataSource { private final ByteBuffer mBuffer; private final long mSize; private final int mSize; /** * Constructs a new {@code ByteBufferDigestSource} based on the data contained in the provided Loading @@ -45,29 +45,39 @@ public class ByteBufferDataSource implements DataSource { } @Override public void feed(long offset, int size, DataSink sink) throws IOException { if (offset < 0) { throw new IllegalArgumentException("offset: " + offset); public ByteBufferDataSource slice(long offset, long size) { if ((offset == 0) && (size == mSize)) { return this; } if (size < 0) { throw new IllegalArgumentException("size: " + size); } if (offset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") > source size (" + mSize + ")"); } long endOffset = offset + size; if (endOffset < offset) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") overflow"); checkChunkValid(offset, size); // checkChunkValid ensures that it's OK to cast offset and size to int. int chunkPosition = (int) offset; int chunkLimit = (int) (chunkPosition + size); // Creating a slice of ByteBuffer modifies the state of the source ByteBuffer (position // and limit fields, to be more specific). We thus use synchronization around these // state-changing operations to make instances of this class thread-safe. synchronized (mBuffer) { // ByteBuffer.limit(int) and .position(int) check that that the position >= limit // invariant is not broken. Thus, the only way to safely change position and limit // without caring about their current values is to first set position to 0 or set the // limit to capacity. mBuffer.position(0); mBuffer.limit(chunkLimit); mBuffer.position(chunkPosition); // Create a ByteBufferDataSource for the slice of the buffer between limit and position. return new ByteBufferDataSource(mBuffer); } if (endOffset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") > source size (" + mSize +")"); } int chunkPosition = (int) offset; // safe to downcast because mSize <= Integer.MAX_VALUE int chunkLimit = (int) endOffset; // safe to downcast because mSize <= Integer.MAX_VALUE @Override public void feed(long offset, long size, DataSink sink) throws IOException { checkChunkValid(offset, size); // checkChunkValid ensures that it's OK to cast offset and size to int. int chunkPosition = (int) offset; int chunkLimit = (int) (chunkPosition + size); ByteBuffer chunk; // Creating a slice of ByteBuffer modifies the state of the source ByteBuffer (position // and limit fields, to be more specific). We thus use synchronization around these Loading @@ -86,4 +96,26 @@ public class ByteBufferDataSource implements DataSource { sink.consume(chunk); } private void checkChunkValid(long offset, long size) { if (offset < 0) { throw new IllegalArgumentException("offset: " + offset); } if (size < 0) { throw new IllegalArgumentException("size: " + size); } if (offset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") > source size (" + mSize + ")"); } long endOffset = offset + size; if (endOffset < offset) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") overflow"); } if (endOffset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") > source size (" + mSize +")"); } } } tools/apksigner/core/src/com/android/apksigner/core/util/DataSource.java +7 −1 Original line number Diff line number Diff line Loading @@ -43,5 +43,11 @@ public interface DataSource { * @param offset index (in bytes) at which the chunk starts inside data source * @param size size (in bytes) of the chunk */ void feed(long offset, int size, DataSink sink) throws IOException; void feed(long offset, long size, DataSink sink) throws IOException; /** * Returns a data source representing the specified region of data of this data source. Changes * to data represented by this data source will also be visible in the returned data source. */ DataSource slice(long offset, long size); } tools/apksigner/core/src/com/android/apksigner/core/util/DataSources.java +2 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,8 @@ public abstract class DataSources { /** * Returns a {@link DataSource} backed by the provided {@link ByteBuffer}. The data source * represents the data contained between the position and limit of the buffer. * represents the data contained between the position and limit of the buffer. Changes to the * buffer's contents will be visible in the data source. */ public static DataSource asDataSource(ByteBuffer buffer) { if (buffer == null) { Loading Loading
tools/apksigner/core/src/com/android/apksigner/core/internal/util/ByteBufferDataSource.java +53 −21 Original line number Diff line number Diff line Loading @@ -28,7 +28,7 @@ import java.nio.ByteBuffer; public class ByteBufferDataSource implements DataSource { private final ByteBuffer mBuffer; private final long mSize; private final int mSize; /** * Constructs a new {@code ByteBufferDigestSource} based on the data contained in the provided Loading @@ -45,29 +45,39 @@ public class ByteBufferDataSource implements DataSource { } @Override public void feed(long offset, int size, DataSink sink) throws IOException { if (offset < 0) { throw new IllegalArgumentException("offset: " + offset); public ByteBufferDataSource slice(long offset, long size) { if ((offset == 0) && (size == mSize)) { return this; } if (size < 0) { throw new IllegalArgumentException("size: " + size); } if (offset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") > source size (" + mSize + ")"); } long endOffset = offset + size; if (endOffset < offset) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") overflow"); checkChunkValid(offset, size); // checkChunkValid ensures that it's OK to cast offset and size to int. int chunkPosition = (int) offset; int chunkLimit = (int) (chunkPosition + size); // Creating a slice of ByteBuffer modifies the state of the source ByteBuffer (position // and limit fields, to be more specific). We thus use synchronization around these // state-changing operations to make instances of this class thread-safe. synchronized (mBuffer) { // ByteBuffer.limit(int) and .position(int) check that that the position >= limit // invariant is not broken. Thus, the only way to safely change position and limit // without caring about their current values is to first set position to 0 or set the // limit to capacity. mBuffer.position(0); mBuffer.limit(chunkLimit); mBuffer.position(chunkPosition); // Create a ByteBufferDataSource for the slice of the buffer between limit and position. return new ByteBufferDataSource(mBuffer); } if (endOffset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") > source size (" + mSize +")"); } int chunkPosition = (int) offset; // safe to downcast because mSize <= Integer.MAX_VALUE int chunkLimit = (int) endOffset; // safe to downcast because mSize <= Integer.MAX_VALUE @Override public void feed(long offset, long size, DataSink sink) throws IOException { checkChunkValid(offset, size); // checkChunkValid ensures that it's OK to cast offset and size to int. int chunkPosition = (int) offset; int chunkLimit = (int) (chunkPosition + size); ByteBuffer chunk; // Creating a slice of ByteBuffer modifies the state of the source ByteBuffer (position // and limit fields, to be more specific). We thus use synchronization around these Loading @@ -86,4 +96,26 @@ public class ByteBufferDataSource implements DataSource { sink.consume(chunk); } private void checkChunkValid(long offset, long size) { if (offset < 0) { throw new IllegalArgumentException("offset: " + offset); } if (size < 0) { throw new IllegalArgumentException("size: " + size); } if (offset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") > source size (" + mSize + ")"); } long endOffset = offset + size; if (endOffset < offset) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") overflow"); } if (endOffset > mSize) { throw new IllegalArgumentException( "offset (" + offset + ") + size (" + size + ") > source size (" + mSize +")"); } } }
tools/apksigner/core/src/com/android/apksigner/core/util/DataSource.java +7 −1 Original line number Diff line number Diff line Loading @@ -43,5 +43,11 @@ public interface DataSource { * @param offset index (in bytes) at which the chunk starts inside data source * @param size size (in bytes) of the chunk */ void feed(long offset, int size, DataSink sink) throws IOException; void feed(long offset, long size, DataSink sink) throws IOException; /** * Returns a data source representing the specified region of data of this data source. Changes * to data represented by this data source will also be visible in the returned data source. */ DataSource slice(long offset, long size); }
tools/apksigner/core/src/com/android/apksigner/core/util/DataSources.java +2 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,8 @@ public abstract class DataSources { /** * Returns a {@link DataSource} backed by the provided {@link ByteBuffer}. The data source * represents the data contained between the position and limit of the buffer. * represents the data contained between the position and limit of the buffer. Changes to the * buffer's contents will be visible in the data source. */ public static DataSource asDataSource(ByteBuffer buffer) { if (buffer == null) { Loading