1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 package org.eclipse.jgit.lib;
46
47 import static java.lang.Integer.valueOf;
48 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
49 import static org.eclipse.jgit.lib.Constants.OBJ_BAD;
50 import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
51 import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
52 import static org.eclipse.jgit.lib.Constants.OBJ_TAG;
53 import static org.eclipse.jgit.lib.Constants.OBJ_TREE;
54 import static org.eclipse.jgit.lib.Constants.encode;
55 import static org.eclipse.jgit.lib.Constants.encodeASCII;
56 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.DUPLICATE_ENTRIES;
57 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.EMPTY_NAME;
58 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.FULL_PATHNAME;
59 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.HAS_DOT;
60 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.HAS_DOTDOT;
61 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.HAS_DOTGIT;
62 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.NULL_SHA1;
63 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.TREE_NOT_SORTED;
64 import static org.eclipse.jgit.lib.ObjectChecker.ErrorType.ZERO_PADDED_FILEMODE;
65 import static org.junit.Assert.assertEquals;
66 import static org.junit.Assert.assertSame;
67 import static org.junit.Assert.fail;
68
69 import java.io.UnsupportedEncodingException;
70 import java.text.MessageFormat;
71
72 import org.eclipse.jgit.errors.CorruptObjectException;
73 import org.eclipse.jgit.internal.JGitText;
74 import org.junit.Before;
75 import org.junit.Test;
76
77 public class ObjectCheckerTest {
78 private ObjectChecker checker;
79
80 @Before
81 public void setUp() throws Exception {
82 checker = new ObjectChecker();
83 }
84
85 @Test
86 public void testInvalidType() {
87 String msg = MessageFormat.format(
88 JGitText.get().corruptObjectInvalidType2,
89 valueOf(OBJ_BAD));
90 assertCorrupt(msg, OBJ_BAD, new byte[0]);
91 }
92
93 @Test
94 public void testCheckBlob() throws CorruptObjectException {
95
96 checker.checkBlob(new byte[0]);
97 checker.checkBlob(new byte[1]);
98
99 checker.check(OBJ_BLOB, new byte[0]);
100 checker.check(OBJ_BLOB, new byte[1]);
101 }
102
103 @Test
104 public void testValidCommitNoParent() throws CorruptObjectException {
105 StringBuilder b = new StringBuilder();
106
107 b.append("tree ");
108 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
109 b.append('\n');
110
111 b.append("author A. U. Thor <author@localhost> 1 +0000\n");
112 b.append("committer A. U. Thor <author@localhost> 1 +0000\n");
113
114 byte[] data = encodeASCII(b.toString());
115 checker.checkCommit(data);
116 checker.check(OBJ_COMMIT, data);
117 }
118
119 @Test
120 public void testValidCommitBlankAuthor() throws CorruptObjectException {
121 StringBuilder b = new StringBuilder();
122
123 b.append("tree ");
124 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
125 b.append('\n');
126
127 b.append("author <> 0 +0000\n");
128 b.append("committer <> 0 +0000\n");
129
130 byte[] data = encodeASCII(b.toString());
131 checker.checkCommit(data);
132 checker.check(OBJ_COMMIT, data);
133 }
134
135 @Test
136 public void testCommitCorruptAuthor() throws CorruptObjectException {
137 StringBuilder b = new StringBuilder();
138 b.append("tree be9bfa841874ccc9f2ef7c48d0c76226f89b7189\n");
139 b.append("author b <b@c> <b@c> 0 +0000\n");
140 b.append("committer <> 0 +0000\n");
141
142 byte[] data = encodeASCII(b.toString());
143 assertCorrupt("bad date", OBJ_COMMIT, data);
144 checker.setAllowInvalidPersonIdent(true);
145 checker.checkCommit(data);
146
147 checker.setAllowInvalidPersonIdent(false);
148 assertSkipListAccepts(OBJ_COMMIT, data);
149 }
150
151 @Test
152 public void testCommitCorruptCommitter() throws CorruptObjectException {
153 StringBuilder b = new StringBuilder();
154 b.append("tree be9bfa841874ccc9f2ef7c48d0c76226f89b7189\n");
155 b.append("author <> 0 +0000\n");
156 b.append("committer b <b@c> <b@c> 0 +0000\n");
157
158 byte[] data = encodeASCII(b.toString());
159 assertCorrupt("bad date", OBJ_COMMIT, data);
160 checker.setAllowInvalidPersonIdent(true);
161 checker.checkCommit(data);
162
163 checker.setAllowInvalidPersonIdent(false);
164 assertSkipListAccepts(OBJ_COMMIT, data);
165 }
166
167 @Test
168 public void testValidCommit1Parent() throws CorruptObjectException {
169 StringBuilder b = new StringBuilder();
170
171 b.append("tree ");
172 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
173 b.append('\n');
174
175 b.append("parent ");
176 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
177 b.append('\n');
178
179 b.append("author A. U. Thor <author@localhost> 1 +0000\n");
180 b.append("committer A. U. Thor <author@localhost> 1 +0000\n");
181
182 byte[] data = encodeASCII(b.toString());
183 checker.checkCommit(data);
184 checker.check(OBJ_COMMIT, data);
185 }
186
187 @Test
188 public void testValidCommit2Parent() throws CorruptObjectException {
189 StringBuilder b = new StringBuilder();
190
191 b.append("tree ");
192 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
193 b.append('\n');
194
195 b.append("parent ");
196 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
197 b.append('\n');
198
199 b.append("parent ");
200 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
201 b.append('\n');
202
203 b.append("author A. U. Thor <author@localhost> 1 +0000\n");
204 b.append("committer A. U. Thor <author@localhost> 1 +0000\n");
205
206 byte[] data = encodeASCII(b.toString());
207 checker.checkCommit(data);
208 checker.check(OBJ_COMMIT, data);
209 }
210
211 @Test
212 public void testValidCommit128Parent() throws CorruptObjectException {
213 StringBuilder b = new StringBuilder();
214
215 b.append("tree ");
216 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
217 b.append('\n');
218
219 for (int i = 0; i < 128; i++) {
220 b.append("parent ");
221 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
222 b.append('\n');
223 }
224
225 b.append("author A. U. Thor <author@localhost> 1 +0000\n");
226 b.append("committer A. U. Thor <author@localhost> 1 +0000\n");
227
228 byte[] data = encodeASCII(b.toString());
229 checker.checkCommit(data);
230 checker.check(OBJ_COMMIT, data);
231 }
232
233 @Test
234 public void testValidCommitNormalTime() throws CorruptObjectException {
235 StringBuilder b = new StringBuilder();
236 String when = "1222757360 -0730";
237
238 b.append("tree ");
239 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
240 b.append('\n');
241
242 b.append("author A. U. Thor <author@localhost> " + when + "\n");
243 b.append("committer A. U. Thor <author@localhost> " + when + "\n");
244
245 byte[] data = encodeASCII(b.toString());
246 checker.checkCommit(data);
247 checker.check(OBJ_COMMIT, data);
248 }
249
250 @Test
251 public void testInvalidCommitNoTree1() {
252 StringBuilder b = new StringBuilder();
253 b.append("parent ");
254 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
255 b.append('\n');
256 assertCorrupt("no tree header", OBJ_COMMIT, b);
257 }
258
259 @Test
260 public void testInvalidCommitNoTree2() {
261 StringBuilder b = new StringBuilder();
262 b.append("trie ");
263 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
264 b.append('\n');
265 assertCorrupt("no tree header", OBJ_COMMIT, b);
266 }
267
268 @Test
269 public void testInvalidCommitNoTree3() {
270 StringBuilder b = new StringBuilder();
271 b.append("tree");
272 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
273 b.append('\n');
274 assertCorrupt("no tree header", OBJ_COMMIT, b);
275 }
276
277 @Test
278 public void testInvalidCommitNoTree4() {
279 StringBuilder b = new StringBuilder();
280 b.append("tree\t");
281 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
282 b.append('\n');
283 assertCorrupt("no tree header", OBJ_COMMIT, b);
284 }
285
286 @Test
287 public void testInvalidCommitInvalidTree1() {
288 StringBuilder b = new StringBuilder();
289 b.append("tree ");
290 b.append("zzzzfa841874ccc9f2ef7c48d0c76226f89b7189");
291 b.append('\n');
292 assertCorrupt("invalid tree", OBJ_COMMIT, b);
293 }
294
295 @Test
296 public void testInvalidCommitInvalidTree2() {
297 StringBuilder b = new StringBuilder();
298 b.append("tree ");
299 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
300 b.append("z\n");
301 assertCorrupt("invalid tree", OBJ_COMMIT, b);
302 }
303
304 @Test
305 public void testInvalidCommitInvalidTree3() {
306 StringBuilder b = new StringBuilder();
307 b.append("tree ");
308 b.append("be9b");
309 b.append("\n");
310
311 byte[] data = encodeASCII(b.toString());
312 assertCorrupt("invalid tree", OBJ_COMMIT, data);
313 }
314
315 @Test
316 public void testInvalidCommitInvalidTree4() {
317 StringBuilder b = new StringBuilder();
318 b.append("tree ");
319 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
320 b.append('\n');
321 assertCorrupt("invalid tree", OBJ_COMMIT, b);
322 }
323
324 @Test
325 public void testInvalidCommitInvalidParent1() {
326 StringBuilder b = new StringBuilder();
327 b.append("tree ");
328 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
329 b.append('\n');
330 b.append("parent ");
331 b.append("\n");
332 assertCorrupt("invalid parent", OBJ_COMMIT, b);
333 }
334
335 @Test
336 public void testInvalidCommitInvalidParent2() {
337 StringBuilder b = new StringBuilder();
338 b.append("tree ");
339 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
340 b.append('\n');
341 b.append("parent ");
342 b.append("zzzzfa841874ccc9f2ef7c48d0c76226f89b7189");
343 b.append("\n");
344 assertCorrupt("invalid parent", OBJ_COMMIT, b);
345 }
346
347 @Test
348 public void testInvalidCommitInvalidParent3() {
349 StringBuilder b = new StringBuilder();
350 b.append("tree ");
351 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
352 b.append('\n');
353 b.append("parent ");
354 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
355 b.append("\n");
356 assertCorrupt("invalid parent", OBJ_COMMIT, b);
357 }
358
359 @Test
360 public void testInvalidCommitInvalidParent4() {
361 StringBuilder b = new StringBuilder();
362 b.append("tree ");
363 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
364 b.append('\n');
365 b.append("parent ");
366 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
367 b.append("z\n");
368 assertCorrupt("invalid parent", OBJ_COMMIT, b);
369 }
370
371 @Test
372 public void testInvalidCommitInvalidParent5() {
373 StringBuilder b = new StringBuilder();
374 b.append("tree ");
375 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
376 b.append('\n');
377 b.append("parent\t");
378 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
379 b.append("\n");
380
381 byte[] data = encodeASCII(b.toString());
382
383
384 assertCorrupt("no author", OBJ_COMMIT, data);
385 }
386
387 @Test
388 public void testInvalidCommitNoAuthor() throws CorruptObjectException {
389 StringBuilder b = new StringBuilder();
390 b.append("tree ");
391 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
392 b.append('\n');
393 b.append("committer A. U. Thor <author@localhost> 1 +0000\n");
394
395 byte[] data = encodeASCII(b.toString());
396 assertCorrupt("no author", OBJ_COMMIT, data);
397 assertSkipListAccepts(OBJ_COMMIT, data);
398 }
399
400 @Test
401 public void testInvalidCommitNoCommitter1() throws CorruptObjectException {
402 StringBuilder b = new StringBuilder();
403 b.append("tree ");
404 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
405 b.append('\n');
406 b.append("author A. U. Thor <author@localhost> 1 +0000\n");
407
408 byte[] data = encodeASCII(b.toString());
409 assertCorrupt("no committer", OBJ_COMMIT, data);
410 assertSkipListAccepts(OBJ_COMMIT, data);
411 }
412
413 @Test
414 public void testInvalidCommitNoCommitter2() throws CorruptObjectException {
415 StringBuilder b = new StringBuilder();
416 b.append("tree ");
417 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
418 b.append('\n');
419 b.append("author A. U. Thor <author@localhost> 1 +0000\n");
420 b.append("\n");
421
422 byte[] data = encodeASCII(b.toString());
423 assertCorrupt("no committer", OBJ_COMMIT, data);
424 assertSkipListAccepts(OBJ_COMMIT, data);
425 }
426
427 @Test
428 public void testInvalidCommitInvalidAuthor1()
429 throws CorruptObjectException {
430 StringBuilder b = new StringBuilder();
431 b.append("tree ");
432 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
433 b.append('\n');
434 b.append("author A. U. Thor <foo 1 +0000\n");
435
436 byte[] data = encodeASCII(b.toString());
437 assertCorrupt("bad email", OBJ_COMMIT, data);
438 assertSkipListAccepts(OBJ_COMMIT, data);
439 }
440
441 @Test
442 public void testInvalidCommitInvalidAuthor2()
443 throws CorruptObjectException {
444 StringBuilder b = new StringBuilder();
445 b.append("tree ");
446 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
447 b.append('\n');
448 b.append("author A. U. Thor foo> 1 +0000\n");
449
450 byte[] data = encodeASCII(b.toString());
451 assertCorrupt("missing email", OBJ_COMMIT, data);
452 assertSkipListAccepts(OBJ_COMMIT, data);
453 }
454
455 @Test
456 public void testInvalidCommitInvalidAuthor3()
457 throws CorruptObjectException {
458 StringBuilder b = new StringBuilder();
459 b.append("tree ");
460 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
461 b.append('\n');
462 b.append("author 1 +0000\n");
463
464 byte[] data = encodeASCII(b.toString());
465 assertCorrupt("missing email", OBJ_COMMIT, data);
466 assertSkipListAccepts(OBJ_COMMIT, data);
467 }
468
469 @Test
470 public void testInvalidCommitInvalidAuthor4()
471 throws CorruptObjectException {
472 StringBuilder b = new StringBuilder();
473 b.append("tree ");
474 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
475 b.append('\n');
476 b.append("author a <b> +0000\n");
477
478 byte[] data = encodeASCII(b.toString());
479 assertCorrupt("bad date", OBJ_COMMIT, data);
480 assertSkipListAccepts(OBJ_COMMIT, data);
481 }
482
483 @Test
484 public void testInvalidCommitInvalidAuthor5()
485 throws CorruptObjectException {
486 StringBuilder b = new StringBuilder();
487 b.append("tree ");
488 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
489 b.append('\n');
490 b.append("author a <b>\n");
491
492 byte[] data = encodeASCII(b.toString());
493 assertCorrupt("bad date", OBJ_COMMIT, data);
494 assertSkipListAccepts(OBJ_COMMIT, data);
495 }
496
497 @Test
498 public void testInvalidCommitInvalidAuthor6()
499 throws CorruptObjectException {
500 StringBuilder b = new StringBuilder();
501 b.append("tree ");
502 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
503 b.append('\n');
504 b.append("author a <b> z");
505
506 byte[] data = encodeASCII(b.toString());
507 assertCorrupt("bad date", OBJ_COMMIT, data);
508 assertSkipListAccepts(OBJ_COMMIT, data);
509 }
510
511 @Test
512 public void testInvalidCommitInvalidAuthor7()
513 throws CorruptObjectException {
514 StringBuilder b = new StringBuilder();
515 b.append("tree ");
516 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
517 b.append('\n');
518 b.append("author a <b> 1 z");
519
520 byte[] data = encodeASCII(b.toString());
521 assertCorrupt("bad time zone", OBJ_COMMIT, data);
522 assertSkipListAccepts(OBJ_COMMIT, data);
523 }
524
525 @Test
526 public void testInvalidCommitInvalidCommitter()
527 throws CorruptObjectException {
528 StringBuilder b = new StringBuilder();
529 b.append("tree ");
530 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
531 b.append('\n');
532 b.append("author a <b> 1 +0000\n");
533 b.append("committer a <");
534
535 byte[] data = encodeASCII(b.toString());
536 assertCorrupt("bad email", OBJ_COMMIT, data);
537 assertSkipListAccepts(OBJ_COMMIT, data);
538 }
539
540 @Test
541 public void testValidTag() throws CorruptObjectException {
542 StringBuilder b = new StringBuilder();
543 b.append("object ");
544 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
545 b.append('\n');
546 b.append("type commit\n");
547 b.append("tag test-tag\n");
548 b.append("tagger A. U. Thor <author@localhost> 1 +0000\n");
549
550 byte[] data = encodeASCII(b.toString());
551 checker.checkTag(data);
552 checker.check(OBJ_TAG, data);
553 }
554
555 @Test
556 public void testInvalidTagNoObject1() {
557 assertCorrupt("no object header", OBJ_TAG, new byte[0]);
558 }
559
560 @Test
561 public void testInvalidTagNoObject2() {
562 StringBuilder b = new StringBuilder();
563 b.append("object\t");
564 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
565 b.append('\n');
566 assertCorrupt("no object header", OBJ_TAG, b);
567 }
568
569 @Test
570 public void testInvalidTagNoObject3() {
571 StringBuilder b = new StringBuilder();
572 b.append("obejct ");
573 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
574 b.append('\n');
575 assertCorrupt("no object header", OBJ_TAG, b);
576 }
577
578 @Test
579 public void testInvalidTagNoObject4() {
580 StringBuilder b = new StringBuilder();
581 b.append("object ");
582 b.append("zz9bfa841874ccc9f2ef7c48d0c76226f89b7189");
583 b.append('\n');
584 assertCorrupt("invalid object", OBJ_TAG, b);
585 }
586
587 @Test
588 public void testInvalidTagNoObject5() {
589 StringBuilder b = new StringBuilder();
590 b.append("object ");
591 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
592 b.append(" \n");
593 assertCorrupt("invalid object", OBJ_TAG, b);
594 }
595
596 @Test
597 public void testInvalidTagNoObject6() {
598 StringBuilder b = new StringBuilder();
599 b.append("object ");
600 b.append("be9");
601 assertCorrupt("invalid object", OBJ_TAG, b);
602 }
603
604 @Test
605 public void testInvalidTagNoType1() {
606 StringBuilder b = new StringBuilder();
607 b.append("object ");
608 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
609 b.append('\n');
610 assertCorrupt("no type header", OBJ_TAG, b);
611 }
612
613 @Test
614 public void testInvalidTagNoType2() {
615 StringBuilder b = new StringBuilder();
616 b.append("object ");
617 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
618 b.append('\n');
619 b.append("type\tcommit\n");
620 assertCorrupt("no type header", OBJ_TAG, b);
621 }
622
623 @Test
624 public void testInvalidTagNoType3() {
625 StringBuilder b = new StringBuilder();
626 b.append("object ");
627 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
628 b.append('\n');
629 b.append("tpye commit\n");
630 assertCorrupt("no type header", OBJ_TAG, b);
631 }
632
633 @Test
634 public void testInvalidTagNoType4() {
635 StringBuilder b = new StringBuilder();
636 b.append("object ");
637 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
638 b.append('\n');
639 b.append("type commit");
640 assertCorrupt("no tag header", OBJ_TAG, b);
641 }
642
643 @Test
644 public void testInvalidTagNoTagHeader1() {
645 StringBuilder b = new StringBuilder();
646 b.append("object ");
647 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
648 b.append('\n');
649 b.append("type commit\n");
650 assertCorrupt("no tag header", OBJ_TAG, b);
651 }
652
653 @Test
654 public void testInvalidTagNoTagHeader2() {
655 StringBuilder b = new StringBuilder();
656 b.append("object ");
657 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
658 b.append('\n');
659 b.append("type commit\n");
660 b.append("tag\tfoo\n");
661 assertCorrupt("no tag header", OBJ_TAG, b);
662 }
663
664 @Test
665 public void testInvalidTagNoTagHeader3() {
666 StringBuilder b = new StringBuilder();
667 b.append("object ");
668 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
669 b.append('\n');
670 b.append("type commit\n");
671 b.append("tga foo\n");
672 assertCorrupt("no tag header", OBJ_TAG, b);
673 }
674
675 @Test
676 public void testValidTagHasNoTaggerHeader() throws CorruptObjectException {
677 StringBuilder b = new StringBuilder();
678 b.append("object ");
679 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
680 b.append('\n');
681 b.append("type commit\n");
682 b.append("tag foo\n");
683 checker.checkTag(encodeASCII(b.toString()));
684 }
685
686 @Test
687 public void testInvalidTagInvalidTaggerHeader1()
688 throws CorruptObjectException {
689 StringBuilder b = new StringBuilder();
690 b.append("object ");
691 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
692 b.append('\n');
693 b.append("type commit\n");
694 b.append("tag foo\n");
695 b.append("tagger \n");
696
697 byte[] data = encodeASCII(b.toString());
698 assertCorrupt("missing email", OBJ_TAG, data);
699 checker.setAllowInvalidPersonIdent(true);
700 checker.checkTag(data);
701
702 checker.setAllowInvalidPersonIdent(false);
703 assertSkipListAccepts(OBJ_TAG, data);
704 }
705
706 @Test
707 public void testInvalidTagInvalidTaggerHeader3()
708 throws CorruptObjectException {
709 StringBuilder b = new StringBuilder();
710 b.append("object ");
711 b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189");
712 b.append('\n');
713 b.append("type commit\n");
714 b.append("tag foo\n");
715 b.append("tagger a < 1 +000\n");
716
717 byte[] data = encodeASCII(b.toString());
718 assertCorrupt("bad email", OBJ_TAG, data);
719 assertSkipListAccepts(OBJ_TAG, data);
720 }
721
722 @Test
723 public void testValidEmptyTree() throws CorruptObjectException {
724 checker.checkTree(new byte[0]);
725 checker.check(OBJ_TREE, new byte[0]);
726 }
727
728 @Test
729 public void testValidTree1() throws CorruptObjectException {
730 StringBuilder b = new StringBuilder();
731 entry(b, "100644 regular-file");
732 checker.checkTree(encodeASCII(b.toString()));
733 }
734
735 @Test
736 public void testValidTree2() throws CorruptObjectException {
737 StringBuilder b = new StringBuilder();
738 entry(b, "100755 executable");
739 checker.checkTree(encodeASCII(b.toString()));
740 }
741
742 @Test
743 public void testValidTree3() throws CorruptObjectException {
744 StringBuilder b = new StringBuilder();
745 entry(b, "40000 tree");
746 checker.checkTree(encodeASCII(b.toString()));
747 }
748
749 @Test
750 public void testValidTree4() throws CorruptObjectException {
751 StringBuilder b = new StringBuilder();
752 entry(b, "120000 symlink");
753 checker.checkTree(encodeASCII(b.toString()));
754 }
755
756 @Test
757 public void testValidTree5() throws CorruptObjectException {
758 StringBuilder b = new StringBuilder();
759 entry(b, "160000 git link");
760 checker.checkTree(encodeASCII(b.toString()));
761 }
762
763 @Test
764 public void testValidTree6() throws CorruptObjectException {
765 StringBuilder b = new StringBuilder();
766 entry(b, "100644 .a");
767 checker.checkTree(encodeASCII(b.toString()));
768 }
769
770 @Test
771 public void testNullSha1InTreeEntry() throws CorruptObjectException {
772 byte[] data = concat(
773 encodeASCII("100644 A"), new byte[] { '\0' },
774 new byte[OBJECT_ID_LENGTH]);
775 assertCorrupt("entry points to null SHA-1", OBJ_TREE, data);
776 assertSkipListAccepts(OBJ_TREE, data);
777 checker.setIgnore(NULL_SHA1, true);
778 checker.checkTree(data);
779 }
780
781 @Test
782 public void testValidPosixTree() throws CorruptObjectException {
783 checkOneName("a<b>c:d|e");
784 checkOneName("test ");
785 checkOneName("test.");
786 checkOneName("NUL");
787 }
788
789 @Test
790 public void testValidTreeSorting1() throws CorruptObjectException {
791 StringBuilder b = new StringBuilder();
792 entry(b, "100644 fooaaa");
793 entry(b, "100755 foobar");
794 checker.checkTree(encodeASCII(b.toString()));
795 }
796
797 @Test
798 public void testValidTreeSorting2() throws CorruptObjectException {
799 StringBuilder b = new StringBuilder();
800 entry(b, "100755 fooaaa");
801 entry(b, "100644 foobar");
802 checker.checkTree(encodeASCII(b.toString()));
803 }
804
805 @Test
806 public void testValidTreeSorting3() throws CorruptObjectException {
807 StringBuilder b = new StringBuilder();
808 entry(b, "40000 a");
809 entry(b, "100644 b");
810 checker.checkTree(encodeASCII(b.toString()));
811 }
812
813 @Test
814 public void testValidTreeSorting4() throws CorruptObjectException {
815 StringBuilder b = new StringBuilder();
816 entry(b, "100644 a");
817 entry(b, "40000 b");
818 checker.checkTree(encodeASCII(b.toString()));
819 }
820
821 @Test
822 public void testValidTreeSorting5() throws CorruptObjectException {
823 StringBuilder b = new StringBuilder();
824 entry(b, "100644 a.c");
825 entry(b, "40000 a");
826 entry(b, "100644 a0c");
827 checker.checkTree(encodeASCII(b.toString()));
828 }
829
830 @Test
831 public void testValidTreeSorting6() throws CorruptObjectException {
832 StringBuilder b = new StringBuilder();
833 entry(b, "40000 a");
834 entry(b, "100644 apple");
835 checker.checkTree(encodeASCII(b.toString()));
836 }
837
838 @Test
839 public void testValidTreeSorting7() throws CorruptObjectException {
840 StringBuilder b = new StringBuilder();
841 entry(b, "40000 an orang");
842 entry(b, "40000 an orange");
843 checker.checkTree(encodeASCII(b.toString()));
844 }
845
846 @Test
847 public void testValidTreeSorting8() throws CorruptObjectException {
848 StringBuilder b = new StringBuilder();
849 entry(b, "100644 a");
850 entry(b, "100644 a0c");
851 entry(b, "100644 b");
852 checker.checkTree(encodeASCII(b.toString()));
853 }
854
855 @Test
856 public void testAcceptTreeModeWithZero() throws CorruptObjectException {
857 StringBuilder b = new StringBuilder();
858 entry(b, "040000 a");
859 byte[] data = encodeASCII(b.toString());
860 checker.setAllowLeadingZeroFileMode(true);
861 checker.checkTree(data);
862
863 checker.setAllowLeadingZeroFileMode(false);
864 assertSkipListAccepts(OBJ_TREE, data);
865
866 checker.setIgnore(ZERO_PADDED_FILEMODE, true);
867 checker.checkTree(data);
868 }
869
870 @Test
871 public void testInvalidTreeModeStartsWithZero1() {
872 StringBuilder b = new StringBuilder();
873 entry(b, "0 a");
874 assertCorrupt("mode starts with '0'", OBJ_TREE, b);
875 }
876
877 @Test
878 public void testInvalidTreeModeStartsWithZero2() {
879 StringBuilder b = new StringBuilder();
880 entry(b, "0100644 a");
881 assertCorrupt("mode starts with '0'", OBJ_TREE, b);
882 }
883
884 @Test
885 public void testInvalidTreeModeStartsWithZero3() {
886 StringBuilder b = new StringBuilder();
887 entry(b, "040000 a");
888 assertCorrupt("mode starts with '0'", OBJ_TREE, b);
889 }
890
891 @Test
892 public void testInvalidTreeModeNotOctal1() {
893 StringBuilder b = new StringBuilder();
894 entry(b, "8 a");
895 assertCorrupt("invalid mode character", OBJ_TREE, b);
896 }
897
898 @Test
899 public void testInvalidTreeModeNotOctal2() {
900 StringBuilder b = new StringBuilder();
901 entry(b, "Z a");
902 byte[] data = encodeASCII(b.toString());
903 assertCorrupt("invalid mode character", OBJ_TREE, data);
904 assertSkipListRejects("invalid mode character", OBJ_TREE, data);
905 }
906
907 @Test
908 public void testInvalidTreeModeNotSupportedMode1() {
909 StringBuilder b = new StringBuilder();
910 entry(b, "1 a");
911 byte[] data = encodeASCII(b.toString());
912 assertCorrupt("invalid mode 1", OBJ_TREE, data);
913 assertSkipListRejects("invalid mode 1", OBJ_TREE, data);
914 }
915
916 @Test
917 public void testInvalidTreeModeNotSupportedMode2() {
918 StringBuilder b = new StringBuilder();
919 entry(b, "170000 a");
920 assertCorrupt("invalid mode " + 0170000, OBJ_TREE, b);
921 }
922
923 @Test
924 public void testInvalidTreeModeMissingName() {
925 StringBuilder b = new StringBuilder();
926 b.append("100644");
927 assertCorrupt("truncated in mode", OBJ_TREE, b);
928 }
929
930 @Test
931 public void testInvalidTreeNameContainsSlash()
932 throws CorruptObjectException {
933 StringBuilder b = new StringBuilder();
934 entry(b, "100644 a/b");
935 byte[] data = encodeASCII(b.toString());
936 assertCorrupt("name contains '/'", OBJ_TREE, data);
937 assertSkipListAccepts(OBJ_TREE, data);
938 checker.setIgnore(FULL_PATHNAME, true);
939 checker.checkTree(data);
940 }
941
942 @Test
943 public void testInvalidTreeNameIsEmpty() throws CorruptObjectException {
944 StringBuilder b = new StringBuilder();
945 entry(b, "100644 ");
946 byte[] data = encodeASCII(b.toString());
947 assertCorrupt("zero length name", OBJ_TREE, data);
948 assertSkipListAccepts(OBJ_TREE, data);
949 checker.setIgnore(EMPTY_NAME, true);
950 checker.checkTree(data);
951 }
952
953 @Test
954 public void testInvalidTreeNameIsDot() throws CorruptObjectException {
955 StringBuilder b = new StringBuilder();
956 entry(b, "100644 .");
957 byte[] data = encodeASCII(b.toString());
958 assertCorrupt("invalid name '.'", OBJ_TREE, data);
959 assertSkipListAccepts(OBJ_TREE, data);
960 checker.setIgnore(HAS_DOT, true);
961 checker.checkTree(data);
962 }
963
964 @Test
965 public void testInvalidTreeNameIsDotDot() throws CorruptObjectException {
966 StringBuilder b = new StringBuilder();
967 entry(b, "100644 ..");
968 byte[] data = encodeASCII(b.toString());
969 assertCorrupt("invalid name '..'", OBJ_TREE, data);
970 assertSkipListAccepts(OBJ_TREE, data);
971 checker.setIgnore(HAS_DOTDOT, true);
972 checker.checkTree(data);
973 }
974
975 @Test
976 public void testInvalidTreeNameIsGit() throws CorruptObjectException {
977 StringBuilder b = new StringBuilder();
978 entry(b, "100644 .git");
979 byte[] data = encodeASCII(b.toString());
980 assertCorrupt("invalid name '.git'", OBJ_TREE, data);
981 assertSkipListAccepts(OBJ_TREE, data);
982 checker.setIgnore(HAS_DOTGIT, true);
983 checker.checkTree(data);
984 }
985
986 @Test
987 public void testInvalidTreeNameIsMixedCaseGit()
988 throws CorruptObjectException {
989 StringBuilder b = new StringBuilder();
990 entry(b, "100644 .GiT");
991 byte[] data = encodeASCII(b.toString());
992 assertCorrupt("invalid name '.GiT'", OBJ_TREE, data);
993 assertSkipListAccepts(OBJ_TREE, data);
994 checker.setIgnore(HAS_DOTGIT, true);
995 checker.checkTree(data);
996 }
997
998 @Test
999 public void testInvalidTreeNameIsMacHFSGit() throws CorruptObjectException {
1000 StringBuilder b = new StringBuilder();
1001 entry(b, "100644 .gi\u200Ct");
1002 byte[] data = encode(b.toString());
1003
1004
1005 checker.checkTree(data);
1006
1007
1008 checker.setSafeForMacOS(true);
1009 assertCorrupt(
1010 "invalid name '.gi\u200Ct' contains ignorable Unicode characters",
1011 OBJ_TREE, data);
1012 assertSkipListAccepts(OBJ_TREE, data);
1013 checker.setIgnore(HAS_DOTGIT, true);
1014 checker.checkTree(data);
1015 }
1016
1017 @Test
1018 public void testInvalidTreeNameIsMacHFSGit2()
1019 throws CorruptObjectException {
1020 StringBuilder b = new StringBuilder();
1021 entry(b, "100644 \u206B.git");
1022 byte[] data = encode(b.toString());
1023
1024
1025 checker.checkTree(data);
1026
1027
1028 checker.setSafeForMacOS(true);
1029 assertCorrupt(
1030 "invalid name '\u206B.git' contains ignorable Unicode characters",
1031 OBJ_TREE, data);
1032 assertSkipListAccepts(OBJ_TREE, data);
1033 checker.setIgnore(HAS_DOTGIT, true);
1034 checker.checkTree(data);
1035 }
1036
1037 @Test
1038 public void testInvalidTreeNameIsMacHFSGit3()
1039 throws CorruptObjectException {
1040 StringBuilder b = new StringBuilder();
1041 entry(b, "100644 .git\uFEFF");
1042 byte[] data = encode(b.toString());
1043
1044
1045 checker.checkTree(data);
1046
1047
1048 checker.setSafeForMacOS(true);
1049 assertCorrupt(
1050 "invalid name '.git\uFEFF' contains ignorable Unicode characters",
1051 OBJ_TREE, data);
1052 assertSkipListAccepts(OBJ_TREE, data);
1053 checker.setIgnore(HAS_DOTGIT, true);
1054 checker.checkTree(data);
1055 }
1056
1057 private static byte[] concat(byte[]... b) {
1058 int n = 0;
1059 for (byte[] a : b) {
1060 n += a.length;
1061 }
1062
1063 byte[] data = new byte[n];
1064 n = 0;
1065 for (byte[] a : b) {
1066 System.arraycopy(a, 0, data, n, a.length);
1067 n += a.length;
1068 }
1069 return data;
1070 }
1071
1072 @Test
1073 public void testInvalidTreeNameIsMacHFSGitCorruptUTF8AtEnd()
1074 throws CorruptObjectException {
1075 byte[] data = concat(encode("100644 .git"),
1076 new byte[] { (byte) 0xef });
1077 StringBuilder b = new StringBuilder();
1078 entry(b, "");
1079 data = concat(data, encode(b.toString()));
1080
1081
1082 checker.checkTree(data);
1083
1084
1085 checker.setSafeForMacOS(true);
1086 assertCorrupt(
1087 "invalid name contains byte sequence '0xef' which is not a valid UTF-8 character",
1088 OBJ_TREE, data);
1089 assertSkipListAccepts(OBJ_TREE, data);
1090 }
1091
1092 @Test
1093 public void testInvalidTreeNameIsMacHFSGitCorruptUTF8AtEnd2()
1094 throws CorruptObjectException {
1095 byte[] data = concat(encode("100644 .git"),
1096 new byte[] {
1097 (byte) 0xe2, (byte) 0xab });
1098 StringBuilder b = new StringBuilder();
1099 entry(b, "");
1100 data = concat(data, encode(b.toString()));
1101
1102
1103 checker.checkTree(data);
1104
1105
1106 checker.setSafeForMacOS(true);
1107 assertCorrupt(
1108 "invalid name contains byte sequence '0xe2ab' which is not a valid UTF-8 character",
1109 OBJ_TREE, data);
1110 assertSkipListAccepts(OBJ_TREE, data);
1111 }
1112
1113 @Test
1114 public void testInvalidTreeNameIsNotMacHFSGit()
1115 throws CorruptObjectException {
1116 StringBuilder b = new StringBuilder();
1117 entry(b, "100644 .git\u200Cx");
1118 byte[] data = encode(b.toString());
1119 checker.setSafeForMacOS(true);
1120 checker.checkTree(data);
1121 }
1122
1123 @Test
1124 public void testInvalidTreeNameIsNotMacHFSGit2()
1125 throws CorruptObjectException {
1126 StringBuilder b = new StringBuilder();
1127 entry(b, "100644 .kit\u200C");
1128 byte[] data = encode(b.toString());
1129 checker.setSafeForMacOS(true);
1130 checker.checkTree(data);
1131 }
1132
1133 @Test
1134 public void testInvalidTreeNameIsNotMacHFSGitOtherPlatform()
1135 throws CorruptObjectException {
1136 StringBuilder b = new StringBuilder();
1137 entry(b, "100644 .git\u200C");
1138 byte[] data = encode(b.toString());
1139 checker.checkTree(data);
1140 }
1141
1142 @Test
1143 public void testInvalidTreeNameIsDotGitDot() throws CorruptObjectException {
1144 StringBuilder b = new StringBuilder();
1145 entry(b, "100644 .git.");
1146 byte[] data = encodeASCII(b.toString());
1147 assertCorrupt("invalid name '.git.'", OBJ_TREE, data);
1148 assertSkipListAccepts(OBJ_TREE, data);
1149 checker.setIgnore(HAS_DOTGIT, true);
1150 checker.checkTree(data);
1151 }
1152
1153 @Test
1154 public void testValidTreeNameIsDotGitDotDot()
1155 throws CorruptObjectException {
1156 StringBuilder b = new StringBuilder();
1157 entry(b, "100644 .git..");
1158 checker.checkTree(encodeASCII(b.toString()));
1159 }
1160
1161 @Test
1162 public void testInvalidTreeNameIsDotGitSpace()
1163 throws CorruptObjectException {
1164 StringBuilder b = new StringBuilder();
1165 entry(b, "100644 .git ");
1166 byte[] data = encodeASCII(b.toString());
1167 assertCorrupt("invalid name '.git '", OBJ_TREE, data);
1168 assertSkipListAccepts(OBJ_TREE, data);
1169 checker.setIgnore(HAS_DOTGIT, true);
1170 checker.checkTree(data);
1171 }
1172
1173 @Test
1174 public void testInvalidTreeNameIsDotGitSomething()
1175 throws CorruptObjectException {
1176 StringBuilder b = new StringBuilder();
1177 entry(b, "100644 .gitfoobar");
1178 byte[] data = encodeASCII(b.toString());
1179 checker.checkTree(data);
1180 }
1181
1182 @Test
1183 public void testInvalidTreeNameIsDotGitSomethingSpaceSomething()
1184 throws CorruptObjectException {
1185 StringBuilder b = new StringBuilder();
1186 entry(b, "100644 .gitfoo bar");
1187 byte[] data = encodeASCII(b.toString());
1188 checker.checkTree(data);
1189 }
1190
1191 @Test
1192 public void testInvalidTreeNameIsDotGitSomethingDot()
1193 throws CorruptObjectException {
1194 StringBuilder b = new StringBuilder();
1195 entry(b, "100644 .gitfoobar.");
1196 byte[] data = encodeASCII(b.toString());
1197 checker.checkTree(data);
1198 }
1199
1200 @Test
1201 public void testInvalidTreeNameIsDotGitSomethingDotDot()
1202 throws CorruptObjectException {
1203 StringBuilder b = new StringBuilder();
1204 entry(b, "100644 .gitfoobar..");
1205 byte[] data = encodeASCII(b.toString());
1206 checker.checkTree(data);
1207 }
1208
1209 @Test
1210 public void testInvalidTreeNameIsDotGitDotSpace()
1211 throws CorruptObjectException {
1212 StringBuilder b = new StringBuilder();
1213 entry(b, "100644 .git. ");
1214 byte[] data = encodeASCII(b.toString());
1215 assertCorrupt("invalid name '.git. '", OBJ_TREE, data);
1216 assertSkipListAccepts(OBJ_TREE, data);
1217 checker.setIgnore(HAS_DOTGIT, true);
1218 checker.checkTree(data);
1219 }
1220
1221 @Test
1222 public void testInvalidTreeNameIsDotGitSpaceDot()
1223 throws CorruptObjectException {
1224 StringBuilder b = new StringBuilder();
1225 entry(b, "100644 .git . ");
1226 byte[] data = encodeASCII(b.toString());
1227 assertCorrupt("invalid name '.git . '", OBJ_TREE, data);
1228 assertSkipListAccepts(OBJ_TREE, data);
1229 checker.setIgnore(HAS_DOTGIT, true);
1230 checker.checkTree(data);
1231 }
1232
1233 @Test
1234 public void testInvalidTreeNameIsGITTilde1() throws CorruptObjectException {
1235 StringBuilder b = new StringBuilder();
1236 entry(b, "100644 GIT~1");
1237 byte[] data = encodeASCII(b.toString());
1238 assertCorrupt("invalid name 'GIT~1'", OBJ_TREE, data);
1239 assertSkipListAccepts(OBJ_TREE, data);
1240 checker.setIgnore(HAS_DOTGIT, true);
1241 checker.checkTree(data);
1242 }
1243
1244 @Test
1245 public void testInvalidTreeNameIsGiTTilde1() throws CorruptObjectException {
1246 StringBuilder b = new StringBuilder();
1247 entry(b, "100644 GiT~1");
1248 byte[] data = encodeASCII(b.toString());
1249 assertCorrupt("invalid name 'GiT~1'", OBJ_TREE, data);
1250 assertSkipListAccepts(OBJ_TREE, data);
1251 checker.setIgnore(HAS_DOTGIT, true);
1252 checker.checkTree(data);
1253 }
1254
1255 @Test
1256 public void testValidTreeNameIsGitTilde11() throws CorruptObjectException {
1257 StringBuilder b = new StringBuilder();
1258 entry(b, "100644 GIT~11");
1259 byte[] data = encodeASCII(b.toString());
1260 checker.checkTree(data);
1261 }
1262
1263 @Test
1264 public void testInvalidTreeTruncatedInName() {
1265 StringBuilder b = new StringBuilder();
1266 b.append("100644 b");
1267 byte[] data = encodeASCII(b.toString());
1268 assertCorrupt("truncated in name", OBJ_TREE, data);
1269 assertSkipListRejects("truncated in name", OBJ_TREE, data);
1270 }
1271
1272 @Test
1273 public void testInvalidTreeTruncatedInObjectId() {
1274 StringBuilder b = new StringBuilder();
1275 b.append("100644 b\0\1\2");
1276 byte[] data = encodeASCII(b.toString());
1277 assertCorrupt("truncated in object id", OBJ_TREE, data);
1278 assertSkipListRejects("truncated in object id", OBJ_TREE, data);
1279 }
1280
1281 @Test
1282 public void testInvalidTreeBadSorting1() throws CorruptObjectException {
1283 StringBuilder b = new StringBuilder();
1284 entry(b, "100644 foobar");
1285 entry(b, "100644 fooaaa");
1286 byte[] data = encodeASCII(b.toString());
1287
1288 assertCorrupt("incorrectly sorted", OBJ_TREE, data);
1289
1290 ObjectId id = idFor(OBJ_TREE, data);
1291 try {
1292 checker.check(id, OBJ_TREE, data);
1293 fail("Did not throw CorruptObjectException");
1294 } catch (CorruptObjectException e) {
1295 assertSame(TREE_NOT_SORTED, e.getErrorType());
1296 assertEquals("treeNotSorted: object " + id.name()
1297 + ": incorrectly sorted", e.getMessage());
1298 }
1299
1300 assertSkipListAccepts(OBJ_TREE, data);
1301 checker.setIgnore(TREE_NOT_SORTED, true);
1302 checker.checkTree(data);
1303 }
1304
1305 @Test
1306 public void testInvalidTreeBadSorting2() throws CorruptObjectException {
1307 StringBuilder b = new StringBuilder();
1308 entry(b, "40000 a");
1309 entry(b, "100644 a.c");
1310 byte[] data = encodeASCII(b.toString());
1311 assertCorrupt("incorrectly sorted", OBJ_TREE, data);
1312 assertSkipListAccepts(OBJ_TREE, data);
1313 checker.setIgnore(TREE_NOT_SORTED, true);
1314 checker.checkTree(data);
1315 }
1316
1317 @Test
1318 public void testInvalidTreeBadSorting3() throws CorruptObjectException {
1319 StringBuilder b = new StringBuilder();
1320 entry(b, "100644 a0c");
1321 entry(b, "40000 a");
1322 byte[] data = encodeASCII(b.toString());
1323 assertCorrupt("incorrectly sorted", OBJ_TREE, data);
1324 assertSkipListAccepts(OBJ_TREE, data);
1325 checker.setIgnore(TREE_NOT_SORTED, true);
1326 checker.checkTree(data);
1327 }
1328
1329 @Test
1330 public void testInvalidTreeDuplicateNames1_File()
1331 throws CorruptObjectException {
1332 StringBuilder b = new StringBuilder();
1333 entry(b, "100644 a");
1334 entry(b, "100644 a");
1335 byte[] data = encodeASCII(b.toString());
1336 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1337 assertSkipListAccepts(OBJ_TREE, data);
1338 checker.setIgnore(DUPLICATE_ENTRIES, true);
1339 checker.checkTree(data);
1340 }
1341
1342 @Test
1343 public void testInvalidTreeDuplicateNames1_Tree()
1344 throws CorruptObjectException {
1345 StringBuilder b = new StringBuilder();
1346 entry(b, "40000 a");
1347 entry(b, "40000 a");
1348 byte[] data = encodeASCII(b.toString());
1349 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1350 assertSkipListAccepts(OBJ_TREE, data);
1351 checker.setIgnore(DUPLICATE_ENTRIES, true);
1352 checker.checkTree(data);
1353 }
1354
1355 @Test
1356 public void testInvalidTreeDuplicateNames2() throws CorruptObjectException {
1357 StringBuilder b = new StringBuilder();
1358 entry(b, "100644 a");
1359 entry(b, "100755 a");
1360 byte[] data = encodeASCII(b.toString());
1361 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1362 assertSkipListAccepts(OBJ_TREE, data);
1363 checker.setIgnore(DUPLICATE_ENTRIES, true);
1364 checker.checkTree(data);
1365 }
1366
1367 @Test
1368 public void testInvalidTreeDuplicateNames3() throws CorruptObjectException {
1369 StringBuilder b = new StringBuilder();
1370 entry(b, "100644 a");
1371 entry(b, "40000 a");
1372 byte[] data = encodeASCII(b.toString());
1373 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1374 assertSkipListAccepts(OBJ_TREE, data);
1375 checker.setIgnore(DUPLICATE_ENTRIES, true);
1376 checker.checkTree(data);
1377 }
1378
1379 @Test
1380 public void testInvalidTreeDuplicateNames4() throws CorruptObjectException {
1381 StringBuilder b = new StringBuilder();
1382 entry(b, "100644 a");
1383 entry(b, "100644 a.c");
1384 entry(b, "100644 a.d");
1385 entry(b, "100644 a.e");
1386 entry(b, "40000 a");
1387 entry(b, "100644 zoo");
1388 byte[] data = encodeASCII(b.toString());
1389 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1390 assertSkipListAccepts(OBJ_TREE, data);
1391 checker.setIgnore(DUPLICATE_ENTRIES, true);
1392 checker.checkTree(data);
1393 }
1394
1395 @Test
1396 public void testInvalidTreeDuplicateNames5()
1397 throws UnsupportedEncodingException, CorruptObjectException {
1398 StringBuilder b = new StringBuilder();
1399 entry(b, "100644 A");
1400 entry(b, "100644 a");
1401 byte[] data = b.toString().getBytes("UTF-8");
1402 checker.setSafeForWindows(true);
1403 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1404 assertSkipListAccepts(OBJ_TREE, data);
1405 checker.setIgnore(DUPLICATE_ENTRIES, true);
1406 checker.checkTree(data);
1407 }
1408
1409 @Test
1410 public void testInvalidTreeDuplicateNames6()
1411 throws UnsupportedEncodingException, CorruptObjectException {
1412 StringBuilder b = new StringBuilder();
1413 entry(b, "100644 A");
1414 entry(b, "100644 a");
1415 byte[] data = b.toString().getBytes("UTF-8");
1416 checker.setSafeForMacOS(true);
1417 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1418 assertSkipListAccepts(OBJ_TREE, data);
1419 checker.setIgnore(DUPLICATE_ENTRIES, true);
1420 checker.checkTree(data);
1421 }
1422
1423 @Test
1424 public void testInvalidTreeDuplicateNames7()
1425 throws UnsupportedEncodingException, CorruptObjectException {
1426 StringBuilder b = new StringBuilder();
1427 entry(b, "100644 \u0065\u0301");
1428 entry(b, "100644 \u00e9");
1429 byte[] data = b.toString().getBytes("UTF-8");
1430 checker.setSafeForMacOS(true);
1431 assertCorrupt("duplicate entry names", OBJ_TREE, data);
1432 assertSkipListAccepts(OBJ_TREE, data);
1433 checker.setIgnore(DUPLICATE_ENTRIES, true);
1434 checker.checkTree(data);
1435 }
1436
1437 @Test
1438 public void testInvalidTreeDuplicateNames8()
1439 throws UnsupportedEncodingException, CorruptObjectException {
1440 StringBuilder b = new StringBuilder();
1441 entry(b, "100644 A");
1442 checker.setSafeForMacOS(true);
1443 checker.checkTree(b.toString().getBytes("UTF-8"));
1444 }
1445
1446 @Test
1447 public void testRejectNulInPathSegment() {
1448 try {
1449 checker.checkPathSegment(encodeASCII("a\u0000b"), 0, 3);
1450 fail("incorrectly accepted NUL in middle of name");
1451 } catch (CorruptObjectException e) {
1452 assertEquals("name contains byte 0x00", e.getMessage());
1453 }
1454 }
1455
1456 @Test
1457 public void testRejectSpaceAtEndOnWindows() {
1458 checker.setSafeForWindows(true);
1459 try {
1460 checkOneName("test ");
1461 fail("incorrectly accepted space at end");
1462 } catch (CorruptObjectException e) {
1463 assertEquals("invalid name ends with ' '", e.getMessage());
1464 }
1465 }
1466
1467 @Test
1468 public void testBug477090() throws CorruptObjectException {
1469 checker.setSafeForMacOS(true);
1470 final byte[] bytes = {
1471
1472 (byte) 0xe2, (byte) 0x88, (byte) 0x9e,
1473
1474 0x2e, 0x68, 0x74, 0x6d, 0x6c };
1475 checker.checkPathSegment(bytes, 0, bytes.length);
1476 }
1477
1478 @Test
1479 public void testRejectDotAtEndOnWindows() {
1480 checker.setSafeForWindows(true);
1481 try {
1482 checkOneName("test.");
1483 fail("incorrectly accepted dot at end");
1484 } catch (CorruptObjectException e) {
1485 assertEquals("invalid name ends with '.'", e.getMessage());
1486 }
1487 }
1488
1489 @Test
1490 public void testRejectDevicesOnWindows() {
1491 checker.setSafeForWindows(true);
1492
1493 String[] bad = { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3",
1494 "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2",
1495 "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };
1496 for (String b : bad) {
1497 try {
1498 checkOneName(b);
1499 fail("incorrectly accepted " + b);
1500 } catch (CorruptObjectException e) {
1501 assertEquals("invalid name '" + b + "'", e.getMessage());
1502 }
1503 try {
1504 checkOneName(b + ".txt");
1505 fail("incorrectly accepted " + b + ".txt");
1506 } catch (CorruptObjectException e) {
1507 assertEquals("invalid name '" + b + "'", e.getMessage());
1508 }
1509 }
1510 }
1511
1512 @Test
1513 public void testRejectInvalidWindowsCharacters() {
1514 checker.setSafeForWindows(true);
1515 rejectName('<');
1516 rejectName('>');
1517 rejectName(':');
1518 rejectName('"');
1519 rejectName('/');
1520 rejectName('\\');
1521 rejectName('|');
1522 rejectName('?');
1523 rejectName('*');
1524
1525 for (int i = 1; i <= 31; i++)
1526 rejectName((byte) i);
1527 }
1528
1529 private void rejectName(char c) {
1530 try {
1531 checkOneName("te" + c + "st");
1532 fail("incorrectly accepted with " + c);
1533 } catch (CorruptObjectException e) {
1534 assertEquals("name contains '" + c + "'", e.getMessage());
1535 }
1536 }
1537
1538 private void rejectName(byte c) {
1539 String h = Integer.toHexString(c);
1540 try {
1541 checkOneName("te" + ((char) c) + "st");
1542 fail("incorrectly accepted with 0x" + h);
1543 } catch (CorruptObjectException e) {
1544 assertEquals("name contains byte 0x" + h, e.getMessage());
1545 }
1546 }
1547
1548 private void checkOneName(String name) throws CorruptObjectException {
1549 StringBuilder b = new StringBuilder();
1550 entry(b, "100644 " + name);
1551 checker.checkTree(encodeASCII(b.toString()));
1552 }
1553
1554 private static void entry(StringBuilder b, final String modeName) {
1555 b.append(modeName);
1556 b.append('\0');
1557 for (int i = 0; i < OBJECT_ID_LENGTH; i++)
1558 b.append((char) i);
1559 }
1560
1561 private void assertCorrupt(String msg, int type, StringBuilder b) {
1562 assertCorrupt(msg, type, encodeASCII(b.toString()));
1563 }
1564
1565 private void assertCorrupt(String msg, int type, byte[] data) {
1566 try {
1567 checker.check(type, data);
1568 fail("Did not throw CorruptObjectException");
1569 } catch (CorruptObjectException e) {
1570 assertEquals(msg, e.getMessage());
1571 }
1572 }
1573
1574 private void assertSkipListAccepts(int type, byte[] data)
1575 throws CorruptObjectException {
1576 ObjectId id = idFor(type, data);
1577 checker.setSkipList(set(id));
1578 checker.check(id, type, data);
1579 checker.setSkipList(null);
1580 }
1581
1582 private void assertSkipListRejects(String msg, int type, byte[] data) {
1583 ObjectId id = idFor(type, data);
1584 checker.setSkipList(set(id));
1585 try {
1586 checker.check(id, type, data);
1587 fail("Did not throw CorruptObjectException");
1588 } catch (CorruptObjectException e) {
1589 assertEquals(msg, e.getMessage());
1590 }
1591 checker.setSkipList(null);
1592 }
1593
1594 private static ObjectIdSet set(final ObjectId... ids) {
1595 return new ObjectIdSet() {
1596 @Override
1597 public boolean contains(AnyObjectId objectId) {
1598 for (ObjectId id : ids) {
1599 if (id.equals(objectId)) {
1600 return true;
1601 }
1602 }
1603 return false;
1604 }
1605 };
1606 }
1607
1608 @SuppressWarnings("resource")
1609 private static ObjectId idFor(int type, byte[] raw) {
1610 return new ObjectInserter.Formatter().idFor(type, raw);
1611 }
1612 }