diff options
author | Sasa Zivkov <sasa.zivkov@sap.com> | 2011-11-22 17:43:00 +0100 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2011-11-22 17:43:00 +0100 |
commit | 1fbe688f51cbc1d951dee5443ae0b9d801904c93 (patch) | |
tree | 912b539d82b7f2d089fd81478be83d8fe2e78347 /org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java | |
parent | 3ee3811afb4f1077c3c991a589e37725585c7e06 (diff) | |
download | jgit-1fbe688f51cbc1d951dee5443ae0b9d801904c93.tar.gz jgit-1fbe688f51cbc1d951dee5443ae0b9d801904c93.zip |
maxObjectSizeLimit for receive-pack.
ReceivePack (and PackParser) can be configured with the
maxObjectSizeLimit in order to prevent users from pushing too large
objects to Git. The limit check is applied to all object types
although it is most likely that a BLOB will exceed the limit. In all
cases the size of the object header is excluded from the object size
which is checked against the limit as this is the size of which a BLOB
object would take in the working tree when checked out as a file.
When an object exceeds the maxObjectSizeLimit the receive-pack will
abort immediately.
Delta objects (both offset and ref delta) are also checked against the
limit. However, for delta objects we will first check the size of the
inflated delta block against the maxObjectSizeLimit and abort
immediately if it exceeds the limit. In this case we even do not know
the exact size of the resolved delta object but we assume it will be
larger than the given maxObjectSizeLimit as delta is generally only
chosen if the delta can copy more data from the base object than the
delta needs to insert or needs to represent the copy ranges. Aborting
early, in this case, avoids unnecessary inflating of the (huge) delta
block.
Unfortunately, it is too expensive (especially for a large delta) to
compute SHA-1 of an object that causes the receive-pack to abort.
This would decrease the value of this feature whose main purpose is to
protect server resources from users pushing huge objects. Therefore
we don't report the SHA-1 in the error message.
Change-Id: I177ef24553faacda444ed5895e40ac8925ca0d1e
Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com>
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java | 46 |
1 files changed, 44 insertions, 2 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java index 1b30e859ec..c62959565f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java @@ -61,6 +61,7 @@ import java.util.zip.Inflater; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.errors.TooLargeObjectInPackException; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.BatchingProgressMonitor; import org.eclipse.jgit.lib.Constants; @@ -180,6 +181,9 @@ public abstract class PackParser { /** Message to protect the pack data from garbage collection. */ private String lockMessage; + /** Git object size limit */ + private long maxObjectSizeLimit; + /** * Initialize a pack parser. * @@ -366,6 +370,19 @@ public abstract class PackParser { } /** + * Set the maximum allowed Git object size. + * <p> + * If an object is larger than the given size the pack-parsing will throw an + * exception aborting the parsing. + * + * @param limit + * the Git object size limit. If zero then there is not limit. + */ + public void setMaxObjectSizeLimit(long limit) { + maxObjectSizeLimit = limit; + } + + /** * Get the number of objects in the stream. * <p> * The object count is only available after {@link #parse(ProgressMonitor)} @@ -584,8 +601,11 @@ public abstract class PackParser { JGitText.get().unknownObjectType, info.type)); } - visit.data = BinaryDelta.apply(visit.parent.data, // - inflateAndReturn(Source.DATABASE, info.size)); + byte[] delta = inflateAndReturn(Source.DATABASE, info.size); + checkIfTooLarge(type, BinaryDelta.getResultSize(delta)); + + visit.data = BinaryDelta.apply(visit.parent.data, delta); + delta = null; if (!checkCRC(visit.delta.crc)) throw new IOException(MessageFormat.format( @@ -613,6 +633,26 @@ public abstract class PackParser { } while (visit != null); } + private final void checkIfTooLarge(int typeCode, long size) + throws IOException { + if (0 < maxObjectSizeLimit && maxObjectSizeLimit < size) + switch (typeCode) { + case Constants.OBJ_COMMIT: + case Constants.OBJ_TREE: + case Constants.OBJ_BLOB: + case Constants.OBJ_TAG: + throw new TooLargeObjectInPackException(size, maxObjectSizeLimit); + + case Constants.OBJ_OFS_DELTA: + case Constants.OBJ_REF_DELTA: + throw new TooLargeObjectInPackException(maxObjectSizeLimit); + + default: + throw new IOException(MessageFormat.format( + JGitText.get().unknownObjectType, typeCode)); + } + } + /** * Read the header of the current object. * <p> @@ -856,6 +896,8 @@ public abstract class PackParser { shift += 7; } + checkIfTooLarge(typeCode, sz); + switch (typeCode) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: |