aboutsummaryrefslogtreecommitdiff
path: root/refstore/reftable
diff options
context:
space:
mode:
Diffstat (limited to 'refstore/reftable')
-rw-r--r--refstore/reftable/lookup.go46
-rw-r--r--refstore/reftable/reftable_test.go15
-rw-r--r--refstore/reftable/table.go31
3 files changed, 70 insertions, 22 deletions
diff --git a/refstore/reftable/lookup.go b/refstore/reftable/lookup.go
index 24f9adb5..724a3727 100644
--- a/refstore/reftable/lookup.go
+++ b/refstore/reftable/lookup.go
@@ -5,13 +5,18 @@ import (
"fmt"
"strings"
+ "codeberg.org/lindenii/furgit/internal/intconv"
"codeberg.org/lindenii/furgit/objectid"
)
// resolveRecord resolves one ref name inside a single table file.
func (table *tableFile) resolveRecord(name string) (recordValue, bool, error) {
if table.refIndexPos != 0 {
- pos, ok, err := table.resolveRefBlockPosFromIndex(name, int(table.refIndexPos))
+ indexPos, err := intconv.Uint64ToInt(table.refIndexPos)
+ if err != nil {
+ return recordValue{}, false, err
+ }
+ pos, ok, err := table.resolveRefBlockPosFromIndex(name, indexPos)
if err != nil {
return recordValue{}, false, err
}
@@ -204,10 +209,11 @@ func lookupChildPosInIndexBlock(block blockView, key string) (int, bool, error)
return 0, false, err
}
if strings.Compare(key, name) <= 0 {
- if childPos > uint64(int(^uint(0)>>1)) {
- return 0, false, fmt.Errorf("index child position overflows int")
+ childPosInt, err := intconv.Uint64ToInt(childPos)
+ if err != nil {
+ return 0, false, fmt.Errorf("index child position conversion: %w", err)
}
- return int(childPos), true, nil
+ return childPosInt, true, nil
}
prev = name
off = nextOff
@@ -309,7 +315,7 @@ func parseBlockLayout(block blockView) (recordsStart int, recordsEnd int, restar
if restartsStart < 4 {
return 0, 0, nil, fmt.Errorf("invalid restart table")
}
- for i := 0; i < restartCount; i++ {
+ for i := range restartCount {
off := restartsStart + i*3
rel := int(readUint24(block.payload[off : off+3]))
base := block.start
@@ -357,14 +363,18 @@ func parseKeyedRecord(buf []byte, off, end int, prev string) (name string, rawTy
if err != nil {
return "", 0, 0, err
}
- suffixLen := int(suffixAndType >> 3)
- if suffixLen < 0 || next+suffixLen > end {
+ suffixLen, err := intconv.Uint64ToInt(suffixAndType >> 3)
+ if err != nil || suffixLen < 0 || next+suffixLen > end {
return "", 0, 0, fmt.Errorf("invalid suffix length")
}
- if int(prefixLen) > len(prev) {
+ prefixLenInt, err := intconv.Uint64ToInt(prefixLen)
+ if err != nil {
+ return "", 0, 0, fmt.Errorf("invalid prefix length")
+ }
+ if prefixLenInt > len(prev) {
return "", 0, 0, fmt.Errorf("invalid prefix length")
}
- name = prev[:prefixLen] + string(buf[next:next+suffixLen])
+ name = prev[:prefixLenInt] + string(buf[next:next+suffixLen])
next += suffixLen
if prev != "" && strings.Compare(name, prev) <= 0 {
return "", 0, 0, fmt.Errorf("keys not strictly increasing")
@@ -399,11 +409,23 @@ func parseRefValue(buf []byte, off, end int, algo objectid.Algorithm, valueType
if err != nil {
return recordValue{}, 0, err
}
- if targetLen > uint64(end-next) {
+ remaining := end - next
+ if remaining < 0 {
+ return recordValue{}, 0, fmt.Errorf("invalid symref target length")
+ }
+ remainingU64, err := intconv.IntToUint64(remaining)
+ if err != nil {
+ return recordValue{}, 0, fmt.Errorf("invalid symref target length")
+ }
+ if targetLen > remainingU64 {
+ return recordValue{}, 0, fmt.Errorf("invalid symref target length")
+ }
+ targetLenInt, err := intconv.Uint64ToInt(targetLen)
+ if err != nil {
return recordValue{}, 0, fmt.Errorf("invalid symref target length")
}
- target := string(buf[next : next+int(targetLen)])
- next += int(targetLen)
+ target := string(buf[next : next+targetLenInt])
+ next += targetLenInt
return recordValue{symbolicTarget: target}, next, nil
default:
return recordValue{}, 0, fmt.Errorf("unsupported ref value type %d", valueType)
diff --git a/refstore/reftable/reftable_test.go b/refstore/reftable/reftable_test.go
index d6345f14..2a6e0738 100644
--- a/refstore/reftable/reftable_test.go
+++ b/refstore/reftable/reftable_test.go
@@ -40,7 +40,8 @@ func openStore(tb testing.TB, repoDir string, algo objectid.Algorithm) *reftable
}
func TestResolveAndResolveFully(t *testing.T) {
- testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
repo := newBareReftableRepo(t, algo)
_, _, id := repo.MakeCommit(t, "resolve")
repo.UpdateRef(t, "refs/heads/main", id)
@@ -74,7 +75,8 @@ func TestResolveAndResolveFully(t *testing.T) {
}
func TestResolveFullyCycle(t *testing.T) {
- testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
repo := newBareReftableRepo(t, algo)
repo.SymbolicRef(t, "refs/heads/a", "refs/heads/b")
repo.SymbolicRef(t, "refs/heads/b", "refs/heads/a")
@@ -87,7 +89,8 @@ func TestResolveFullyCycle(t *testing.T) {
}
func TestListAndShorten(t *testing.T) {
- testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
repo := newBareReftableRepo(t, algo)
_, _, id := repo.MakeCommit(t, "list")
repo.UpdateRef(t, "refs/heads/main", id)
@@ -133,7 +136,8 @@ func TestListAndShorten(t *testing.T) {
}
func TestTombstoneNewestWins(t *testing.T) {
- testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
repo := newBareReftableRepo(t, algo)
_, _, oldID := repo.MakeCommit(t, "old")
repo.UpdateRef(t, "refs/heads/main", oldID)
@@ -149,7 +153,8 @@ func TestTombstoneNewestWins(t *testing.T) {
}
func TestAnnotatedTagPeeled(t *testing.T) {
- testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
repo := newBareReftableRepo(t, algo)
_, _, commitID := repo.MakeCommit(t, "tagged")
tagID := repo.TagAnnotated(t, "v1.0.0", commitID, "annotated")
diff --git a/refstore/reftable/table.go b/refstore/reftable/table.go
index bbef1957..35982bf9 100644
--- a/refstore/reftable/table.go
+++ b/refstore/reftable/table.go
@@ -8,6 +8,7 @@ import (
"os"
"syscall"
+ "codeberg.org/lindenii/furgit/internal/intconv"
"codeberg.org/lindenii/furgit/objectid"
"codeberg.org/lindenii/furgit/ref"
)
@@ -80,7 +81,12 @@ func openTableFile(root *os.Root, name string, algo objectid.Algorithm) (*tableF
_ = file.Close()
return nil, fmt.Errorf("refstore/reftable: table %q has unsupported size", name)
}
- data, err := syscall.Mmap(int(file.Fd()), 0, int(size), syscall.PROT_READ, syscall.MAP_PRIVATE)
+ fd, err := intconv.UintptrToInt(file.Fd())
+ if err != nil {
+ _ = file.Close()
+ return nil, err
+ }
+ data, err := syscall.Mmap(fd, 0, int(size), syscall.PROT_READ, syscall.MAP_PRIVATE)
if err != nil {
_ = file.Close()
return nil, err
@@ -178,7 +184,10 @@ func (table *tableFile) parseMeta() error {
_ = objIndexPos
_ = logIndexPos
- refEnd := uint64(footerStart)
+ refEnd, err := intconv.IntToUint64(footerStart)
+ if err != nil {
+ return fmt.Errorf("refstore/reftable: table %q: invalid footer offset: %w", table.name, err)
+ }
if table.refIndexPos != 0 && table.refIndexPos < refEnd {
refEnd = table.refIndexPos
}
@@ -188,13 +197,25 @@ func (table *tableFile) parseMeta() error {
if logPos != 0 && logPos < refEnd {
refEnd = logPos
}
- if refEnd < uint64(table.headerLen) || refEnd > uint64(len(table.data)) {
+ headerLenU64, err := intconv.IntToUint64(table.headerLen)
+ if err != nil {
+ return fmt.Errorf("refstore/reftable: table %q: invalid header length: %w", table.name, err)
+ }
+ dataLenU64, err := intconv.IntToUint64(len(table.data))
+ if err != nil {
+ return fmt.Errorf("refstore/reftable: table %q: invalid data length: %w", table.name, err)
+ }
+ if refEnd < headerLenU64 || refEnd > dataLenU64 {
return fmt.Errorf("refstore/reftable: table %q: invalid ref section", table.name)
}
- if table.refIndexPos > uint64(len(table.data)) {
+ if table.refIndexPos > dataLenU64 {
return fmt.Errorf("refstore/reftable: table %q: invalid ref index position", table.name)
}
- table.refEnd = int(refEnd)
+ refEndInt, err := intconv.Uint64ToInt(refEnd)
+ if err != nil {
+ return fmt.Errorf("refstore/reftable: table %q: invalid ref section end: %w", table.name, err)
+ }
+ table.refEnd = refEndInt
return nil
}