Skip to content

Commit

Permalink
api: fix crash when itemsPerPage is zero and there are items
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed Jun 4, 2024
1 parent 011ea47 commit bf315ca
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 85 deletions.
53 changes: 0 additions & 53 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"os"
"reflect"
"sort"
"strconv"
"strings"
"sync"
"time"
Expand All @@ -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
Expand Down
32 changes: 0 additions & 32 deletions internal/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
63 changes: 63 additions & 0 deletions internal/api/paginate.go
Original file line number Diff line number Diff line change
@@ -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 changes: 65 additions & 0 deletions internal/api/paginate_test.go
Original file line number Diff line number Diff line change
@@ -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)

Check failure on line 63 in internal/api/paginate_test.go

View workflow job for this annotation

GitHub Actions / golangci_lint

Error return value is not checked (errcheck)
})
}
3 changes: 3 additions & 0 deletions internal/api/testdata/fuzz/FuzzPaginate/23731da0f18d31d0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
go test fuzz v1
string("A")
string("0")
3 changes: 3 additions & 0 deletions internal/api/testdata/fuzz/FuzzPaginate/34523a772174e26e
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
go test fuzz v1
string("1")
string("A")
3 changes: 3 additions & 0 deletions internal/api/testdata/fuzz/FuzzPaginate/85649d45641911d0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
go test fuzz v1
string("0")
string("")

0 comments on commit bf315ca

Please sign in to comment.