Bound remote asset content verification

This commit is contained in:
2026-11-02 03:29:59 +00:00
parent 76676ee5a6
commit 2b23574ece
5 changed files with 149 additions and 10 deletions

View File

@@ -77,11 +77,11 @@ func inspectRemoteAssets(ctx context.Context, backend forge.Backend, releaseHand
case 0:
observation.State = AssetMissing
case 1:
digest, err := remoteAssetDigest(ctx, backend, matches[0].Handle)
digest, sizeMatches, err := remoteAssetDigest(ctx, backend, matches[0].Handle, item.Size)
if err != nil {
observation.State = AssetUnverifiable
observation.Err = err
} else if digest == item.SHA256 {
} else if sizeMatches && digest == item.SHA256 {
observation.State = AssetMatching
} else {
observation.State = AssetConflicting
@@ -99,18 +99,40 @@ func inspectRemoteAssets(ctx context.Context, backend forge.Backend, releaseHand
return inspection, nil
}
func remoteAssetDigest(ctx context.Context, backend forge.Backend, handle any) (string, error) {
func remoteAssetDigest(ctx context.Context, backend forge.Backend, handle any, expectedSize int64) (string, bool, error) {
if err := ctx.Err(); err != nil {
return "", false, err
}
stream, err := backend.OpenAsset(ctx, handle)
if err != nil {
return "", err
return "", false, err
}
hasher := sha256.New()
_, readErr := io.Copy(hasher, stream)
closeErr := stream.Close()
if err := errors.Join(readErr, closeErr); err != nil {
return "", &forge.Failure{Kind: forge.FailureUnverifiable, Err: err}
read, readErr := io.Copy(hasher, io.LimitReader(stream, expectedSize))
excess := false
if readErr == nil && read == expectedSize {
var probe [1]byte
for attempts := 0; ; attempts++ {
var n int
n, readErr = stream.Read(probe[:])
excess = n != 0
if readErr != nil || excess {
if readErr == io.EOF {
readErr = nil
}
break
}
if attempts == 99 {
readErr = io.ErrNoProgress
break
}
}
}
return hex.EncodeToString(hasher.Sum(nil)), nil
closeErr := stream.Close()
if err := errors.Join(readErr, closeErr, ctx.Err()); err != nil {
return "", false, &forge.Failure{Kind: forge.FailureUnverifiable, Err: err}
}
return hex.EncodeToString(hasher.Sum(nil)), read == expectedSize && !excess, nil
}
func uploadMissingAssets(ctx context.Context, backend forge.Backend, releaseHandle any, inspection Inspection) (result UploadResult, err error) {