From 355f5b3dc9ae560827cd274e113f43d09ee9ac49 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Thu, 5 Mar 2026 21:09:07 +0800 Subject: *: Fix overflows --- format/pack/ingest/finalize.go | 9 +++++- format/pack/ingest/idx_write.go | 9 +++++- format/pack/ingest/resolve.go | 13 +++++++- format/pack/ingest/rev_write.go | 11 +++++-- format/pack/ingest/stream_scan.go | 17 ++++++++-- format/pack/ingest/thin_fix.go | 65 ++++++++++++++++++++++++++++++++------- 6 files changed, 106 insertions(+), 18 deletions(-) (limited to 'format') 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 -- cgit v1.3.1-10-gc9f91