mirror of
https://github.com/bluenviron/mediamtx
synced 2025-02-19 04:56:53 +00:00
api: fix crash when itemsPerPage is zero and there are items (#3425)
This commit is contained in:
parent
011ea47142
commit
efb51044db
@ -10,7 +10,6 @@ import (
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -36,58 +35,6 @@ func interfaceIsEmpty(i interface{}) bool {
|
||||
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 {
|
||||
ret := make([]string, len(paths))
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
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("")
|
Loading…
Reference in New Issue
Block a user