mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-14 03:01:48 +00:00
Limit amount of data fetched from git repository.
Like limiting the size of an archive, it is a supplementary check meant to limit resource consumption prior to the final check done in `StoreManifest()`.
This commit is contained in:
23
src/fetch.go
23
src/fetch.go
@@ -23,6 +23,8 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var ErrRepositoryTooLarge = errors.New("repository too large")
|
||||
|
||||
func FetchRepository(
|
||||
ctx context.Context, repoURL string, branch string, oldManifest *Manifest,
|
||||
) (
|
||||
@@ -152,9 +154,10 @@ func FetchRepository(
|
||||
// This will only succeed if a `blob:none` filter isn't supported and we got a full
|
||||
// clone despite asking for a partial clone.
|
||||
for hash, manifestEntry := range blobsNeeded {
|
||||
if err := readGitBlob(repo, hash, manifestEntry); err == nil {
|
||||
dataBytesTransferred += manifestEntry.GetOriginalSize()
|
||||
if err := readGitBlob(repo, hash, manifestEntry, &dataBytesTransferred); err == nil {
|
||||
delete(blobsNeeded, hash)
|
||||
} else if errors.Is(err, ErrRepositoryTooLarge) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,10 +196,9 @@ func FetchRepository(
|
||||
|
||||
// All remaining blobs should now be available.
|
||||
for hash, manifestEntry := range blobsNeeded {
|
||||
if err := readGitBlob(repo, hash, manifestEntry); err != nil {
|
||||
if err := readGitBlob(repo, hash, manifestEntry, &dataBytesTransferred); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dataBytesTransferred += manifestEntry.GetOriginalSize()
|
||||
delete(blobsNeeded, hash)
|
||||
}
|
||||
}
|
||||
@@ -210,7 +212,9 @@ func FetchRepository(
|
||||
return manifest, nil
|
||||
}
|
||||
|
||||
func readGitBlob(repo *git.Repository, hash plumbing.Hash, entry *Entry) error {
|
||||
func readGitBlob(
|
||||
repo *git.Repository, hash plumbing.Hash, entry *Entry, bytesTransferred *int64,
|
||||
) error {
|
||||
blob, err := repo.BlobObject(hash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("git blob %s: %w", hash, err)
|
||||
@@ -239,5 +243,14 @@ func readGitBlob(repo *git.Repository, hash plumbing.Hash, entry *Entry) error {
|
||||
entry.Transform = Transform_Identity.Enum()
|
||||
entry.OriginalSize = proto.Int64(blob.Size)
|
||||
entry.CompressedSize = proto.Int64(blob.Size)
|
||||
|
||||
*bytesTransferred += blob.Size
|
||||
if uint64(*bytesTransferred) > config.Limits.MaxSiteSize.Bytes() {
|
||||
return fmt.Errorf("%w: fetch exceeds %s limit",
|
||||
ErrRepositoryTooLarge,
|
||||
config.Limits.MaxSiteSize.HR(),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -607,6 +607,8 @@ func reportUpdateResult(w http.ResponseWriter, r *http.Request, result UpdateRes
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
} else if errors.Is(result.err, ErrArchiveTooLarge) {
|
||||
w.WriteHeader(http.StatusRequestEntityTooLarge)
|
||||
} else if errors.Is(result.err, ErrRepositoryTooLarge) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
} else if errors.Is(result.err, ErrMalformedPatch) {
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
} else if errors.Is(result.err, ErrPreconditionFailed) {
|
||||
|
||||
Reference in New Issue
Block a user