aboutsummaryrefslogtreecommitdiff
path: root/format/pack
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-05 21:09:07 +0800
committerGravatar Runxi Yu2026-03-05 21:14:24 +0800
commit355f5b3dc9ae560827cd274e113f43d09ee9ac49 (patch)
tree2046f5d51110fff82aecf35c75884222f51ac36c /format/pack
parentobjectid, format/pack/ingest: Pack hash ID in algo (diff)
signatureNo signature
*: Fix overflows
Diffstat (limited to 'format/pack')
-rw-r--r--format/pack/ingest/finalize.go9
-rw-r--r--format/pack/ingest/idx_write.go9
-rw-r--r--format/pack/ingest/resolve.go13
-rw-r--r--format/pack/ingest/rev_write.go11
-rw-r--r--format/pack/ingest/stream_scan.go17
-rw-r--r--format/pack/ingest/thin_fix.go65
6 files changed, 106 insertions, 18 deletions
diff --git a/format/pack/ingest/finalize.go b/format/pack/ingest/finalize.go
index e0516c4b..9b04a7c1 100644
--- a/format/pack/ingest/finalize.go
+++ b/format/pack/ingest/finalize.go
@@ -5,6 +5,8 @@ import (
"fmt"
"io/fs"
"strings"
+
+ "codeberg.org/lindenii/furgit/internal/intconv"
)
// finalizeArtifacts links temporary files to final names and returns Result.
@@ -35,12 +37,17 @@ func finalizeArtifacts(state *ingestState) (Result, error) {
}
}
+ objectCount, err := intconv.IntToUint32(len(state.records))
+ if err != nil {
+ return Result{}, err
+ }
+
return Result{
PackName: packFinal,
IdxName: idxFinal,
RevName: revFinal,
PackHash: state.packHash,
- ObjectCount: uint32(len(state.records)),
+ ObjectCount: objectCount,
ThinFixed: state.thinFixed,
}, nil
}
diff --git a/format/pack/ingest/idx_write.go b/format/pack/ingest/idx_write.go
index 8db11ba0..904afb6c 100644
--- a/format/pack/ingest/idx_write.go
+++ b/format/pack/ingest/idx_write.go
@@ -7,6 +7,8 @@ import (
"hash"
"io"
"slices"
+
+ "codeberg.org/lindenii/furgit/internal/intconv"
)
const (
@@ -87,7 +89,12 @@ func writeIdx(state *ingestState) error {
for _, recordIdx := range order {
offset := state.records[recordIdx].offset
if offset >= 0x80000000 {
- word := 0x80000000 | uint32(len(largeOffsets))
+ largeOffsetIdx, err := intconv.IntToUint32(len(largeOffsets))
+ if err != nil {
+ return err
+ }
+
+ word := 0x80000000 | largeOffsetIdx
largeOffsets = append(largeOffsets, offset)
binary.BigEndian.PutUint32(scratch[:4], word)
diff --git a/format/pack/ingest/resolve.go b/format/pack/ingest/resolve.go
index f024bb62..e357e1aa 100644
--- a/format/pack/ingest/resolve.go
+++ b/format/pack/ingest/resolve.go
@@ -10,6 +10,7 @@ import (
deltaapply "codeberg.org/lindenii/furgit/format/delta/apply"
packfmt "codeberg.org/lindenii/furgit/format/pack"
"codeberg.org/lindenii/furgit/internal/compress/zlib"
+ "codeberg.org/lindenii/furgit/internal/intconv"
"codeberg.org/lindenii/furgit/objectheader"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/objecttype"
@@ -237,7 +238,17 @@ func inflateRecordPayload(state *ingestState, idx int) ([]byte, error) {
compressedOffset := record.offset + uint64(record.headerLen)
compressedLen := record.packedLen - uint64(record.headerLen)
- section := io.NewSectionReader(state.packFile, int64(compressedOffset), int64(compressedLen))
+ compressedOffsetInt64, err := intconv.Uint64ToInt64(compressedOffset)
+ if err != nil {
+ return nil, err
+ }
+
+ compressedLenInt64, err := intconv.Uint64ToInt64(compressedLen)
+ if err != nil {
+ return nil, err
+ }
+
+ section := io.NewSectionReader(state.packFile, compressedOffsetInt64, compressedLenInt64)
reader, err := zlib.NewReader(section)
if err != nil {
diff --git a/format/pack/ingest/rev_write.go b/format/pack/ingest/rev_write.go
index afa9b4a9..8d30474a 100644
--- a/format/pack/ingest/rev_write.go
+++ b/format/pack/ingest/rev_write.go
@@ -3,6 +3,8 @@ package ingest
import (
"encoding/binary"
"slices"
+
+ "codeberg.org/lindenii/furgit/internal/intconv"
)
const (
@@ -53,9 +55,14 @@ func writeRev(state *ingestState) error {
}
for _, recordIdx := range packOrder {
- binary.BigEndian.PutUint32(scratch[:4], uint32(recordToIdxPos[recordIdx]))
+ recordPos, err := intconv.IntToUint32(recordToIdxPos[recordIdx])
+ if err != nil {
+ return err
+ }
+
+ binary.BigEndian.PutUint32(scratch[:4], recordPos)
- err := writeAndHash(state.revFile, hashImpl, scratch[:4])
+ err = writeAndHash(state.revFile, hashImpl, scratch[:4])
if err != nil {
return err
}
diff --git a/format/pack/ingest/stream_scan.go b/format/pack/ingest/stream_scan.go
index b3cf4c00..97bb0ae8 100644
--- a/format/pack/ingest/stream_scan.go
+++ b/format/pack/ingest/stream_scan.go
@@ -8,6 +8,7 @@ import (
deltaapply "codeberg.org/lindenii/furgit/format/delta/apply"
packfmt "codeberg.org/lindenii/furgit/format/pack"
"codeberg.org/lindenii/furgit/internal/compress/zlib"
+ "codeberg.org/lindenii/furgit/internal/intconv"
"codeberg.org/lindenii/furgit/objectheader"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/objecttype"
@@ -215,7 +216,13 @@ func parseEntryPrefix(state *ingestState, startOffset uint64) (objectRecord, err
}
record.baseObject = baseID
- headerLen += uint32(len(baseRaw))
+
+ baseRawLen, err := intconv.IntToUint32(len(baseRaw))
+ if err != nil {
+ return record, err
+ }
+
+ headerLen += baseRawLen
case objecttype.TypeOfsDelta:
dist, consumed, err := readOfsDistanceFromStream(state.stream)
if err != nil {
@@ -227,7 +234,13 @@ func parseEntryPrefix(state *ingestState, startOffset uint64) (objectRecord, err
}
record.baseOffset = startOffset - dist
- headerLen += uint32(consumed)
+
+ consumedUint32, err := intconv.IntToUint32(consumed)
+ if err != nil {
+ return record, err
+ }
+
+ headerLen += consumedUint32
case objecttype.TypeInvalid, objecttype.TypeFuture:
return record, &ErrMalformedPackEntry{Offset: startOffset, Reason: fmt.Sprintf("unsupported object type %d", record.packedType)}
default:
diff --git a/format/pack/ingest/thin_fix.go b/format/pack/ingest/thin_fix.go
index 05ad9494..6ac3c75a 100644
--- a/format/pack/ingest/thin_fix.go
+++ b/format/pack/ingest/thin_fix.go
@@ -8,6 +8,7 @@ import (
"os"
"codeberg.org/lindenii/furgit/internal/compress/zlib"
+ "codeberg.org/lindenii/furgit/internal/intconv"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/objecttype"
)
@@ -45,7 +46,12 @@ func maybeFixThin(state *ingestState) error {
return err
}
- state.stream.consumed = uint64(newEnd)
+ consumed, err := intconv.Int64ToUint64(newEnd)
+ if err != nil {
+ return err
+ }
+
+ state.stream.consumed = consumed
baseIDs := unresolvedThinBaseIDs(state)
for _, id := range baseIDs {
@@ -76,12 +82,18 @@ func appendBaseObject(state *ingestState, id objectid.ObjectID, realType objectt
header := encodePackEntryHeader(realType, int64(len(content)))
- _, err := state.packFile.WriteAt(header, int64(start))
+ startInt64, err := intconv.Uint64ToInt64(start)
+ if err != nil {
+ return 0, err
+ }
+
+ _, err = state.packFile.WriteAt(header, startInt64)
if err != nil {
return 0, err
}
- section := &fileSectionWriter{file: state.packFile, off: int64(start) + int64(len(header))}
+ headerLenInt64 := int64(len(header))
+ section := &fileSectionWriter{file: state.packFile, off: startInt64 + headerLenInt64}
crc := crc32.NewIEEE()
_, _ = crc.Write(header)
counting := &countingWriter{dst: section}
@@ -98,19 +110,34 @@ func appendBaseObject(state *ingestState, id objectid.ObjectID, realType objectt
return 0, err
}
- packedLen := uint64(len(header)) + uint64(counting.n)
+ headerLenUint64, err := intconv.IntToUint64(len(header))
+ if err != nil {
+ return 0, err
+ }
+
+ countingNUint64, err := intconv.IntToUint64(counting.n)
+ if err != nil {
+ return 0, err
+ }
+
+ packedLen := headerLenUint64 + countingNUint64
end := start + packedLen
state.stream.consumed = end
+ headerLenUint32, err := intconv.IntToUint32(len(header))
+ if err != nil {
+ return 0, err
+ }
+
record := objectRecord{
offset: start,
- headerLen: uint32(len(header)),
+ headerLen: headerLenUint32,
packedLen: packedLen,
crc32: crc.Sum32(),
packedType: realType,
realType: realType,
declaredSize: int64(len(content)),
- dataOffset: start + uint64(len(header)),
+ dataOffset: start + headerLenUint64,
objectID: id,
resolved: true,
}
@@ -160,9 +187,14 @@ func (writer *countingWriter) Write(src []byte) (int, error) {
// rewritePackHeaderAndTrailer rewrites object count and trailer hash using ReadAt/WriteAt.
func rewritePackHeaderAndTrailer(state *ingestState) error {
var countRaw [4]byte
- binary.BigEndian.PutUint32(countRaw[:], uint32(len(state.records)))
+ recordCountUint32, err := intconv.IntToUint32(len(state.records))
+ if err != nil {
+ return err
+ }
+
+ binary.BigEndian.PutUint32(countRaw[:], recordCountUint32)
- _, err := state.packFile.WriteAt(countRaw[:], 8)
+ _, err = state.packFile.WriteAt(countRaw[:], 8)
if err != nil {
return err
}
@@ -217,8 +249,15 @@ func rewritePackHeaderAndTrailer(state *ingestState) error {
}
state.packHash = packHash
- state.objectCountHeader = uint32(len(state.records))
- state.stream.consumed = uint64(endWithoutTrailer + int64(len(sum)))
+ state.objectCountHeader = recordCountUint32
+
+ sumLenInt64 := int64(len(sum))
+ newConsumed, err := intconv.Int64ToUint64(endWithoutTrailer + sumLenInt64)
+ if err != nil {
+ return err
+ }
+
+ state.stream.consumed = newConsumed
return nil
}
@@ -228,7 +267,11 @@ func encodePackEntryHeader(ty objecttype.Type, size int64) []byte {
var out [16]byte
n := 0
- s := uint64(size)
+ s, err := intconv.Int64ToUint64(size)
+ if err != nil {
+ panic(err)
+ }
+
c := byte((uint8(ty) << 4) | byte(s&0x0f))
s >>= 4