aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Runxi Yu2025-11-17 00:00:00 +0000
committerGravatar Runxi Yu2025-11-17 00:00:00 +0000
commit1dcb92427c23d0a8b23c0154b892243c749afa5a (patch)
tree0683fa19e05d2ea0ceac324dafdcd49eb6cdb2ec
parentAdd internal todo (diff)
signature
Compute checksum when reading packfiles
-rw-r--r--pack_idx.go17
-rw-r--r--pack_midx.go18
-rw-r--r--pack_pack.go24
-rw-r--r--repo.go2
4 files changed, 58 insertions, 3 deletions
diff --git a/pack_idx.go b/pack_idx.go
index 03397286..3cb89701 100644
--- a/pack_idx.go
+++ b/pack_idx.go
@@ -196,6 +196,23 @@ func (pi *packIndex) parse(buf []byte) error {
pi.numObjects = nobj
pi.names = buf[namesStart:namesEnd]
pi.crcs = buf[crcStart:crcEnd]
+
+ if len(buf) < 2*pi.repo.hashSize {
+ return ErrInvalidObject
+ }
+ idxChecksumStart := len(buf) - pi.repo.hashSize
+ idxChecksumInFile := buf[idxChecksumStart:]
+
+ hashFn, ok := hashFuncs[pi.repo.hashSize]
+ if !ok {
+ return fmt.Errorf("furgit: unsupported hash size %d", pi.repo.hashSize)
+ }
+
+ computedHash := hashFn(buf[:idxChecksumStart])
+ if !bytes.Equal(computedHash.data[:pi.repo.hashSize], idxChecksumInFile) {
+ return fmt.Errorf("furgit: index checksum mismatch in %s", pi.idxRel)
+ }
+
return nil
}
diff --git a/pack_midx.go b/pack_midx.go
index 748bdaf6..04151dfe 100644
--- a/pack_midx.go
+++ b/pack_midx.go
@@ -1,6 +1,7 @@
package furgit
import (
+ "bytes"
"fmt"
"os"
"path/filepath"
@@ -235,6 +236,23 @@ func (midx *multiPackIndex) parse(buf []byte) error {
midx.oids = oids
midx.offsets = offsets
midx.largeOffs = largeOffs
+
+ if len(buf) < midx.repo.hashSize {
+ return ErrInvalidObject
+ }
+ midxChecksumStart := len(buf) - midx.repo.hashSize
+ midxChecksumInFile := buf[midxChecksumStart:]
+
+ hashFn, ok := hashFuncs[midx.repo.hashSize]
+ if !ok {
+ return fmt.Errorf("furgit: unsupported hash size %d", midx.repo.hashSize)
+ }
+
+ computedHash := hashFn(buf[:midxChecksumStart])
+ if !bytes.Equal(computedHash.data[:midx.repo.hashSize], midxChecksumInFile) {
+ return fmt.Errorf("furgit: multi-pack-index checksum mismatch")
+ }
+
return nil
}
diff --git a/pack_pack.go b/pack_pack.go
index 5c2c8628..6d740b73 100644
--- a/pack_pack.go
+++ b/pack_pack.go
@@ -487,7 +487,7 @@ type packFile struct {
closeMu sync.Once
}
-func openPackFile(absPath, rel string) (*packFile, error) {
+func openPackFile(absPath, rel string, hashSize int) (*packFile, error) {
f, err := os.Open(absPath)
if err != nil {
return nil, err
@@ -498,7 +498,7 @@ func openPackFile(absPath, rel string) (*packFile, error) {
_ = f.Close()
return nil, err
}
- if stat.Size() < 12 {
+ if stat.Size() < 12+int64(hashSize) {
_ = f.Close()
return nil, ErrInvalidObject
}
@@ -532,6 +532,26 @@ func openPackFile(absPath, rel string) (*packFile, error) {
_ = syscall.Munmap(region)
return nil, err
}
+
+ if len(region) < hashSize {
+ _ = syscall.Munmap(region)
+ return nil, ErrInvalidObject
+ }
+ dataEnd := len(region) - hashSize
+ checksumInFile := region[dataEnd:]
+
+ hashFn, ok := hashFuncs[hashSize]
+ if !ok {
+ _ = syscall.Munmap(region)
+ return nil, fmt.Errorf("furgit: unsupported hash size %d", hashSize)
+ }
+
+ computedHash := hashFn(region[:dataEnd])
+ if !bytes.Equal(computedHash.data[:hashSize], checksumInFile) {
+ _ = syscall.Munmap(region)
+ return nil, fmt.Errorf("furgit: pack checksum mismatch in %s", rel)
+ }
+
return &packFile{
relPath: rel,
size: stat.Size(),
diff --git a/repo.go b/repo.go
index 0fdfa5dd..50849c0d 100644
--- a/repo.go
+++ b/repo.go
@@ -132,7 +132,7 @@ func (repo *Repository) packFile(rel string) (*packFile, error) {
if pf, ok := repo.packFiles.Load(rel); ok {
return pf.(*packFile), nil
}
- pf, err := openPackFile(repo.repoPath(rel), rel)
+ pf, err := openPackFile(repo.repoPath(rel), rel, repo.hashSize)
if err != nil {
return nil, err
}