From bd91bf5f3bcffe5d1023ab9a37e4a9425830aba9 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sun, 16 Nov 2025 00:00:00 +0000 Subject: hash: Make fewer helper functions need explicit hash length fields --- loose.go | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'loose.go') diff --git a/loose.go b/loose.go index c1371991..d79b2f48 100644 --- a/loose.go +++ b/loose.go @@ -12,9 +12,13 @@ import ( const looseHeaderLimit = 4096 -func loosePath(id Hash, hashSize int) string { - hex := id.StringWithSize(hashSize) - return filepath.Join("objects", hex[:2], hex[2:]) +// loosePath returns the path for a loose object, validating hash size. +func (repo *Repository) loosePath(id Hash) (string, error) { + if id.size != repo.HashSize { + return "", fmt.Errorf("furgit: hash size mismatch: got %d, expected %d", id.size, repo.HashSize) + } + hex := id.String() + return filepath.Join("objects", hex[:2], hex[2:]), nil } func (repo *Repository) looseRead(id Hash) (Object, error) { @@ -22,11 +26,15 @@ func (repo *Repository) looseRead(id Hash) (Object, error) { if err != nil { return nil, err } - return parseObjectBody(ty, id, body, repo.HashSize) + return parseObjectBody(ty, id, body, repo) } func (repo *Repository) looseReadTyped(id Hash) (ObjType, []byte, error) { - path := repo.repoPath(loosePath(id, repo.HashSize)) + path, err := repo.loosePath(id) + if err != nil { + return ObjInvalid, nil, err + } + path = repo.repoPath(path) f, err := os.Open(path) if err != nil { if os.IsNotExist(err) { @@ -62,7 +70,7 @@ func (repo *Repository) looseReadTyped(id Hash) (ObjType, []byte, error) { if declaredSize != int64(len(body)) { return ObjInvalid, nil, ErrInvalidObject } - if !verifyRawObject(raw, id, repo.HashSize) { + if !repo.verifyRawObject(raw, id) { return ObjInvalid, nil, ErrInvalidObject } @@ -71,7 +79,11 @@ func (repo *Repository) looseReadTyped(id Hash) (ObjType, []byte, error) { } func (repo *Repository) looseTypeSize(id Hash) (ObjType, int64, error) { - path := repo.repoPath(loosePath(id, repo.HashSize)) + path, err := repo.loosePath(id) + if err != nil { + return ObjInvalid, 0, err + } + path = repo.repoPath(path) // #nosec G304 f, err := os.Open(path) if err != nil { @@ -161,13 +173,13 @@ func (repo *Repository) WriteLooseObject(obj Object) (Hash, error) { switch o := obj.(type) { case *Blob: - raw, err = o.Serialize(repo.HashSize) + raw, err = o.Serialize() case *Tree: - raw, err = o.Serialize(repo.HashSize) + raw, err = o.Serialize() case *Commit: - raw, err = o.Serialize(repo.HashSize) + raw, err = o.Serialize() case *Tag: - raw, err = o.Serialize(repo.HashSize) + raw, err = o.Serialize() default: return Hash{}, fmt.Errorf("furgit: unsupported object type for writing: %T", obj) } @@ -177,8 +189,12 @@ func (repo *Repository) WriteLooseObject(obj Object) (Hash, error) { return Hash{}, err } - id := computeRawHash(raw, repo.HashSize) - path := repo.repoPath(loosePath(id, repo.HashSize)) + id := repo.computeRawHash(raw) + path, err := repo.loosePath(id) + if err != nil { + return Hash{}, err + } + path = repo.repoPath(path) if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return Hash{}, err -- cgit v1.3.1-10-gc9f91