View Javadoc
1   /*
2    * Copyright (C) 2010, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.http.test;
12  
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertTrue;
15  
16  import java.io.ByteArrayOutputStream;
17  import java.io.IOException;
18  import java.io.InputStream;
19  import java.io.OutputStream;
20  import java.net.HttpURLConnection;
21  import java.net.URL;
22  
23  import javax.servlet.http.HttpServletRequest;
24  
25  import org.eclipse.jetty.servlet.ServletContextHandler;
26  import org.eclipse.jetty.servlet.ServletHolder;
27  import org.eclipse.jgit.errors.RepositoryNotFoundException;
28  import org.eclipse.jgit.http.server.GitServlet;
29  import org.eclipse.jgit.http.server.GitSmartHttpTools;
30  import org.eclipse.jgit.internal.JGitText;
31  import org.eclipse.jgit.junit.TestRepository;
32  import org.eclipse.jgit.junit.http.HttpTestCase;
33  import org.eclipse.jgit.lib.Constants;
34  import org.eclipse.jgit.lib.ObjectId;
35  import org.eclipse.jgit.lib.Repository;
36  import org.eclipse.jgit.lib.StoredConfig;
37  import org.eclipse.jgit.revwalk.RevBlob;
38  import org.eclipse.jgit.transport.PacketLineIn;
39  import org.eclipse.jgit.transport.PacketLineOut;
40  import org.eclipse.jgit.transport.URIish;
41  import org.eclipse.jgit.util.NB;
42  import org.junit.Before;
43  import org.junit.Test;
44  
45  public class ProtocolErrorTest extends HttpTestCase {
46  	private Repository remoteRepository;
47  
48  	private URIish remoteURI;
49  
50  	private RevBlob a_blob;
51  
52  	@Override
53  	@Before
54  	public void setUp() throws Exception {
55  		super.setUp();
56  
57  		final TestRepository<Repository> src = createTestRepository();
58  		final String srcName = src.getRepository().getDirectory().getName();
59  
60  		ServletContextHandler app = server.addContext("/git");
61  		GitServlet gs = new GitServlet();
62  		gs.setRepositoryResolver((HttpServletRequest req, String name) -> {
63  			if (!name.equals(srcName)) {
64  				throw new RepositoryNotFoundException(name);
65  			}
66  			final Repository db = src.getRepository();
67  			db.incrementOpen();
68  			return db;
69  		});
70  		app.addServlet(new ServletHolder(gs), "/*");
71  
72  		server.setUp();
73  
74  		remoteRepository = src.getRepository();
75  		remoteURI = toURIish(app, srcName);
76  
77  		StoredConfig cfg = remoteRepository.getConfig();
78  		cfg.setBoolean("http", null, "receivepack", true);
79  		cfg.save();
80  
81  		a_blob = src.blob("a");
82  	}
83  
84  	@Test
85  	public void testPush_UnpackError_TruncatedPack() throws Exception {
86  		StringBuilder sb = new StringBuilder();
87  		sb.append(ObjectId.zeroId().name());
88  		sb.append(' ');
89  		sb.append(a_blob.name());
90  		sb.append(' ');
91  		sb.append("refs/objects/A");
92  		sb.append('\0');
93  		sb.append("report-status");
94  
95  		ByteArrayOutputStream reqbuf = new ByteArrayOutputStream();
96  		PacketLineOut reqpck = new PacketLineOut(reqbuf);
97  		reqpck.writeString(sb.toString());
98  		reqpck.end();
99  
100 		packHeader(reqbuf, 1);
101 
102 		byte[] reqbin = reqbuf.toByteArray();
103 
104 		URL u = new URL(remoteURI.toString() + "/git-receive-pack");
105 		HttpURLConnection c = (HttpURLConnection) u.openConnection();
106 		try {
107 			c.setRequestMethod("POST");
108 			c.setDoOutput(true);
109 			c.setRequestProperty("Content-Type",
110 					GitSmartHttpTools.RECEIVE_PACK_REQUEST_TYPE);
111 			c.setFixedLengthStreamingMode(reqbin.length);
112 			try (OutputStream out = c.getOutputStream()) {
113 				out.write(reqbin);
114 			}
115 
116 			assertEquals(200, c.getResponseCode());
117 			assertEquals(GitSmartHttpTools.RECEIVE_PACK_RESULT_TYPE,
118 					c.getContentType());
119 
120 			try (InputStream rawin = c.getInputStream()) {
121 				PacketLineIn pckin = new PacketLineIn(rawin);
122 				assertEquals("unpack error "
123 						+ JGitText.get().packfileIsTruncatedNoParam,
124 						pckin.readString());
125 				assertEquals("ng refs/objects/A n/a (unpacker error)",
126 						pckin.readString());
127 				assertTrue(PacketLineIn.isEnd(pckin.readString()));
128 			}
129 		} finally {
130 			c.disconnect();
131 		}
132 	}
133 
134 	private static void packHeader(ByteArrayOutputStream tinyPack, int cnt)
135 			throws IOException {
136 		final byte[] hdr = new byte[8];
137 		NB.encodeInt32(hdr, 0, 2);
138 		NB.encodeInt32(hdr, 4, cnt);
139 
140 		tinyPack.write(Constants.PACK_SIGNATURE);
141 		tinyPack.write(hdr, 0, 8);
142 	}
143 }