From 7e66c81be27e564fbf75bb353662d73ecf11b545 Mon Sep 17 00:00:00 2001 From: Eshiv Pandey Date: Wed, 5 Aug 2026 22:35:37 +0530 Subject: [PATCH 1/3] fix(hygon,metax): guard int32 narrowing in GenerateResourceRequests GenerateResourceRequests in the hygon and metax-sgpu backends converts user-controlled int64 resource limits (count, memory, cores) into int32 fields on ContainerDeviceRequest (Nums, Memreq, Coresreq) without bounds checking. A limit exceeding math.MaxInt32 silently wraps, producing an incorrect small or negative value that flows into Fit(). For example, hygon.com/dcumem: 16Gi yields AsInt64() = 17179869184. After applying MemoryFactor, int32(result) wraps to 0, causing the scheduler to treat the device as having sufficient memory when it does not. Add range guards that return empty ContainerDeviceRequest{} (the existing reject sentinel) before any int32() narrowing, matching the overflow protection already in enflame, iluvatar, mthreads, and amd backends. Add test coverage for pre-factor overflow (16Gi direct) and post-factor overflow (3000000 * 1024 > MaxInt32) in hygon, and out-of-range memory in metax-sgpu. AI assistance disclosure: I used an AI tool for codebase navigation and review support. Signed-off-by: Eshiv Pandey --- pkg/device/hygon/device.go | 17 +++++++++++++++ pkg/device/hygon/device_test.go | 36 ++++++++++++++++++++++++++++++++ pkg/device/metax/sdevice.go | 15 ++++++++++++- pkg/device/metax/sdevice_test.go | 13 ++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/pkg/device/hygon/device.go b/pkg/device/hygon/device.go index 0852ba3e5d..5464c98303 100644 --- a/pkg/device/hygon/device.go +++ b/pkg/device/hygon/device.go @@ -19,6 +19,7 @@ package hygon import ( "errors" "flag" + "math" "slices" "strings" @@ -175,6 +176,10 @@ func (dev *DCUDevices) GenerateResourceRequests(ctr *corev1.Container) device.Co } if ok { if n, ok := v.AsInt64(); ok { + if n <= 0 || n > math.MaxInt32 { + klog.ErrorS(nil, "dcu device count request is out of range", "container", ctr.Name, "request", n) + return device.ContainerDeviceRequest{} + } klog.Info("Found dcu devices") memnum := 0 mem, ok := ctr.Resources.Limits[dcuResourceMem] @@ -184,9 +189,17 @@ func (dev *DCUDevices) GenerateResourceRequests(ctr *corev1.Container) device.Co if ok { memnums, ok := mem.AsInt64() if ok { + if memnums < 0 || memnums > math.MaxInt32 { + klog.ErrorS(nil, "dcu device memory request is out of range", "container", ctr.Name, "request", mem.String()) + return device.ContainerDeviceRequest{} + } if MemoryFactor > 1 { rawMemnums := memnums memnums = memnums * int64(MemoryFactor) + if memnums > math.MaxInt32 { + klog.ErrorS(nil, "dcu device memory request overflows int32 after applying memory factor", "container", ctr.Name, "raw", rawMemnums, "scaled", memnums, "factor", MemoryFactor) + return device.ContainerDeviceRequest{} + } klog.V(4).Infof("Update memory request. before %d, after %d, factor %d", rawMemnums, memnums, MemoryFactor) } memnum = int(memnums) @@ -200,6 +213,10 @@ func (dev *DCUDevices) GenerateResourceRequests(ctr *corev1.Container) device.Co if ok { corenums, ok := core.AsInt64() if ok { + if corenums < 0 || corenums > math.MaxInt32 { + klog.ErrorS(nil, "dcu device core request is out of range", "container", ctr.Name, "request", core.String()) + return device.ContainerDeviceRequest{} + } corenum = int32(corenums) } } diff --git a/pkg/device/hygon/device_test.go b/pkg/device/hygon/device_test.go index 0811002227..292e208003 100644 --- a/pkg/device/hygon/device_test.go +++ b/pkg/device/hygon/device_test.go @@ -592,6 +592,18 @@ func Test_GenerateResourceRequests(t *testing.T) { Coresreq: int32(1), }, }, + { + name: "oversized dcu memory request exceeds int32 range", + args: &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "hygon.com/dcunum": resource.MustParse("1"), + "hygon.com/dcumem": resource.MustParse("16Gi"), + }, + }, + }, + want: device.ContainerDeviceRequest{}, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -604,6 +616,30 @@ func Test_GenerateResourceRequests(t *testing.T) { } } +// Test_GenerateResourceRequests_MemoryFactorOverflow covers the case where the +// raw memory request fits in int32 but overflows once MemoryFactor is applied. +func Test_GenerateResourceRequests_MemoryFactorOverflow(t *testing.T) { + origFactor := MemoryFactor + MemoryFactor = 1024 + defer func() { MemoryFactor = origFactor }() + + dev := DCUDevices{} + fs := flag.FlagSet{} + ParseConfig(&fs) + + // 3000000 fits in int32, but 3000000 * 1024 exceeds math.MaxInt32. + ctr := &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "hygon.com/dcunum": resource.MustParse("1"), + "hygon.com/dcumem": resource.MustParse("3000000"), + }, + }, + } + result := dev.GenerateResourceRequests(ctr) + assert.DeepEqual(t, result, device.ContainerDeviceRequest{}) +} + func TestDevices_LockNode(t *testing.T) { tests := []struct { name string diff --git a/pkg/device/metax/sdevice.go b/pkg/device/metax/sdevice.go index d716fdc59c..a31a895fe6 100644 --- a/pkg/device/metax/sdevice.go +++ b/pkg/device/metax/sdevice.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "maps" + "math" "slices" "sort" "strconv" @@ -229,11 +230,19 @@ func (sdev *MetaxSDevices) GenerateResourceRequests(ctr *corev1.Container) devic ctr.Name, MetaxResourceNameVCount) return device.ContainerDeviceRequest{} } + if count <= 0 || count > math.MaxInt32 { + klog.ErrorS(nil, "metax sgpu device count request is out of range", "container", ctr.Name, "request", count) + return device.ContainerDeviceRequest{} + } core := int64(100) coreQuantity, ok := ctr.Resources.Limits[corev1.ResourceName(MetaxResourceNameVCore)] if ok { if v, ok := coreQuantity.AsInt64(); ok { + if v < 0 || v > math.MaxInt32 { + klog.ErrorS(nil, "metax sgpu device core request is out of range", "container", ctr.Name, "request", coreQuantity.String()) + return device.ContainerDeviceRequest{} + } core = v } } @@ -250,7 +259,11 @@ func (sdev *MetaxSDevices) GenerateResourceRequests(ctr *corev1.Container) devic if hasUnit { mem = v / 1024 / 1024 } else { - mem = v * MemoryFactor + mem = v * int64(MemoryFactor) + } + if mem < 0 || mem > math.MaxInt32 { + klog.ErrorS(nil, "metax sgpu device memory request is out of range", "container", ctr.Name, "request", memQuantity.String()) + return device.ContainerDeviceRequest{} } } } diff --git a/pkg/device/metax/sdevice_test.go b/pkg/device/metax/sdevice_test.go index b6603f6d28..f55d42606a 100644 --- a/pkg/device/metax/sdevice_test.go +++ b/pkg/device/metax/sdevice_test.go @@ -453,6 +453,19 @@ func TestGenerateResourceRequests(t *testing.T) { Coresreq: 60, }, }, + { + name: "oversized memory request exceeds int32 range", + container: &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "metax-tech.com/sgpu": resource.MustParse("1"), + "metax-tech.com/vmemory": resource.MustParse("2100001"), + }, + }, + }, + + expected: device.ContainerDeviceRequest{}, + }, } { t.Run(ts.name, func(t *testing.T) { metaxSDevice := &MetaxSDevices{} From 12ca202d378a12240db74bf66e2239fd749bba22 Mon Sep 17 00:00:00 2001 From: Eshiv Pandey Date: Wed, 5 Aug 2026 23:17:12 +0530 Subject: [PATCH 2/3] fix(metax): reject memory request before applying MemoryFactor The int32 range check ran after `mem = v * int64(MemoryFactor)`, so the multiplication could itself overflow int64 and wrap to a small in-range value that slipped past the check. Validate `v` against `math.MaxInt32 / MemoryFactor` before multiplying in the no-unit branch. Also add regression tests for the reachable overflow guards in both backends (device count and core out-of-range, negative core), raising patch coverage of the new validation paths. AI assistance disclosure: I used an AI tool for codebase navigation and review support. Signed-off-by: Eshiv Pandey --- pkg/device/hygon/device_test.go | 41 ++++++++++++++++++++++++++++++++ pkg/device/metax/sdevice.go | 7 ++++++ pkg/device/metax/sdevice_test.go | 26 ++++++++++++++++++-- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/pkg/device/hygon/device_test.go b/pkg/device/hygon/device_test.go index 292e208003..8c6f565adf 100644 --- a/pkg/device/hygon/device_test.go +++ b/pkg/device/hygon/device_test.go @@ -616,6 +616,47 @@ func Test_GenerateResourceRequests(t *testing.T) { } } +func Test_GenerateResourceRequests_OutOfRangeValues(t *testing.T) { + tests := []struct { + name string + args *corev1.Container + want device.ContainerDeviceRequest + }{ + { + name: "oversized dcu count exceeds int32 range", + args: &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "hygon.com/dcunum": resource.MustParse("2200000000"), + }, + }, + }, + want: device.ContainerDeviceRequest{}, + }, + { + name: "negative dcu cores", + args: &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "hygon.com/dcunum": resource.MustParse("1"), + "hygon.com/dcucores": resource.MustParse("-1"), + }, + }, + }, + want: device.ContainerDeviceRequest{}, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + dev := DCUDevices{} + fs := flag.FlagSet{} + ParseConfig(&fs) + result := dev.GenerateResourceRequests(test.args) + assert.DeepEqual(t, result, test.want) + }) + } +} + // Test_GenerateResourceRequests_MemoryFactorOverflow covers the case where the // raw memory request fits in int32 but overflows once MemoryFactor is applied. func Test_GenerateResourceRequests_MemoryFactorOverflow(t *testing.T) { diff --git a/pkg/device/metax/sdevice.go b/pkg/device/metax/sdevice.go index a31a895fe6..55a0d7846f 100644 --- a/pkg/device/metax/sdevice.go +++ b/pkg/device/metax/sdevice.go @@ -259,6 +259,13 @@ func (sdev *MetaxSDevices) GenerateResourceRequests(ctr *corev1.Container) devic if hasUnit { mem = v / 1024 / 1024 } else { + // Guard the multiplication itself: v * MemoryFactor can overflow + // int64 and wrap to a small value that slips past the range check + // below, so reject before multiplying. + if v < 0 || v > int64(math.MaxInt32)/int64(MemoryFactor) { + klog.ErrorS(nil, "metax sgpu device memory request is out of range", "container", ctr.Name, "request", memQuantity.String()) + return device.ContainerDeviceRequest{} + } mem = v * int64(MemoryFactor) } if mem < 0 || mem > math.MaxInt32 { diff --git a/pkg/device/metax/sdevice_test.go b/pkg/device/metax/sdevice_test.go index f55d42606a..8bfa2d1799 100644 --- a/pkg/device/metax/sdevice_test.go +++ b/pkg/device/metax/sdevice_test.go @@ -454,7 +454,7 @@ func TestGenerateResourceRequests(t *testing.T) { }, }, { - name: "oversized memory request exceeds int32 range", + name: "oversized memory request exceeds int32 range (no unit, pre-multiply guard)", container: &corev1.Container{ Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ @@ -463,7 +463,29 @@ func TestGenerateResourceRequests(t *testing.T) { }, }, }, - + expected: device.ContainerDeviceRequest{}, + }, + { + name: "oversized sgpu count exceeds int32 range", + container: &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "metax-tech.com/sgpu": resource.MustParse("2200000000"), + }, + }, + }, + expected: device.ContainerDeviceRequest{}, + }, + { + name: "oversized vcore exceeds int32 range", + container: &corev1.Container{ + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "metax-tech.com/sgpu": resource.MustParse("1"), + "metax-tech.com/vcore": resource.MustParse("2200000000"), + }, + }, + }, expected: device.ContainerDeviceRequest{}, }, } { From d987f407b3242aeb8b867ea8a1180de6640d1c8e Mon Sep 17 00:00:00 2001 From: Eshiv Pandey Date: Thu, 6 Aug 2026 15:31:17 +0530 Subject: [PATCH 3/3] fix(metax): remove comments from sdevice.go Address review feedback: drop the explanatory comments on the pre-factor overflow guard in GenerateResourceRequests. The check is self-explanatory and the surrounding backends keep these guards uncommented. AI assistance disclosure: I used an AI tool for codebase navigation and review support. Signed-off-by: Eshiv Pandey --- pkg/device/metax/sdevice.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/device/metax/sdevice.go b/pkg/device/metax/sdevice.go index 55a0d7846f..4cc947b6fe 100644 --- a/pkg/device/metax/sdevice.go +++ b/pkg/device/metax/sdevice.go @@ -259,9 +259,6 @@ func (sdev *MetaxSDevices) GenerateResourceRequests(ctr *corev1.Container) devic if hasUnit { mem = v / 1024 / 1024 } else { - // Guard the multiplication itself: v * MemoryFactor can overflow - // int64 and wrap to a small value that slips past the range check - // below, so reject before multiplying. if v < 0 || v > int64(math.MaxInt32)/int64(MemoryFactor) { klog.ErrorS(nil, "metax sgpu device memory request is out of range", "container", ctr.Name, "request", memQuantity.String()) return device.ContainerDeviceRequest{}