Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ linters:
- dupl
- errcheck
- gocritic
- gosec
- govet
- ineffassign
- misspell
Expand Down Expand Up @@ -38,6 +39,7 @@ linters:
- path: _test\.go
linters:
- errcheck
- gosec

formatters:
enable:
Expand Down
7 changes: 5 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,11 +450,14 @@ func (c *Config) unmarshalPack() error {
if window == "" {
c.Pack.Window = DefaultPackWindow
} else {
winUint, err := strconv.ParseUint(window, 10, 32)
winInt, err := strconv.Atoi(window)
if err != nil {
return err
}
c.Pack.Window = uint(winUint)
if winInt < 0 {
return fmt.Errorf("pack.window cannot be negative: %d", winInt)
}
c.Pack.Window = uint(winInt)
}
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion internal/transport/test/receive_pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func (s *ReceivePackSuite) receivePackNoCheck(ep *transport.Endpoint,

for _, file := range files {
path := filepath.Join(objectPath, file.Name())
err = os.Chmod(path, 0o644)
err = os.Chmod(path, 0o644) //nolint:gosec // G302: test file, relaxed permissions are intentional
s.Require().NoError(err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion plumbing/format/commitgraph/commitgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (c *CommitData) GenerationV2Data() uint64 {
if c.GenerationV2 == 0 || c.GenerationV2 == math.MaxUint64 {
return 0
}
return c.GenerationV2 - uint64(c.When.Unix())
return c.GenerationV2 - uint64(c.When.Unix()) //nolint:gosec // G115: Unix timestamp is always positive for valid commits
}

// Index represents a representation of commit graph that allows indexed
Expand Down
17 changes: 9 additions & 8 deletions plumbing/format/commitgraph/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (e *Encoder) Encode(idx Index) error {
hashToIndex, fanout, extraEdgesCount, generationV2OverflowCount := e.prepare(idx, hashes)

chunkSignatures := [][]byte{OIDFanoutChunk.Signature(), OIDLookupChunk.Signature(), CommitDataChunk.Signature()}
//nolint:gosec // G115: len() and hash.Size() are always small positive values
chunkSizes := []uint64{szUint32 * lenFanout, uint64(len(hashes) * e.hash.Size()), uint64(len(hashes) * (e.hash.Size() + szCommitData))}
if extraEdgesCount > 0 {
chunkSignatures = append(chunkSignatures, ExtraEdgeListChunk.Signature())
Expand Down Expand Up @@ -86,7 +87,7 @@ func (e *Encoder) prepare(idx Index, hashes []plumbing.Hash) (hashToIndex map[pl
hashToIndex = make(map[plumbing.Hash]uint32)
fanout = make([]uint32, lenFanout)
for i, hash := range hashes {
hashToIndex[hash] = uint32(i)
hashToIndex[hash] = uint32(i) //nolint:gosec // G115: i is loop index bounded by hashes count
fanout[hash.Bytes()[0]]++
}

Expand All @@ -99,9 +100,9 @@ func (e *Encoder) prepare(idx Index, hashes []plumbing.Hash) (hashToIndex map[pl

// Find out if we will need extra edge table
for i := range len(hashes) {
v, _ := idx.GetCommitDataByIndex(uint32(i))
v, _ := idx.GetCommitDataByIndex(uint32(i)) //nolint:gosec // G115: i is loop index
if len(v.ParentHashes) > 2 {
extraEdgesCount += uint32(len(v.ParentHashes) - 1)
extraEdgesCount += uint32(len(v.ParentHashes) - 1) //nolint:gosec // G115: parent count is small
}
if hasGenerationV2 && v.GenerationV2Data() > math.MaxUint32 {
generationV2OverflowCount++
Expand All @@ -114,7 +115,7 @@ func (e *Encoder) prepare(idx Index, hashes []plumbing.Hash) (hashToIndex map[pl
func (e *Encoder) encodeFileHeader(chunkCount int) (err error) {
if _, err = e.Write(commitFileSignature); err == nil {
version := byte(1)
if crypto.Hash(e.hash.Size()) == crypto.Hash(crypto.SHA256.Size()) {
if crypto.Hash(e.hash.Size()) == crypto.Hash(crypto.SHA256.Size()) { //nolint:gosec // G115: hash.Size() is always small positive
version = byte(2)
}
_, err = e.Write([]byte{1, version, byte(chunkCount), 0})
Expand All @@ -124,7 +125,7 @@ func (e *Encoder) encodeFileHeader(chunkCount int) (err error) {

func (e *Encoder) encodeChunkHeaders(chunkSignatures [][]byte, chunkSizes []uint64) (err error) {
// 8 bytes of file header, 12 bytes for each chunk header and 12 byte for terminator
offset := uint64(szSignature + szHeader + (len(chunkSignatures)+1)*(szChunkSig+szUint64))
offset := uint64(szSignature + szHeader + (len(chunkSignatures)+1)*(szChunkSig+szUint64)) //nolint:gosec // G115: small constants
for i, signature := range chunkSignatures {
if _, err = e.Write(signature); err == nil {
err = binary.WriteUint64(e, offset)
Expand Down Expand Up @@ -182,7 +183,7 @@ func (e *Encoder) encodeCommitData(hashes []plumbing.Hash, hashToIndex map[plumb
parent2 = hashToIndex[commitData.ParentHashes[1]]
default:
parent1 = hashToIndex[commitData.ParentHashes[0]]
parent2 = uint32(len(extraEdges)) | parentOctopusUsed
parent2 = uint32(len(extraEdges)) | parentOctopusUsed //nolint:gosec // G115: extraEdges count is bounded
for _, parentHash := range commitData.ParentHashes[1:] {
extraEdges = append(extraEdges, hashToIndex[parentHash])
}
Expand All @@ -196,7 +197,7 @@ func (e *Encoder) encodeCommitData(hashes []plumbing.Hash, hashToIndex map[plumb
return extraEdges, generationV2Data, err
}

unixTime := uint64(commitData.When.Unix())
unixTime := uint64(commitData.When.Unix()) //nolint:gosec // G115: Unix timestamp is always positive for valid commits
unixTime |= uint64(commitData.Generation) << 34
if err = binary.WriteUint64(e, unixTime); err != nil {
return extraEdges, generationV2Data, err
Expand All @@ -222,7 +223,7 @@ func (e *Encoder) encodeGenerationV2Data(generationV2Data []uint64) (overflows [
for _, data := range generationV2Data {
if data >= 0x80000000 {
// overflow
if err = binary.WriteUint32(e, uint32(head)|0x80000000); err != nil {
if err = binary.WriteUint32(e, uint32(head)|0x80000000); err != nil { //nolint:gosec // G115: head is bounded
return nil, err
}
generationV2Data[head] = data
Expand Down
4 changes: 2 additions & 2 deletions plumbing/format/commitgraph/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func (fi *fileIndex) readChunkHeaders() error {
if chunkType == ZeroChunk || int(chunkType) >= len(fi.offsets) {
break
}
fi.offsets[chunkType] = int64(chunkOffset)
fi.offsets[chunkType] = int64(chunkOffset) //nolint:gosec // G115: file offset fits in int64
}

if fi.offsets[OIDFanoutChunk] <= 0 || fi.offsets[OIDLookupChunk] <= 0 || fi.offsets[CommitDataChunk] <= 0 {
Expand Down Expand Up @@ -332,7 +332,7 @@ func (fi *fileIndex) GetCommitDataByIndex(idx uint32) (*CommitData, error) {
ParentHashes: parentHashes,
Generation: genAndTime >> 34,
GenerationV2: generationV2,
When: time.Unix(int64(genAndTime&0x3FFFFFFFF), 0),
When: time.Unix(int64(genAndTime&0x3FFFFFFFF), 0), //nolint:gosec // G115: masked timestamp fits in int64
}, nil
}

Expand Down
8 changes: 4 additions & 4 deletions plumbing/format/commitgraph/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (mi *MemoryIndex) GetIndexByHash(h plumbing.Hash) (uint32, error) {

// GetHashByIndex gets the hash given an index in the commit graph
func (mi *MemoryIndex) GetHashByIndex(i uint32) (plumbing.Hash, error) {
if i >= uint32(len(mi.commitData)) {
if i >= uint32(len(mi.commitData)) { //nolint:gosec // G115: len fits in uint32
return plumbing.ZeroHash, plumbing.ErrObjectNotFound
}

Expand All @@ -49,7 +49,7 @@ func (mi *MemoryIndex) GetHashByIndex(i uint32) (plumbing.Hash, error) {
// GetCommitDataByIndex gets the commit node from the commit graph using index
// obtained from child node, if available
func (mi *MemoryIndex) GetCommitDataByIndex(i uint32) (*CommitData, error) {
if i >= uint32(len(mi.commitData)) {
if i >= uint32(len(mi.commitData)) { //nolint:gosec // G115: len fits in uint32
return nil, plumbing.ErrObjectNotFound
}

Expand Down Expand Up @@ -85,7 +85,7 @@ func (mi *MemoryIndex) Add(hash plumbing.Hash, data *CommitData) {
// which allows adding nodes out of order as long as all parents
// are eventually resolved
data.ParentIndexes = nil
mi.indexMap[hash] = uint32(len(mi.commitData))
mi.indexMap[hash] = uint32(len(mi.commitData)) //nolint:gosec // G115: len fits in uint32
mi.commitData = append(mi.commitData, commitData{Hash: hash, CommitData: data})
if data.GenerationV2 == math.MaxUint64 { // if GenerationV2 is not available reset it to zero
data.GenerationV2 = 0
Expand All @@ -105,5 +105,5 @@ func (mi *MemoryIndex) Close() error {

// MaximumNumberOfHashes returns the maximum number of hashes in the index.
func (mi *MemoryIndex) MaximumNumberOfHashes() uint32 {
return uint32(len(mi.indexMap))
return uint32(len(mi.indexMap)) //nolint:gosec // G115: len fits in uint32
}
2 changes: 1 addition & 1 deletion plumbing/format/idxfile/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func readObjectNames(idx *MemoryIndex, r io.Reader) error {

idx.FanoutMapping[k] = len(idx.Names)

nameLen := int(buckets * uint32(idx.idSize()))
nameLen := int(buckets * uint32(idx.idSize())) //nolint:gosec // G115: idSize() returns small hash size (20 or 32)
bin := make([]byte, nameLen)
if _, err := io.ReadFull(r, bin); err != nil {
return err
Expand Down
11 changes: 7 additions & 4 deletions plumbing/format/idxfile/idxfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,16 @@ func (idx *MemoryIndex) findHashIndex(h plumbing.Hash) (int, bool) {
low := uint64(0)
for {
mid := (low + high) >> 1
//nolint:gosec // G115: idSize() returns small hash size (20 or 32)
offset := mid * uint64(idx.idSize())

//nolint:gosec // G115: idSize() returns small hash size (20 or 32)
cmp := h.Compare(data[offset : offset+uint64(idx.idSize())])
switch {
case cmp < 0:
high = mid
case cmp == 0:
return int(mid), true
return int(mid), true //nolint:gosec // G115: mid is bounded by index size
default:
low = mid + 1
}
Expand Down Expand Up @@ -141,10 +143,10 @@ func (idx *MemoryIndex) FindOffset(h plumbing.Hash) (int64, error) {
if idx.offsetHash == nil {
idx.offsetHash = make(map[int64]plumbing.Hash)
}
idx.offsetHash[int64(offset)] = h
idx.offsetHash[int64(offset)] = h //nolint:gosec // G115: packfile offsets fit in int64
idx.mu.Unlock()

return int64(offset), nil
return int64(offset), nil //nolint:gosec // G115: packfile offsets fit in int64
}

const isO64Mask = uint64(1) << 31
Expand Down Expand Up @@ -227,8 +229,9 @@ func (idx *MemoryIndex) genOffsetHash() error {
for firstLevel, fanoutValue := range idx.Fanout {
mappedFirstLevel := idx.FanoutMapping[firstLevel]
for secondLevel := uint32(0); i < fanoutValue; i++ {
//nolint:gosec // G115: idSize() returns small hash size (20 or 32)
_, _ = hash.Write(idx.Names[mappedFirstLevel][secondLevel*uint32(idx.idSize()):])
offset := int64(idx.getOffset(mappedFirstLevel, int(secondLevel)))
offset := int64(idx.getOffset(mappedFirstLevel, int(secondLevel))) //nolint:gosec // G115: offsets fit in int64
offsetHash[offset] = hash
secondLevel++
}
Expand Down
10 changes: 5 additions & 5 deletions plumbing/format/idxfile/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (w *Writer) OnInflatedObjectHeader(_ plumbing.ObjectType, _, _ int64) error

// OnInflatedObjectContent implements packfile.Observer interface.
func (w *Writer) OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, _ []byte) error {
w.Add(h, uint64(pos), crc)
w.Add(h, uint64(pos), crc) //nolint:gosec // G115: pos is always non-negative in packfile
return nil
}

Expand Down Expand Up @@ -114,11 +114,11 @@ func (w *Writer) createIndex() (*MemoryIndex, error) {

// fill the gaps between fans
for j := last + 1; j < int(fan); j++ {
idx.Fanout[j] = uint32(i)
idx.Fanout[j] = uint32(i) //nolint:gosec // G115: i is loop index bounded by objects count
}

// update the number of objects for this position
idx.Fanout[fan] = uint32(i + 1)
idx.Fanout[fan] = uint32(i + 1) //nolint:gosec // G115: i is loop index bounded by objects count

// we move from one bucket to another, update counters and allocate
// memory
Expand All @@ -144,7 +144,7 @@ func (w *Writer) createIndex() (*MemoryIndex, error) {
}

buf.Truncate(0)
if err := binary.WriteUint32(buf, uint32(offset)); err != nil {
if err := binary.WriteUint32(buf, uint32(offset)); err != nil { //nolint:gosec // G115: checked against limit above
return nil, err
}
idx.Offset32[bucket] = append(idx.Offset32[bucket], buf.Bytes()...)
Expand All @@ -157,7 +157,7 @@ func (w *Writer) createIndex() (*MemoryIndex, error) {
}

for j := last + 1; j < 256; j++ {
idx.Fanout[j] = uint32(len(w.objects))
idx.Fanout[j] = uint32(len(w.objects)) //nolint:gosec // G115: objects count fits in uint32
}

idx.Version = VersionSupported
Expand Down
3 changes: 2 additions & 1 deletion plumbing/format/index/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ func (d *Decoder) readExtension(idx *Index) error {
default:
// See https://git-scm.com/docs/index-format, which says:
// If the first byte is 'A'..'Z' the extension is optional and can be ignored.
if header[0] < 'A' || header[0] > 'Z' {
first := header[0]
if first < 'A' || first > 'Z' {
return ErrUnknownExtension
}

Expand Down
8 changes: 4 additions & 4 deletions plumbing/format/index/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (e *Encoder) encodeHeader(idx *Index) error {
return binary.Write(e.w,
indexSignature,
idx.Version,
uint32(len(idx.Entries)),
uint32(len(idx.Entries)), //nolint:gosec // G115: entries count fits in uint32
)
}

Expand Down Expand Up @@ -102,7 +102,7 @@ func (e *Encoder) encodeEntry(idx *Index, entry *Entry) error {
return err
}

flags := uint16(entry.Stage&0x3) << 12
flags := uint16(entry.Stage&0x3) << 12 //nolint:gosec // G115: Stage is masked to 2 bits (0-3)
if l := len(entry.Name); l < nameMask {
flags |= uint16(l)
} else {
Expand Down Expand Up @@ -191,7 +191,7 @@ func (e *Encoder) encodeRawExtension(signature string, data []byte) error {
return err
}

err = binary.WriteUint32(e.w, uint32(len(data)))
err = binary.WriteUint32(e.w, uint32(len(data))) //nolint:gosec // G115: data length fits in uint32
if err != nil {
return err
}
Expand All @@ -213,7 +213,7 @@ func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
return 0, 0, ErrInvalidTimestamp
}

return uint32(t.Unix()), uint32(t.Nanosecond()), nil
return uint32(t.Unix()), uint32(t.Nanosecond()), nil //nolint:gosec // G115: checked non-negative above
}

func (e *Encoder) padEntry(idx *Index, wrote int) error {
Expand Down
3 changes: 2 additions & 1 deletion plumbing/format/packfile/delta_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ func (s *deltaIndexScanner) scan(buf []byte, end int) {
}

func tableSize(worstCaseBlockCnt int) int {
//nolint:gosec // G115: int to uint32 for hash calculation
shift := 32 - leadingZeros(uint32(worstCaseBlockCnt))
sz := 1 << uint(shift-1)
sz := 1 << uint(shift-1) //nolint:gosec // G115: shift is bounded by leading zeros calculation
if sz < worstCaseBlockCnt {
sz <<= 1
}
Expand Down
12 changes: 9 additions & 3 deletions plumbing/format/packfile/delta_selector.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package packfile

import (
"math"
"sort"
"sync"

Expand Down Expand Up @@ -220,12 +221,17 @@ func (dw *deltaSelector) walk(
objectsToPack []*ObjectToPack,
packWindow uint,
) error {
window := math.MaxInt
if packWindow < uint(math.MaxInt) {
window = int(packWindow)
}

indexMap := make(map[plumbing.Hash]*deltaIndex)
for i := range len(objectsToPack) {
// Clean up the index map and reconstructed delta objects for anything
// outside our pack window, to save memory.
if i > int(packWindow) {
obj := objectsToPack[i-int(packWindow)]
if i > window {
obj := objectsToPack[i-window]

delete(indexMap, obj.Hash())

Expand All @@ -249,7 +255,7 @@ func (dw *deltaSelector) walk(
continue
}

for j := i - 1; j >= 0 && i-j < int(packWindow); j-- {
for j := i - 1; j >= 0 && i-j < window; j-- {
base := objectsToPack[j]
// Objects must use only the same type as their delta base.
// Since objectsToPack is sorted by type and size, once we find
Expand Down
2 changes: 1 addition & 1 deletion plumbing/format/packfile/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func (e *Encoder) head(numEntries int) error {
e.w,
signature,
int32(VersionSupported),
int32(numEntries),
int32(numEntries), //nolint:gosec // G115: numEntries is bounded by packfile limits
)
}

Expand Down
2 changes: 1 addition & 1 deletion plumbing/format/packfile/packfile_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (i *objectIter) next() (plumbing.EncodedObject, error) {
return nil, err
}

oh, err := i.p.headerFromOffset(int64(e.Offset))
oh, err := i.p.headerFromOffset(int64(e.Offset)) //nolint:gosec // G115: offset fits in int64
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion plumbing/format/packfile/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ func (p *Parser) applyPatchBaseHeader(ota *ObjectHeader, delta io.Reader, target

if ota.Hash == plumbing.ZeroHash {
ota.Type = typ
ota.Size = int64(sz)
ota.Size = int64(sz) //nolint:gosec // G115: sz is object size from packfile
ota.Hash = h
}

Expand Down
Loading
Loading