filer leveldb2: saturate size options instead of overflowing int

The option fields take int, so a MiB config value past math.MaxInt/MiB
(e.g. 2048 on 32-bit) wrapped negative and goleveldb would panic sizing
the memtable. Clamp the product instead of the input.
This commit is contained in:
Devin
2026-10-21 15:11:42 -07:00
parent fcf4d7c156
commit e93e7fadc5
2 changed files with 27 additions and 4 deletions
+14 -4
View File
@@ -6,6 +6,7 @@ import (
"crypto/md5"
"fmt"
"io"
"math"
"os"
"github.com/syndtr/goleveldb/leveldb"
@@ -56,20 +57,29 @@ func (store *LevelDB2Store) buildOptions() *opt.Options {
ReadOnly: store.ReadOnly,
}
if store.blockCacheSizeMB > 0 {
opts.BlockCacheCapacity = store.blockCacheSizeMB * 1024 * 1024
opts.BlockCacheCapacity = scaled(store.blockCacheSizeMB, 1<<20)
}
if store.writeBufferSizeMB > 0 {
opts.WriteBuffer = store.writeBufferSizeMB * 1024 * 1024
opts.WriteBuffer = scaled(store.writeBufferSizeMB, 1<<20)
}
if store.blockSizeKB > 0 {
opts.BlockSize = store.blockSizeKB * 1024
opts.BlockSize = scaled(store.blockSizeKB, 1<<10)
}
if store.compactionTableSizeMB > 0 {
opts.CompactionTableSize = store.compactionTableSizeMB * 1024 * 1024
opts.CompactionTableSize = scaled(store.compactionTableSizeMB, 1<<20)
}
return opts
}
// scaled converts a size option to bytes, saturating instead of wrapping a
// huge value into a negative int on 32-bit builds.
func scaled(v, scale int) int {
if v > math.MaxInt/scale {
return math.MaxInt
}
return v * scale
}
func (store *LevelDB2Store) initialize(dir string, dbCount int) (err error) {
glog.Infof("filer store leveldb2 dir: %s", dir)
os.MkdirAll(dir, 0755)
@@ -2,6 +2,7 @@ package leveldb
import (
"context"
"math"
"testing"
"github.com/seaweedfs/seaweedfs/weed/filer"
@@ -138,6 +139,18 @@ func TestInitializeDefaultOptions(t *testing.T) {
}
}
func TestScaledSaturates(t *testing.T) {
if got := scaled(math.MaxInt, 1<<20); got != math.MaxInt {
t.Errorf("expected saturation at %d, got %d", math.MaxInt, got)
}
if got := scaled(64, 1<<20); got != 64*1024*1024 {
t.Errorf("expected 64MiB, got %d", got)
}
if got := scaled(4, 1<<10); got != 4*1024 {
t.Errorf("expected 4KiB, got %d", got)
}
}
func TestEmptyRoot(t *testing.T) {
testFiler := filer.NewFiler(pb.ServerDiscovery{}, nil, "", "", "", "", "", 255, nil)
dir := t.TempDir()