mirror of
https://github.com/aler9/rtsp-simple-server
synced 2025-10-05 07:36:57 +08:00
api: fix crash when itemsPerPage is zero and there are items (#3425)
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -36,58 +35,6 @@ func interfaceIsEmpty(i interface{}) bool {
|
|||||||
return reflect.ValueOf(i).Kind() != reflect.Ptr || reflect.ValueOf(i).IsNil()
|
return reflect.ValueOf(i).Kind() != reflect.Ptr || reflect.ValueOf(i).IsNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func paginate2(itemsPtr interface{}, itemsPerPage int, page int) int {
|
|
||||||
ritems := reflect.ValueOf(itemsPtr).Elem()
|
|
||||||
|
|
||||||
itemsLen := ritems.Len()
|
|
||||||
if itemsLen == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pageCount := (itemsLen / itemsPerPage)
|
|
||||||
if (itemsLen % itemsPerPage) != 0 {
|
|
||||||
pageCount++
|
|
||||||
}
|
|
||||||
|
|
||||||
min := page * itemsPerPage
|
|
||||||
if min > itemsLen {
|
|
||||||
min = itemsLen
|
|
||||||
}
|
|
||||||
|
|
||||||
max := (page + 1) * itemsPerPage
|
|
||||||
if max > itemsLen {
|
|
||||||
max = itemsLen
|
|
||||||
}
|
|
||||||
|
|
||||||
ritems.Set(ritems.Slice(min, max))
|
|
||||||
|
|
||||||
return pageCount
|
|
||||||
}
|
|
||||||
|
|
||||||
func paginate(itemsPtr interface{}, itemsPerPageStr string, pageStr string) (int, error) {
|
|
||||||
itemsPerPage := 100
|
|
||||||
|
|
||||||
if itemsPerPageStr != "" {
|
|
||||||
tmp, err := strconv.ParseUint(itemsPerPageStr, 10, 31)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
itemsPerPage = int(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
page := 0
|
|
||||||
|
|
||||||
if pageStr != "" {
|
|
||||||
tmp, err := strconv.ParseUint(pageStr, 10, 31)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
page = int(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
return paginate2(itemsPtr, itemsPerPage, page), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sortedKeys(paths map[string]*conf.Path) []string {
|
func sortedKeys(paths map[string]*conf.Path) []string {
|
||||||
ret := make([]string, len(paths))
|
ret := make([]string, len(paths))
|
||||||
i := 0
|
i := 0
|
||||||
|
@@ -74,38 +74,6 @@ func checkError(t *testing.T, msg string, body io.Reader) {
|
|||||||
require.Equal(t, map[string]interface{}{"error": msg}, resErr)
|
require.Equal(t, map[string]interface{}{"error": msg}, resErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPaginate(t *testing.T) {
|
|
||||||
items := make([]int, 5)
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
items[i] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
pageCount, err := paginate(&items, "1", "1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 5, pageCount)
|
|
||||||
require.Equal(t, []int{1}, items)
|
|
||||||
|
|
||||||
items = make([]int, 5)
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
items[i] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
pageCount, err = paginate(&items, "3", "2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 2, pageCount)
|
|
||||||
require.Equal(t, []int{}, items)
|
|
||||||
|
|
||||||
items = make([]int, 6)
|
|
||||||
for i := 0; i < 6; i++ {
|
|
||||||
items[i] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
pageCount, err = paginate(&items, "4", "1")
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 2, pageCount)
|
|
||||||
require.Equal(t, []int{4, 5}, items)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConfigAuth(t *testing.T) {
|
func TestConfigAuth(t *testing.T) {
|
||||||
cnf := tempConf(t, "api: yes\n")
|
cnf := tempConf(t, "api: yes\n")
|
||||||
|
|
||||||
|
63
internal/api/paginate.go
Normal file
63
internal/api/paginate.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func paginate2(itemsPtr interface{}, itemsPerPage int, page int) int {
|
||||||
|
ritems := reflect.ValueOf(itemsPtr).Elem()
|
||||||
|
|
||||||
|
itemsLen := ritems.Len()
|
||||||
|
if itemsLen == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pageCount := (itemsLen / itemsPerPage)
|
||||||
|
if (itemsLen % itemsPerPage) != 0 {
|
||||||
|
pageCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
min := page * itemsPerPage
|
||||||
|
if min > itemsLen {
|
||||||
|
min = itemsLen
|
||||||
|
}
|
||||||
|
|
||||||
|
max := (page + 1) * itemsPerPage
|
||||||
|
if max > itemsLen {
|
||||||
|
max = itemsLen
|
||||||
|
}
|
||||||
|
|
||||||
|
ritems.Set(ritems.Slice(min, max))
|
||||||
|
|
||||||
|
return pageCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func paginate(itemsPtr interface{}, itemsPerPageStr string, pageStr string) (int, error) {
|
||||||
|
itemsPerPage := 100
|
||||||
|
|
||||||
|
if itemsPerPageStr != "" {
|
||||||
|
tmp, err := strconv.ParseUint(itemsPerPageStr, 10, 31)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
itemsPerPage = int(tmp)
|
||||||
|
|
||||||
|
if itemsPerPage == 0 {
|
||||||
|
return 0, fmt.Errorf("invalid items per page")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
page := 0
|
||||||
|
|
||||||
|
if pageStr != "" {
|
||||||
|
tmp, err := strconv.ParseUint(pageStr, 10, 31)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
page = int(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return paginate2(itemsPtr, itemsPerPage, page), nil
|
||||||
|
}
|
65
internal/api/paginate_test.go
Normal file
65
internal/api/paginate_test.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPaginate(t *testing.T) {
|
||||||
|
func() {
|
||||||
|
items := make([]int, 5)
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
items[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
pageCount, err := paginate(&items, "1", "1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 5, pageCount)
|
||||||
|
require.Equal(t, []int{1}, items)
|
||||||
|
}()
|
||||||
|
|
||||||
|
func() {
|
||||||
|
items := make([]int, 5)
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
items[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
pageCount, err := paginate(&items, "3", "2")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 2, pageCount)
|
||||||
|
require.Equal(t, []int{}, items)
|
||||||
|
}()
|
||||||
|
|
||||||
|
func() {
|
||||||
|
items := make([]int, 6)
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
items[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
pageCount, err := paginate(&items, "4", "1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 2, pageCount)
|
||||||
|
require.Equal(t, []int{4, 5}, items)
|
||||||
|
}()
|
||||||
|
|
||||||
|
func() {
|
||||||
|
items := make([]int, 0)
|
||||||
|
|
||||||
|
pageCount, err := paginate(&items, "1", "0")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, pageCount)
|
||||||
|
require.Equal(t, []int{}, items)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzPaginate(f *testing.F) {
|
||||||
|
f.Fuzz(func(_ *testing.T, str1 string, str2 string) {
|
||||||
|
items := make([]int, 6)
|
||||||
|
for i := 0; i < 6; i++ {
|
||||||
|
items[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
paginate(&items, str1, str2) //nolint:errcheck
|
||||||
|
})
|
||||||
|
}
|
3
internal/api/testdata/fuzz/FuzzPaginate/23731da0f18d31d0
vendored
Normal file
3
internal/api/testdata/fuzz/FuzzPaginate/23731da0f18d31d0
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
string("A")
|
||||||
|
string("0")
|
3
internal/api/testdata/fuzz/FuzzPaginate/34523a772174e26e
vendored
Normal file
3
internal/api/testdata/fuzz/FuzzPaginate/34523a772174e26e
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
string("1")
|
||||||
|
string("A")
|
3
internal/api/testdata/fuzz/FuzzPaginate/85649d45641911d0
vendored
Normal file
3
internal/api/testdata/fuzz/FuzzPaginate/85649d45641911d0
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
string("0")
|
||||||
|
string("")
|
Reference in New Issue
Block a user