mirror of
https://github.com/FiloSottile/age.git
synced 2026-09-04 07:07:16 +00:00
internal/stream: reject negative and overflowing encrypted sizes
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
@@ -20,6 +21,9 @@ import (
|
||||
const ChunkSize = 64 * 1024
|
||||
|
||||
func EncryptedChunkCount(encryptedSize int64) (int64, error) {
|
||||
if encryptedSize < 0 || encryptedSize > math.MaxInt64-encChunkSize+1 {
|
||||
return 0, fmt.Errorf("invalid encrypted payload size: %d", encryptedSize)
|
||||
}
|
||||
chunks := (encryptedSize + encChunkSize - 1) / encChunkSize
|
||||
|
||||
plaintextSize := encryptedSize - chunks*chacha20poly1305.Overhead
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
|
||||
@@ -631,6 +632,17 @@ func TestDecryptReaderAtInvalidSize(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Error("invalid size (empty final chunk): expected error, got nil")
|
||||
}
|
||||
|
||||
// Negative sizes and sizes that would overflow the chunk count computation
|
||||
// must be rejected with an error rather than a panic.
|
||||
for _, size := range []int64{-1, -70000, math.MaxInt64, math.MaxInt64 - 200, math.MaxInt64 - 65550} {
|
||||
if _, err := stream.EncryptedChunkCount(size); err == nil {
|
||||
t.Errorf("EncryptedChunkCount(%d): expected error, got nil", size)
|
||||
}
|
||||
if _, err := stream.NewDecryptReaderAt(key, bytes.NewReader(ciphertext), size); err == nil {
|
||||
t.Errorf("NewDecryptReaderAt(%d): expected error, got nil", size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecryptReaderAtTruncated(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user