public virtual void TestUsingHiddenDeltaBaseFails() { byte[] delta = new byte[] { unchecked ((int)(0x1)), unchecked ((int)(0x1)), unchecked ( (int)(0x1)), (byte)('c') }; TestRepository <Repository> s = new TestRepository <Repository>(src); RevCommit N = s.Commit().Parent(B).Add("q", s.Blob(BinaryDelta.Apply(dst.Open(b). GetCachedBytes(), delta))).Create(); TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); PackHeader(pack, 3); Copy(pack, src.Open(N)); Copy(pack, src.Open(s.ParseBody(N).Tree)); pack.Write((Constants.OBJ_REF_DELTA) << 4 | 4); b.CopyRawTo(pack); Deflate(pack, delta); Digest(pack); TemporaryBuffer.Heap inBuf = new TemporaryBuffer.Heap(1024); PacketLineOut inPckLine = new PacketLineOut(inBuf); inPckLine.WriteString(ObjectId.ZeroId.Name + ' ' + N.Name + ' ' + "refs/heads/s" + '\0' + BasePackPushConnection.CAPABILITY_REPORT_STATUS); inPckLine.End(); pack.WriteTo(inBuf, PM); TemporaryBuffer.Heap outBuf = new TemporaryBuffer.Heap(1024); ReceivePack rp = new ReceivePack(dst); rp.SetCheckReceivedObjects(true); rp.SetCheckReferencedObjectsAreReachable(true); rp.SetAdvertiseRefsHook(new ReceivePackAdvertiseRefsHookTest.HidePrivateHook()); try { Receive(rp, inBuf, outBuf); NUnit.Framework.Assert.Fail("Expected UnpackException"); } catch (UnpackException failed) { Exception err = failed.InnerException; NUnit.Framework.Assert.IsTrue(err is MissingObjectException); MissingObjectException moe = (MissingObjectException)err; NUnit.Framework.Assert.AreEqual(b, moe.GetObjectId()); } PacketLineIn r = AsPacketLineIn(outBuf); string master = r.ReadString(); int nul = master.IndexOf('\0'); NUnit.Framework.Assert.IsTrue(nul > 0, "has capability list"); NUnit.Framework.Assert.AreEqual(B.Name + ' ' + R_MASTER, Sharpen.Runtime.Substring (master, 0, nul)); NUnit.Framework.Assert.AreSame(PacketLineIn.END, r.ReadString()); NUnit.Framework.Assert.AreEqual("unpack error Missing blob " + b.Name, r.ReadString ()); NUnit.Framework.Assert.AreEqual("ng refs/heads/s n/a (unpacker error)", r.ReadString ()); NUnit.Framework.Assert.AreSame(PacketLineIn.END, r.ReadString()); }
/// <exception cref="System.IO.IOException"></exception> internal virtual ObjectLoader Load(WindowCursor curs, long pos) { try { byte[] ib = curs.tempId; PackFile.Delta delta = null; byte[] data = null; int type = Constants.OBJ_BAD; bool cached = false; for (; ;) { ReadFully(pos, ib, 0, 20, curs); int c = ib[0] & unchecked ((int)(0xff)); int typeCode = (c >> 4) & 7; long sz = c & 15; int shift = 4; int p = 1; while ((c & unchecked ((int)(0x80))) != 0) { c = ib[p++] & unchecked ((int)(0xff)); sz += ((long)(c & unchecked ((int)(0x7f)))) << shift; shift += 7; } switch (typeCode) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: { if (sz < curs.GetStreamFileThreshold()) { data = Decompress(pos + p, (int)sz, curs); } if (delta != null) { type = typeCode; goto SEARCH_break; } if (data != null) { return(new ObjectLoader.SmallObject(typeCode, data)); } else { return(new LargePackedWholeObject(typeCode, sz, pos, p, this, curs.db)); } goto case Constants.OBJ_OFS_DELTA; } case Constants.OBJ_OFS_DELTA: { c = ib[p++] & unchecked ((int)(0xff)); long @base = c & 127; while ((c & 128) != 0) { @base += 1; c = ib[p++] & unchecked ((int)(0xff)); @base <<= 7; @base += (c & 127); } @base = pos - @base; delta = new PackFile.Delta(delta, pos, (int)sz, p, @base); if (sz != delta.deltaSize) { goto SEARCH_break; } DeltaBaseCache.Entry e = curs.GetDeltaBaseCache().Get(this, @base); if (e != null) { type = e.type; data = e.data; cached = true; goto SEARCH_break; } pos = @base; goto SEARCH_continue; } case Constants.OBJ_REF_DELTA: { ReadFully(pos + p, ib, 0, 20, curs); long @base = FindDeltaBase(ObjectId.FromRaw(ib)); delta = new PackFile.Delta(delta, pos, (int)sz, p + 20, @base); if (sz != delta.deltaSize) { goto SEARCH_break; } DeltaBaseCache.Entry e = curs.GetDeltaBaseCache().Get(this, @base); if (e != null) { type = e.type; data = e.data; cached = true; goto SEARCH_break; } pos = @base; goto SEARCH_continue; } default: { throw new IOException(MessageFormat.Format(JGitText.Get().unknownObjectType, Sharpen.Extensions.ValueOf (typeCode))); } } SEARCH_continue :; } SEARCH_break :; // At this point there is at least one delta to apply to data. // (Whole objects with no deltas to apply return early above.) if (data == null) { return(delta.Large(this, curs)); } do { // Cache only the base immediately before desired object. if (cached) { cached = false; } else { if (delta.next == null) { curs.GetDeltaBaseCache().Store(this, delta.basePos, data, type); } } pos = delta.deltaPos; byte[] cmds = Decompress(pos + delta.hdrLen, delta.deltaSize, curs); if (cmds == null) { data = null; // Discard base in case of OutOfMemoryError return(delta.Large(this, curs)); } long sz = BinaryDelta.GetResultSize(cmds); if (int.MaxValue <= sz) { return(delta.Large(this, curs)); } byte[] result; try { result = new byte[(int)sz]; } catch (OutOfMemoryException) { data = null; // Discard base in case of OutOfMemoryError return(delta.Large(this, curs)); } BinaryDelta.Apply(data, cmds, result); data = result; delta = delta.next; }while (delta != null); return(new ObjectLoader.SmallObject(type, data)); } catch (SharpZipBaseException dfe) { CorruptObjectException coe = new CorruptObjectException(MessageFormat.Format(JGitText .Get().objectAtHasBadZlibStream, Sharpen.Extensions.ValueOf(pos), GetPackFile()) ); Sharpen.Extensions.InitCause(coe, dfe); throw coe; } }
private void ResolveDeltas(long pos, int oldCrc, int type, byte[] data, PackedObjectInfo oe) { _crc.Reset(); Position(pos); int c = ReadFromFile(); int typecode = (c >> 4) & 7; long sz = c & 15; int shift = 4; while ((c & 0x80) != 0) { c = ReadFromFile(); sz += (c & 0x7f) << shift; shift += 7; } switch (typecode) { case Constants.OBJ_COMMIT: case Constants.OBJ_TREE: case Constants.OBJ_BLOB: case Constants.OBJ_TAG: type = typecode; data = InflateFromFile((int)sz); break; case Constants.OBJ_OFS_DELTA: c = ReadFromFile() & 0xff; while ((c & 128) != 0) { c = ReadFromFile() & 0xff; } data = BinaryDelta.Apply(data, InflateFromFile((int)sz)); break; case Constants.OBJ_REF_DELTA: _crc.Update(_buffer, FillFromFile(20), 20); Use(20); data = BinaryDelta.Apply(data, InflateFromFile((int)sz)); break; default: throw new IOException("Unknown object type " + typecode + "."); } var crc32 = (int)_crc.Value; if (oldCrc != crc32) { throw new IOException("Corruption detected re-reading at " + pos); } if (oe == null) { _objectDigest.Update(Constants.encodedTypeString(type)); _objectDigest.Update((byte)' '); _objectDigest.Update(Constants.encodeASCII(data.Length)); _objectDigest.Update(0); _objectDigest.Update(data); _tempObjectId.FromRaw(_objectDigest.Digest(), 0); VerifySafeObject(_tempObjectId, type, data); oe = new PackedObjectInfo(pos, crc32, _tempObjectId); addObjectAndTrack(oe); } ResolveChildDeltas(pos, type, data, oe); }