mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-29 06:31:58 +00:00
fix(service): keep chunk capacity math from overflowing
chunkStrings/chunkInts sized their result with (len+size-1)/size, so a size near MaxInt wrapped negative and make panicked with "cap out of range"; count the chunks with div+remainder instead. NormalizeUDPHop's len-hops+1 is bounded by len(masks) since hops >= 1, so cap at that. Resolves CodeQL go/allocation-size-overflow alerts #119 and #120.
This commit is contained in:
1 parent
b5a04ea95f
commit
ab1c509329
3 files changed
+29
-4
No files matched your search
@@ -51,7 +51,7 @@ func NormalizeUDPHop(finalmask any) bool {
|
|||||||
if last < 0 || (hops == 1 && last == len(masks)-1) {
|
if last < 0 || (hops == 1 && last == len(masks)-1) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
kept := make([]any, 0, len(masks)-hops+1)
|
kept := make([]any, 0, len(masks)) // hops >= 1, so the re-appended hop still fits
|
||||||
for _, mask := range masks {
|
for _, mask := range masks {
|
||||||
if !isUDPHopMask(mask) {
|
if !isUDPHopMask(mask) {
|
||||||
kept = append(kept, mask)
|
kept = append(kept, mask)
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func chunkStrings(s []string, size int) [][]string {
|
|||||||
if size <= 0 || len(s) == 0 {
|
if size <= 0 || len(s) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := make([][]string, 0, (len(s)+size-1)/size)
|
out := make([][]string, 0, chunkCount(len(s), size))
|
||||||
for i := 0; i < len(s); i += size {
|
for i := 0; i < len(s); i += size {
|
||||||
end := min(i+size, len(s))
|
end := min(i+size, len(s))
|
||||||
out = append(out, s[i:end])
|
out = append(out, s[i:end])
|
||||||
@@ -86,10 +86,19 @@ func chunkInts(s []int, size int) [][]int {
|
|||||||
if size <= 0 || len(s) == 0 {
|
if size <= 0 || len(s) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out := make([][]int, 0, (len(s)+size-1)/size)
|
out := make([][]int, 0, chunkCount(len(s), size))
|
||||||
for i := 0; i < len(s); i += size {
|
for i := 0; i < len(s); i += size {
|
||||||
end := min(i+size, len(s))
|
end := min(i+size, len(s))
|
||||||
out = append(out, s[i:end])
|
out = append(out, s[i:end])
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chunkCount is ceil(n/size) without the n+size-1 sum, which overflows for a size near MaxInt.
|
||||||
|
func chunkCount(n, size int) int {
|
||||||
|
count := n / size
|
||||||
|
if n%size != 0 {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"math"
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestNormalizeSubSortIndex(t *testing.T) {
|
func TestNormalizeSubSortIndex(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
@@ -18,3 +22,15 @@ func TestNormalizeSubSortIndex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A size near MaxInt used to overflow the capacity math and panic in make (CodeQL #119).
|
||||||
|
func TestChunkHugeSizeKeepsOneBatch(t *testing.T) {
|
||||||
|
strs := []string{"a", "b", "c"}
|
||||||
|
if got := chunkStrings(strs, math.MaxInt); len(got) != 1 || !slices.Equal(got[0], strs) {
|
||||||
|
t.Fatalf("chunkStrings(MaxInt) = %v, want [%v]", got, strs)
|
||||||
|
}
|
||||||
|
ints := []int{1, 2, 3}
|
||||||
|
if got := chunkInts(ints, math.MaxInt); len(got) != 1 || !slices.Equal(got[0], ints) {
|
||||||
|
t.Fatalf("chunkInts(MaxInt) = %v, want [%v]", got, ints)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user