@ -97,6 +97,7 @@ import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevSort ;
import org.eclipse.jgit.revwalk.RevSort ;
import org.eclipse.jgit.revwalk.RevTree ;
import org.eclipse.jgit.revwalk.RevTree ;
import org.eclipse.jgit.revwalk.RevWalk ;
import org.eclipse.jgit.revwalk.RevWalk ;
import org.eclipse.jgit.transport.PacketLineIn.InputOverLimitIOException ;
import org.eclipse.jgit.transport.ReceiveCommand.Result ;
import org.eclipse.jgit.transport.ReceiveCommand.Result ;
import org.eclipse.jgit.util.io.InterruptTimer ;
import org.eclipse.jgit.util.io.InterruptTimer ;
import org.eclipse.jgit.util.io.LimitedInputStream ;
import org.eclipse.jgit.util.io.LimitedInputStream ;
@ -244,6 +245,8 @@ public abstract class BaseReceivePack {
String userAgent ;
String userAgent ;
private Set < ObjectId > clientShallowCommits ;
private Set < ObjectId > clientShallowCommits ;
private List < ReceiveCommand > commands ;
private List < ReceiveCommand > commands ;
private long maxCommandBytes ;
private long maxDiscardBytes ;
private StringBuilder advertiseError ;
private StringBuilder advertiseError ;
@ -318,6 +321,8 @@ public abstract class BaseReceivePack {
allowNonFastForwards = rc . allowNonFastForwards ;
allowNonFastForwards = rc . allowNonFastForwards ;
allowOfsDelta = rc . allowOfsDelta ;
allowOfsDelta = rc . allowOfsDelta ;
allowPushOptions = rc . allowPushOptions ;
allowPushOptions = rc . allowPushOptions ;
maxCommandBytes = rc . maxCommandBytes ;
maxDiscardBytes = rc . maxDiscardBytes ;
advertiseRefsHook = AdvertiseRefsHook . DEFAULT ;
advertiseRefsHook = AdvertiseRefsHook . DEFAULT ;
refFilter = RefFilter . DEFAULT ;
refFilter = RefFilter . DEFAULT ;
advertisedHaves = new HashSet < ObjectId > ( ) ;
advertisedHaves = new HashSet < ObjectId > ( ) ;
@ -338,7 +343,8 @@ public abstract class BaseReceivePack {
final boolean allowNonFastForwards ;
final boolean allowNonFastForwards ;
final boolean allowOfsDelta ;
final boolean allowOfsDelta ;
final boolean allowPushOptions ;
final boolean allowPushOptions ;
final long maxCommandBytes ;
final long maxDiscardBytes ;
final SignedPushConfig signedPush ;
final SignedPushConfig signedPush ;
ReceiveConfig ( final Config config ) {
ReceiveConfig ( final Config config ) {
@ -350,6 +356,12 @@ public abstract class BaseReceivePack {
true ) ;
true ) ;
allowPushOptions = config . getBoolean ( "receive" , "pushoptions" , //$NON-NLS-1$ //$NON-NLS-2$
allowPushOptions = config . getBoolean ( "receive" , "pushoptions" , //$NON-NLS-1$ //$NON-NLS-2$
false ) ;
false ) ;
maxCommandBytes = config . getLong ( "receive" , //$NON-NLS-1$
"maxCommandBytes" , //$NON-NLS-1$
3 < < 20 ) ;
maxDiscardBytes = config . getLong ( "receive" , //$NON-NLS-1$
"maxCommandDiscardBytes" , //$NON-NLS-1$
- 1 ) ;
signedPush = SignedPushConfig . KEY . parse ( config ) ;
signedPush = SignedPushConfig . KEY . parse ( config ) ;
}
}
}
}
@ -728,6 +740,38 @@ public abstract class BaseReceivePack {
timeout = seconds ;
timeout = seconds ;
}
}
/ * *
* Set the maximum number of command bytes to read from the client .
*
* @param limit
* command limit in bytes ; if 0 there is no limit .
* @since 4 . 7
* /
public void setMaxCommandBytes ( long limit ) {
maxCommandBytes = limit ;
}
/ * *
* Set the maximum number of command bytes to discard from the client .
* < p >
* Discarding remaining bytes allows this instance to consume the rest of
* the command block and send a human readable over - limit error via the
* side - band channel . If the client sends an excessive number of bytes this
* limit kicks in and the instance disconnects , resulting in a non - specific
* ' pipe closed ' , ' end of stream ' , or similar generic error at the client .
* < p >
* When the limit is set to { @code - 1 } the implementation will default to
* the larger of { @code 3 * maxCommandBytes } or { @code 3 MiB } .
*
* @param limit
* discard limit in bytes ; if 0 there is no limit ; if - 1 the
* implementation tries to set a reasonable default .
* @since 4 . 7
* /
public void setMaxCommandDiscardBytes ( long limit ) {
maxDiscardBytes = limit ;
}
/ * *
/ * *
* Set the maximum allowed Git object size .
* Set the maximum allowed Git object size .
* < p >
* < p >
@ -741,7 +785,6 @@ public abstract class BaseReceivePack {
maxObjectSizeLimit = limit ;
maxObjectSizeLimit = limit ;
}
}
/ * *
/ * *
* Set the maximum allowed pack size .
* Set the maximum allowed pack size .
* < p >
* < p >
@ -1134,13 +1177,16 @@ public abstract class BaseReceivePack {
* @throws IOException
* @throws IOException
* /
* /
protected void recvCommands ( ) throws IOException {
protected void recvCommands ( ) throws IOException {
PacketLineIn pck = maxCommandBytes > 0
? new PacketLineIn ( rawIn , maxCommandBytes )
: pckIn ;
PushCertificateParser certParser = getPushCertificateParser ( ) ;
PushCertificateParser certParser = getPushCertificateParser ( ) ;
boolean firstPkt = true ;
boolean firstPkt = true ;
try {
try {
for ( ; ; ) {
for ( ; ; ) {
String line ;
String line ;
try {
try {
line = pckIn . readString ( ) ;
line = pck . readString ( ) ;
} catch ( EOFException eof ) {
} catch ( EOFException eof ) {
if ( commands . isEmpty ( ) )
if ( commands . isEmpty ( ) )
return ;
return ;
@ -1163,13 +1209,13 @@ public abstract class BaseReceivePack {
enableCapabilities ( ) ;
enableCapabilities ( ) ;
if ( line . equals ( GitProtocolConstants . OPTION_PUSH_CERT ) ) {
if ( line . equals ( GitProtocolConstants . OPTION_PUSH_CERT ) ) {
certParser . receiveHeader ( pckIn , ! isBiDirectionalPipe ( ) ) ;
certParser . receiveHeader ( pck , ! isBiDirectionalPipe ( ) ) ;
continue ;
continue ;
}
}
}
}
if ( line . equals ( PushCertificateParser . BEGIN_SIGNATURE ) ) {
if ( line . equals ( PushCertificateParser . BEGIN_SIGNATURE ) ) {
certParser . receiveSignature ( pckIn ) ;
certParser . receiveSignature ( pck ) ;
continue ;
continue ;
}
}
@ -1186,18 +1232,31 @@ public abstract class BaseReceivePack {
}
}
pushCert = certParser . build ( ) ;
pushCert = certParser . build ( ) ;
if ( hasCommands ( ) ) {
if ( hasCommands ( ) ) {
readPostCommands ( pckIn ) ;
readPostCommands ( pck ) ;
}
}
} catch ( PackProtocolException e ) {
} catch ( PackProtocolException e ) {
if ( sideBand ) {
discardCommands ( ) ;
try {
pckIn . discardUntilEnd ( ) ;
} catch ( IOException e2 ) {
// Ignore read failures attempting to discard.
}
}
fatalError ( e . getMessage ( ) ) ;
fatalError ( e . getMessage ( ) ) ;
throw e ;
throw e ;
} catch ( InputOverLimitIOException e ) {
String msg = JGitText . get ( ) . tooManyCommands ;
discardCommands ( ) ;
fatalError ( msg ) ;
throw new PackProtocolException ( msg ) ;
}
}
private void discardCommands ( ) {
if ( sideBand ) {
long max = maxDiscardBytes ;
if ( max < 0 ) {
max = Math . max ( 3 * maxCommandBytes , 3L < < 20 ) ;
}
try {
new PacketLineIn ( rawIn , max ) . discardUntilEnd ( ) ;
} catch ( IOException e ) {
// Ignore read failures attempting to discard.
}
}
}
}
}